@mk-drag-and-drop/dom 0.1.0

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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +460 -0
  3. package/dist/controller/controller-internals.d.ts +5 -0
  4. package/dist/controller/controller-internals.js +11 -0
  5. package/dist/controller/create-drag-controller.d.ts +36 -0
  6. package/dist/controller/create-drag-controller.js +232 -0
  7. package/dist/draggable/create-draggable-binding.d.ts +8 -0
  8. package/dist/draggable/create-draggable-binding.js +52 -0
  9. package/dist/draggable/create-draggable.d.ts +46 -0
  10. package/dist/draggable/create-draggable.js +57 -0
  11. package/dist/droppable/create-drop-container-binding.d.ts +8 -0
  12. package/dist/droppable/create-drop-container-binding.js +28 -0
  13. package/dist/droppable/create-drop-container.d.ts +18 -0
  14. package/dist/droppable/create-drop-container.js +36 -0
  15. package/dist/droppable/create-droppable-binding.d.ts +9 -0
  16. package/dist/droppable/create-droppable-binding.js +29 -0
  17. package/dist/droppable/create-droppable.d.ts +17 -0
  18. package/dist/droppable/create-droppable.js +31 -0
  19. package/dist/geometry/measurement.d.ts +4 -0
  20. package/dist/geometry/measurement.js +33 -0
  21. package/dist/geometry/overlay.d.ts +19 -0
  22. package/dist/geometry/overlay.js +32 -0
  23. package/dist/geometry/rects.d.ts +17 -0
  24. package/dist/geometry/rects.js +34 -0
  25. package/dist/index.d.ts +16 -0
  26. package/dist/index.js +9 -0
  27. package/dist/input/config.d.ts +35 -0
  28. package/dist/input/config.js +56 -0
  29. package/dist/input/create-drag-handle.d.ts +4 -0
  30. package/dist/input/create-drag-handle.js +4 -0
  31. package/dist/input/drag-handle.d.ts +10 -0
  32. package/dist/input/drag-handle.js +74 -0
  33. package/dist/input/keyboard-drag.d.ts +28 -0
  34. package/dist/input/keyboard-drag.js +77 -0
  35. package/dist/input/pointer-activation.d.ts +31 -0
  36. package/dist/input/pointer-activation.js +97 -0
  37. package/dist/integration/index.d.ts +10 -0
  38. package/dist/integration/index.js +6 -0
  39. package/dist/modifiers/built-ins.d.ts +6 -0
  40. package/dist/modifiers/built-ins.js +62 -0
  41. package/dist/modifiers/pipeline.d.ts +18 -0
  42. package/dist/modifiers/pipeline.js +34 -0
  43. package/dist/modifiers/types.d.ts +32 -0
  44. package/dist/modifiers/types.js +1 -0
  45. package/dist/runtime/drag-runtime-handle.d.ts +22 -0
  46. package/dist/runtime/drag-runtime-handle.js +33 -0
  47. package/dist/runtime/drag-runtime.d.ts +96 -0
  48. package/dist/runtime/drag-runtime.js +798 -0
  49. package/dist/runtime/drop-target-registry.d.ts +101 -0
  50. package/dist/runtime/drop-target-registry.js +855 -0
  51. package/dist/runtime/lifecycle.d.ts +44 -0
  52. package/dist/runtime/lifecycle.js +1 -0
  53. package/dist/runtime/types.d.ts +65 -0
  54. package/dist/runtime/types.js +1 -0
  55. package/dist/sortable/create-sortable-binding.d.ts +10 -0
  56. package/dist/sortable/create-sortable-binding.js +58 -0
  57. package/dist/sortable/create-sortable.d.ts +19 -0
  58. package/dist/sortable/create-sortable.js +55 -0
  59. package/dist/sortable/sortable-options.d.ts +17 -0
  60. package/dist/sortable/sortable-options.js +20 -0
  61. package/dist/sortable/sortable-preview.d.ts +79 -0
  62. package/dist/sortable/sortable-preview.js +357 -0
  63. package/dist/sortable/sortable-registry.d.ts +113 -0
  64. package/dist/sortable/sortable-registry.js +145 -0
  65. package/dist/targeting/algorithms.d.ts +6 -0
  66. package/dist/targeting/algorithms.js +56 -0
  67. package/dist/targeting/constraints.d.ts +15 -0
  68. package/dist/targeting/constraints.js +58 -0
  69. package/dist/targeting/types.d.ts +23 -0
  70. package/dist/targeting/types.js +1 -0
  71. package/package.json +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matthias Kramer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,460 @@
1
+ # @mk-drag-and-drop/dom
2
+
3
+ `@mk-drag-and-drop/dom` is the DOM-first behavior package for
4
+ `mk-drag-and-drop`. It handles pointer and keyboard drag input, target
5
+ registration and measurement, targeting, lifecycle callbacks, drag overlays,
6
+ movement modifiers, sortable previews, and drop-container placement.
7
+
8
+ The package is headless. Apps own DOM structure, rendering, styling, data,
9
+ persistence, and final commits. The DOM package reports what happened; it does
10
+ not own application data.
11
+
12
+ ## Import Paths
13
+
14
+ Use the root package import for application code:
15
+
16
+ ```ts
17
+ import {
18
+ createDragController,
19
+ createDraggable,
20
+ createDroppable,
21
+ createSortable,
22
+ } from "@mk-drag-and-drop/dom";
23
+ ```
24
+
25
+ The package also exports `@mk-drag-and-drop/dom/integration` for adapter authors
26
+ who need lower-level DOM behavior factories and a runtime handle. Deep imports
27
+ into `src` or `dist` files are not part of the public package exports.
28
+
29
+ ## Public Root API
30
+
31
+ The root export includes:
32
+
33
+ - `createDragController`
34
+ - `createDraggable`
35
+ - `createDroppable`
36
+ - `createDropContainer`
37
+ - `createSortable`
38
+ - `createDragHandle`
39
+ - lifecycle types: `DragStartEvent`, `DragUpdateEvent`, `DragEndEvent`,
40
+ `DropEvent`, `DragSource`, `DragEndResult`, `DragLifecycleCallbacks`,
41
+ `DragLifecycleHelpers`
42
+ - placement types: `SortableDropPlacement`, `RemeasureDropTargetsInput`
43
+ - targeting helpers and types: `pointerToCenter`, `centerToCenter`,
44
+ `pointerToRectDistance`, `getDistanceToRect`,
45
+ `maxPointerDistanceToRect`, `maxOverlayCenterDistanceToRect`, `DropTarget`,
46
+ `TargetingAlgorithm`, `TargetingAlgorithmInput`,
47
+ `TargetingConstraint`, `TargetingConstraintInput`
48
+ - modifiers and types: `lockToXAxis`, `lockToYAxis`, `restrictToContainer`,
49
+ `RestrictToContainerResolver`, `DragModifier`, `DragModifierInput`,
50
+ `DragModifierSetupInput`, `DragModifierTransformInput`
51
+ - input and geometry types: `KeyboardCommand`, `KeyboardConfiguration`,
52
+ `PointerConfiguration`, `DragPoint`, `DragRect`
53
+
54
+ Internal classes and helpers such as the underlying runtime class, registries,
55
+ input controllers, measurement helpers, sortable preview internals, and modifier
56
+ pipeline internals are not public root APIs.
57
+
58
+ ## Integration Subpath
59
+
60
+ `@mk-drag-and-drop/dom/integration` exports:
61
+
62
+ - `createDragRuntimeHandle`
63
+ - `DragRuntimeHandle`, `DragRuntimeHandleOptions`,
64
+ `DragRuntimeHandleConfigureInput`
65
+ - `DragState`, `DragOverlayPhase`, `DragOverlayRenderState`
66
+ - `DragRuntimeSubscription`
67
+ - `createDomDraggable`, `createDomDroppable`, `createDomDropContainer`,
68
+ `createDomSortable`
69
+ - the related DOM behavior/input/runtime types
70
+ - `domDragHandleAttribute`
71
+
72
+ Use this subpath when building a framework adapter or custom behavior layer. For
73
+ ordinary DOM usage, prefer the root controller and binding helpers.
74
+
75
+ ## Controller
76
+
77
+ `createDragController(options?)` creates the public DOM controller used by the
78
+ root binding helpers. Controller options include:
79
+
80
+ - lifecycle callbacks: `onDragStart`, `onDragUpdate`, `onDragEnd`, `onDrop`
81
+ - `announcements`: lifecycle callbacks that return polite live-region text
82
+ - `dragOverlay(input)`: returns an overlay `HTMLElement` or `null`
83
+ - `overlayRoot`: optional root for the DOM overlay wrapper
84
+ - `keepOverlayOnDrop`: keeps the overlay in the `"released"` phase until
85
+ `finishOverlay` or the overlay input `finish` callback removes it
86
+ - `targetingAlgorithm` and `targetingConstraint`
87
+ - `modifiers`
88
+ - `pointerConfiguration`
89
+ - `keyboardConfiguration`
90
+
91
+ The returned controller has:
92
+
93
+ - `update(options)`: replaces runtime/controller configuration
94
+ - `remeasureDropTargets(input?)`: remeasures all targets, one target id, an
95
+ array of target ids, or `{ group }`
96
+ - `cleanup()`: ends active drag resources and removes the current overlay
97
+ - `dispose()`: final teardown for the controller, runtime registrations,
98
+ subscriptions, overlays, live region, and registered dispose callbacks
99
+ - `finishOverlay()`: removes a kept overlay
100
+
101
+ ## Drag Overlays
102
+
103
+ `dragOverlay(input)` is a creation hook. The controller calls it when overlay
104
+ content is mounted for the `"dragging"` phase, and once more for the
105
+ `"released"` phase when `keepOverlayOnDrop` is enabled. Pointer movement does
106
+ not call `dragOverlay`.
107
+
108
+ Apps own the returned overlay element and any dynamic content inside it. The
109
+ package owns the overlay wrapper, movement, cleanup, and geometry measurement
110
+ used by targeting and modifiers. The wrapper is positioned with `position:
111
+ fixed`, source rect dimensions, `pointer-events: none`, and a transform derived
112
+ from the current pointer delta.
113
+
114
+ The controller measures the returned overlay element on mount/replacement. When
115
+ `ResizeObserver` is available, it also remeasures when that element changes
116
+ size. The runtime derives the current overlay rect from that cached measurement
117
+ plus pointer movement.
118
+
119
+ For dynamic overlay content, keep a reference to the element and update it from
120
+ lifecycle callbacks or subscriptions:
121
+
122
+ ```ts
123
+ let overlayElement: HTMLElement | null = null;
124
+
125
+ const controller = createDragController({
126
+ dragOverlay({ dragState }) {
127
+ overlayElement = document.createElement("div");
128
+ overlayElement.textContent = dragState.draggableId;
129
+ return overlayElement;
130
+ },
131
+ onDragUpdate({ pointerPosition }) {
132
+ if (overlayElement) {
133
+ overlayElement.textContent = `${pointerPosition.x}, ${pointerPosition.y}`;
134
+ }
135
+ },
136
+ onDragEnd() {
137
+ overlayElement = null;
138
+ },
139
+ });
140
+ ```
141
+
142
+ ## Lifecycle Events
143
+
144
+ Lifecycle callbacks receive an event and helper methods.
145
+
146
+ Event shapes:
147
+
148
+ ```ts
149
+ type DragStartEvent = {
150
+ draggableId: string;
151
+ source: DragSource;
152
+ pointerPosition: DragPoint;
153
+ sourceRect: DragRect;
154
+ };
155
+
156
+ type DragUpdateEvent = {
157
+ draggableId: string;
158
+ source: DragSource;
159
+ pointerPosition: DragPoint;
160
+ activeDropTargetId: string | null;
161
+ previousDropTargetId: string | null;
162
+ };
163
+
164
+ type DragSource = "pointer" | "keyboard";
165
+
166
+ type DragEndResult =
167
+ | "dropped"
168
+ | "no-target"
169
+ | "invalid-target"
170
+ | "canceled";
171
+
172
+ type DragEndEvent = {
173
+ draggableId: string;
174
+ source: DragSource;
175
+ result: DragEndResult;
176
+ dropTargetId: string | null;
177
+ };
178
+
179
+ type DropEvent = {
180
+ draggableId: string;
181
+ source: DragSource;
182
+ dropTargetId: string;
183
+ sortablePlacement?: SortableDropPlacement;
184
+ };
185
+
186
+ type SortableDropPlacement = {
187
+ sourceContainerId: string | null;
188
+ containerId: string | null;
189
+ previousDraggableId: string | null;
190
+ nextDraggableId: string | null;
191
+ targetDraggableId: string | null;
192
+ side: "before" | "after" | null;
193
+ };
194
+ ```
195
+
196
+ Helpers:
197
+
198
+ - `getDropTargetRect(dropTargetId)`
199
+
200
+ `onDrop` only runs for a valid successful drop. `onDragEnd` runs whenever a drag
201
+ ends. `result: "dropped"` means a valid target was accepted and `onDrop` also
202
+ runs. `result: "no-target"` means the user ended normally with no active target.
203
+ `result: "invalid-target"` means an active target candidate was stale by finish
204
+ time. `result: "canceled"` means the drag was canceled, such as Escape,
205
+ pointercancel, or runtime cancellation.
206
+
207
+ ## Bindings
208
+
209
+ Root binding helpers attach behavior to DOM elements and return `void`.
210
+ Registrations and listeners are tied to the controller lifetime.
211
+
212
+ `createDraggable(input)` accepts:
213
+
214
+ - `controller`
215
+ - `element`
216
+ - `draggableId`
217
+ - `group`, defaulting to `"default"`
218
+
219
+ `createDroppable(input)` accepts:
220
+
221
+ - `controller`
222
+ - `element`
223
+ - `dropTargetId`
224
+ - `group`, defaulting to `"default"`
225
+ - `containerId`, defaulting to `null`
226
+
227
+ `createDropContainer(input)` accepts:
228
+
229
+ - `controller`
230
+ - `element`
231
+ - `containerId`
232
+ - `group`, defaulting to `"default"`
233
+
234
+ `createSortable(input)` accepts:
235
+
236
+ - `controller`
237
+ - `element`
238
+ - `draggableId`
239
+ - `group`, defaulting to `"default"`
240
+ - `containerId`, defaulting to `null`
241
+
242
+ `createDragHandle({ element })` marks an element with the drag-handle data
243
+ attribute. When a draggable or sortable contains a handle, pointer and keyboard
244
+ dragging are handled from that handle instead of unrelated children.
245
+
246
+ ## Placement Data
247
+
248
+ Plain droppable drops are id-only: `draggableId`, `dropTargetId`, and `source`.
249
+ Sortable behavior may add sortable-specific placement under
250
+ `event.sortablePlacement`:
251
+
252
+ ```ts
253
+ type SortableDropPlacement = {
254
+ sourceContainerId: string | null;
255
+ containerId: string | null;
256
+ previousDraggableId: string | null;
257
+ nextDraggableId: string | null;
258
+ targetDraggableId: string | null;
259
+ side: "before" | "after" | null;
260
+ };
261
+ ```
262
+
263
+ No sortable placement is included for plain droppable drops. No-op sortable drops
264
+ may omit `sortablePlacement`.
265
+ `targetDraggableId` and `side` preserve the active sortable item anchor when a
266
+ drop lands relative to an item. They are `null` for container-only placements.
267
+
268
+ Sortable behavior owns only a transient DOM preview during the drag. It may move
269
+ DOM nodes to show where an item would land, but it does not commit app data. On
270
+ drop, the app reads `event.sortablePlacement` and updates its own data/rendering.
271
+
272
+ ## Targeting
273
+
274
+ A measured target passed to custom targeting code has:
275
+
276
+ ```ts
277
+ type DropTarget = {
278
+ dropTargetId: string;
279
+ dropTargetRect: DragRect;
280
+ };
281
+ ```
282
+
283
+ Built-in targeting algorithms:
284
+
285
+ - `pointerToCenter`
286
+ - `centerToCenter`
287
+ - `pointerToRectDistance`
288
+
289
+ Built-in targeting helpers/constraints:
290
+
291
+ - `getDistanceToRect(point, rect)`
292
+ - `maxPointerDistanceToRect({ maxDistance?, maxXDistance?, maxYDistance? })`
293
+ - `maxOverlayCenterDistanceToRect({ maxDistance?, maxXDistance?, maxYDistance? })`
294
+
295
+ Custom `TargetingAlgorithm` functions receive `pointerPosition`, `overlayRect`,
296
+ and the filtered `dropTargets` list. Algorithms decide which geometry to use:
297
+ `pointerToCenter` and `pointerToRectDistance` are pointer based, while
298
+ `centerToCenter` computes the overlay center from `overlayRect` and returns no
299
+ target when no overlay rect is available. Custom `TargetingConstraint`
300
+ functions receive `pointerPosition`, `overlayRect`, and one `dropTarget`, and
301
+ return whether that candidate is eligible. Use the pointer or overlay-center
302
+ distance helper that matches the intended behavior.
303
+
304
+ Sortable placement is separate from targeting. The configured targeting
305
+ algorithm alone chooses `activeDropTarget`; sortable only decides before/after
306
+ preview placement relative to that active target.
307
+
308
+ ## Modifiers
309
+
310
+ Modifiers transform pointer movement before drag state updates. Built-ins:
311
+
312
+ - `lockToXAxis()`
313
+ - `lockToYAxis()`
314
+ - `restrictToContainer(resolver)`
315
+
316
+ `restrictToContainer` receives a resolver function with
317
+ `DragModifierSetupInput` and returns an `HTMLElement | null`.
318
+
319
+ Custom modifiers can provide:
320
+
321
+ - `setup(input)`: optional setup state for the active drag
322
+ - `transform(input)`: returns the next `DragPoint`
323
+
324
+ Modifier input includes `draggableId`, `group`, source rect, initial pointer
325
+ position, raw pointer position, current pointer position, overlay rect, and
326
+ modifier state.
327
+
328
+ ## Measurement
329
+
330
+ Targets are measured when registered and remeasured at drag start. The explicit
331
+ remeasurement entry point is `controller.remeasureDropTargets(input?)`; call it
332
+ when app-owned layout changes during a drag should affect targeting.
333
+
334
+ `RemeasureDropTargetsInput` accepts:
335
+
336
+ - no argument for all targets
337
+ - a target id string
338
+ - an array of target id strings
339
+ - `{ group: string }`
340
+
341
+ Sortable preview movement does not automatically remeasure a group. Targeting
342
+ continues from the runtime's cached target rects until the app explicitly
343
+ remeasures. Final sortable placement is derived from the current preview DOM
344
+ order, so app-owned layout changes such as expanding tree rows or changing
345
+ grouped sections during a drag should call the public remeasure API when those
346
+ changes need to affect targeting.
347
+
348
+ ## Data Ownership
349
+
350
+ The DOM package never owns application data. Item ids, target ids, group ids,
351
+ and container ids are identifiers that your app maps to its own model.
352
+
353
+ Commit data in lifecycle callbacks, usually `onDrop`. Rerender or patch the DOM
354
+ using your app's normal rendering path after the commit.
355
+
356
+ ## Cleanup Model
357
+
358
+ Root binding helpers do not return per-item disposers. Dispose the controller
359
+ when tearing down the view or application area that owns those bindings.
360
+
361
+ Use:
362
+
363
+ - `controller.cleanup()` to end active drag work and remove the active overlay
364
+ - `controller.dispose()` for final teardown
365
+
366
+ Disconnected drop targets are pruned on drag-critical paths, and dispose clears
367
+ runtime registrations. React users usually rely on `DragProvider` and hooks for
368
+ runtime and binding lifetime.
369
+
370
+ ## Accessibility Scope
371
+
372
+ Keyboard dragging is available when `keyboardConfiguration.enabled` is not
373
+ disabled. Defaults use Space or Enter to start/drop, Escape to cancel, arrow
374
+ keys to move, and a default movement distance of 24.
375
+
376
+ Draggable or sortable elements may receive `tabIndex` and keyboard handlers
377
+ when keyboard dragging is enabled. Drag handles and focusable draggable elements
378
+ should have clear labels.
379
+
380
+ Announcements are opt-in through `announcements`. The controller creates a
381
+ polite live region only when announcement callbacks are provided. The package
382
+ does not claim complete screen-reader drag-and-drop support; apps should provide
383
+ domain-specific instructions and announcements for their interaction model.
384
+ The lifecycle `onDragUpdate` callback runs for drag updates; the announcement
385
+ `onDragUpdate` callback is intended for active-drop-target transitions and
386
+ dedupes repeated messages to avoid live-region spam. Use lifecycle
387
+ `onDragUpdate` for per-frame side effects, not announcements.
388
+
389
+ ## Example
390
+
391
+ ```ts
392
+ import {
393
+ createDragController,
394
+ createDraggable,
395
+ createDroppable,
396
+ } from "@mk-drag-and-drop/dom";
397
+
398
+ const state = {
399
+ itemLocation: "todo",
400
+ };
401
+
402
+ const controller = createDragController({
403
+ onDrop({ draggableId, dropTargetId }) {
404
+ state.itemLocation = dropTargetId;
405
+ console.log(`${draggableId} moved to ${dropTargetId}`);
406
+ },
407
+ });
408
+
409
+ const item = document.createElement("button");
410
+ item.type = "button";
411
+ item.textContent = "Drag me";
412
+
413
+ createDraggable({
414
+ controller,
415
+ element: item,
416
+ draggableId: "task-1",
417
+ });
418
+
419
+ for (const columnId of ["todo", "done"]) {
420
+ const column = document.createElement("section");
421
+
422
+ createDroppable({
423
+ controller,
424
+ element: column,
425
+ dropTargetId: columnId,
426
+ });
427
+
428
+ document.body.append(column);
429
+ }
430
+
431
+ document.body.append(item);
432
+ window.addEventListener("pagehide", () => controller.dispose(), { once: true });
433
+ ```
434
+
435
+ ## Examples
436
+
437
+ Vanilla DOM examples live in `apps/web/src/vanilla`:
438
+
439
+ - `basicDrag.ts`
440
+ - `dropzoneList.ts`
441
+ - `sortableList.ts`
442
+ - `kanbanExample.ts`
443
+ - `groupedExample.ts`
444
+ - `treeExample.ts`
445
+
446
+ They use root imports from `@mk-drag-and-drop/dom`.
447
+
448
+ ## Development
449
+
450
+ ```bash
451
+ pnpm --filter @mk-drag-and-drop/dom build
452
+ pnpm --filter @mk-drag-and-drop/dom lint
453
+ pnpm --filter @mk-drag-and-drop/dom test
454
+ ```
455
+
456
+ Example app verification:
457
+
458
+ ```bash
459
+ pnpm --filter web build
460
+ ```
@@ -0,0 +1,5 @@
1
+ import type { DragRuntimeHandle, InternalBindingCleanupRuntime } from "../runtime/drag-runtime-handle.js";
2
+ import type { DragController } from "./create-drag-controller.js";
3
+ export type DragControllerRuntimeHandle = DragRuntimeHandle & InternalBindingCleanupRuntime;
4
+ export declare function setControllerRuntime(controller: DragController, runtime: DragRuntimeHandle): void;
5
+ export declare function getControllerRuntime(controller: DragController): DragControllerRuntimeHandle;
@@ -0,0 +1,11 @@
1
+ const controllerRuntimes = new WeakMap();
2
+ export function setControllerRuntime(controller, runtime) {
3
+ controllerRuntimes.set(controller, runtime);
4
+ }
5
+ export function getControllerRuntime(controller) {
6
+ const runtime = controllerRuntimes.get(controller);
7
+ if (!runtime) {
8
+ throw new Error("Unknown drag controller. Create controllers with createDragController before passing them to DOM bindings.");
9
+ }
10
+ return runtime;
11
+ }
@@ -0,0 +1,36 @@
1
+ import type { KeyboardConfiguration, PointerConfiguration } from "../input/config.js";
2
+ import type { DragModifierInput } from "../modifiers/types.js";
3
+ import type { RemeasureDropTargetsInput } from "../runtime/drop-target-registry.js";
4
+ import type { DragEndEvent, DragLifecycleCallbacks, DragStartEvent, DragUpdateEvent, DropEvent } from "../runtime/lifecycle.js";
5
+ import type { DragOverlayPhase, DragState } from "../runtime/types.js";
6
+ import type { TargetingAlgorithm, TargetingConstraint } from "../targeting/types.js";
7
+ export type DragControllerAnnouncements = {
8
+ onDragStart?: (event: DragStartEvent) => string | null;
9
+ onDragUpdate?: (event: DragUpdateEvent) => string | null;
10
+ onDragEnd?: (event: DragEndEvent) => string | null;
11
+ onDrop?: (event: DropEvent) => string | null;
12
+ };
13
+ export type DragControllerOverlayInput = {
14
+ dragState: DragState;
15
+ phase: DragOverlayPhase;
16
+ finish: () => void;
17
+ };
18
+ export type DragControllerOptions = {
19
+ announcements?: DragControllerAnnouncements;
20
+ dragOverlay?: (input: DragControllerOverlayInput) => HTMLElement | null;
21
+ keyboardConfiguration?: KeyboardConfiguration;
22
+ keepOverlayOnDrop?: boolean;
23
+ modifiers?: readonly DragModifierInput[];
24
+ overlayRoot?: HTMLElement;
25
+ pointerConfiguration?: PointerConfiguration;
26
+ targetingAlgorithm?: TargetingAlgorithm;
27
+ targetingConstraint?: TargetingConstraint;
28
+ } & DragLifecycleCallbacks;
29
+ export type DragController = {
30
+ update: (options: DragControllerOptions) => void;
31
+ cleanup: () => void;
32
+ dispose: () => void;
33
+ finishOverlay: () => void;
34
+ remeasureDropTargets: (input?: RemeasureDropTargetsInput) => void;
35
+ };
36
+ export declare function createDragController(options?: DragControllerOptions): DragController;