@mk-drag-and-drop/react 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matthias Kramer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,594 @@
1
+ # @mk-drag-and-drop/react
2
+
3
+ ## What It Is
4
+
5
+ `@mk-drag-and-drop/react` is the React adapter for the DOM-first
6
+ `@mk-drag-and-drop/dom` drag-and-drop runtime. It provides React hooks and a
7
+ provider for wiring rendered DOM nodes into the shared runtime.
8
+
9
+ The package is headless. It is not a component library, and it does not own your
10
+ markup, styling, data model, rendering strategy, or persistence. It provides
11
+ behavior, registration, targeting, lifecycle information, overlays, modifiers,
12
+ and placement data. Your app decides what the UI looks like and how a completed
13
+ drop changes application data.
14
+
15
+ The React package supports draggable items, droppable targets, sortable
16
+ lists and boards, drag handles, drop containers, drag overlays, modifiers,
17
+ targeting configuration, keyboard and pointer configuration, lifecycle
18
+ callbacks, and optional announcements.
19
+
20
+ ## Relationship To The DOM Package
21
+
22
+ The React package wraps `@mk-drag-and-drop/dom`.
23
+
24
+ `DragProvider` creates and configures the DOM runtime through the package
25
+ integration handle.
26
+ Hooks such as `useDraggable`, `useDroppable`, `useSortable`, and
27
+ `useDropContainer` register DOM nodes with that runtime through React refs.
28
+ React hooks are adapters over DOM behavior, not a separate implementation.
29
+
30
+ Consumers should import React APIs from the package root,
31
+ `@mk-drag-and-drop/react`. The React package does not expose public subpath
32
+ exports. It uses `@mk-drag-and-drop/dom/integration` internally for lower-level
33
+ DOM behavior wiring.
34
+
35
+ Deep imports into package `src` or `dist` files are not part of the public
36
+ package exports.
37
+
38
+ The vanilla and React examples use the same underlying behavior. React users can
39
+ use the React package for provider and ref integration. Users who are not
40
+ rendering with React, or who are building another framework adapter, can use
41
+ `@mk-drag-and-drop/dom` directly.
42
+
43
+ ## Public Root API
44
+
45
+ The React root export includes:
46
+
47
+ - `DragProvider`, `DragProviderProps`, `DragAnnouncements`
48
+ - `DragOverlayInput`
49
+ - `useDraggable`, `UseDraggableOptions`, `UseDraggableResult`
50
+ - `useDroppable`, `UseDroppableOptions`, `UseDroppableResult`
51
+ - `useDropContainer`, `UseDropContainerOptions`, `UseDropContainerResult`
52
+ - `useSortable`, `UseSortableOptions`, `UseSortableResult`
53
+ - `useDragHandle`, `UseDragHandleResult`
54
+ - `useRemeasureDropTargets`
55
+ - `composeRefs`
56
+ - React-friendly `restrictToContainer`, `ReactRestrictToContainerInput`
57
+ - DOM targeting helpers, modifier helpers, lifecycle/source/result types,
58
+ sortable placement types, keyboard/pointer configuration types, and geometry
59
+ types re-exported from the DOM package
60
+ - `DragState` and `DragOverlayPhase` from the DOM integration layer
61
+
62
+ ## Core Mental Model
63
+
64
+ 1. Wrap the interactive area in `DragProvider`.
65
+ 2. Register drag sources with `useDraggable` or `useSortable`.
66
+ 3. Register drop targets with `useDroppable` or `useDropContainer`.
67
+ 4. Optionally attach `useDragHandle` to a handle element.
68
+ 5. Use lifecycle callbacks, especially `onDrop`, to update app data.
69
+ 6. Render the result however your app wants.
70
+
71
+ The package reports drag/drop operations. Your app owns the data and the final
72
+ UI commit. React state is one common way to commit the result, but it is not
73
+ required by the package.
74
+
75
+ ## Installation
76
+
77
+ This workspace currently marks `@mk-drag-and-drop/react` as private. Install the
78
+ React and DOM packages from your workspace or package registry when they are
79
+ available:
80
+
81
+ - `@mk-drag-and-drop/react`
82
+ - `@mk-drag-and-drop/dom`
83
+
84
+ `react` is a peer dependency of the React package.
85
+
86
+ ## Quick Start
87
+
88
+ ```tsx
89
+ import { useState, type ReactNode } from "react";
90
+ import {
91
+ DragProvider,
92
+ useDragHandle,
93
+ useDraggable,
94
+ useDroppable,
95
+ } from "@mk-drag-and-drop/react";
96
+
97
+ type Location = "left" | "right";
98
+
99
+ export function Example() {
100
+ const [location, setLocation] = useState<Location>("left");
101
+
102
+ return (
103
+ <DragProvider
104
+ onDrop={({ draggableId, dropTargetId }) => {
105
+ if (
106
+ draggableId === "card" &&
107
+ (dropTargetId === "left" || dropTargetId === "right")
108
+ ) {
109
+ setLocation(dropTargetId);
110
+ }
111
+ }}
112
+ >
113
+ <div>
114
+ <DropZone dropTargetId="left">
115
+ {location === "left" ? <Card /> : null}
116
+ </DropZone>
117
+ <DropZone dropTargetId="right">
118
+ {location === "right" ? <Card /> : null}
119
+ </DropZone>
120
+ </div>
121
+ </DragProvider>
122
+ );
123
+ }
124
+
125
+ function Card() {
126
+ const draggable = useDraggable({ draggableId: "card", group: "demo" });
127
+ const dragHandle = useDragHandle<HTMLButtonElement>();
128
+
129
+ return (
130
+ <div {...draggable}>
131
+ <button {...dragHandle} type="button" aria-label="Drag card">
132
+ Drag
133
+ </button>
134
+ <span>Card</span>
135
+ </div>
136
+ );
137
+ }
138
+
139
+ function DropZone({
140
+ dropTargetId,
141
+ children,
142
+ }: {
143
+ dropTargetId: Location;
144
+ children: ReactNode;
145
+ }) {
146
+ const droppable = useDroppable({ dropTargetId, group: "demo" });
147
+
148
+ return <div {...droppable}>{children}</div>;
149
+ }
150
+ ```
151
+
152
+ Real apps own the markup, layout, styling, state updates, and persistence.
153
+
154
+ ## DragProvider
155
+
156
+ `DragProvider` owns the runtime lifetime for the React subtree. It creates the
157
+ DOM runtime, configures it from props, exposes it through React context, renders
158
+ an optional drag overlay, and disposes the runtime when the provider unmounts.
159
+
160
+ Key props:
161
+
162
+ - `onDragStart(event, helpers)`: called when a drag starts.
163
+ - `onDragUpdate(event, helpers)`: called for drag updates.
164
+ - `onDragEnd(event, helpers)`: called when dragging ends, with or without a
165
+ valid drop.
166
+ - `onDrop(event, helpers)`: called when an item is dropped on a valid target.
167
+ - `dragOverlay(input)`: creates the visual overlay for the active drag.
168
+ - `targetingAlgorithm`: chooses one target from the measured targets.
169
+ - `targetingConstraint`: filters measured targets before targeting runs.
170
+ - `modifiers`: transforms pointer movement, such as axis locking or bounds.
171
+ - `pointerConfiguration`: configures pointer activation delay and distance.
172
+ - `keyboardConfiguration`: enables and configures keyboard drag commands.
173
+ - `announcements`: optional callbacks that return live-region messages.
174
+ - `keepOverlayOnDrop`: keeps the overlay in the released phase until the overlay
175
+ calls `finish`.
176
+
177
+ Callbacks receive operation information and helper methods from the runtime.
178
+ Use those callbacks to commit app data. Do not mutate package internals.
179
+
180
+ ## Lifecycle Events
181
+
182
+ `DragProvider` lifecycle callbacks and `announcements` callbacks receive these
183
+ event shapes:
184
+
185
+ ```ts
186
+ type DragSource = "pointer" | "keyboard";
187
+
188
+ type DragEndResult =
189
+ | "dropped"
190
+ | "no-target"
191
+ | "invalid-target"
192
+ | "canceled";
193
+
194
+ type DragStartEvent = {
195
+ draggableId: string;
196
+ source: DragSource;
197
+ pointerPosition: DragPoint;
198
+ sourceRect: DragRect;
199
+ };
200
+
201
+ type DragUpdateEvent = {
202
+ draggableId: string;
203
+ source: DragSource;
204
+ pointerPosition: DragPoint;
205
+ activeDropTargetId: string | null;
206
+ previousDropTargetId: string | null;
207
+ };
208
+
209
+ type DragEndEvent = {
210
+ draggableId: string;
211
+ source: DragSource;
212
+ result: DragEndResult;
213
+ dropTargetId: string | null;
214
+ };
215
+
216
+ type DropEvent = {
217
+ draggableId: string;
218
+ source: DragSource;
219
+ dropTargetId: string;
220
+ sortablePlacement?: SortableDropPlacement;
221
+ };
222
+ ```
223
+
224
+ `onDrop` only runs for a valid successful drop. `onDragEnd.result` distinguishes
225
+ successful drops, normal releases with no target, stale/invalid targets, and
226
+ cancellations such as Escape or pointercancel. Plain drops are id-only.
227
+ Sortable drops may include `event.sortablePlacement`; apps still own the data
228
+ commit.
229
+
230
+ ## Hooks
231
+
232
+ Hook result types are generic over the host element type and default to
233
+ `HTMLElement`. Specify a narrower element type when you want element-specific
234
+ ref and attribute typing; the hooks are not limited to `div` elements.
235
+
236
+ ### useDraggable
237
+
238
+ `useDraggable` registers an item as a drag source.
239
+
240
+ ```tsx
241
+ const draggable = useDraggable({
242
+ draggableId: "card-1",
243
+ group: "cards",
244
+ });
245
+
246
+ return <div {...draggable}>Card</div>;
247
+ ```
248
+
249
+ Options:
250
+
251
+ - `draggableId`: stable string identifier for the dragged item.
252
+ - `group`: optional drag group. Defaults to `"default"`.
253
+
254
+ Return shape:
255
+
256
+ - `ref`: attaches the rendered element to the runtime.
257
+ - `onPointerDown`: starts pointer activation when allowed.
258
+ - `tabIndex` and `onKeyDown`: included when keyboard dragging is enabled.
259
+
260
+ Use `useDragHandle` when dragging should start only from a specific handle.
261
+
262
+ ### useDroppable
263
+
264
+ `useDroppable` registers a DOM node as a valid drop target.
265
+
266
+ ```tsx
267
+ const droppable = useDroppable({
268
+ dropTargetId: "archive",
269
+ group: "cards",
270
+ });
271
+
272
+ return <div {...droppable} />;
273
+ ```
274
+
275
+ Options:
276
+
277
+ - `dropTargetId`: stable string identifier for the target.
278
+ - `group`: optional drag group. Only items in the same group target it.
279
+ - `containerId`: optional container identity for placement-aware behavior.
280
+
281
+ Use droppable targets for custom drop zones, tree rows, grouped rows, insertion
282
+ lines, and other app-defined target geometry.
283
+
284
+ ### useSortable
285
+
286
+ `useSortable` combines draggable behavior and drop-target behavior for sortable
287
+ items.
288
+
289
+ ```tsx
290
+ const sortable = useSortable<HTMLArticleElement>({
291
+ draggableId: item.id,
292
+ group: "cards",
293
+ containerId: column.id,
294
+ });
295
+
296
+ return <article {...sortable}>{item.title}</article>;
297
+ ```
298
+
299
+ Options:
300
+
301
+ - `draggableId`: stable string identifier for the sortable item.
302
+ - `group`: optional drag group. Defaults to `"default"`.
303
+ - `containerId`: optional container identity for lists, boards, and columns.
304
+
305
+ Return shape:
306
+
307
+ - `ref`: attaches and registers the sortable element.
308
+ - `onPointerDown`: starts pointer activation when allowed.
309
+ - `tabIndex` and `onKeyDown`: included when keyboard dragging is enabled.
310
+
311
+ During drag, the runtime may temporarily move sortable DOM nodes to preview
312
+ placement. That preview is transient. It does not commit application order.
313
+ On drop, read `event.sortablePlacement` and update your own data. Plain
314
+ droppable drops do not include sortable placement.
315
+
316
+ ### useDropContainer
317
+
318
+ `useDropContainer` registers a container for placement-aware sortable/drop
319
+ behavior.
320
+
321
+ ```tsx
322
+ const container = useDropContainer({
323
+ containerId: "backlog",
324
+ group: "cards",
325
+ });
326
+
327
+ return <div {...container}>{cards}</div>;
328
+ ```
329
+
330
+ Use drop containers for boards, multiple lists, columns, and empty containers
331
+ that should accept items. A container does not imply orientation by itself.
332
+ Sortable placement is determined from the registered items' layout and the
333
+ targeting behavior.
334
+
335
+ ### useDragHandle
336
+
337
+ `useDragHandle` marks an element as the drag handle for the nearest draggable or
338
+ sortable element.
339
+
340
+ ```tsx
341
+ const handle = useDragHandle<HTMLButtonElement>();
342
+
343
+ return (
344
+ <button {...handle} type="button" aria-label="Drag item">
345
+ Drag
346
+ </button>
347
+ );
348
+ ```
349
+
350
+ When a draggable contains a handle, pointer dragging starts from the handle.
351
+ This helps keep other interactive children usable.
352
+
353
+ ### useRemeasureDropTargets
354
+
355
+ `useRemeasureDropTargets` returns a function for explicitly remeasuring targets
356
+ after layout changes during a drag.
357
+
358
+ ```tsx
359
+ const remeasureDropTargets = useRemeasureDropTargets();
360
+
361
+ requestAnimationFrame(() => {
362
+ remeasureDropTargets({ group: "tree" });
363
+ });
364
+ ```
365
+
366
+ It accepts no argument, a target id, an array of target ids, or `{ group }`.
367
+ Use it intentionally for expand/collapse, grouped trees, or drag-state layout
368
+ changes. It is not needed for normal cleanup and should not run on every render.
369
+ Sortable preview movement does not automatically remeasure a group; call this
370
+ function when an app-owned layout change needs to affect targeting.
371
+
372
+ ## Sortable Behavior
373
+
374
+ Sortable preview is transient. The runtime may move DOM temporarily to show
375
+ where an item would land, then restore or clear that preview as the drag ends.
376
+ Preview movement does not trigger full target remeasurement. The app still
377
+ commits data on drop, using placement derived from the current preview DOM
378
+ order. React rendering should then reflect the final data.
379
+
380
+ Examples may rerender a full list for simplicity, but granular state management,
381
+ external stores, server commits, and imperative rendering strategies are
382
+ compatible. The package does not require React state.
383
+
384
+ ```tsx
385
+ <DragProvider
386
+ onDrop={({ draggableId, sortablePlacement }) => {
387
+ const placement = sortablePlacement;
388
+
389
+ if (!placement) {
390
+ return;
391
+ }
392
+
393
+ setItems((items) => reorderData(items, draggableId, placement));
394
+ }}
395
+ >
396
+ {/* sortable items */}
397
+ </DragProvider>
398
+ ```
399
+
400
+ `reorderData` is app code. It should translate `draggableId`,
401
+ `placement.containerId`, `placement.targetDraggableId`, `placement.side`,
402
+ `placement.previousDraggableId`, and `placement.nextDraggableId` into your data
403
+ shape.
404
+
405
+ ## Drag Overlays
406
+
407
+ `dragOverlay` creates a visual representation during drag.
408
+
409
+ ```tsx
410
+ <DragProvider
411
+ dragOverlay={({ dragState }) => (
412
+ <div className="dragOverlay">{dragState.draggableId}</div>
413
+ )}
414
+ >
415
+ {children}
416
+ </DragProvider>
417
+ ```
418
+
419
+ The overlay input includes:
420
+
421
+ - `dragState`: item id, group, source rect, start pointer, and current pointer.
422
+ - `phase`: `"dragging"` or `"released"`.
423
+ - `finish`: call this when a kept release overlay should be removed.
424
+
425
+ Overlay rendering is app-owned. `DragProvider` mounts overlay content for the
426
+ dragging phase and, when `keepOverlayOnDrop` is enabled, replaces it once for
427
+ the released phase. Pointer movement updates the package-owned overlay host
428
+ imperatively and does not call `dragOverlay` by default.
429
+
430
+ The package owns overlay hosting, movement, cleanup, and measurement for
431
+ targeting and modifiers. It measures overlay content on mount/replacement and
432
+ uses `ResizeObserver` when available to remeasure content size changes. Dynamic
433
+ overlay content should use overlay-local state, component effects, lifecycle
434
+ callbacks feeding a subscription/external store, or another app-owned update
435
+ path rather than relying on `dragOverlay` being called for every pointer move.
436
+
437
+ ## Targeting And Modifiers
438
+
439
+ Targeting algorithms choose among measured drop targets. Targeting constraints
440
+ filter targets before an algorithm runs. Modifiers transform movement during a
441
+ drag.
442
+
443
+ Custom targeting algorithms receive `pointerPosition`, `overlayRect`, and
444
+ measured targets. Constraints receive `pointerPosition`, `overlayRect`, and one
445
+ candidate target. Algorithms and constraints choose their own geometry:
446
+ pointer helpers use the pointer position, while `centerToCenter` computes the
447
+ overlay center from `overlayRect`.
448
+
449
+ The React package re-exports targeting helpers such as `pointerToCenter`,
450
+ `centerToCenter`, `pointerToRectDistance`, `getDistanceToRect`, and
451
+ `maxPointerDistanceToRect` / `maxOverlayCenterDistanceToRect`, plus modifier
452
+ helpers. Sortable placement remains separate from targeting: the configured
453
+ targeting algorithm chooses the active target, and sortable only chooses
454
+ before/after placement relative to that target.
455
+
456
+ - `lockToXAxis()`
457
+ - `lockToYAxis()`
458
+ - `restrictToContainer(refOrResolver)`
459
+
460
+ `restrictToContainer` accepts either a React ref object or a resolver function.
461
+ Use the DOM package directly when you are building non-React integrations or
462
+ imperative DOM behavior.
463
+
464
+ ### Memoize Modifiers And Composed Refs
465
+
466
+ Modifier factories such as `restrictToContainer(...)` return modifier objects.
467
+ When passing modifiers to `DragProvider`, create the array with `useMemo` so the
468
+ runtime is not reconfigured with a new array every render.
469
+
470
+ `composeRefs(...)` returns a ref callback. When the composed ref is used on a
471
+ registered draggable, droppable, sortable, or drop container element, memoize it
472
+ with `useMemo` so React does not clear and reassign the ref on every render.
473
+
474
+ ```tsx
475
+ const modifiers = useMemo(
476
+ () => [restrictToContainer(containerRef)],
477
+ [],
478
+ );
479
+
480
+ const combinedRef = useMemo(
481
+ () => composeRefs(localRef, droppable.ref),
482
+ [droppable.ref],
483
+ );
484
+ ```
485
+
486
+ Custom targeting algorithms receive `pointerPosition`, `overlayRect`, and a
487
+ list of measured `dropTargets`. Each target has `dropTargetId` and
488
+ `dropTargetRect`. Custom constraints receive one candidate `dropTarget` and
489
+ return whether it should be eligible.
490
+
491
+ ## Accessibility
492
+
493
+ The runtime has keyboard dragging support through `keyboardConfiguration`.
494
+ When keyboard dragging is enabled, draggable and sortable hooks add keyboard
495
+ props to registered elements.
496
+
497
+ Accessibility still depends on the app's markup and product behavior:
498
+
499
+ - Prefer button or focusable drag handles with clear labels.
500
+ - Do not hijack editable controls or unrelated interactive children.
501
+ - Provide domain-specific instructions for what dragging does.
502
+ - Use `announcements` when you want the provider to render polite live-region
503
+ updates from lifecycle callbacks. `announcements.onDragUpdate` runs for
504
+ active-drop-target transitions and dedupes repeated messages to avoid
505
+ live-region spam and provider rerenders; use lifecycle `onDragUpdate` for
506
+ per-frame side effects.
507
+ - Do not assume this package alone provides complete screen-reader drag-and-drop
508
+ support for your domain.
509
+
510
+ ## Cleanup And Effects
511
+
512
+ Hooks attach input props and register DOM nodes through refs and lifecycle
513
+ effects. Users should not manually clean runtime entries for normal React
514
+ mount/unmount.
515
+
516
+ `DragProvider` owns runtime lifetime and disposes the runtime when it unmounts.
517
+ `useDropContainer` also cleans its DOM binding on effect cleanup.
518
+ `useDraggable`, `useDroppable`, and `useSortable` rely on React prop/ref updates
519
+ for normal mount, unmount, and element replacement behavior.
520
+
521
+ `useRemeasureDropTargets` is for layout changes, not cleanup. The runtime also
522
+ prunes disconnected targets on drag-critical paths such as remeasurement.
523
+
524
+ ## Examples
525
+
526
+ React examples live in `apps/react-web/src/react`:
527
+
528
+ - Basic drag: moves one item between two droppable containers with an overlay.
529
+ - Dropzone list: uses generated droppable insertion lines for list reordering.
530
+ - Sortable list: uses `useSortable` and commits order from sortable placement.
531
+ - Kanban: combines sortable columns, sortable cards, drop containers, overlays,
532
+ and a container modifier.
533
+ - Grouped drag and drop: mixes parent sorting, child dragging, custom targets,
534
+ expansion state, and explicit remeasurement.
535
+ - Tree: uses app-defined tree projection, generated targets, custom targeting,
536
+ and app-owned hierarchy updates.
537
+
538
+ ## API Reference
539
+
540
+ - `DragProvider`: creates/configures the DOM runtime for a React subtree.
541
+ Important props include lifecycle callbacks, overlay rendering, targeting,
542
+ constraints, modifiers, pointer/keyboard configuration, announcements, and
543
+ `keepOverlayOnDrop`.
544
+ - `useDraggable(options)`: registers a drag source. Important options:
545
+ `draggableId`, `group`. Returns ref and input props.
546
+ - `useDroppable(options)`: registers a drop target. Important options:
547
+ `dropTargetId`, `group`, `containerId`. Returns a ref prop.
548
+ - `useSortable(options)`: registers a sortable item as both source and target.
549
+ Important options: `draggableId`, `group`, `containerId`. Returns ref and input
550
+ props.
551
+ - `useDropContainer(options)`: registers a placement-aware container. Important
552
+ options: `containerId`, `group`. Returns a ref prop.
553
+ - `useDragHandle()`: returns the handle attribute props for a handle element.
554
+ - `useRemeasureDropTargets()`: returns a function for remeasuring all targets,
555
+ one target, multiple targets, or a group.
556
+ - `composeRefs`: helper for combining the refs returned by hooks with app refs.
557
+ - `lockToXAxis`, `lockToYAxis`: DOM movement modifiers re-exported by React.
558
+ - `restrictToContainer`: React-friendly container-bound modifier.
559
+
560
+ Important event/helper types are re-exported from the React package, including
561
+ `DragStartEvent`, `DragUpdateEvent`, `DragEndEvent`, `DropEvent`,
562
+ `DragSource`, `DragEndResult`, `DragLifecycleHelpers`, `DragState`,
563
+ `DragOverlayPhase`, `SortableDropPlacement`, `RemeasureDropTargetsInput`,
564
+ `PointerConfiguration`, `KeyboardConfiguration`, `KeyboardCommand`, `DropTarget`,
565
+ targeting types, geometry types, and modifier types.
566
+
567
+ ## When To Use DOM Directly
568
+
569
+ Use `@mk-drag-and-drop/dom` directly when:
570
+
571
+ - You are not using React.
572
+ - You are integrating with another rendering framework.
573
+ - You are managing DOM imperatively.
574
+ - You are building a lower-level adapter.
575
+
576
+ Use `@mk-drag-and-drop/react` when:
577
+
578
+ - Your UI is rendered with React.
579
+ - You want ref-based hooks for registration.
580
+ - You want provider-based runtime lifetime and lifecycle integration.
581
+
582
+ ## Development
583
+
584
+ Package scripts in this workspace:
585
+
586
+ ```bash
587
+ pnpm --filter @mk-drag-and-drop/react... build
588
+ pnpm --filter @mk-drag-and-drop/react lint
589
+ pnpm --filter @mk-drag-and-drop/react test
590
+ pnpm --filter react-web build
591
+ ```
592
+
593
+ The React example app also has `dev` and `preview` scripts, but they start local
594
+ Vite processes and are not required for package verification.
@@ -0,0 +1,6 @@
1
+ import type { DragRuntimeHandle } from "@mk-drag-and-drop/dom/integration";
2
+ export type DragContextValue = {
3
+ runtime: DragRuntimeHandle;
4
+ keyboardDragEnabled: boolean;
5
+ };
6
+ export declare const DragContext: import("react").Context<DragContextValue | null>;
@@ -0,0 +1,2 @@
1
+ import { createContext } from "react";
2
+ export const DragContext = createContext(null);
@@ -0,0 +1,18 @@
1
+ import { type ReactNode } from "react";
2
+ import type { DragRect } from "@mk-drag-and-drop/dom";
3
+ import type { DragOverlayPhase, DragState } from "@mk-drag-and-drop/dom/integration";
4
+ export type DragOverlayInput = {
5
+ dragState: DragState;
6
+ phase: DragOverlayPhase;
7
+ finish: () => void;
8
+ };
9
+ export type DragOverlayHostHandle = {
10
+ move: (dragState: DragState) => void;
11
+ };
12
+ export declare const DragOverlayHost: import("react").NamedExoticComponent<{
13
+ dragState: DragState;
14
+ children: ReactNode;
15
+ contentId: number;
16
+ onHostReady?: (host: DragOverlayHostHandle | null) => void;
17
+ onOverlayRectChange?: (overlayRect: DragRect | null) => void;
18
+ }>;