forked from open-doubao-ai/OpenDoubao
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsplit-resize.ts
More file actions
90 lines (82 loc) · 2.37 KB
/
Copy pathsplit-resize.ts
File metadata and controls
90 lines (82 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/** Vertical split handle: drag / keyboard to set left pane %. */
export function mountVerticalSplit(opts: {
split: HTMLElement;
handle: HTMLElement;
/** CSS custom property on `split`, e.g. --admin-list-pct */
cssVar: string;
storageKey: string;
defaultPct?: number;
minPct?: number;
maxPct?: number;
/** class on body while dragging */
bodyClass?: string;
/** keep sibling layouts in sync (same CSS var) */
syncSplits?: HTMLElement[];
}): void {
const min = opts.minPct ?? 20;
const max = opts.maxPct ?? 80;
const bodyClass = opts.bodyClass ?? "is-resizing-split";
const load = (): number => {
try {
const n = Number(localStorage.getItem(opts.storageKey));
if (Number.isFinite(n) && n >= min && n <= max) return n;
} catch {
/* ignore */
}
return opts.defaultPct ?? 40;
};
const save = (pct: number) => {
try {
localStorage.setItem(opts.storageKey, String(Math.round(pct)));
} catch {
/* ignore */
}
};
const apply = (pct: number) => {
const clamped = Math.min(max, Math.max(min, pct));
const targets = [opts.split, ...(opts.syncSplits ?? [])];
for (const el of targets) {
el.style.setProperty(opts.cssVar, `${clamped}%`);
}
save(clamped);
};
apply(load());
let dragging = false;
const onMove = (clientX: number) => {
const rect = opts.split.getBoundingClientRect();
if (rect.width < 80) return;
apply(((clientX - rect.left) / rect.width) * 100);
};
opts.handle.addEventListener("pointerdown", (e) => {
e.preventDefault();
dragging = true;
opts.handle.setPointerCapture(e.pointerId);
document.body.classList.add(bodyClass);
});
opts.handle.addEventListener("pointermove", (e) => {
if (!dragging) return;
onMove(e.clientX);
});
const endDrag = (e: PointerEvent) => {
if (!dragging) return;
dragging = false;
try {
opts.handle.releasePointerCapture(e.pointerId);
} catch {
/* ignore */
}
document.body.classList.remove(bodyClass);
};
opts.handle.addEventListener("pointerup", endDrag);
opts.handle.addEventListener("pointercancel", endDrag);
opts.handle.addEventListener("keydown", (e) => {
const cur = load();
if (e.key === "ArrowLeft") {
e.preventDefault();
apply(cur - 2);
} else if (e.key === "ArrowRight") {
e.preventDefault();
apply(cur + 2);
}
});
}