generated from solidjs-community/solid-lib-starter
-
Notifications
You must be signed in to change notification settings - Fork 33
/
create-pointer-sensor.ts
112 lines (90 loc) · 2.76 KB
/
create-pointer-sensor.ts
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import { onCleanup, onMount } from "solid-js";
import {
Coordinates,
Id,
SensorActivator,
useDragDropContext,
} from "./drag-drop-context";
import { Transform } from "./layout";
const createPointerSensor = (id: Id = "pointer-sensor"): void => {
const [
state,
{
addSensor,
removeSensor,
sensorStart,
sensorMove,
sensorEnd,
dragStart,
dragEnd,
},
] = useDragDropContext()!;
const activationDelay = 250; // milliseconds
const activationDistance = 10; // pixels
onMount(() => {
addSensor({ id, activators: { pointerdown: attach } });
});
onCleanup(() => {
removeSensor(id);
});
const isActiveSensor = () => state.active.sensorId === id;
const initialCoordinates: Coordinates = { x: 0, y: 0 };
let activationDelayTimeoutId: number | null = null;
let activationDraggableId: Id | null = null;
const attach: SensorActivator<"pointerdown"> = (event, draggableId) => {
if (event.button !== 0) return;
document.addEventListener("pointermove", onPointerMove);
document.addEventListener("pointerup", onPointerUp);
activationDraggableId = draggableId;
initialCoordinates.x = event.clientX;
initialCoordinates.y = event.clientY;
activationDelayTimeoutId = window.setTimeout(onActivate, activationDelay);
};
const detach = (): void => {
if (activationDelayTimeoutId) {
clearTimeout(activationDelayTimeoutId);
activationDelayTimeoutId = null;
}
document.removeEventListener("pointermove", onPointerMove);
document.removeEventListener("pointerup", onPointerUp);
document.removeEventListener("selectionchange", clearSelection);
};
const onActivate = (): void => {
if (!state.active.sensor) {
sensorStart(id, initialCoordinates);
dragStart(activationDraggableId!);
clearSelection();
document.addEventListener("selectionchange", clearSelection);
} else if (!isActiveSensor()) {
detach();
}
};
const onPointerMove = (event: PointerEvent): void => {
const coordinates: Coordinates = { x: event.clientX, y: event.clientY };
if (!state.active.sensor) {
const transform: Transform = {
x: coordinates.x - initialCoordinates.x,
y: coordinates.y - initialCoordinates.y,
};
if (Math.sqrt(transform.x ** 2 + transform.y ** 2) > activationDistance) {
onActivate();
}
}
if (isActiveSensor()) {
event.preventDefault();
sensorMove(coordinates);
}
};
const onPointerUp = (event: PointerEvent): void => {
detach();
if (isActiveSensor()) {
event.preventDefault();
dragEnd();
sensorEnd();
}
};
const clearSelection = () => {
window.getSelection()?.removeAllRanges();
};
};
export { createPointerSensor };