Changeset 0.25.2 (#162)
This commit is contained in:
@@ -345,115 +345,99 @@ function _createHandle(direction, splitEl, index, surfaceId, splitId) {
|
||||
splitEl.appendChild(handle);
|
||||
}
|
||||
|
||||
// Drag logic
|
||||
let startX, startY, leftEl, rightEl, startLeftBasis, startRightBasis;
|
||||
// Track adjacent panes for dblclick reset
|
||||
let lastLeftEl = null, lastRightEl = null;
|
||||
|
||||
const onMouseDown = (e) => {
|
||||
e.preventDefault();
|
||||
const allPanes = Array.from(splitEl.querySelectorAll(':scope > .pane, :scope > .pane-split'));
|
||||
// Find the two panes adjacent to this handle
|
||||
const handleIdx = Array.from(splitEl.children).indexOf(handle);
|
||||
leftEl = splitEl.children[handleIdx - 1];
|
||||
rightEl = splitEl.children[handleIdx + 1];
|
||||
if (!leftEl || !rightEl) return;
|
||||
initDragResize(handle, {
|
||||
direction,
|
||||
onStart(_clientPos) {
|
||||
// Find the two panes adjacent to this handle
|
||||
const handleIdx = Array.from(splitEl.children).indexOf(handle);
|
||||
const leftEl = splitEl.children[handleIdx - 1];
|
||||
const rightEl = splitEl.children[handleIdx + 1];
|
||||
if (!leftEl || !rightEl) return false;
|
||||
|
||||
startX = e.clientX;
|
||||
startY = e.clientY;
|
||||
// Use current rendered size (matches what flex layout computed)
|
||||
startLeftBasis = leftEl.getBoundingClientRect().width;
|
||||
startRightBasis = rightEl.getBoundingClientRect().width;
|
||||
lastLeftEl = leftEl;
|
||||
lastRightEl = rightEl;
|
||||
|
||||
// Immediately lock the non-flex panes to their current sizes
|
||||
// so the first move delta doesn't cause a visual snap
|
||||
if (leftEl.dataset.paneFlex !== '1') {
|
||||
leftEl.style.flexBasis = startLeftBasis + 'px';
|
||||
leftEl.style.flexGrow = '0';
|
||||
leftEl.style.flexShrink = '0';
|
||||
}
|
||||
if (rightEl.dataset.paneFlex !== '1') {
|
||||
rightEl.style.flexBasis = startRightBasis + 'px';
|
||||
rightEl.style.flexGrow = '0';
|
||||
rightEl.style.flexShrink = '0';
|
||||
}
|
||||
const isHoriz = direction === 'horizontal';
|
||||
const dim = isHoriz ? 'width' : 'height';
|
||||
const startLeftBasis = leftEl.getBoundingClientRect()[dim];
|
||||
const startRightBasis = rightEl.getBoundingClientRect()[dim];
|
||||
|
||||
handle.classList.add('pane-handle--active');
|
||||
document.body.style.cursor = direction === 'horizontal' ? 'col-resize' : 'row-resize';
|
||||
document.body.style.userSelect = 'none';
|
||||
// Lock non-flex panes to current rendered size so the first
|
||||
// move delta doesn't cause a visual snap
|
||||
if (leftEl.dataset.paneFlex !== '1') {
|
||||
leftEl.style.flexBasis = startLeftBasis + 'px';
|
||||
leftEl.style.flexGrow = '0';
|
||||
leftEl.style.flexShrink = '0';
|
||||
}
|
||||
if (rightEl.dataset.paneFlex !== '1') {
|
||||
rightEl.style.flexBasis = startRightBasis + 'px';
|
||||
rightEl.style.flexGrow = '0';
|
||||
rightEl.style.flexShrink = '0';
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
};
|
||||
handle.classList.add('pane-handle--active');
|
||||
|
||||
const onMouseMove = (e) => {
|
||||
const delta = direction === 'horizontal'
|
||||
? e.clientX - startX
|
||||
: e.clientY - startY;
|
||||
return { leftEl, rightEl, startLeftBasis, startRightBasis };
|
||||
},
|
||||
onMove(delta, ctx) {
|
||||
const { leftEl, rightEl, startLeftBasis, startRightBasis } = ctx;
|
||||
const leftIsFlex = leftEl.dataset.paneFlex === '1';
|
||||
const rightIsFlex = rightEl.dataset.paneFlex === '1';
|
||||
const isHoriz = direction === 'horizontal';
|
||||
const dim = isHoriz ? 'width' : 'height';
|
||||
const maxSize = splitEl.getBoundingClientRect()[dim] * 0.6;
|
||||
|
||||
const leftIsFlex = leftEl.dataset.paneFlex === '1';
|
||||
const rightIsFlex = rightEl.dataset.paneFlex === '1';
|
||||
// Cap: no single fixed pane should exceed 60% of container
|
||||
const maxSize = splitEl.getBoundingClientRect().width * 0.6;
|
||||
|
||||
if (leftIsFlex) {
|
||||
// Only adjust the right (fixed) pane; left flex absorbs remainder
|
||||
const newRight = Math.min(maxSize, Math.max(50, startRightBasis - delta));
|
||||
rightEl.style.flexBasis = newRight + 'px';
|
||||
rightEl.style.flexGrow = '0';
|
||||
rightEl.style.flexShrink = '0';
|
||||
} else if (rightIsFlex) {
|
||||
// Only adjust the left (fixed) pane; right flex absorbs remainder
|
||||
const newLeft = Math.min(maxSize, Math.max(50, startLeftBasis + delta));
|
||||
leftEl.style.flexBasis = newLeft + 'px';
|
||||
leftEl.style.flexGrow = '0';
|
||||
leftEl.style.flexShrink = '0';
|
||||
} else {
|
||||
// Both fixed — adjust both (original behavior)
|
||||
const newLeft = Math.max(50, startLeftBasis + delta);
|
||||
const newRight = Math.max(50, startRightBasis - delta);
|
||||
leftEl.style.flexBasis = newLeft + 'px';
|
||||
leftEl.style.flexGrow = '0';
|
||||
leftEl.style.flexShrink = '0';
|
||||
rightEl.style.flexBasis = newRight + 'px';
|
||||
rightEl.style.flexGrow = '0';
|
||||
rightEl.style.flexShrink = '0';
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
handle.classList.remove('pane-handle--active');
|
||||
document.body.style.cursor = '';
|
||||
document.body.style.userSelect = '';
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
|
||||
// Persist sizes
|
||||
_persistSizes(surfaceId, splitEl);
|
||||
};
|
||||
|
||||
handle.addEventListener('mousedown', onMouseDown);
|
||||
if (leftIsFlex) {
|
||||
const newRight = Math.min(maxSize, Math.max(50, startRightBasis - delta));
|
||||
rightEl.style.flexBasis = newRight + 'px';
|
||||
rightEl.style.flexGrow = '0';
|
||||
rightEl.style.flexShrink = '0';
|
||||
} else if (rightIsFlex) {
|
||||
const newLeft = Math.min(maxSize, Math.max(50, startLeftBasis + delta));
|
||||
leftEl.style.flexBasis = newLeft + 'px';
|
||||
leftEl.style.flexGrow = '0';
|
||||
leftEl.style.flexShrink = '0';
|
||||
} else {
|
||||
const newLeft = Math.max(50, startLeftBasis + delta);
|
||||
const newRight = Math.max(50, startRightBasis - delta);
|
||||
leftEl.style.flexBasis = newLeft + 'px';
|
||||
leftEl.style.flexGrow = '0';
|
||||
leftEl.style.flexShrink = '0';
|
||||
rightEl.style.flexBasis = newRight + 'px';
|
||||
rightEl.style.flexGrow = '0';
|
||||
rightEl.style.flexShrink = '0';
|
||||
}
|
||||
},
|
||||
onEnd(_ctx) {
|
||||
handle.classList.remove('pane-handle--active');
|
||||
_persistSizes(surfaceId, splitEl);
|
||||
},
|
||||
});
|
||||
|
||||
// Double-click resets to default
|
||||
handle.addEventListener('dblclick', () => {
|
||||
if (leftEl) {
|
||||
if (leftEl.dataset.paneFlex === '1') {
|
||||
leftEl.style.flex = '1'; leftEl.style.flexBasis = ''; leftEl.style.flexGrow = ''; leftEl.style.flexShrink = '';
|
||||
} else {
|
||||
leftEl.style.flexBasis = ''; leftEl.style.flexGrow = ''; leftEl.style.flexShrink = '';
|
||||
}
|
||||
}
|
||||
if (rightEl) {
|
||||
if (rightEl.dataset.paneFlex === '1') {
|
||||
rightEl.style.flex = '1'; rightEl.style.flexBasis = ''; rightEl.style.flexGrow = ''; rightEl.style.flexShrink = '';
|
||||
} else {
|
||||
rightEl.style.flexBasis = ''; rightEl.style.flexGrow = ''; rightEl.style.flexShrink = '';
|
||||
}
|
||||
}
|
||||
_resetPaneSize(lastLeftEl);
|
||||
_resetPaneSize(lastRightEl);
|
||||
_persistSizes(surfaceId, splitEl);
|
||||
});
|
||||
|
||||
return { handle, splitEl, index, direction };
|
||||
}
|
||||
|
||||
/** Reset a pane element to its default flex sizing. */
|
||||
function _resetPaneSize(el) {
|
||||
if (!el) return;
|
||||
if (el.dataset.paneFlex === '1') {
|
||||
el.style.flex = '1';
|
||||
}
|
||||
el.style.flexBasis = '';
|
||||
el.style.flexGrow = '';
|
||||
el.style.flexShrink = '';
|
||||
}
|
||||
|
||||
// ── Persistence ─────────────────────────────
|
||||
|
||||
function _persistSizes(surfaceId, splitEl) {
|
||||
|
||||
Reference in New Issue
Block a user