58 lines
2.3 KiB
JavaScript
58 lines
2.3 KiB
JavaScript
// Resources belong to the view that creates them, including every close path.
|
|
export function createViewScope() {
|
|
const controller = new AbortController();
|
|
const cleanups = new Set();
|
|
const onDispose = cleanup => {
|
|
if (controller.signal.aborted) cleanup();
|
|
else cleanups.add(cleanup);
|
|
return () => cleanups.delete(cleanup);
|
|
};
|
|
return {
|
|
signal: controller.signal,
|
|
onDispose,
|
|
listen(target, event, handler, options) {
|
|
target.addEventListener(event, handler, options);
|
|
return onDispose(() => target.removeEventListener(event, handler, options));
|
|
},
|
|
dispose() {
|
|
if (controller.signal.aborted) return;
|
|
controller.abort();
|
|
for (const cleanup of cleanups) cleanup();
|
|
cleanups.clear();
|
|
},
|
|
};
|
|
}
|
|
|
|
export function bindDrawerResize(handle, panel, scope, { side, minWidth, setWidth, saveWidth, enabled = () => true }) {
|
|
let finish = null;
|
|
handle.onmousedown = event => {
|
|
if (event.button !== 0 || scope.signal.aborted || !enabled()) return;
|
|
finish?.();
|
|
event.preventDefault();
|
|
const startX = event.clientX;
|
|
const startWidth = panel.getBoundingClientRect().width;
|
|
const previousSelect = document.body.style.userSelect;
|
|
const previousCursor = document.body.style.cursor;
|
|
document.body.style.userSelect = 'none';
|
|
document.body.style.cursor = 'ew-resize';
|
|
handle.classList.add('is-resizing');
|
|
const move = moveEvent => {
|
|
const delta = (moveEvent.clientX - startX) * (side() === 'left' ? 1 : -1);
|
|
setWidth(Math.max(minWidth, Math.min(window.innerWidth * 0.85, startWidth + delta)));
|
|
};
|
|
const stop = () => {
|
|
window.removeEventListener('mousemove', move);
|
|
window.removeEventListener('mouseup', up);
|
|
document.body.style.userSelect = previousSelect;
|
|
document.body.style.cursor = previousCursor;
|
|
handle.classList.remove('is-resizing');
|
|
finish = null;
|
|
};
|
|
const up = () => { stop(); saveWidth(panel.getBoundingClientRect().width); };
|
|
finish = stop;
|
|
window.addEventListener('mousemove', move);
|
|
window.addEventListener('mouseup', up);
|
|
};
|
|
scope.onDispose(() => { finish?.(); handle.onmousedown = null; });
|
|
}
|