@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.
- package/README.md +111 -35
- package/dist/controller/controller-internals.d.ts +4 -4
- package/dist/controller/create-drag-controller.d.ts +11 -8
- package/dist/controller/create-drag-controller.js +29 -53
- package/dist/draggable/create-draggable-binding.js +3 -3
- package/dist/droppable/create-drop-container-binding.js +4 -4
- package/dist/droppable/create-drop-container.d.ts +1 -1
- package/dist/droppable/create-drop-container.js +3 -3
- package/dist/droppable/create-droppable-binding.js +4 -4
- package/dist/droppable/create-droppable.d.ts +1 -1
- package/dist/droppable/create-droppable.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/input/pointer-activation.d.ts +4 -2
- package/dist/input/pointer-activation.js +28 -16
- package/dist/integration/index.d.ts +2 -2
- package/dist/integration/index.js +1 -1
- package/dist/runtime/drag-runtime-scope.d.ts +21 -0
- package/dist/runtime/{drag-runtime-handle.js → drag-runtime-scope.js} +8 -9
- package/dist/runtime/drag-runtime.d.ts +21 -17
- package/dist/runtime/drag-runtime.js +279 -155
- package/dist/runtime/lifecycle.d.ts +7 -0
- package/dist/runtime/types.d.ts +3 -2
- package/dist/sortable/create-sortable-binding.js +4 -4
- package/dist/sortable/create-sortable.d.ts +1 -1
- package/dist/sortable/create-sortable.js +3 -3
- package/dist/sortable/sortable-preview.js +20 -17
- package/dist/sortable/sortable-registry.d.ts +15 -6
- package/dist/sortable/sortable-registry.js +65 -47
- package/package.json +2 -1
- 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
|
|
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
|
-
- `
|
|
63
|
-
- `
|
|
64
|
-
`
|
|
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
|
|
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
|
-
- `
|
|
85
|
-
|
|
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
|
-
- `
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
105
|
-
|
|
106
|
-
|
|
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,
|
|
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
|
|
204
|
-
|
|
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
|
|
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?)`;
|
|
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
|
-
##
|
|
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
|
-
|
|
359
|
-
|
|
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
|
-
|
|
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
|
-
|
|
364
|
-
-
|
|
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
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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 {
|
|
1
|
+
import type { DragRuntimeScope, InternalStaleDomBindingRuntime } from "../runtime/drag-runtime-scope.js";
|
|
2
2
|
import type { DragController } from "./create-drag-controller.js";
|
|
3
|
-
export type
|
|
4
|
-
export declare function setControllerRuntime(controller: DragController, runtime:
|
|
5
|
-
export declare function getControllerRuntime(controller: DragController):
|
|
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 {
|
|
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:
|
|
16
|
-
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
72
|
+
clearOverlayHost();
|
|
105
73
|
}
|
|
106
74
|
function mountOverlay(overlayState) {
|
|
107
75
|
if (!currentOptions.dragOverlay) {
|
|
108
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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.
|
|
49
|
-
|
|
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
|
|
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.
|
|
22
|
+
behavior.releaseRegistration();
|
|
23
23
|
};
|
|
24
|
-
runtime.
|
|
25
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
28
|
+
releaseRegistration();
|
|
29
29
|
if (!element) {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
registerElement(element);
|
|
33
33
|
},
|
|
34
|
-
|
|
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
|
|
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.
|
|
23
|
+
behavior.releaseRegistration();
|
|
24
24
|
};
|
|
25
|
-
runtime.
|
|
26
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
30
|
-
private
|
|
29
|
+
cancelPendingActivation(): void;
|
|
30
|
+
private clearPendingActivation;
|
|
31
|
+
private clearPendingActivationTimer;
|
|
32
|
+
private activatePendingPointerDrag;
|
|
31
33
|
}
|