refactor: split prompt studio views and unify UI lifecycle
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
// 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; });
|
||||
}
|
||||
Reference in New Issue
Block a user