@mk-drag-and-drop/dom 0.1.0 → 0.3.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 (30) hide show
  1. package/README.md +111 -35
  2. package/dist/controller/controller-internals.d.ts +4 -4
  3. package/dist/controller/create-drag-controller.d.ts +11 -8
  4. package/dist/controller/create-drag-controller.js +29 -53
  5. package/dist/draggable/create-draggable-binding.js +3 -3
  6. package/dist/droppable/create-drop-container-binding.js +4 -4
  7. package/dist/droppable/create-drop-container.d.ts +1 -1
  8. package/dist/droppable/create-drop-container.js +3 -3
  9. package/dist/droppable/create-droppable-binding.js +4 -4
  10. package/dist/droppable/create-droppable.d.ts +1 -1
  11. package/dist/droppable/create-droppable.js +3 -3
  12. package/dist/index.d.ts +1 -0
  13. package/dist/input/pointer-activation.d.ts +4 -2
  14. package/dist/input/pointer-activation.js +28 -16
  15. package/dist/integration/index.d.ts +2 -2
  16. package/dist/integration/index.js +1 -1
  17. package/dist/runtime/drag-runtime-scope.d.ts +21 -0
  18. package/dist/runtime/{drag-runtime-handle.js → drag-runtime-scope.js} +8 -9
  19. package/dist/runtime/drag-runtime.d.ts +21 -17
  20. package/dist/runtime/drag-runtime.js +279 -155
  21. package/dist/runtime/lifecycle.d.ts +7 -0
  22. package/dist/runtime/types.d.ts +3 -2
  23. package/dist/sortable/create-sortable-binding.js +4 -4
  24. package/dist/sortable/create-sortable.d.ts +1 -1
  25. package/dist/sortable/create-sortable.js +3 -3
  26. package/dist/sortable/sortable-preview.js +20 -17
  27. package/dist/sortable/sortable-registry.d.ts +15 -6
  28. package/dist/sortable/sortable-registry.js +65 -47
  29. package/package.json +2 -1
  30. package/dist/runtime/drag-runtime-handle.d.ts +0 -22
package/README.md CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  ```
24
24
 
25
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
26
+ who need lower-level DOM behavior factories and a runtime scope. Deep imports
27
27
  into `src` or `dist` files are not part of the public package exports.
28
28
 
29
29
  ## Public Root API
@@ -36,10 +36,13 @@ The root export includes:
36
36
  - `createDropContainer`
37
37
  - `createSortable`
38
38
  - `createDragHandle`
39
+ - controller types: `DragController`, `DragControllerOptions`,
40
+ `DragControllerOverlayInput`, `DragControllerAnnouncements`
39
41
  - lifecycle types: `DragStartEvent`, `DragUpdateEvent`, `DragEndEvent`,
40
42
  `DropEvent`, `DragSource`, `DragEndResult`, `DragLifecycleCallbacks`,
41
43
  `DragLifecycleHelpers`
42
44
  - placement types: `SortableDropPlacement`, `RemeasureDropTargetsInput`
45
+ - overlay types: `OverlayReleaseMode`
43
46
  - targeting helpers and types: `pointerToCenter`, `centerToCenter`,
44
47
  `pointerToRectDistance`, `getDistanceToRect`,
45
48
  `maxPointerDistanceToRect`, `maxOverlayCenterDistanceToRect`, `DropTarget`,
@@ -59,10 +62,11 @@ pipeline internals are not public root APIs.
59
62
 
60
63
  `@mk-drag-and-drop/dom/integration` exports:
61
64
 
62
- - `createDragRuntimeHandle`
63
- - `DragRuntimeHandle`, `DragRuntimeHandleOptions`,
64
- `DragRuntimeHandleConfigureInput`
65
- - `DragState`, `DragOverlayPhase`, `DragOverlayRenderState`
65
+ - `createDragRuntimeScope`
66
+ - `DragRuntimeScope`, `DragRuntimeScopeOptions`,
67
+ `DragRuntimeScopeConfigureInput`
68
+ - `DragState`, `DragOverlayPhase`, `DragOverlayRenderState`,
69
+ `OverlayReleaseMode`
66
70
  - `DragRuntimeSubscription`
67
71
  - `createDomDraggable`, `createDomDroppable`, `createDomDropContainer`,
68
72
  `createDomSortable`
@@ -74,15 +78,15 @@ ordinary DOM usage, prefer the root controller and binding helpers.
74
78
 
75
79
  ## Controller
76
80
 
77
- `createDragController(options?)` creates the public DOM controller used by the
78
- root binding helpers. Controller options include:
81
+ `createDragController(options?)` creates the public DOM drag-and-drop scope used
82
+ by the root binding helpers. Controller options include:
79
83
 
80
84
  - lifecycle callbacks: `onDragStart`, `onDragUpdate`, `onDragEnd`, `onDrop`
81
85
  - `announcements`: lifecycle callbacks that return polite live-region text
82
86
  - `dragOverlay(input)`: returns an overlay `HTMLElement` or `null`
83
87
  - `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
88
+ - `overlayRelease`: `"auto"` removes overlays on drag end; `"manual"` keeps a
89
+ released overlay until its `removeOverlay` callback is called
86
90
  - `targetingAlgorithm` and `targetingConstraint`
87
91
  - `modifiers`
88
92
  - `pointerConfiguration`
@@ -90,23 +94,38 @@ root binding helpers. Controller options include:
90
94
 
91
95
  The returned controller has:
92
96
 
93
- - `update(options)`: replaces runtime/controller configuration
94
97
  - `remeasureDropTargets(input?)`: remeasures all targets, one target id, an
95
98
  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
99
+ - `remeasureOverlay()`: remeasures the currently mounted drag overlay element;
100
+ it is a safe no-op when no overlay is mounted or no drag is active
101
+
102
+ The controller does not expose runtime teardown, disposal, update, or broad
103
+ overlay removal methods. Runtime objects are ordinary JavaScript objects; DOM
104
+ bindings and active drag resources are owned by their own lifetimes.
100
105
 
101
106
  ## Drag Overlays
102
107
 
103
108
  `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`.
109
+ content is mounted for the `"dragging"` phase. By default, overlays are removed
110
+ immediately when a drag ends. When `overlayRelease: "manual"` is configured, the
111
+ controller calls `dragOverlay` once more for the `"released"` phase and passes
112
+ `removeOverlay`; call that function when app-owned release animation is done.
113
+ Pointer movement does not call `dragOverlay`.
114
+
115
+ The overlay input includes:
116
+
117
+ - `dragState`: item id, group, source rect, start pointer, and current pointer.
118
+ - `phase`: `"dragging"` or `"released"`.
119
+ - `remeasureOverlay`: manually refreshes the cached overlay measurement.
120
+ - `removeOverlay`: present only for `"released"` overlays in manual release
121
+ mode; call it when app-owned release animation should remove the overlay.
122
+
123
+ `removeOverlay` is only present for released overlays in manual release mode.
124
+ Calling it more than once is safe. It removes the overlay host state only; it is
125
+ not a controller or runtime teardown API.
107
126
 
108
127
  Apps own the returned overlay element and any dynamic content inside it. The
109
- package owns the overlay wrapper, movement, cleanup, and geometry measurement
128
+ package owns the overlay wrapper, movement, release, and geometry measurement
110
129
  used by targeting and modifiers. The wrapper is positioned with `position:
111
130
  fixed`, source rect dimensions, `pointer-events: none`, and a transform derived
112
131
  from the current pointer delta.
@@ -114,7 +133,31 @@ from the current pointer delta.
114
133
  The controller measures the returned overlay element on mount/replacement. When
115
134
  `ResizeObserver` is available, it also remeasures when that element changes
116
135
  size. The runtime derives the current overlay rect from that cached measurement
117
- plus pointer movement.
136
+ plus modified pointer movement, and it does not measure overlay DOM on every
137
+ pointer move.
138
+
139
+ Manual `remeasureOverlay()` is for cases automatic observation cannot cover or
140
+ where the app knows visual geometry changed. CSS transforms can change visual
141
+ bounds without necessarily triggering `ResizeObserver`.
142
+
143
+ ```ts
144
+ controller.remeasureOverlay();
145
+ ```
146
+
147
+ ```ts
148
+ const controller = createDragController({
149
+ dragOverlay({ dragState, remeasureOverlay }) {
150
+ const element = document.createElement("div");
151
+ element.textContent = dragState.draggableId;
152
+
153
+ element.addEventListener("transitionend", () => {
154
+ remeasureOverlay();
155
+ });
156
+
157
+ return element;
158
+ },
159
+ });
160
+ ```
118
161
 
119
162
  For dynamic overlay content, keep a reference to the element and update it from
120
163
  lifecycle callbacks or subscriptions:
@@ -157,6 +200,7 @@ type DragUpdateEvent = {
157
200
  draggableId: string;
158
201
  source: DragSource;
159
202
  pointerPosition: DragPoint;
203
+ overlayRect: DragRect | null;
160
204
  activeDropTargetId: string | null;
161
205
  previousDropTargetId: string | null;
162
206
  };
@@ -174,6 +218,7 @@ type DragEndEvent = {
174
218
  source: DragSource;
175
219
  result: DragEndResult;
176
220
  dropTargetId: string | null;
221
+ overlayRect: DragRect | null;
177
222
  };
178
223
 
179
224
  type DropEvent = {
@@ -193,6 +238,14 @@ type SortableDropPlacement = {
193
238
  };
194
239
  ```
195
240
 
241
+ `DragUpdateEvent.overlayRect` is the current viewport-space rectangle for the
242
+ drag overlay. `DragEndEvent.overlayRect` is the final viewport-space rectangle
243
+ at the moment the drag ends. Both are `null` when no drag overlay is configured.
244
+ When an overlay is configured, the runtime uses cached overlay measurement plus
245
+ modified pointer movement. Before overlay content has been measured, it uses the
246
+ same translated source-rect fallback as the visual overlay. The drag update and
247
+ drag end paths do not read overlay DOM just to produce this field.
248
+
196
249
  Helpers:
197
250
 
198
251
  - `getDropTargetRect(dropTargetId)`
@@ -200,14 +253,15 @@ Helpers:
200
253
  `onDrop` only runs for a valid successful drop. `onDragEnd` runs whenever a drag
201
254
  ends. `result: "dropped"` means a valid target was accepted and `onDrop` also
202
255
  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,
256
+ `result: "invalid-target"` means an active target candidate was stale by drag
257
+ end. `result: "canceled"` means the drag was canceled, such as Escape,
205
258
  pointercancel, or runtime cancellation.
206
259
 
207
260
  ## Bindings
208
261
 
209
262
  Root binding helpers attach behavior to DOM elements and return `void`.
210
- Registrations and listeners are tied to the controller lifetime.
263
+ Registrations are WeakRef-backed and stale disconnected elements are pruned on
264
+ drag-critical paths and explicit remeasurement.
211
265
 
212
266
  `createDraggable(input)` accepts:
213
267
 
@@ -303,7 +357,10 @@ distance helper that matches the intended behavior.
303
357
 
304
358
  Sortable placement is separate from targeting. The configured targeting
305
359
  algorithm alone chooses `activeDropTarget`; sortable only decides before/after
306
- preview placement relative to that active target.
360
+ preview placement relative to that active target. For sortable groups, the
361
+ registry may narrow measured candidates to relevant sortable item, neighbor, or
362
+ container entries before the targeting algorithm runs; the algorithm still makes
363
+ the active-target decision from that narrowed measured list.
307
364
 
308
365
  ## Modifiers
309
366
 
@@ -328,8 +385,14 @@ modifier state.
328
385
  ## Measurement
329
386
 
330
387
  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.
388
+ target remeasurement entry point is `controller.remeasureDropTargets(input?)`;
389
+ call it when app-owned layout changes during a drag should affect targeting.
390
+
391
+ Overlay measurement is separate from target measurement. Overlay content is
392
+ measured on mount/replacement and by `ResizeObserver` when available. Use
393
+ `controller.remeasureOverlay()` when the current overlay geometry should be
394
+ refreshed manually, such as after an app-owned transition or transform that
395
+ changes visual bounds without a normal size-observer notification.
333
396
 
334
397
  `RemeasureDropTargetsInput` accepts:
335
398
 
@@ -353,19 +416,33 @@ and container ids are identifiers that your app maps to its own model.
353
416
  Commit data in lifecycle callbacks, usually `onDrop`. Rerender or patch the DOM
354
417
  using your app's normal rendering path after the commit.
355
418
 
356
- ## Cleanup Model
419
+ ## Lifetime Model
420
+
421
+ Root binding helpers do not return per-item disposers. Runtime/controller
422
+ objects are ordinary JavaScript objects and are released by garbage collection
423
+ when unreachable.
357
424
 
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.
425
+ DOM registrations are a separate lifetime. Bindings keep WeakRef-backed records,
426
+ and disconnected drop targets/sortables are pruned on drag-critical paths and
427
+ explicit remeasurement. Active drag resources are owned by the input drag
428
+ lifecycle and are released on drop, cancel, and pointercancel.
360
429
 
361
- Use:
430
+ Pending pointer activation is also separate from an active drag. Activation
431
+ delay timers, the pending activation state, and the latest pre-activation
432
+ pointer position are canceled by pointerup, pointercancel, activation success,
433
+ activation failure, or active drag reset.
362
434
 
363
- - `controller.cleanup()` to end active drag work and remove the active overlay
364
- - `controller.dispose()` for final teardown
435
+ Active drag resources include pointer/window listeners, keyboard listeners, RAF
436
+ pointer updates, text-selection suppression, active target/session state,
437
+ overlay host state, active modifiers, and sortable preview/snapshot state. They
438
+ are released by active drag lifecycle paths. Runtime disposal is not the cleanup
439
+ mechanism for those resources.
365
440
 
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.
441
+ Sortable registration state and sortable active preview state are separate.
442
+ Registered sortable elements, ids, groups, containers, and options remain until
443
+ they are unregistered or pruned as stale DOM. Per-drag sortable snapshots,
444
+ dragged attributes, preview placement, and moved DOM are restored by active drag
445
+ cleanup.
369
446
 
370
447
  ## Accessibility Scope
371
448
 
@@ -429,7 +506,6 @@ for (const columnId of ["todo", "done"]) {
429
506
  }
430
507
 
431
508
  document.body.append(item);
432
- window.addEventListener("pagehide", () => controller.dispose(), { once: true });
433
509
  ```
434
510
 
435
511
  ## Examples
@@ -1,5 +1,5 @@
1
- import type { DragRuntimeHandle, InternalBindingCleanupRuntime } from "../runtime/drag-runtime-handle.js";
1
+ import type { DragRuntimeScope, InternalStaleDomBindingRuntime } from "../runtime/drag-runtime-scope.js";
2
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;
3
+ export type DragControllerRuntimeScope = DragRuntimeScope & InternalStaleDomBindingRuntime;
4
+ export declare function setControllerRuntime(controller: DragController, runtime: DragRuntimeScope): void;
5
+ export declare function getControllerRuntime(controller: DragController): DragControllerRuntimeScope;
@@ -2,7 +2,7 @@ import type { KeyboardConfiguration, PointerConfiguration } from "../input/confi
2
2
  import type { DragModifierInput } from "../modifiers/types.js";
3
3
  import type { RemeasureDropTargetsInput } from "../runtime/drop-target-registry.js";
4
4
  import type { DragEndEvent, DragLifecycleCallbacks, DragStartEvent, DragUpdateEvent, DropEvent } from "../runtime/lifecycle.js";
5
- import type { DragOverlayPhase, DragState } from "../runtime/types.js";
5
+ import type { DragState, OverlayReleaseMode } from "../runtime/types.js";
6
6
  import type { TargetingAlgorithm, TargetingConstraint } from "../targeting/types.js";
7
7
  export type DragControllerAnnouncements = {
8
8
  onDragStart?: (event: DragStartEvent) => string | null;
@@ -12,25 +12,28 @@ export type DragControllerAnnouncements = {
12
12
  };
13
13
  export type DragControllerOverlayInput = {
14
14
  dragState: DragState;
15
- phase: DragOverlayPhase;
16
- finish: () => void;
15
+ phase: "dragging";
16
+ remeasureOverlay: () => void;
17
+ removeOverlay?: never;
18
+ } | {
19
+ dragState: DragState;
20
+ phase: "released";
21
+ remeasureOverlay: () => void;
22
+ removeOverlay: () => void;
17
23
  };
18
24
  export type DragControllerOptions = {
19
25
  announcements?: DragControllerAnnouncements;
20
26
  dragOverlay?: (input: DragControllerOverlayInput) => HTMLElement | null;
21
27
  keyboardConfiguration?: KeyboardConfiguration;
22
- keepOverlayOnDrop?: boolean;
23
28
  modifiers?: readonly DragModifierInput[];
29
+ overlayRelease?: OverlayReleaseMode;
24
30
  overlayRoot?: HTMLElement;
25
31
  pointerConfiguration?: PointerConfiguration;
26
32
  targetingAlgorithm?: TargetingAlgorithm;
27
33
  targetingConstraint?: TargetingConstraint;
28
34
  } & DragLifecycleCallbacks;
29
35
  export type DragController = {
30
- update: (options: DragControllerOptions) => void;
31
- cleanup: () => void;
32
- dispose: () => void;
33
- finishOverlay: () => void;
34
36
  remeasureDropTargets: (input?: RemeasureDropTargetsInput) => void;
37
+ remeasureOverlay: () => void;
35
38
  };
36
39
  export declare function createDragController(options?: DragControllerOptions): DragController;
@@ -1,56 +1,28 @@
1
1
  import { rectToDragRect } from "../geometry/rects.js";
2
- import { createDragRuntimeHandle } from "../runtime/drag-runtime-handle.js";
2
+ import { createDragRuntimeScope } from "../runtime/drag-runtime-scope.js";
3
3
  import { pointerToCenter } from "../targeting/algorithms.js";
4
4
  import { setControllerRuntime } from "./controller-internals.js";
5
5
  export function createDragController(options = {}) {
6
- let currentOptions = options;
6
+ const currentOptions = options;
7
7
  let overlayWrapper = null;
8
8
  let overlayElement = null;
9
9
  let overlayResizeObserver = null;
10
10
  let liveRegion = null;
11
11
  let lastAnnouncement = null;
12
- let disposed = false;
13
- const runtime = createDragRuntimeHandle({
12
+ const runtime = createDragRuntimeScope({
14
13
  updateOverlayHost,
15
14
  targetingAlgorithm: options.targetingAlgorithm ?? pointerToCenter,
16
15
  targetingConstraint: options.targetingConstraint,
17
16
  hasDragOverlay: hasDragOverlay(options),
18
- keepOverlayOnDrop: options.keepOverlayOnDrop ?? false,
17
+ overlayRelease: options.overlayRelease ?? "auto",
19
18
  });
20
19
  configureRuntime(options);
21
20
  syncLiveRegion();
22
21
  const controller = {
23
- update: (nextOptions) => {
24
- if (disposed) {
25
- return;
26
- }
27
- currentOptions = nextOptions;
28
- configureRuntime(nextOptions);
29
- syncLiveRegion();
30
- if (!hasDragOverlay(nextOptions)) {
31
- removeOverlay();
32
- }
33
- },
34
- cleanup: () => {
35
- if (disposed) {
36
- return;
37
- }
38
- runtime.cleanup();
39
- removeOverlay();
40
- },
41
- dispose: () => {
42
- if (disposed) {
43
- return;
44
- }
45
- runtime.dispose();
46
- removeOverlay();
47
- removeLiveRegion();
48
- disposed = true;
49
- },
50
- finishOverlay,
51
22
  remeasureDropTargets: (input) => {
52
23
  runtime.remeasureDropTargets(input);
53
24
  },
25
+ remeasureOverlay,
54
26
  };
55
27
  setControllerRuntime(controller, runtime);
56
28
  return controller;
@@ -59,7 +31,7 @@ export function createDragController(options = {}) {
59
31
  targetingAlgorithm: nextOptions.targetingAlgorithm ?? pointerToCenter,
60
32
  targetingConstraint: nextOptions.targetingConstraint,
61
33
  hasDragOverlay: hasDragOverlay(nextOptions),
62
- keepOverlayOnDrop: nextOptions.keepOverlayOnDrop ?? false,
34
+ overlayRelease: nextOptions.overlayRelease ?? "auto",
63
35
  lifecycleCallbacks: createLifecycleCallbacks(nextOptions),
64
36
  keyboardConfiguration: nextOptions.keyboardConfiguration,
65
37
  modifiers: nextOptions.modifiers,
@@ -89,10 +61,6 @@ export function createDragController(options = {}) {
89
61
  };
90
62
  }
91
63
  function updateOverlayHost(update) {
92
- if (disposed) {
93
- removeOverlay();
94
- return;
95
- }
96
64
  if (update.type === "mount" || update.type === "release") {
97
65
  mountOverlay(update.state);
98
66
  return;
@@ -101,20 +69,16 @@ export function createDragController(options = {}) {
101
69
  moveOverlay(update.dragState);
102
70
  return;
103
71
  }
104
- removeOverlay();
72
+ clearOverlayHost();
105
73
  }
106
74
  function mountOverlay(overlayState) {
107
75
  if (!currentOptions.dragOverlay) {
108
- removeOverlay();
76
+ clearOverlayHost();
109
77
  return;
110
78
  }
111
- const nextOverlayElement = currentOptions.dragOverlay({
112
- dragState: overlayState.dragState,
113
- phase: overlayState.phase,
114
- finish: finishOverlay,
115
- });
79
+ const nextOverlayElement = currentOptions.dragOverlay(createOverlayInput(overlayState));
116
80
  if (!nextOverlayElement) {
117
- removeOverlay();
81
+ clearOverlayHost();
118
82
  return;
119
83
  }
120
84
  const wrapper = getOverlayWrapper(currentOptions.overlayRoot ?? document.body);
@@ -161,6 +125,9 @@ export function createDragController(options = {}) {
161
125
  }
162
126
  runtime.setOverlayRect(rectToDragRect(overlayElement.getBoundingClientRect()));
163
127
  }
128
+ function remeasureOverlay() {
129
+ measureOverlayElement();
130
+ }
164
131
  function disconnectOverlayResizeObserver() {
165
132
  overlayResizeObserver?.disconnect();
166
133
  overlayResizeObserver = null;
@@ -174,19 +141,28 @@ export function createDragController(options = {}) {
174
141
  }
175
142
  return overlayWrapper;
176
143
  }
177
- function finishOverlay() {
178
- if (disposed) {
179
- return;
180
- }
181
- removeOverlay();
182
- }
183
- function removeOverlay() {
144
+ function clearOverlayHost() {
184
145
  disconnectOverlayResizeObserver();
185
146
  overlayElement = null;
186
147
  runtime.setOverlayRect(null);
187
148
  overlayWrapper?.remove();
188
149
  overlayWrapper = null;
189
150
  }
151
+ function createOverlayInput(overlayState) {
152
+ if (overlayState.phase === "released") {
153
+ return {
154
+ dragState: overlayState.dragState,
155
+ phase: "released",
156
+ remeasureOverlay,
157
+ removeOverlay: clearOverlayHost,
158
+ };
159
+ }
160
+ return {
161
+ dragState: overlayState.dragState,
162
+ phase: "dragging",
163
+ remeasureOverlay,
164
+ };
165
+ }
190
166
  function syncLiveRegion() {
191
167
  if (currentOptions.announcements) {
192
168
  ensureLiveRegion();
@@ -25,7 +25,7 @@ export function createDraggable(input) {
25
25
  input.element.addEventListener("keydown", onKeyDown);
26
26
  keyDownAttached = true;
27
27
  }
28
- const cleanup = () => {
28
+ const releaseDomBinding = () => {
29
29
  if (cleanedUp) {
30
30
  return;
31
31
  }
@@ -45,8 +45,8 @@ export function createDraggable(input) {
45
45
  }
46
46
  }
47
47
  };
48
- runtime.registerBindingCleanup({
49
- cleanup,
48
+ runtime.registerStaleDomBinding({
49
+ release: releaseDomBinding,
50
50
  isConnected: () => elementRef.deref()?.isConnected === true,
51
51
  });
52
52
  }
@@ -11,7 +11,7 @@ export function createDropContainer(input) {
11
11
  getElement: () => elementRef.deref() ?? null,
12
12
  });
13
13
  let cleanedUp = false;
14
- const cleanup = () => {
14
+ const releaseDomBinding = () => {
15
15
  if (cleanedUp) {
16
16
  return;
17
17
  }
@@ -19,10 +19,10 @@ export function createDropContainer(input) {
19
19
  if (!elementRef.deref()) {
20
20
  return;
21
21
  }
22
- behavior.cleanup();
22
+ behavior.releaseRegistration();
23
23
  };
24
- runtime.registerBindingCleanup({
25
- cleanup,
24
+ runtime.registerStaleDomBinding({
25
+ release: releaseDomBinding,
26
26
  isConnected: () => elementRef.deref()?.isConnected === true,
27
27
  });
28
28
  }
@@ -13,6 +13,6 @@ export type CreateDomDropContainerInput = {
13
13
  };
14
14
  export type DomDropContainerBehavior = {
15
15
  setElement: (element: HTMLElement | null) => void;
16
- cleanup: () => void;
16
+ releaseRegistration: () => void;
17
17
  };
18
18
  export declare function createDomDropContainer(input: CreateDomDropContainerInput): DomDropContainerBehavior;
@@ -1,7 +1,7 @@
1
1
  export function createDomDropContainer(input) {
2
2
  let registeredElementRef = null;
3
3
  let registeredContainerId = null;
4
- const cleanup = () => {
4
+ const releaseRegistration = () => {
5
5
  const registeredElement = registeredElementRef?.deref() ?? null;
6
6
  if (registeredContainerId !== null) {
7
7
  input.runtime.unregisterDropContainer(registeredContainerId, registeredElement ?? undefined);
@@ -25,12 +25,12 @@ export function createDomDropContainer(input) {
25
25
  registeredContainerId === input.containerId) {
26
26
  return;
27
27
  }
28
- cleanup();
28
+ releaseRegistration();
29
29
  if (!element) {
30
30
  return;
31
31
  }
32
32
  registerElement(element);
33
33
  },
34
- cleanup,
34
+ releaseRegistration,
35
35
  };
36
36
  }
@@ -12,7 +12,7 @@ export function createDroppable(input) {
12
12
  });
13
13
  let cleanedUp = false;
14
14
  behavior.setElement(input.element);
15
- const cleanup = () => {
15
+ const releaseDomBinding = () => {
16
16
  if (cleanedUp) {
17
17
  return;
18
18
  }
@@ -20,10 +20,10 @@ export function createDroppable(input) {
20
20
  if (!elementRef.deref()) {
21
21
  return;
22
22
  }
23
- behavior.cleanup();
23
+ behavior.releaseRegistration();
24
24
  };
25
- runtime.registerBindingCleanup({
26
- cleanup,
25
+ runtime.registerStaleDomBinding({
26
+ release: releaseDomBinding,
27
27
  isConnected: () => elementRef.deref()?.isConnected === true,
28
28
  });
29
29
  }
@@ -12,6 +12,6 @@ export type CreateDomDroppableInput = {
12
12
  };
13
13
  export type DomDroppableBehavior = {
14
14
  setElement: (element: HTMLElement | null) => void;
15
- cleanup: () => void;
15
+ releaseRegistration: () => void;
16
16
  };
17
17
  export declare function createDomDroppable(input: CreateDomDroppableInput): DomDroppableBehavior;
@@ -1,7 +1,7 @@
1
1
  export function createDomDroppable(input) {
2
2
  let registeredElementRef = null;
3
3
  let registeredTargetId = null;
4
- const cleanup = () => {
4
+ const releaseRegistration = () => {
5
5
  const registeredElement = registeredElementRef?.deref() ?? null;
6
6
  if (registeredTargetId !== null) {
7
7
  input.runtime.unregisterDropTarget(registeredTargetId, registeredElement ?? undefined);
@@ -16,7 +16,7 @@ export function createDomDroppable(input) {
16
16
  registeredTargetId === input.dropTargetId) {
17
17
  return;
18
18
  }
19
- cleanup();
19
+ releaseRegistration();
20
20
  if (!element) {
21
21
  return;
22
22
  }
@@ -26,6 +26,6 @@ export function createDomDroppable(input) {
26
26
  registeredElementRef = new WeakRef(element);
27
27
  registeredTargetId = input.dropTargetId;
28
28
  },
29
- cleanup,
29
+ releaseRegistration,
30
30
  };
31
31
  }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export type { SortableAxis, SortablePlacementBoundary, } from "./sortable/sortab
7
7
  export { createDragHandle, type CreateDragHandleInput, } from "./input/create-drag-handle.js";
8
8
  export type { DragEndResult, DragEndEvent, DragLifecycleCallbacks, DragLifecycleHelpers, DragSource, DragStartEvent, DragUpdateEvent, DropEvent, } from "./runtime/lifecycle.js";
9
9
  export type { RemeasureDropTargetsInput, SortableDropPlacement, } from "./runtime/drop-target-registry.js";
10
+ export type { OverlayReleaseMode } from "./runtime/types.js";
10
11
  export { centerToCenter, pointerToCenter, pointerToRectDistance, } from "./targeting/algorithms.js";
11
12
  export { getDistanceToRect, maxOverlayCenterDistanceToRect, maxPointerDistanceToRect, } from "./targeting/constraints.js";
12
13
  export type { DropTarget, TargetingAlgorithm, TargetingAlgorithmInput, TargetingConstraint, TargetingConstraintInput, } from "./targeting/types.js";
@@ -26,6 +26,8 @@ export declare class PointerActivationController {
26
26
  private pendingActivation;
27
27
  constructor(options: PointerActivationControllerOptions);
28
28
  request(request: PointerDragActivationRequest): void;
29
- cancel(): void;
30
- private activatePending;
29
+ cancelPendingActivation(): void;
30
+ private clearPendingActivation;
31
+ private clearPendingActivationTimer;
32
+ private activatePendingPointerDrag;
31
33
  }