@mk-drag-and-drop/dom 0.3.0 → 0.4.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 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
@@ -408,6 +411,36 @@ order, so app-owned layout changes such as expanding tree rows or changing
408
411
  grouped sections during a drag should call the public remeasure API when those
409
412
  changes need to affect targeting.
410
413
 
414
+ ## Active Drag Recompute
415
+
416
+ `controller.recomputeActiveDrag()` reruns the active drag update path from the
417
+ last stored raw pointer position. It reapplies modifiers, derives the overlay
418
+ rect from cached overlay measurement, recomputes the active drop target from
419
+ cached target measurements, updates the overlay host, and sends the normal drag
420
+ update notifications. This is the same update path used by pointer movement.
421
+ Calling it with no active drag is safe and does nothing.
422
+
423
+ Use it when something external changes what is under the pointer during an
424
+ active drag without producing a new pointer event.
425
+
426
+ ```ts
427
+ controller.recomputeActiveDrag();
428
+ ```
429
+
430
+ Recompute does not remeasure drop targets. If target geometry or registrations
431
+ changed and those changes should affect targeting, remeasure first and then
432
+ recompute.
433
+
434
+ ```ts
435
+ controller.remeasureDropTargets({ group: "items" });
436
+ controller.recomputeActiveDrag();
437
+ ```
438
+
439
+ ```ts
440
+ // Example: after external scrolling changes what is under the pointer
441
+ controller.recomputeActiveDrag();
442
+ ```
443
+
411
444
  ## Data Ownership
412
445
 
413
446
  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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mk-drag-and-drop/dom",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Headless DOM drag-and-drop primitives for draggable, droppable, sortable, and grouped interactions.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://mkramer.dev",
@@ -47,8 +47,8 @@
47
47
  "jsdom": "^24.1.3",
48
48
  "typescript": "5.5.4",
49
49
  "vitest": "^2.1.9",
50
- "@repo/eslint-config": "0.0.0",
51
- "@repo/typescript-config": "0.0.0"
50
+ "@repo/typescript-config": "0.0.0",
51
+ "@repo/eslint-config": "0.0.0"
52
52
  },
53
53
  "scripts": {
54
54
  "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",