@mk-drag-and-drop/dom 0.3.0 → 0.4.1
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 +44 -0
- package/dist/controller/create-drag-controller.d.ts +1 -0
- package/dist/controller/create-drag-controller.js +3 -0
- package/dist/runtime/drag-runtime-scope.d.ts +1 -0
- package/dist/runtime/drag-runtime-scope.js +1 -0
- package/dist/runtime/drag-runtime.d.ts +1 -0
- package/dist/runtime/drag-runtime.js +7 -0
- package/dist/sortable/sortable-preview.d.ts +1 -0
- package/dist/sortable/sortable-preview.js +20 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -98,6 +98,9 @@ The returned controller has:
|
|
|
98
98
|
array of target ids, or `{ group }`
|
|
99
99
|
- `remeasureOverlay()`: remeasures the currently mounted drag overlay element;
|
|
100
100
|
it is a safe no-op when no overlay is mounted or no drag is active
|
|
101
|
+
- `recomputeActiveDrag()`: reruns active targeting and drag update from the
|
|
102
|
+
last pointer position; it is a safe no-op when no drag is active and does not
|
|
103
|
+
remeasure drop targets
|
|
101
104
|
|
|
102
105
|
The controller does not expose runtime teardown, disposal, update, or broad
|
|
103
106
|
overlay removal methods. Runtime objects are ordinary JavaScript objects; DOM
|
|
@@ -362,6 +365,17 @@ registry may narrow measured candidates to relevant sortable item, neighbor, or
|
|
|
362
365
|
container entries before the targeting algorithm runs; the algorithm still makes
|
|
363
366
|
the active-target decision from that narrowed measured list.
|
|
364
367
|
|
|
368
|
+
Same-container sortable preview keeps its movement-responsive first-placement
|
|
369
|
+
behavior: forward movement places after a newly active target, backward movement
|
|
370
|
+
places before, and no sortable-axis movement uses the target midpoint. When a
|
|
371
|
+
sortable item first enters a different DOM container, the initial side is based
|
|
372
|
+
on the target midpoint on the sortable axis: above or left of midpoint places
|
|
373
|
+
before, while below or right of midpoint places after.
|
|
374
|
+
|
|
375
|
+
`placementBoundary` is used after a preview placement already exists to control
|
|
376
|
+
same-target reversal and hysteresis thresholds. It does not decide the initial
|
|
377
|
+
side for cross-container sortable entry.
|
|
378
|
+
|
|
365
379
|
## Modifiers
|
|
366
380
|
|
|
367
381
|
Modifiers transform pointer movement before drag state updates. Built-ins:
|
|
@@ -408,6 +422,36 @@ order, so app-owned layout changes such as expanding tree rows or changing
|
|
|
408
422
|
grouped sections during a drag should call the public remeasure API when those
|
|
409
423
|
changes need to affect targeting.
|
|
410
424
|
|
|
425
|
+
## Active Drag Recompute
|
|
426
|
+
|
|
427
|
+
`controller.recomputeActiveDrag()` reruns the active drag update path from the
|
|
428
|
+
last stored raw pointer position. It reapplies modifiers, derives the overlay
|
|
429
|
+
rect from cached overlay measurement, recomputes the active drop target from
|
|
430
|
+
cached target measurements, updates the overlay host, and sends the normal drag
|
|
431
|
+
update notifications. This is the same update path used by pointer movement.
|
|
432
|
+
Calling it with no active drag is safe and does nothing.
|
|
433
|
+
|
|
434
|
+
Use it when something external changes what is under the pointer during an
|
|
435
|
+
active drag without producing a new pointer event.
|
|
436
|
+
|
|
437
|
+
```ts
|
|
438
|
+
controller.recomputeActiveDrag();
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Recompute does not remeasure drop targets. If target geometry or registrations
|
|
442
|
+
changed and those changes should affect targeting, remeasure first and then
|
|
443
|
+
recompute.
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
controller.remeasureDropTargets({ group: "items" });
|
|
447
|
+
controller.recomputeActiveDrag();
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
// Example: after external scrolling changes what is under the pointer
|
|
452
|
+
controller.recomputeActiveDrag();
|
|
453
|
+
```
|
|
454
|
+
|
|
411
455
|
## Data Ownership
|
|
412
456
|
|
|
413
457
|
The DOM package never owns application data. Item ids, target ids, group ids,
|
|
@@ -35,5 +35,6 @@ export type DragControllerOptions = {
|
|
|
35
35
|
export type DragController = {
|
|
36
36
|
remeasureDropTargets: (input?: RemeasureDropTargetsInput) => void;
|
|
37
37
|
remeasureOverlay: () => void;
|
|
38
|
+
recomputeActiveDrag: () => void;
|
|
38
39
|
};
|
|
39
40
|
export declare function createDragController(options?: DragControllerOptions): DragController;
|
|
@@ -23,6 +23,9 @@ export function createDragController(options = {}) {
|
|
|
23
23
|
runtime.remeasureDropTargets(input);
|
|
24
24
|
},
|
|
25
25
|
remeasureOverlay,
|
|
26
|
+
recomputeActiveDrag: () => {
|
|
27
|
+
runtime.recomputeActiveDrag();
|
|
28
|
+
},
|
|
26
29
|
};
|
|
27
30
|
setControllerRuntime(controller, runtime);
|
|
28
31
|
return controller;
|
|
@@ -11,6 +11,7 @@ export type DragRuntimeScope = DomDraggableRuntime & DomDroppableRuntime & DomDr
|
|
|
11
11
|
configure: (input: DragRuntimeScopeConfigureInput) => void;
|
|
12
12
|
cancelDrag: () => void;
|
|
13
13
|
releaseActiveDragResources: () => void;
|
|
14
|
+
recomputeActiveDrag: () => void;
|
|
14
15
|
setOverlayRect: (overlayRect: DragRect | null) => void;
|
|
15
16
|
};
|
|
16
17
|
export type InternalStaleDomBindingRuntime = {
|
|
@@ -5,6 +5,7 @@ export function createDragRuntimeScope(options) {
|
|
|
5
5
|
configure: (input) => runtime.configure(input),
|
|
6
6
|
cancelDrag: () => runtime.cancelDrag(),
|
|
7
7
|
releaseActiveDragResources: () => runtime.releaseActiveDragResources(),
|
|
8
|
+
recomputeActiveDrag: () => runtime.recomputeActiveDrag(),
|
|
8
9
|
setOverlayRect: (overlayRect) => runtime.setOverlayRect(overlayRect),
|
|
9
10
|
requestDragStart: (input) => runtime.requestDragStart(input),
|
|
10
11
|
isKeyboardDragEnabled: () => runtime.isKeyboardDragEnabled(),
|
|
@@ -43,6 +43,7 @@ export declare class DragRuntime {
|
|
|
43
43
|
requestKeyboardDragStart(input: RequestKeyboardDragStartInput): void;
|
|
44
44
|
moveKeyboardDrag(direction: KeyboardMoveDirection): void;
|
|
45
45
|
updatePointer(rawPointerPosition: Point): void;
|
|
46
|
+
recomputeActiveDrag(): void;
|
|
46
47
|
private updatePointerNow;
|
|
47
48
|
private updatePointerNowOrRelease;
|
|
48
49
|
private finishDragAfterQueuedPointerUpdate;
|
|
@@ -180,6 +180,13 @@ export class DragRuntime {
|
|
|
180
180
|
}
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
|
+
recomputeActiveDrag() {
|
|
184
|
+
const session = this.getDraggingSession();
|
|
185
|
+
if (!session) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.updatePointerNowOrRelease(session.rawPointerPosition);
|
|
189
|
+
}
|
|
183
190
|
updatePointerNow(rawPointerPosition) {
|
|
184
191
|
const session = this.getDraggingSession();
|
|
185
192
|
if (!session) {
|
|
@@ -56,6 +56,7 @@ export declare function getSortablePreviewPlacement(input: {
|
|
|
56
56
|
movement: SortablePointerMovementState | null;
|
|
57
57
|
previewPlacement: SortablePreviewPlacementState | null;
|
|
58
58
|
options: NormalizedSortableOptions;
|
|
59
|
+
useMidpointInitialPlacement?: boolean;
|
|
59
60
|
}): SortablePreviewPlacementDecision;
|
|
60
61
|
export declare function isSortablePreviewAlreadyPlaced(input: {
|
|
61
62
|
draggedElement: HTMLElement;
|
|
@@ -106,6 +106,7 @@ export function moveSortablePreview(input) {
|
|
|
106
106
|
if (!listElement) {
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
|
+
const useMidpointInitialPlacement = draggedElement.parentElement !== listElement;
|
|
109
110
|
if (!target.capabilities.sortable) {
|
|
110
111
|
return;
|
|
111
112
|
}
|
|
@@ -120,6 +121,7 @@ export function moveSortablePreview(input) {
|
|
|
120
121
|
movement: input.registry.activeDrag.pointerMovement,
|
|
121
122
|
previewPlacement: input.registry.activeDrag.previewPlacement,
|
|
122
123
|
options: input.options,
|
|
124
|
+
useMidpointInitialPlacement,
|
|
123
125
|
});
|
|
124
126
|
const placement = placementDecision.placement;
|
|
125
127
|
setSortablePreviewPlacementState({
|
|
@@ -165,12 +167,18 @@ export function getSortablePreviewPlacement(input) {
|
|
|
165
167
|
previousPlacement.placement === null ||
|
|
166
168
|
previousPlacement.movementDirection === "none") {
|
|
167
169
|
return {
|
|
168
|
-
placement:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
placement: input.useMidpointInitialPlacement
|
|
171
|
+
? getPlacementSideFromTargetMidpoint({
|
|
172
|
+
axis,
|
|
173
|
+
axisPosition,
|
|
174
|
+
targetRect,
|
|
175
|
+
})
|
|
176
|
+
: getOptimisticPlacement({
|
|
177
|
+
axis,
|
|
178
|
+
axisPosition,
|
|
179
|
+
currentDirection,
|
|
180
|
+
targetRect,
|
|
181
|
+
}),
|
|
174
182
|
movementDirection: currentDirection,
|
|
175
183
|
};
|
|
176
184
|
}
|
|
@@ -222,6 +230,12 @@ function getOptimisticPlacement(input) {
|
|
|
222
230
|
endRatio: neutralPlacementBoundaryRatio,
|
|
223
231
|
}));
|
|
224
232
|
}
|
|
233
|
+
function getPlacementSideFromTargetMidpoint(input) {
|
|
234
|
+
const targetStart = input.axis === "horizontal" ? input.targetRect.left : input.targetRect.top;
|
|
235
|
+
const targetSize = input.axis === "horizontal" ? input.targetRect.width : input.targetRect.height;
|
|
236
|
+
const midpoint = targetStart + targetSize / 2;
|
|
237
|
+
return input.axisPosition < midpoint ? "before" : "after";
|
|
238
|
+
}
|
|
225
239
|
function getCurrentAxisMovementDirection(input) {
|
|
226
240
|
const axisPosition = getAxisPosition(input.placementPosition, input.axis);
|
|
227
241
|
const previousAxisPosition = input.movement
|
package/package.json
CHANGED