@dnd-kit/solid 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js ADDED
@@ -0,0 +1,417 @@
1
+ import { createComponent, Dynamic, memo } from 'solid-js/web';
2
+ import { createContext, createMemo, onCleanup, createEffect, useContext, createSignal, Show, on, batch } from 'solid-js';
3
+ import { DragDropManager, defaultPreset, Draggable, Feedback, Droppable } from '@dnd-kit/dom';
4
+ export { KeyboardSensor, PointerSensor } from '@dnd-kit/dom';
5
+ import { isSortable } from '@dnd-kit/dom/sortable';
6
+ import { effect, untracked } from '@dnd-kit/state';
7
+
8
+ // src/core/context/DragDropProvider.tsx
9
+ var DragDropContext = createContext(null);
10
+ function useRenderer() {
11
+ const [transitionCount, setTransitionCount] = createSignal(0);
12
+ let rendering = null;
13
+ let resolver = null;
14
+ createEffect(
15
+ on(transitionCount, () => {
16
+ resolver?.();
17
+ rendering = null;
18
+ })
19
+ );
20
+ return {
21
+ renderer: {
22
+ get rendering() {
23
+ return rendering ?? Promise.resolve();
24
+ }
25
+ },
26
+ trackRendering(callback) {
27
+ if (!rendering) {
28
+ rendering = new Promise((resolve) => {
29
+ resolver = resolve;
30
+ });
31
+ }
32
+ batch(() => {
33
+ callback();
34
+ setTransitionCount((c) => c + 1);
35
+ });
36
+ }
37
+ };
38
+ }
39
+
40
+ // src/utilities/saveElementPosition.ts
41
+ function createSaveElementPosition() {
42
+ let savedPosition = null;
43
+ const savePosition = (source) => {
44
+ const element = source.element;
45
+ const id = source.id;
46
+ const prevElement = element.previousElementSibling;
47
+ const nextElement = element.nextElementSibling;
48
+ const parentElement = element.parentElement;
49
+ savedPosition = {
50
+ id,
51
+ element,
52
+ prevElement: prevElement === element ? null : prevElement,
53
+ nextElement: nextElement === element ? null : nextElement,
54
+ parentElement
55
+ };
56
+ };
57
+ const restorePosition = (element) => {
58
+ if (!savedPosition) return;
59
+ const { prevElement, nextElement, parentElement } = savedPosition;
60
+ if (prevElement && element.previousElementSibling !== prevElement) {
61
+ prevElement.insertAdjacentElement("afterend", element);
62
+ } else if (nextElement && element.nextElementSibling !== nextElement) {
63
+ nextElement.insertAdjacentElement("beforebegin", element);
64
+ } else if (!prevElement && !nextElement && parentElement) {
65
+ parentElement.appendChild(element);
66
+ }
67
+ };
68
+ const clearPosition = () => {
69
+ savedPosition = null;
70
+ };
71
+ return {
72
+ savePosition,
73
+ clearPosition,
74
+ restorePosition
75
+ };
76
+ }
77
+
78
+ // src/core/context/DragDropProvider.tsx
79
+ function DragDropProvider(props) {
80
+ const {
81
+ savePosition,
82
+ restorePosition,
83
+ clearPosition
84
+ } = createSaveElementPosition();
85
+ const {
86
+ renderer,
87
+ trackRendering
88
+ } = useRenderer();
89
+ const manager = createMemo(() => props.manager ?? new DragDropManager(props));
90
+ onCleanup(() => {
91
+ if (!props.manager) {
92
+ manager().destroy();
93
+ }
94
+ });
95
+ createEffect(() => {
96
+ const _manager = manager();
97
+ _manager.renderer = renderer;
98
+ _manager.plugins = props.plugins ?? defaultPreset.plugins;
99
+ _manager.sensors = props.sensors ?? defaultPreset.sensors;
100
+ _manager.modifiers = props.modifiers ?? defaultPreset.modifiers;
101
+ });
102
+ createEffect(() => {
103
+ const disposers = [];
104
+ const monitor = manager().monitor;
105
+ disposers.push(monitor.addEventListener("beforedragstart", (event, manager2) => {
106
+ if (isSortable(event.operation.source)) {
107
+ savePosition(event.operation.source);
108
+ }
109
+ const callback = props.onBeforeDragStart;
110
+ if (callback) {
111
+ trackRendering(() => callback(event, manager2));
112
+ }
113
+ }), monitor.addEventListener("dragstart", (event, manager2) => {
114
+ props.onDragStart?.(event, manager2);
115
+ }), monitor.addEventListener("dragover", (event, manager2) => {
116
+ const callback = props.onDragOver;
117
+ if (callback) {
118
+ trackRendering(() => callback(event, manager2));
119
+ if (isSortable(event.operation.source)) {
120
+ const source = event.operation.source;
121
+ queueMicrotask(() => savePosition(source));
122
+ }
123
+ }
124
+ }), monitor.addEventListener("dragmove", (event, manager2) => {
125
+ const callback = props.onDragMove;
126
+ if (callback) {
127
+ trackRendering(() => callback(event, manager2));
128
+ }
129
+ }), monitor.addEventListener("dragend", (event, manager2) => {
130
+ if (isSortable(event.operation.source)) {
131
+ restorePosition(event.operation.source.element);
132
+ }
133
+ const callback = props.onDragEnd;
134
+ if (callback) {
135
+ trackRendering(() => callback(event, manager2));
136
+ }
137
+ clearPosition();
138
+ }), monitor.addEventListener("collision", (event, manager2) => {
139
+ props.onCollision?.(event, manager2);
140
+ }));
141
+ onCleanup(() => {
142
+ disposers.forEach((cleanup) => cleanup());
143
+ });
144
+ });
145
+ return createComponent(DragDropContext.Provider, {
146
+ get value() {
147
+ return manager();
148
+ },
149
+ get children() {
150
+ return props.children;
151
+ }
152
+ });
153
+ }
154
+ function useDeepSignal(target) {
155
+ const tracked = /* @__PURE__ */ new Map();
156
+ const [dirty, setDirty] = createSignal(0);
157
+ createEffect(() => {
158
+ const _target = target();
159
+ if (!_target) {
160
+ tracked.clear();
161
+ return;
162
+ }
163
+ const dispose = effect(() => {
164
+ let stale = false;
165
+ for (const entry of tracked) {
166
+ const [key] = entry;
167
+ const value = untracked(() => entry[1]);
168
+ const latestValue = _target[key];
169
+ if (value !== latestValue) {
170
+ stale = true;
171
+ tracked.set(key, latestValue);
172
+ }
173
+ }
174
+ if (stale) {
175
+ setDirty((v) => v + 1);
176
+ }
177
+ });
178
+ onCleanup(dispose);
179
+ });
180
+ return () => {
181
+ const _target = target();
182
+ void dirty();
183
+ return _target ? new Proxy(_target, {
184
+ get(target2, key) {
185
+ const value = target2[key];
186
+ tracked.set(key, value);
187
+ return value;
188
+ }
189
+ }) : _target;
190
+ };
191
+ }
192
+ function useDragDropManager() {
193
+ return useContext(DragDropContext);
194
+ }
195
+
196
+ // src/core/hooks/useInstance.ts
197
+ function useInstance(initializer) {
198
+ const manager = useDragDropManager() ?? void 0;
199
+ const instance = initializer(manager);
200
+ createEffect(() => {
201
+ instance.manager = manager;
202
+ const cleanup = instance.register();
203
+ onCleanup(() => cleanup?.());
204
+ });
205
+ return instance;
206
+ }
207
+
208
+ // src/core/draggable/useDraggable.ts
209
+ function useDraggable(input) {
210
+ const draggable = useInstance(
211
+ (manager) => new Draggable(
212
+ {
213
+ ...input,
214
+ register: false,
215
+ element: input.element,
216
+ handle: input.handle
217
+ },
218
+ manager
219
+ )
220
+ );
221
+ const trackedDraggable = useDeepSignal(() => draggable);
222
+ const [element, setElement] = createSignal(
223
+ input.element
224
+ );
225
+ const [handle, setHandle] = createSignal(input.handle);
226
+ createEffect(() => {
227
+ const el = element();
228
+ if (el) draggable.element = el;
229
+ const h = handle();
230
+ if (h) draggable.handle = h;
231
+ draggable.id = input.id;
232
+ draggable.disabled = input.disabled ?? false;
233
+ draggable.feedback = input.feedback ?? "default";
234
+ draggable.alignment = input.alignment;
235
+ draggable.modifiers = input.modifiers;
236
+ draggable.sensors = input.sensors;
237
+ if (input.data) {
238
+ draggable.data = input.data;
239
+ }
240
+ });
241
+ return {
242
+ get draggable() {
243
+ return draggable;
244
+ },
245
+ isDragging: () => trackedDraggable().isDragging,
246
+ isDropping: () => trackedDraggable().isDropping,
247
+ isDragSource: () => trackedDraggable().isDragSource,
248
+ ref: setElement,
249
+ handleRef: setHandle
250
+ };
251
+ }
252
+
253
+ // src/core/hooks/useDragOperation.ts
254
+ function useDragOperation() {
255
+ const manager = useDragDropManager();
256
+ const trackedDragOperation = useDeepSignal(
257
+ () => manager?.dragOperation
258
+ );
259
+ return {
260
+ source: () => trackedDragOperation()?.source,
261
+ target: () => trackedDragOperation()?.target,
262
+ status: () => trackedDragOperation()?.status
263
+ };
264
+ }
265
+
266
+ // src/core/draggable/DragOverlay.tsx
267
+ function DragOverlay(props) {
268
+ const [element, setElement] = createSignal();
269
+ const manager = useDragDropManager();
270
+ const patchedManager = createPatchedManager(() => manager);
271
+ const dragOperation = useDragOperation();
272
+ const source = () => dragOperation.source();
273
+ const isDisabled = () => {
274
+ if (typeof props.disabled === "function") {
275
+ return props.disabled(source());
276
+ }
277
+ return props.disabled ?? false;
278
+ };
279
+ createEffect(() => {
280
+ if (!source()) {
281
+ setElement(void 0);
282
+ }
283
+ });
284
+ createEffect(() => {
285
+ const _manager = manager;
286
+ if (!_manager || isDisabled()) return;
287
+ const feedback = _manager.plugins.find((plugin) => plugin instanceof Feedback);
288
+ if (!feedback) return;
289
+ feedback.overlay = element();
290
+ onCleanup(() => {
291
+ feedback.overlay = void 0;
292
+ });
293
+ });
294
+ return createComponent(DragDropContext.Provider, {
295
+ get value() {
296
+ return patchedManager();
297
+ },
298
+ get children() {
299
+ return createComponent(Show, {
300
+ get when() {
301
+ return memo(() => !!!isDisabled())() ? source() : void 0;
302
+ },
303
+ children: (src) => createComponent(Dynamic, {
304
+ get component() {
305
+ return props.tag || "div";
306
+ },
307
+ get ["class"]() {
308
+ return props.class;
309
+ },
310
+ get style() {
311
+ return props.style;
312
+ },
313
+ "data-dnd-overlay": true,
314
+ ref: setElement,
315
+ get children() {
316
+ return memo(() => typeof props.children === "function")() ? props.children(src()) : props.children;
317
+ }
318
+ })
319
+ });
320
+ }
321
+ });
322
+ }
323
+ function createPatchedManager(manager) {
324
+ return createMemo(() => {
325
+ const _manager = manager();
326
+ if (!_manager) return null;
327
+ const patchedRegistry = new Proxy(_manager.registry, {
328
+ get(target, property) {
329
+ if (property === "register" || property === "unregister") {
330
+ return noop;
331
+ }
332
+ return target[property];
333
+ }
334
+ });
335
+ return new Proxy(_manager, {
336
+ get(target, property) {
337
+ if (property === "registry") {
338
+ return patchedRegistry;
339
+ }
340
+ return target[property];
341
+ }
342
+ });
343
+ });
344
+ }
345
+ function noop() {
346
+ return () => {
347
+ };
348
+ }
349
+ function useDroppable(input) {
350
+ const droppable = useInstance(
351
+ (manager) => new Droppable(
352
+ {
353
+ ...input,
354
+ register: false,
355
+ element: input.element
356
+ },
357
+ manager
358
+ )
359
+ );
360
+ const trackedDroppable = useDeepSignal(() => droppable);
361
+ const [element, setElement] = createSignal(
362
+ input.element
363
+ );
364
+ createEffect(() => {
365
+ const el = element();
366
+ if (el) droppable.element = el;
367
+ droppable.id = input.id;
368
+ droppable.accept = input.accept;
369
+ droppable.type = input.type;
370
+ droppable.disabled = input.disabled ?? false;
371
+ if (input.collisionDetector) {
372
+ droppable.collisionDetector = input.collisionDetector;
373
+ }
374
+ if (input.data) {
375
+ droppable.data = input.data;
376
+ }
377
+ });
378
+ return {
379
+ get droppable() {
380
+ return droppable;
381
+ },
382
+ isDropTarget: () => trackedDroppable().isDropTarget,
383
+ ref: setElement
384
+ };
385
+ }
386
+ function useDragDropMonitor(handlers) {
387
+ const manager = useDragDropManager();
388
+ createEffect(() => {
389
+ if (!manager) {
390
+ if (process.env.NODE_ENV !== "production") {
391
+ console.warn(
392
+ "useDragDropMonitor hook was called outside of a DragDropProvider. Make sure your app is wrapped in a DragDropProvider component."
393
+ );
394
+ }
395
+ return;
396
+ }
397
+ const cleanupFns = Object.entries(handlers).reduce(
398
+ (acc, [handlerName, handler]) => {
399
+ if (handler) {
400
+ const eventName = handlerName.replace(/^on/, "").toLowerCase();
401
+ const unsubscribe = manager.monitor.addEventListener(
402
+ eventName,
403
+ handler
404
+ );
405
+ acc.push(unsubscribe);
406
+ }
407
+ return acc;
408
+ },
409
+ []
410
+ );
411
+ onCleanup(() => cleanupFns.forEach((cleanup) => cleanup()));
412
+ });
413
+ }
414
+
415
+ export { DragDropProvider, DragOverlay, useDragDropManager, useDragDropMonitor, useDragOperation, useDraggable, useDroppable, useInstance };
416
+ //# sourceMappingURL=index.js.map
417
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@dnd-kit/solid",
3
+ "version": "0.2.3",
4
+ "main": "./index.cjs",
5
+ "module": "./index.js",
6
+ "type": "module",
7
+ "types": "./index.d.ts",
8
+ "sideEffects": false,
9
+ "license": "MIT",
10
+ "files": [
11
+ "LICENSE",
12
+ "README.md",
13
+ "index.js",
14
+ "index.d.ts",
15
+ "index.cjs",
16
+ "hooks.js",
17
+ "hooks.d.ts",
18
+ "hooks.cjs",
19
+ "sortable.js",
20
+ "sortable.d.ts",
21
+ "sortable.cjs",
22
+ "utilities.js",
23
+ "utilities.d.ts",
24
+ "utilities.cjs"
25
+ ],
26
+ "exports": {
27
+ ".": {
28
+ "types": "./index.d.ts",
29
+ "import": "./index.js",
30
+ "require": "./index.cjs"
31
+ },
32
+ "./hooks": {
33
+ "types": "./hooks.d.ts",
34
+ "import": "./hooks.js",
35
+ "require": "./hooks.cjs"
36
+ },
37
+ "./sortable": {
38
+ "types": "./sortable.d.ts",
39
+ "import": "./sortable.js",
40
+ "require": "./sortable.cjs"
41
+ },
42
+ "./utilities": {
43
+ "types": "./utilities.d.ts",
44
+ "import": "./utilities.js",
45
+ "require": "./utilities.cjs"
46
+ }
47
+ },
48
+ "scripts": {
49
+ "build": "bun build:utilities && bun build:hooks && bun build:core && bun build:sortable",
50
+ "build:core": "tsup src/core/index.ts",
51
+ "build:hooks": "tsup --entry.hooks src/hooks/index.ts",
52
+ "build:sortable": "tsup --entry.sortable src/sortable/index.ts",
53
+ "build:utilities": "tsup --entry.utilities src/utilities/index.ts",
54
+ "dev": "bun build:utilities --watch & bun build:hooks --watch & bun build:core --watch & bun build:sortable --watch",
55
+ "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
56
+ },
57
+ "dependencies": {
58
+ "@dnd-kit/abstract": "^0.2.3",
59
+ "@dnd-kit/dom": "^0.2.3",
60
+ "@dnd-kit/state": "^0.2.3",
61
+ "tslib": "^2.6.2"
62
+ },
63
+ "peerDependencies": {
64
+ "solid-js": "^1.8.0"
65
+ },
66
+ "devDependencies": {
67
+ "esbuild-plugin-solid": "^0.6.0",
68
+ "tsup": "8.3.0",
69
+ "typescript": "^5.5.2",
70
+ "solid-js": "^1.9.0"
71
+ },
72
+ "publishConfig": {
73
+ "access": "public"
74
+ },
75
+ "repository": {
76
+ "type": "git",
77
+ "url": "https://github.com/clauderic/dnd-kit"
78
+ }
79
+ }
package/sortable.cjs ADDED
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ var sortable = require('@dnd-kit/dom/sortable');
4
+ var state = require('@dnd-kit/state');
5
+ var solidJs = require('solid-js');
6
+ var hooks = require('@dnd-kit/solid/hooks');
7
+ var solid = require('@dnd-kit/solid');
8
+
9
+ // src/sortable/useSortable.ts
10
+ function useSortable(input) {
11
+ const transition = {
12
+ ...sortable.defaultSortableTransition,
13
+ ...input.transition
14
+ };
15
+ const sortable$1 = solid.useInstance((manager) => {
16
+ return new sortable.Sortable(
17
+ {
18
+ ...input,
19
+ register: false,
20
+ transition,
21
+ element: input.element,
22
+ handle: input.handle,
23
+ target: input.target
24
+ },
25
+ manager
26
+ );
27
+ });
28
+ const trackedSortable = hooks.useDeepSignal(() => sortable$1);
29
+ const [element, setElement] = solidJs.createSignal(
30
+ input.element
31
+ );
32
+ const [handle, setHandle] = solidJs.createSignal(input.handle);
33
+ const [source, setSource] = solidJs.createSignal(input.source);
34
+ const [target, setTarget] = solidJs.createSignal(input.target);
35
+ solidJs.createEffect(() => {
36
+ const el = element();
37
+ if (el) sortable$1.element = el;
38
+ const h = handle();
39
+ if (h) sortable$1.handle = h;
40
+ const s = source();
41
+ if (s) sortable$1.source = s;
42
+ const t = target();
43
+ if (t) sortable$1.target = t;
44
+ sortable$1.id = input.id;
45
+ sortable$1.disabled = input.disabled ?? false;
46
+ sortable$1.feedback = input.feedback ?? "default";
47
+ sortable$1.alignment = input.alignment;
48
+ sortable$1.modifiers = input.modifiers;
49
+ sortable$1.sensors = input.sensors;
50
+ sortable$1.accept = input.accept;
51
+ sortable$1.type = input.type;
52
+ sortable$1.collisionPriority = input.collisionPriority;
53
+ sortable$1.transition = input.transition ? { ...sortable.defaultSortableTransition, ...input.transition } : sortable.defaultSortableTransition;
54
+ if (input.collisionDetector) {
55
+ sortable$1.collisionDetector = input.collisionDetector;
56
+ }
57
+ if (input.data) {
58
+ sortable$1.data = input.data;
59
+ }
60
+ });
61
+ solidJs.createEffect(
62
+ solidJs.on(
63
+ () => [input.group, input.index],
64
+ () => {
65
+ state.batch(() => {
66
+ sortable$1.group = input.group;
67
+ sortable$1.index = input.index;
68
+ });
69
+ }
70
+ )
71
+ );
72
+ solidJs.createEffect(
73
+ solidJs.on(
74
+ () => input.index,
75
+ () => {
76
+ if (sortable$1.manager?.dragOperation.status.idle && sortable$1.transition?.idle) {
77
+ sortable$1.refreshShape();
78
+ }
79
+ }
80
+ )
81
+ );
82
+ return {
83
+ get sortable() {
84
+ return sortable$1;
85
+ },
86
+ isDragging: () => trackedSortable().isDragging,
87
+ isDropping: () => trackedSortable().isDropping,
88
+ isDragSource: () => trackedSortable().isDragSource,
89
+ isDropTarget: () => trackedSortable().isDropTarget,
90
+ ref: setElement,
91
+ handleRef: setHandle,
92
+ sourceRef: setSource,
93
+ targetRef: setTarget
94
+ };
95
+ }
96
+
97
+ Object.defineProperty(exports, "isSortable", {
98
+ enumerable: true,
99
+ get: function () { return sortable.isSortable; }
100
+ });
101
+ exports.useSortable = useSortable;
102
+ //# sourceMappingURL=sortable.cjs.map
103
+ //# sourceMappingURL=sortable.cjs.map
package/sortable.d.ts ADDED
@@ -0,0 +1,24 @@
1
+ import * as solid_js from 'solid-js';
2
+ import { Data } from '@dnd-kit/abstract';
3
+ import { SortableInput, Sortable } from '@dnd-kit/dom/sortable';
4
+ export { isSortable } from '@dnd-kit/dom/sortable';
5
+
6
+ interface UseSortableInput<T extends Data = Data> extends Omit<SortableInput<T>, 'handle' | 'element' | 'source' | 'target'> {
7
+ handle?: Element;
8
+ element?: Element;
9
+ source?: Element;
10
+ target?: Element;
11
+ }
12
+ declare function useSortable<T extends Data = Data>(input: UseSortableInput<T>): {
13
+ readonly sortable: Sortable<T>;
14
+ isDragging: () => boolean;
15
+ isDropping: () => boolean;
16
+ isDragSource: () => boolean;
17
+ isDropTarget: () => boolean;
18
+ ref: solid_js.Setter<Element | undefined>;
19
+ handleRef: solid_js.Setter<Element | undefined>;
20
+ sourceRef: solid_js.Setter<Element | undefined>;
21
+ targetRef: solid_js.Setter<Element | undefined>;
22
+ };
23
+
24
+ export { type UseSortableInput, useSortable };