80 lines
2.6 KiB
TypeScript
80 lines
2.6 KiB
TypeScript
import { useCallback } from 'react';
|
|
import { getUiPreferences, patchUiPreferences } from '../../utils/uiPreferencesDb';
|
|
|
|
function clamp(value: number, min: number, max: number): number {
|
|
return Math.min(max, Math.max(min, value));
|
|
}
|
|
|
|
type Axis = 'horizontal' | 'vertical';
|
|
|
|
export function usePanelResize(
|
|
axis: Axis,
|
|
onResize: (next: number) => void,
|
|
getCurrent: () => number,
|
|
min: number,
|
|
max: number,
|
|
onCommit?: (value: number) => void,
|
|
) {
|
|
return useCallback((e: React.PointerEvent<HTMLDivElement>) => {
|
|
e.preventDefault();
|
|
const startX = e.clientX;
|
|
const startY = e.clientY;
|
|
const start = getCurrent();
|
|
const cursor = axis === 'vertical' ? 'col-resize' : 'row-resize';
|
|
|
|
document.body.style.cursor = cursor;
|
|
document.body.style.userSelect = 'none';
|
|
e.currentTarget.setPointerCapture(e.pointerId);
|
|
e.currentTarget.classList.add('se-splitter--active');
|
|
const splitter = e.currentTarget;
|
|
|
|
const onMove = (ev: PointerEvent) => {
|
|
const delta = axis === 'vertical' ? ev.clientX - startX : startY - ev.clientY;
|
|
onResize(clamp(start + delta, min, max));
|
|
};
|
|
|
|
const onUp = (ev: PointerEvent) => {
|
|
document.body.style.cursor = '';
|
|
document.body.style.userSelect = '';
|
|
splitter.releasePointerCapture(ev.pointerId);
|
|
splitter.classList.remove('se-splitter--active');
|
|
window.removeEventListener('pointermove', onMove);
|
|
window.removeEventListener('pointerup', onUp);
|
|
onCommit?.(getCurrent());
|
|
};
|
|
|
|
window.addEventListener('pointermove', onMove);
|
|
window.addEventListener('pointerup', onUp);
|
|
}, [axis, onResize, getCurrent, min, max, onCommit]);
|
|
}
|
|
|
|
export function readStoredSize(key: string, fallback: number): number {
|
|
try {
|
|
const raw = getUiPreferences().panels?.[key];
|
|
if (raw == null) return fallback;
|
|
const n = typeof raw === 'number' ? raw : Number(raw);
|
|
return Number.isFinite(n) ? n : fallback;
|
|
} catch {
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
export function storeSize(key: string, value: number): void {
|
|
const panels = { ...getUiPreferences().panels, [key]: Math.round(value) };
|
|
patchUiPreferences({ panels });
|
|
}
|
|
|
|
export function readStoredBool(key: string, fallback: boolean): boolean {
|
|
try {
|
|
const raw = getUiPreferences().panels?.[key];
|
|
if (raw === true || raw === '1' || raw === 'true') return true;
|
|
if (raw === false || raw === '0' || raw === 'false') return false;
|
|
} catch { /* ignore */ }
|
|
return fallback;
|
|
}
|
|
|
|
export function storeBool(key: string, value: boolean): void {
|
|
const panels = { ...getUiPreferences().panels, [key]: value };
|
|
patchUiPreferences({ panels });
|
|
}
|