@mk-drag-and-drop/react 0.1.0 → 0.2.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 +60 -28
- package/dist/drag-context.d.ts +2 -2
- package/dist/drag-overlay.d.ts +7 -3
- package/dist/drag-provider.d.ts +3 -3
- package/dist/drag-provider.js +30 -21
- package/dist/hooks/use-drop-container.js +2 -2
- package/dist/hooks/use-droppable.js +11 -1
- package/dist/hooks/use-sortable.js +9 -1
- package/dist/index.d.ts +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ callbacks, and optional announcements.
|
|
|
22
22
|
The React package wraps `@mk-drag-and-drop/dom`.
|
|
23
23
|
|
|
24
24
|
`DragProvider` creates and configures the DOM runtime through the package
|
|
25
|
-
integration
|
|
25
|
+
integration scope.
|
|
26
26
|
Hooks such as `useDraggable`, `useDroppable`, `useSortable`, and
|
|
27
27
|
`useDropContainer` register DOM nodes with that runtime through React refs.
|
|
28
28
|
React hooks are adapters over DOM behavior, not a separate implementation.
|
|
@@ -57,6 +57,7 @@ The React root export includes:
|
|
|
57
57
|
- DOM targeting helpers, modifier helpers, lifecycle/source/result types,
|
|
58
58
|
sortable placement types, keyboard/pointer configuration types, and geometry
|
|
59
59
|
types re-exported from the DOM package
|
|
60
|
+
- `OverlayReleaseMode`
|
|
60
61
|
- `DragState` and `DragOverlayPhase` from the DOM integration layer
|
|
61
62
|
|
|
62
63
|
## Core Mental Model
|
|
@@ -72,11 +73,28 @@ The package reports drag/drop operations. Your app owns the data and the final
|
|
|
72
73
|
UI commit. React state is one common way to commit the result, but it is not
|
|
73
74
|
required by the package.
|
|
74
75
|
|
|
76
|
+
## Lifetime Model
|
|
77
|
+
|
|
78
|
+
`DragProvider` is a drag-and-drop scope for a React subtree. It does not expose
|
|
79
|
+
runtime lifecycle controls, and application code does not dispose of the
|
|
80
|
+
runtime. The internal runtime is normal JavaScript memory and is released by
|
|
81
|
+
garbage collection when unreachable.
|
|
82
|
+
|
|
83
|
+
Hooks are adapters over the DOM behavior layer. They register committed DOM
|
|
84
|
+
nodes through refs/effects, update those registrations when ids, groups, or
|
|
85
|
+
container ids change, and unregister current nodes on ref/effect unmount.
|
|
86
|
+
Stale disconnected DOM registrations are still pruned by the shared DOM runtime
|
|
87
|
+
while the scope remains alive.
|
|
88
|
+
|
|
89
|
+
Pending pointer activation resources and active drag resources belong to the
|
|
90
|
+
input/drag lifecycle. Provider unmount releases active resources through the
|
|
91
|
+
same active-drag resource path used by DOM drag cancellation; it is not a
|
|
92
|
+
terminal runtime destructor. React StrictMode replay is supported for
|
|
93
|
+
draggable, droppable, sortable, overlay, callback, and announcement behavior.
|
|
94
|
+
|
|
75
95
|
## Installation
|
|
76
96
|
|
|
77
|
-
|
|
78
|
-
React and DOM packages from your workspace or package registry when they are
|
|
79
|
-
available:
|
|
97
|
+
Install the React and DOM packages from your workspace or package registry:
|
|
80
98
|
|
|
81
99
|
- `@mk-drag-and-drop/react`
|
|
82
100
|
- `@mk-drag-and-drop/dom`
|
|
@@ -153,9 +171,11 @@ Real apps own the markup, layout, styling, state updates, and persistence.
|
|
|
153
171
|
|
|
154
172
|
## DragProvider
|
|
155
173
|
|
|
156
|
-
`DragProvider`
|
|
157
|
-
|
|
158
|
-
|
|
174
|
+
`DragProvider` creates a DOM runtime scope for the React subtree, configures it
|
|
175
|
+
from props, exposes it through React context, and renders an optional drag
|
|
176
|
+
overlay. Provider effect cleanup is not a runtime destructor; runtime objects
|
|
177
|
+
are ordinary JavaScript objects and active drag resources are released by drag
|
|
178
|
+
drop/cancel paths.
|
|
159
179
|
|
|
160
180
|
Key props:
|
|
161
181
|
|
|
@@ -171,8 +191,8 @@ Key props:
|
|
|
171
191
|
- `pointerConfiguration`: configures pointer activation delay and distance.
|
|
172
192
|
- `keyboardConfiguration`: enables and configures keyboard drag commands.
|
|
173
193
|
- `announcements`: optional callbacks that return live-region messages.
|
|
174
|
-
- `
|
|
175
|
-
|
|
194
|
+
- `overlayRelease`: `"auto"` removes overlays on drag end; `"manual"` keeps a
|
|
195
|
+
released overlay until its `removeOverlay` callback is called.
|
|
176
196
|
|
|
177
197
|
Callbacks receive operation information and helper methods from the runtime.
|
|
178
198
|
Use those callbacks to commit app data. Do not mutate package internals.
|
|
@@ -365,9 +385,10 @@ requestAnimationFrame(() => {
|
|
|
365
385
|
|
|
366
386
|
It accepts no argument, a target id, an array of target ids, or `{ group }`.
|
|
367
387
|
Use it intentionally for expand/collapse, grouped trees, or drag-state layout
|
|
368
|
-
changes. It is not needed for normal
|
|
369
|
-
Sortable preview movement does not automatically remeasure a
|
|
370
|
-
function when an app-owned layout change needs to affect
|
|
388
|
+
changes. It is not needed for normal resource release and should not run on
|
|
389
|
+
every render. Sortable preview movement does not automatically remeasure a
|
|
390
|
+
group; call this function when an app-owned layout change needs to affect
|
|
391
|
+
targeting.
|
|
371
392
|
|
|
372
393
|
## Sortable Behavior
|
|
373
394
|
|
|
@@ -420,14 +441,20 @@ The overlay input includes:
|
|
|
420
441
|
|
|
421
442
|
- `dragState`: item id, group, source rect, start pointer, and current pointer.
|
|
422
443
|
- `phase`: `"dragging"` or `"released"`.
|
|
423
|
-
- `
|
|
444
|
+
- `removeOverlay`: present only for `"released"` overlays in manual release
|
|
445
|
+
mode; call it when app-owned release animation should remove the overlay.
|
|
424
446
|
|
|
425
447
|
Overlay rendering is app-owned. `DragProvider` mounts overlay content for the
|
|
426
|
-
dragging phase
|
|
427
|
-
|
|
428
|
-
|
|
448
|
+
dragging phase. Default `overlayRelease: "auto"` removes the overlay
|
|
449
|
+
immediately on drag end. Manual release replaces it once for the released phase
|
|
450
|
+
and leaves removal to `removeOverlay`. Pointer movement updates the
|
|
451
|
+
package-owned overlay host imperatively and does not call `dragOverlay` by
|
|
452
|
+
default.
|
|
453
|
+
|
|
454
|
+
`removeOverlay` is idempotent and belongs to overlay release only. It is not a
|
|
455
|
+
provider, controller, or runtime teardown API.
|
|
429
456
|
|
|
430
|
-
The package owns overlay hosting, movement,
|
|
457
|
+
The package owns overlay hosting, movement, release, and measurement for
|
|
431
458
|
targeting and modifiers. It measures overlay content on mount/replacement and
|
|
432
459
|
uses `ResizeObserver` when available to remeasure content size changes. Dynamic
|
|
433
460
|
overlay content should use overlay-local state, component effects, lifecycle
|
|
@@ -451,7 +478,10 @@ The React package re-exports targeting helpers such as `pointerToCenter`,
|
|
|
451
478
|
`maxPointerDistanceToRect` / `maxOverlayCenterDistanceToRect`, plus modifier
|
|
452
479
|
helpers. Sortable placement remains separate from targeting: the configured
|
|
453
480
|
targeting algorithm chooses the active target, and sortable only chooses
|
|
454
|
-
before/after placement relative to that target.
|
|
481
|
+
before/after placement relative to that target. For sortable groups, the shared
|
|
482
|
+
DOM registry may narrow measured candidates to relevant sortable item, neighbor,
|
|
483
|
+
or container entries before the targeting algorithm runs; the algorithm still
|
|
484
|
+
chooses from that narrowed measured list.
|
|
455
485
|
|
|
456
486
|
- `lockToXAxis()`
|
|
457
487
|
- `lockToYAxis()`
|
|
@@ -507,19 +537,20 @@ Accessibility still depends on the app's markup and product behavior:
|
|
|
507
537
|
- Do not assume this package alone provides complete screen-reader drag-and-drop
|
|
508
538
|
support for your domain.
|
|
509
539
|
|
|
510
|
-
##
|
|
540
|
+
## Lifetime And Effects
|
|
511
541
|
|
|
512
542
|
Hooks attach input props and register DOM nodes through refs and lifecycle
|
|
513
|
-
effects. Users should not manually
|
|
543
|
+
effects. Users should not manually release runtime entries for normal React
|
|
514
544
|
mount/unmount.
|
|
515
545
|
|
|
516
|
-
`DragProvider`
|
|
517
|
-
`useDropContainer`
|
|
546
|
+
`DragProvider` does not call a terminal runtime destructor when it unmounts.
|
|
547
|
+
`useDropContainer` releases its current DOM registration from effect cleanup.
|
|
518
548
|
`useDraggable`, `useDroppable`, and `useSortable` rely on React prop/ref updates
|
|
519
549
|
for normal mount, unmount, and element replacement behavior.
|
|
520
550
|
|
|
521
|
-
`useRemeasureDropTargets` is for layout changes, not
|
|
522
|
-
prunes disconnected targets on drag-critical paths such as
|
|
551
|
+
`useRemeasureDropTargets` is for layout changes, not resource release. The
|
|
552
|
+
runtime also prunes disconnected targets on drag-critical paths such as
|
|
553
|
+
remeasurement.
|
|
523
554
|
|
|
524
555
|
## Examples
|
|
525
556
|
|
|
@@ -540,7 +571,7 @@ React examples live in `apps/react-web/src/react`:
|
|
|
540
571
|
- `DragProvider`: creates/configures the DOM runtime for a React subtree.
|
|
541
572
|
Important props include lifecycle callbacks, overlay rendering, targeting,
|
|
542
573
|
constraints, modifiers, pointer/keyboard configuration, announcements, and
|
|
543
|
-
`
|
|
574
|
+
`overlayRelease`.
|
|
544
575
|
- `useDraggable(options)`: registers a drag source. Important options:
|
|
545
576
|
`draggableId`, `group`. Returns ref and input props.
|
|
546
577
|
- `useDroppable(options)`: registers a drop target. Important options:
|
|
@@ -561,8 +592,9 @@ Important event/helper types are re-exported from the React package, including
|
|
|
561
592
|
`DragStartEvent`, `DragUpdateEvent`, `DragEndEvent`, `DropEvent`,
|
|
562
593
|
`DragSource`, `DragEndResult`, `DragLifecycleHelpers`, `DragState`,
|
|
563
594
|
`DragOverlayPhase`, `SortableDropPlacement`, `RemeasureDropTargetsInput`,
|
|
564
|
-
`
|
|
565
|
-
targeting types, geometry types, and modifier
|
|
595
|
+
`OverlayReleaseMode`, `PointerConfiguration`, `KeyboardConfiguration`,
|
|
596
|
+
`KeyboardCommand`, `DropTarget`, targeting types, geometry types, and modifier
|
|
597
|
+
types.
|
|
566
598
|
|
|
567
599
|
## When To Use DOM Directly
|
|
568
600
|
|
|
@@ -577,7 +609,7 @@ Use `@mk-drag-and-drop/react` when:
|
|
|
577
609
|
|
|
578
610
|
- Your UI is rendered with React.
|
|
579
611
|
- You want ref-based hooks for registration.
|
|
580
|
-
- You want provider-based runtime
|
|
612
|
+
- You want provider-based runtime scoping and lifecycle integration.
|
|
581
613
|
|
|
582
614
|
## Development
|
|
583
615
|
|
package/dist/drag-context.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DragRuntimeScope } from "@mk-drag-and-drop/dom/integration";
|
|
2
2
|
export type DragContextValue = {
|
|
3
|
-
runtime:
|
|
3
|
+
runtime: DragRuntimeScope;
|
|
4
4
|
keyboardDragEnabled: boolean;
|
|
5
5
|
};
|
|
6
6
|
export declare const DragContext: import("react").Context<DragContextValue | null>;
|
package/dist/drag-overlay.d.ts
CHANGED
|
@@ -3,9 +3,13 @@ import type { DragRect } from "@mk-drag-and-drop/dom";
|
|
|
3
3
|
import type { DragOverlayPhase, DragState } from "@mk-drag-and-drop/dom/integration";
|
|
4
4
|
export type DragOverlayInput = {
|
|
5
5
|
dragState: DragState;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
} & ({
|
|
7
|
+
phase: Extract<DragOverlayPhase, "dragging">;
|
|
8
|
+
removeOverlay?: never;
|
|
9
|
+
} | {
|
|
10
|
+
phase: Extract<DragOverlayPhase, "released">;
|
|
11
|
+
removeOverlay: () => void;
|
|
12
|
+
});
|
|
9
13
|
export type DragOverlayHostHandle = {
|
|
10
14
|
move: (dragState: DragState) => void;
|
|
11
15
|
};
|
package/dist/drag-provider.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import { type DragEndEvent, type DragLifecycleCallbacks, type DragModifierInput, type DragStartEvent, type DragUpdateEvent, type DropEvent, type KeyboardConfiguration, type PointerConfiguration, type TargetingAlgorithm, type TargetingConstraint } from "@mk-drag-and-drop/dom";
|
|
2
|
+
import { type DragEndEvent, type DragLifecycleCallbacks, type DragModifierInput, type DragStartEvent, type DragUpdateEvent, type DropEvent, type KeyboardConfiguration, type OverlayReleaseMode, type PointerConfiguration, type TargetingAlgorithm, type TargetingConstraint } from "@mk-drag-and-drop/dom";
|
|
3
3
|
import { type DragOverlayInput } from "./drag-overlay.js";
|
|
4
4
|
export type DragAnnouncements = {
|
|
5
5
|
onDragStart?: (event: DragStartEvent) => string | null;
|
|
@@ -12,10 +12,10 @@ export type DragProviderProps = {
|
|
|
12
12
|
announcements?: DragAnnouncements;
|
|
13
13
|
dragOverlay?: (overlay: DragOverlayInput) => ReactNode;
|
|
14
14
|
keyboardConfiguration?: KeyboardConfiguration;
|
|
15
|
-
keepOverlayOnDrop?: boolean;
|
|
16
15
|
modifiers?: readonly DragModifierInput[];
|
|
16
|
+
overlayRelease?: OverlayReleaseMode;
|
|
17
17
|
pointerConfiguration?: PointerConfiguration;
|
|
18
18
|
targetingAlgorithm?: TargetingAlgorithm;
|
|
19
19
|
targetingConstraint?: TargetingConstraint;
|
|
20
20
|
} & DragLifecycleCallbacks;
|
|
21
|
-
export declare function DragProvider({ children, announcements, dragOverlay, keyboardConfiguration,
|
|
21
|
+
export declare function DragProvider({ children, announcements, dragOverlay, keyboardConfiguration, modifiers, overlayRelease, pointerConfiguration, targetingAlgorithm, targetingConstraint, onDragStart, onDragUpdate, onDragEnd, onDrop, }: DragProviderProps): import("react").JSX.Element;
|
package/dist/drag-provider.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
3
3
|
import { pointerToCenter, } from "@mk-drag-and-drop/dom";
|
|
4
|
-
import {
|
|
4
|
+
import { createDragRuntimeScope, } from "@mk-drag-and-drop/dom/integration";
|
|
5
5
|
import { DragContext } from "./drag-context.js";
|
|
6
6
|
import { DragOverlayHost, } from "./drag-overlay.js";
|
|
7
7
|
const visuallyHiddenStyle = {
|
|
@@ -15,7 +15,7 @@ const visuallyHiddenStyle = {
|
|
|
15
15
|
whiteSpace: "nowrap",
|
|
16
16
|
border: 0,
|
|
17
17
|
};
|
|
18
|
-
export function DragProvider({ children, announcements, dragOverlay, keyboardConfiguration,
|
|
18
|
+
export function DragProvider({ children, announcements, dragOverlay, keyboardConfiguration, modifiers, overlayRelease = "auto", pointerConfiguration, targetingAlgorithm = pointerToCenter, targetingConstraint, onDragStart, onDragUpdate, onDragEnd, onDrop, }) {
|
|
19
19
|
const [overlayRequest, setOverlayRequest] = useState(null);
|
|
20
20
|
const [announcementState, setAnnouncementState] = useState({
|
|
21
21
|
id: 0,
|
|
@@ -38,7 +38,7 @@ export function DragProvider({ children, announcements, dragOverlay, keyboardCon
|
|
|
38
38
|
const lifecycleCallbacksRef = useRef(null);
|
|
39
39
|
const runtimeConfigurationSnapshotRef = useRef(null);
|
|
40
40
|
const keyboardDragEnabled = isKeyboardDragEnabledFromConfiguration(keyboardConfiguration);
|
|
41
|
-
const
|
|
41
|
+
const clearOverlayHost = useCallback(() => {
|
|
42
42
|
pendingOverlayDragStateRef.current = null;
|
|
43
43
|
overlayHostRef.current = null;
|
|
44
44
|
overlaySnapshotRef.current = null;
|
|
@@ -72,7 +72,7 @@ export function DragProvider({ children, announcements, dragOverlay, keyboardCon
|
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
if (runtimeRef.current === null) {
|
|
75
|
-
runtimeRef.current =
|
|
75
|
+
runtimeRef.current = createDragRuntimeScope({
|
|
76
76
|
updateOverlayHost: handleOverlayHostUpdate,
|
|
77
77
|
});
|
|
78
78
|
}
|
|
@@ -81,11 +81,16 @@ export function DragProvider({ children, announcements, dragOverlay, keyboardCon
|
|
|
81
81
|
runtime,
|
|
82
82
|
keyboardDragEnabled,
|
|
83
83
|
}), [keyboardDragEnabled, runtime]);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
return () => {
|
|
86
|
+
runtime.releaseActiveDragResources();
|
|
87
|
+
};
|
|
88
|
+
}, [runtime]);
|
|
84
89
|
const nextRuntimeConfiguration = {
|
|
85
90
|
targetingAlgorithm,
|
|
86
91
|
targetingConstraint,
|
|
87
92
|
hasDragOverlay: dragOverlay !== undefined,
|
|
88
|
-
|
|
93
|
+
overlayRelease,
|
|
89
94
|
lifecycleCallbacks: lifecycleCallbacksRef.current,
|
|
90
95
|
keyboardConfiguration,
|
|
91
96
|
modifiers,
|
|
@@ -109,16 +114,11 @@ export function DragProvider({ children, announcements, dragOverlay, keyboardCon
|
|
|
109
114
|
runtimeConfigurationSnapshotRef.current =
|
|
110
115
|
createRuntimeConfigurationSnapshot(nextRuntimeConfiguration);
|
|
111
116
|
});
|
|
112
|
-
useEffect(() => {
|
|
113
|
-
return () => {
|
|
114
|
-
runtime.dispose();
|
|
115
|
-
};
|
|
116
|
-
}, [runtime]);
|
|
117
117
|
useEffect(() => {
|
|
118
118
|
if (!dragOverlay) {
|
|
119
|
-
|
|
119
|
+
clearOverlayHost();
|
|
120
120
|
}
|
|
121
|
-
}, [dragOverlay,
|
|
121
|
+
}, [dragOverlay, clearOverlayHost]);
|
|
122
122
|
useEffect(() => {
|
|
123
123
|
if (!announcements) {
|
|
124
124
|
lastAnnouncementRef.current = null;
|
|
@@ -154,13 +154,13 @@ export function DragProvider({ children, announcements, dragOverlay, keyboardCon
|
|
|
154
154
|
moveOverlay(update.dragState);
|
|
155
155
|
return;
|
|
156
156
|
}
|
|
157
|
-
|
|
157
|
+
clearOverlayHost();
|
|
158
158
|
}
|
|
159
159
|
function mountOverlay(state) {
|
|
160
160
|
pendingOverlayDragStateRef.current = state.dragState;
|
|
161
161
|
overlayHostRef.current?.move(state.dragState);
|
|
162
162
|
if (!dragOverlayRef.current) {
|
|
163
|
-
|
|
163
|
+
clearOverlayHost();
|
|
164
164
|
return;
|
|
165
165
|
}
|
|
166
166
|
overlayContentIdRef.current += 1;
|
|
@@ -184,21 +184,30 @@ export function DragProvider({ children, announcements, dragOverlay, keyboardCon
|
|
|
184
184
|
overlaySnapshotRef.current = {
|
|
185
185
|
id: overlayRequest.id,
|
|
186
186
|
state: overlayRequest.state,
|
|
187
|
-
content: dragOverlay(
|
|
188
|
-
dragState: overlayRequest.state.dragState,
|
|
189
|
-
phase: overlayRequest.state.phase,
|
|
190
|
-
finish: finishOverlay,
|
|
191
|
-
}),
|
|
187
|
+
content: dragOverlay(createOverlayInput(overlayRequest.state)),
|
|
192
188
|
};
|
|
193
189
|
return overlaySnapshotRef.current;
|
|
194
190
|
}
|
|
191
|
+
function createOverlayInput(overlayState) {
|
|
192
|
+
if (overlayState.phase === "released") {
|
|
193
|
+
return {
|
|
194
|
+
dragState: overlayState.dragState,
|
|
195
|
+
phase: "released",
|
|
196
|
+
removeOverlay: clearOverlayHost,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return {
|
|
200
|
+
dragState: overlayState.dragState,
|
|
201
|
+
phase: "dragging",
|
|
202
|
+
};
|
|
203
|
+
}
|
|
195
204
|
}
|
|
196
205
|
function createRuntimeConfigurationSnapshot(input) {
|
|
197
206
|
return {
|
|
198
207
|
targetingAlgorithm: input.targetingAlgorithm,
|
|
199
208
|
targetingConstraint: input.targetingConstraint,
|
|
200
209
|
hasDragOverlay: input.hasDragOverlay,
|
|
201
|
-
|
|
210
|
+
overlayRelease: input.overlayRelease,
|
|
202
211
|
keyboardConfiguration: cloneKeyboardConfiguration(input.keyboardConfiguration),
|
|
203
212
|
modifiers: input.modifiers ? Array.from(input.modifiers) : undefined,
|
|
204
213
|
pointerConfiguration: input.pointerConfiguration
|
|
@@ -211,7 +220,7 @@ function areRuntimeConfigurationSnapshotsEqual(previous, next) {
|
|
|
211
220
|
previous.targetingAlgorithm === next.targetingAlgorithm &&
|
|
212
221
|
previous.targetingConstraint === next.targetingConstraint &&
|
|
213
222
|
previous.hasDragOverlay === next.hasDragOverlay &&
|
|
214
|
-
previous.
|
|
223
|
+
previous.overlayRelease === next.overlayRelease &&
|
|
215
224
|
areKeyboardConfigurationsEqual(previous.keyboardConfiguration, next.keyboardConfiguration) &&
|
|
216
225
|
arePointerConfigurationsEqual(previous.pointerConfiguration, next.pointerConfiguration) &&
|
|
217
226
|
areModifierInputsEqual(previous.modifiers, next.modifiers));
|
|
@@ -19,7 +19,7 @@ export function useDropContainer({ containerId, group = defaultDropContainerGrou
|
|
|
19
19
|
existingBehavior.group === group) {
|
|
20
20
|
return existingBehavior.behavior;
|
|
21
21
|
}
|
|
22
|
-
existingBehavior?.behavior.
|
|
22
|
+
existingBehavior?.behavior.releaseRegistration();
|
|
23
23
|
const behavior = createDomDropContainer({
|
|
24
24
|
runtime,
|
|
25
25
|
containerId,
|
|
@@ -44,7 +44,7 @@ export function useDropContainer({ containerId, group = defaultDropContainerGrou
|
|
|
44
44
|
behavior.setElement(nodeRef.current);
|
|
45
45
|
}
|
|
46
46
|
return () => {
|
|
47
|
-
behavior.
|
|
47
|
+
behavior.releaseRegistration();
|
|
48
48
|
if (behaviorRef.current?.behavior === behavior) {
|
|
49
49
|
behaviorRef.current = null;
|
|
50
50
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { useCallback, useContext, useMemo, } from "react";
|
|
1
|
+
import { useCallback, useContext, useEffect, useMemo, useRef, } from "react";
|
|
2
2
|
import { createDomDroppable } from "@mk-drag-and-drop/dom/integration";
|
|
3
3
|
import { DragContext } from "../drag-context.js";
|
|
4
4
|
const defaultDroppableGroup = "default";
|
|
5
5
|
export function useDroppable({ dropTargetId, group = defaultDroppableGroup, containerId = null, }) {
|
|
6
6
|
const context = useContext(DragContext);
|
|
7
|
+
const nodeRef = useRef(null);
|
|
7
8
|
if (!context) {
|
|
8
9
|
throw new Error("useDroppable must be used inside DragProvider");
|
|
9
10
|
}
|
|
@@ -15,8 +16,17 @@ export function useDroppable({ dropTargetId, group = defaultDroppableGroup, cont
|
|
|
15
16
|
containerId,
|
|
16
17
|
}), [containerId, dropTargetId, group, runtime]);
|
|
17
18
|
const setNodeRef = useCallback((node) => {
|
|
19
|
+
nodeRef.current = node;
|
|
18
20
|
behavior.setElement(node);
|
|
19
21
|
}, [behavior]);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (nodeRef.current) {
|
|
24
|
+
behavior.setElement(nodeRef.current);
|
|
25
|
+
}
|
|
26
|
+
return () => {
|
|
27
|
+
behavior.releaseRegistration();
|
|
28
|
+
};
|
|
29
|
+
}, [behavior]);
|
|
20
30
|
return useMemo(() => ({
|
|
21
31
|
ref: setNodeRef,
|
|
22
32
|
}), [setNodeRef]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useContext, useMemo, useRef, } from "react";
|
|
1
|
+
import { useCallback, useContext, useEffect, useMemo, useRef, } from "react";
|
|
2
2
|
import { createDomSortable, } from "@mk-drag-and-drop/dom/integration";
|
|
3
3
|
import { DragContext } from "../drag-context.js";
|
|
4
4
|
const defaultSortableGroup = "default";
|
|
@@ -33,6 +33,14 @@ export function useSortable({ draggableId, group = defaultSortableGroup, contain
|
|
|
33
33
|
nodeRef.current = node;
|
|
34
34
|
behavior.setElement(node);
|
|
35
35
|
}, [behavior]);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (nodeRef.current) {
|
|
38
|
+
behavior.setElement(nodeRef.current);
|
|
39
|
+
}
|
|
40
|
+
return () => {
|
|
41
|
+
behavior.releaseRegistration();
|
|
42
|
+
};
|
|
43
|
+
}, [behavior]);
|
|
36
44
|
return useMemo(() => {
|
|
37
45
|
const sortableProps = {
|
|
38
46
|
ref: setNodeRef,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { DragProvider, type DragAnnouncements, type DragProviderProps, } from "./drag-provider.js";
|
|
2
2
|
export type { DragOverlayInput } from "./drag-overlay.js";
|
|
3
|
-
export { centerToCenter, getDistanceToRect, lockToXAxis, lockToYAxis, maxOverlayCenterDistanceToRect, maxPointerDistanceToRect, pointerToCenter, pointerToRectDistance, type DragEndResult, type DragEndEvent, type DragLifecycleCallbacks, type DragLifecycleHelpers, type DragModifier, type DragModifierInput, type DragModifierSetupInput, type DragModifierTransformInput, type DragPoint, type DragRect, type DragSource, type DragStartEvent, type DragUpdateEvent, type DropEvent, type DropTarget, type KeyboardCommand, type KeyboardConfiguration, type PointerConfiguration, type RemeasureDropTargetsInput, type SortableAxis, type SortableDropPlacement, type SortablePlacementBoundary, type TargetingAlgorithm, type TargetingAlgorithmInput, type TargetingConstraint, type TargetingConstraintInput, } from "@mk-drag-and-drop/dom";
|
|
3
|
+
export { centerToCenter, getDistanceToRect, lockToXAxis, lockToYAxis, maxOverlayCenterDistanceToRect, maxPointerDistanceToRect, pointerToCenter, pointerToRectDistance, type DragEndResult, type DragEndEvent, type DragLifecycleCallbacks, type DragLifecycleHelpers, type DragModifier, type DragModifierInput, type DragModifierSetupInput, type DragModifierTransformInput, type DragPoint, type DragRect, type DragSource, type DragStartEvent, type DragUpdateEvent, type DropEvent, type DropTarget, type KeyboardCommand, type KeyboardConfiguration, type OverlayReleaseMode, type PointerConfiguration, type RemeasureDropTargetsInput, type SortableAxis, type SortableDropPlacement, type SortablePlacementBoundary, type TargetingAlgorithm, type TargetingAlgorithmInput, type TargetingConstraint, type TargetingConstraintInput, } from "@mk-drag-and-drop/dom";
|
|
4
4
|
export { restrictToContainer, type ReactRestrictToContainerInput, } from "./modifiers/restrict-to-container.js";
|
|
5
5
|
export type { DragOverlayPhase, DragState, } from "@mk-drag-and-drop/dom/integration";
|
|
6
6
|
export { useDragHandle, type UseDragHandleResult, } from "./hooks/use-drag-handle.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mk-drag-and-drop/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
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",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"dist"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@mk-drag-and-drop/dom": "0.
|
|
41
|
+
"@mk-drag-and-drop/dom": "0.2.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"react": "^19.0.0"
|