-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathcreate-draggable.ts
More file actions
121 lines (105 loc) · 3.09 KB
/
create-draggable.ts
File metadata and controls
121 lines (105 loc) · 3.09 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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import {
createEffect,
createSignal,
onCleanup,
onMount,
Setter,
} from "solid-js";
import { Id, Listeners, useDragDropContext } from "./drag-drop-context";
import {
elementLayout,
noopTransform,
Transform,
transformsAreEqual,
} from "./layout";
import { transformStyle } from "./style";
interface Draggable {
(element: HTMLElement, accessor?: () => { skipTransform?: boolean }): void;
ref: Setter<HTMLElement | null>;
get isActiveDraggable(): boolean;
get dragActivators(): Listeners;
get transform(): Transform;
}
const createDraggable = (id: Id, data: Record<string, any> = {}): Draggable => {
const [state, { addDraggable, removeDraggable, draggableActivators }] =
useDragDropContext()!;
const [node, setNode] = createSignal<HTMLElement | null>(null);
onMount(() => {
const resolvedNode = node();
if (resolvedNode) {
addDraggable({
id,
node: resolvedNode,
layout: elementLayout(resolvedNode),
data,
});
}
});
onCleanup(() => removeDraggable(id));
const isActiveDraggable = () => state.active.draggableId === id;
const transform = () => {
return state.draggables[id]?.transform || noopTransform();
};
const draggable = Object.defineProperties(
(element: HTMLElement, accessor?: () => { skipTransform?: boolean }) => {
const config = accessor ? accessor() : {};
createEffect(() => {
const resolvedNode = node();
const activators = draggableActivators(id);
if (resolvedNode) {
for (const key in activators) {
resolvedNode.addEventListener(key, activators[key]);
}
}
onCleanup(() => {
if (resolvedNode) {
for (const key in activators) {
resolvedNode.removeEventListener(key, activators[key]);
}
}
});
});
setNode(element);
if (!config.skipTransform) {
createEffect(() => {
const resolvedTransform = transform();
if (state.active.forceImmediateTransition) {
element.style.setProperty("transition-property", "transform");
element.style.setProperty("transition-duration", "0ms");
} else {
element.style.removeProperty("transition-property");
element.style.removeProperty("transition-duration");
}
if (!transformsAreEqual(resolvedTransform, noopTransform())) {
const style = transformStyle(resolvedTransform);
element.style.setProperty("transform", style.transform);
} else {
element.style.removeProperty("transform");
}
});
}
},
{
ref: {
enumerable: true,
value: setNode,
},
isActiveDraggable: {
enumerable: true,
get: isActiveDraggable,
},
dragActivators: {
enumerable: true,
get: () => {
return draggableActivators(id, true);
},
},
transform: {
enumerable: true,
get: transform,
},
}
) as Draggable;
return draggable;
};
export { createDraggable };