/**
* Drag-to-resize Svelte action. Attaches pointerdown to the host element
* (a thin handle on the inner edge of a sidebar) and writes the new width
* back via the supplied setter. The pointer is captured so the drag keeps
* tracking when the cursor leaves the handle.
*
* edge: 'right' — handle on the right edge of the panel; drag right widens
* edge: 'left' — handle on the left edge of the panel; drag left widens
*
* Usage:
*
view.leftSidebarWidth, setWidth: setLeftSidebarWidth }} />
*/
export interface ResizableParams {
edge: 'right' | 'left';
getWidth: () => number;
setWidth: (px: number) => void;
}
export function resizable(node: HTMLElement, initial: ResizableParams) {
let params = initial;
let pointerId = -1;
let startX = 0;
let startWidth = 0;
function onDown(e: PointerEvent) {
if (e.button !== 0) return;
pointerId = e.pointerId;
startX = e.clientX;
startWidth = params.getWidth();
node.setPointerCapture(pointerId);
document.body.style.cursor = 'col-resize';
document.body.style.userSelect = 'none';
node.addEventListener('pointermove', onMove);
node.addEventListener('pointerup', onUp);
node.addEventListener('pointercancel', onUp);
}
function onMove(e: PointerEvent) {
if (e.pointerId !== pointerId) return;
const dx = e.clientX - startX;
const delta = params.edge === 'right' ? dx : -dx;
params.setWidth(startWidth + delta);
}
function onUp(e: PointerEvent) {
if (pointerId === -1) return;
try {
node.releasePointerCapture(pointerId);
} catch {
// Pointer may already be released; ignore.
}
pointerId = -1;
document.body.style.cursor = '';
document.body.style.userSelect = '';
node.removeEventListener('pointermove', onMove);
node.removeEventListener('pointerup', onUp);
node.removeEventListener('pointercancel', onUp);
}
function onDoubleClick() {
// Reset to the current default-ish midpoint. Callers can override by
// providing their own dblclick handler; we just stop pointer events
// from leaking up so the page underneath doesn't react.
}
node.addEventListener('pointerdown', onDown);
node.addEventListener('dblclick', onDoubleClick);
return {
update(next: ResizableParams) {
params = next;
},
destroy() {
node.removeEventListener('pointerdown', onDown);
node.removeEventListener('dblclick', onDoubleClick);
}
};
}