@mk-drag-and-drop/react 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 CHANGED
@@ -52,6 +52,7 @@ The React root export includes:
52
52
  - `useSortable`, `UseSortableOptions`, `UseSortableResult`
53
53
  - `useDragHandle`, `UseDragHandleResult`
54
54
  - `useRemeasureDropTargets`
55
+ - `useRecomputeActiveDrag`
55
56
  - `useRemeasureOverlay`
56
57
  - `composeRefs`
57
58
  - React-friendly `restrictToContainer`, `ReactRestrictToContainerInput`
@@ -402,6 +403,32 @@ every render. Sortable preview movement does not automatically remeasure a
402
403
  group; call this function when an app-owned layout change needs to affect
403
404
  targeting.
404
405
 
406
+ ### useRecomputeActiveDrag
407
+
408
+ `useRecomputeActiveDrag` returns a function for rerunning the active drag update
409
+ path from the last pointer position. It must be used inside `DragProvider` and
410
+ is a thin wrapper over the DOM runtime operation. It follows the same update
411
+ path as DOM pointer movement. Calling the returned function with no active drag
412
+ is safe and does nothing.
413
+
414
+ ```tsx
415
+ const recomputeActiveDrag = useRecomputeActiveDrag();
416
+
417
+ recomputeActiveDrag();
418
+ ```
419
+
420
+ Use it after external changes that require active targeting to run again without
421
+ a new pointer event. It does not remeasure drop targets. When target
422
+ measurements changed, call `useRemeasureDropTargets()` first.
423
+
424
+ ```tsx
425
+ const remeasureDropTargets = useRemeasureDropTargets();
426
+ const recomputeActiveDrag = useRecomputeActiveDrag();
427
+
428
+ remeasureDropTargets({ group: "items" });
429
+ recomputeActiveDrag();
430
+ ```
431
+
405
432
  ### useRemeasureOverlay
406
433
 
407
434
  `useRemeasureOverlay` returns a function for manually refreshing the current
@@ -426,6 +453,16 @@ Preview movement does not trigger full target remeasurement. The app still
426
453
  commits data on drop, using placement derived from the current preview DOM
427
454
  order. React rendering should then reflect the final data.
428
455
 
456
+ React uses the DOM package placement rules. Same-container sortable preview
457
+ keeps its movement-responsive first-placement behavior: forward movement places
458
+ after a newly active target, backward movement places before, and no
459
+ sortable-axis movement uses the target midpoint. When a sortable item first
460
+ enters a different DOM container, the initial side is based on the target
461
+ midpoint on the sortable axis: above or left of midpoint places before, while
462
+ below or right of midpoint places after. `placementBoundary` remains a
463
+ same-target reversal and hysteresis control after preview placement exists; it
464
+ does not decide the initial side for cross-container sortable entry.
465
+
429
466
  Examples may rerender a full list for simplicity, but granular state management,
430
467
  external stores, server commits, and imperative rendering strategies are
431
468
  compatible. The package does not require React state.
@@ -525,6 +562,10 @@ DOM registry may narrow measured candidates to relevant sortable item, neighbor,
525
562
  or container entries before the targeting algorithm runs; the algorithm still
526
563
  chooses from that narrowed measured list.
527
564
 
565
+ The before/after side follows the DOM package sortable placement behavior
566
+ described above, including midpoint initial placement for cross-container entry
567
+ and `placementBoundary` for later same-target reversal behavior.
568
+
528
569
  - `lockToXAxis()`
529
570
  - `lockToYAxis()`
530
571
  - `restrictToContainer(refOrResolver)`
@@ -590,9 +631,10 @@ mount/unmount.
590
631
  `useDraggable`, `useDroppable`, and `useSortable` rely on React prop/ref updates
591
632
  for normal mount, unmount, and element replacement behavior.
592
633
 
593
- `useRemeasureDropTargets` and `useRemeasureOverlay` are for geometry changes,
594
- not resource release. The runtime also prunes disconnected targets on
595
- drag-critical paths such as remeasurement.
634
+ `useRemeasureDropTargets`, `useRecomputeActiveDrag`, and `useRemeasureOverlay`
635
+ are for active drag geometry or targeting changes, not resource release. The
636
+ runtime also prunes disconnected targets on drag-critical paths such as
637
+ remeasurement.
596
638
 
597
639
  ## Examples
598
640
 
@@ -626,6 +668,8 @@ React examples live in `apps/react-web/src/react`:
626
668
  - `useDragHandle()`: returns the handle attribute props for a handle element.
627
669
  - `useRemeasureDropTargets()`: returns a function for remeasuring all targets,
628
670
  one target, multiple targets, or a group.
671
+ - `useRecomputeActiveDrag()`: returns a function for rerunning active targeting
672
+ and drag update from the last pointer position without remeasuring targets.
629
673
  - `useRemeasureOverlay()`: returns a function for manually refreshing the
630
674
  currently mounted overlay measurement.
631
675
  - `composeRefs`: helper for combining the refs returned by hooks with app refs.
@@ -0,0 +1 @@
1
+ export declare function useRecomputeActiveDrag(): () => void;
@@ -0,0 +1,12 @@
1
+ import { useCallback, useContext } from "react";
2
+ import { DragContext } from "../drag-context.js";
3
+ export function useRecomputeActiveDrag() {
4
+ const context = useContext(DragContext);
5
+ if (!context) {
6
+ throw new Error("useRecomputeActiveDrag must be used inside DragProvider");
7
+ }
8
+ const { runtime } = context;
9
+ return useCallback(() => {
10
+ runtime.recomputeActiveDrag();
11
+ }, [runtime]);
12
+ }
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export { useDraggable, type UseDraggableOptions, type UseDraggableResult, } from
8
8
  export { useDropContainer, type UseDropContainerOptions, type UseDropContainerResult, } from "./hooks/use-drop-container.js";
9
9
  export { useDroppable, type UseDroppableOptions, type UseDroppableResult, } from "./hooks/use-droppable.js";
10
10
  export { useRemeasureDropTargets } from "./hooks/use-remeasure-drop-targets.js";
11
+ export { useRecomputeActiveDrag } from "./hooks/use-recompute-active-drag.js";
11
12
  export { useRemeasureOverlay } from "./hooks/use-remeasure-overlay.js";
12
13
  export { useSortable, type UseSortableOptions, type UseSortableResult, } from "./hooks/use-sortable.js";
13
14
  export { composeRefs } from "./utils/compose-refs.js";
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export { useDraggable, } from "./hooks/use-draggable.js";
6
6
  export { useDropContainer, } from "./hooks/use-drop-container.js";
7
7
  export { useDroppable, } from "./hooks/use-droppable.js";
8
8
  export { useRemeasureDropTargets } from "./hooks/use-remeasure-drop-targets.js";
9
+ export { useRecomputeActiveDrag } from "./hooks/use-recompute-active-drag.js";
9
10
  export { useRemeasureOverlay } from "./hooks/use-remeasure-overlay.js";
10
11
  export { useSortable, } from "./hooks/use-sortable.js";
11
12
  export { composeRefs } from "./utils/compose-refs.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mk-drag-and-drop/react",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "React hooks and provider for the mk drag-and-drop DOM runtime.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://mkramer.dev",
@@ -39,7 +39,7 @@
39
39
  ],
40
40
  "sideEffects": false,
41
41
  "dependencies": {
42
- "@mk-drag-and-drop/dom": "^0.3.0"
42
+ "@mk-drag-and-drop/dom": "^0.4.1"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "react": "^19.0.0"
@@ -57,8 +57,8 @@
57
57
  "react-dom": "^19.2.7",
58
58
  "vitest": "^2.1.9",
59
59
  "typescript": "5.5.4",
60
- "@repo/eslint-config": "0.0.0",
61
- "@repo/typescript-config": "0.0.0"
60
+ "@repo/typescript-config": "0.0.0",
61
+ "@repo/eslint-config": "0.0.0"
62
62
  },
63
63
  "scripts": {
64
64
  "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"",