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
|
import { splitProps, type JSX } from "solid-js"
export interface ResizeHandleProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, "onResize"> {
direction: "horizontal" | "vertical"
size: number
min: number
max: number
onResize: (size: number) => void
onCollapse?: () => void
collapseThreshold?: number
}
export function ResizeHandle(props: ResizeHandleProps) {
const [local, rest] = splitProps(props, [
"direction",
"size",
"min",
"max",
"onResize",
"onCollapse",
"collapseThreshold",
"class",
"classList",
])
const handleMouseDown = (e: MouseEvent) => {
e.preventDefault()
const start = local.direction === "horizontal" ? e.clientX : e.clientY
const startSize = local.size
let current = startSize
document.body.style.userSelect = "none"
document.body.style.overflow = "hidden"
const onMouseMove = (moveEvent: MouseEvent) => {
const pos = local.direction === "horizontal" ? moveEvent.clientX : moveEvent.clientY
const delta = local.direction === "vertical" ? start - pos : pos - start
current = startSize + delta
const clamped = Math.min(local.max, Math.max(local.min, current))
local.onResize(clamped)
}
const onMouseUp = () => {
document.body.style.userSelect = ""
document.body.style.overflow = ""
document.removeEventListener("mousemove", onMouseMove)
document.removeEventListener("mouseup", onMouseUp)
const threshold = local.collapseThreshold ?? 0
if (local.onCollapse && threshold > 0 && current < threshold) {
local.onCollapse()
}
}
document.addEventListener("mousemove", onMouseMove)
document.addEventListener("mouseup", onMouseUp)
}
return (
<div
{...rest}
data-component="resize-handle"
data-direction={local.direction}
classList={{
...(local.classList ?? {}),
[local.class ?? ""]: !!local.class,
}}
onMouseDown={handleMouseDown}
/>
)
}
|