@snapgridjs/dnd 0.4.0 → 0.6.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 +1 -0
- package/dist/index.cjs +58 -6
- package/dist/index.d.cts +67 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +67 -6
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +60 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ One per-manager engine, plus the pieces a binding wires up:
|
|
|
23
23
|
- **`GridController`** — the observable per-grid render bridge. A binding writes per-grid config into it and subscribes to the rendered layout / per-tile snapshots (e.g. via `useSyncExternalStore`).
|
|
24
24
|
- **`registerController` / `getController`** — resolve a grid's controller by id, scoped to a manager.
|
|
25
25
|
- **Interaction helpers** — `gridCollisionDetector`, `SnapToGrid`, `buildItemSensors`, `domElement`, and the pure `dragFlow` decision functions (`classifyDrop`, `receiveCell`, …).
|
|
26
|
+
- **`snapMove(layout, event, ctx)`** — the consumer-facing reducer for dnd-kit ecosystem interop (drag a `useSortable` card into a grid, or a tile between a grid and a sortable list); also re-exported from `@snapgridjs/react`.
|
|
26
27
|
- **Config & event types** — `DragConfig`, `ResizeConfig`, `DropConfig`, `GridDropData`, `GridEventCallback` (also re-exported from `@snapgridjs/react`).
|
|
27
28
|
|
|
28
29
|
The layout math — compaction, geometry, move/resize, and the drag-session state machine — lives in [`@snapgridjs/core`](https://www.npmjs.com/package/@snapgridjs/core); this package adds the dnd-kit interaction layer on top, and the framework bindings add rendering.
|
package/dist/index.cjs
CHANGED
|
@@ -573,6 +573,45 @@ function attachEngine(manager) {
|
|
|
573
573
|
};
|
|
574
574
|
}
|
|
575
575
|
//#endregion
|
|
576
|
+
//#region src/snapMove.ts
|
|
577
|
+
/** Place the event's dragged item into `layout` at the pointer cell; returns the new layout. */
|
|
578
|
+
function snapMove(layout, event, ctx) {
|
|
579
|
+
const op = event.operation;
|
|
580
|
+
const source = op.source;
|
|
581
|
+
if (!source) return layout;
|
|
582
|
+
const id = String(source.id);
|
|
583
|
+
const data = source.data?.snapGrid;
|
|
584
|
+
const size = data?.kind === "move" ? {
|
|
585
|
+
w: data.item.w,
|
|
586
|
+
h: data.item.h
|
|
587
|
+
} : ctx.defaultItem ?? {
|
|
588
|
+
w: 1,
|
|
589
|
+
h: 1
|
|
590
|
+
};
|
|
591
|
+
const rect = ctx.gridRect ?? domElement(op.target)?.getBoundingClientRect() ?? {
|
|
592
|
+
left: 0,
|
|
593
|
+
top: 0
|
|
594
|
+
};
|
|
595
|
+
const p = op.position.current;
|
|
596
|
+
const cell = receiveCell({
|
|
597
|
+
x: p.x,
|
|
598
|
+
y: p.y
|
|
599
|
+
}, rect, {
|
|
600
|
+
x: 0,
|
|
601
|
+
y: 0
|
|
602
|
+
}, size.w, size.h, ctx.positionParams);
|
|
603
|
+
return (0, _snapgridjs_core.insertItemWithCompactor)(layout, {
|
|
604
|
+
i: id,
|
|
605
|
+
x: cell.x,
|
|
606
|
+
y: cell.y,
|
|
607
|
+
w: size.w,
|
|
608
|
+
h: size.h
|
|
609
|
+
}, cell.x, cell.y, {
|
|
610
|
+
compactor: ctx.compactor,
|
|
611
|
+
cols: ctx.positionParams.cols
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
//#endregion
|
|
576
615
|
//#region src/dnd/collision.ts
|
|
577
616
|
/**
|
|
578
617
|
* Marker attribute set on every grid container element. Used by {@link gridDepth}
|
|
@@ -596,14 +635,26 @@ function gridDepth(el) {
|
|
|
596
635
|
return depth;
|
|
597
636
|
}
|
|
598
637
|
/**
|
|
599
|
-
* Collision detector for grid droppables.
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
603
|
-
*
|
|
638
|
+
* Collision detector for grid droppables. Uses **pointer** intersection (not
|
|
639
|
+
* dnd-kit's default, which is pointer-first but falls back to the dragged SHAPE
|
|
640
|
+
* when the pointer leaves a droppable): a grid claims a drag only while the
|
|
641
|
+
* pointer is genuinely inside it. The shape fallback was actively wrong here —
|
|
642
|
+
* the grid's priority boost (below) made a large dragged tile keep winning the
|
|
643
|
+
* grid via mere rect-overlap even after the pointer moved off onto a sibling
|
|
644
|
+
* droppable (e.g. a sortable card beside the grid), so the tile could never
|
|
645
|
+
* leave the grid for that target. Pointer-only also aligns collision with the
|
|
646
|
+
* receive math, which maps the pointer (not the tile rect) to a cell.
|
|
647
|
+
*
|
|
648
|
+
* When the pointer IS inside, rank the grid above the dragged tile's own
|
|
649
|
+
* sortable droppable (so an in-grid move resolves to the container, letting RGL
|
|
650
|
+
* drive it — not dnd-kit's sortable reorder) and above a sibling droppable the
|
|
651
|
+
* pointer also happens to be over. For nested grids whose rects overlap (the
|
|
652
|
+
* pointer is over both an inner grid and its outer one), boost priority by the
|
|
653
|
+
* grid's nesting depth so the **innermost** grid wins; for non-nested grids
|
|
654
|
+
* depth is 0, so priority is unchanged.
|
|
604
655
|
*/
|
|
605
656
|
const gridCollisionDetector = (input) => {
|
|
606
|
-
const collision = (0, _dnd_kit_collision.
|
|
657
|
+
const collision = (0, _dnd_kit_collision.pointerIntersection)(input);
|
|
607
658
|
if (!collision) return null;
|
|
608
659
|
return {
|
|
609
660
|
...collision,
|
|
@@ -674,3 +725,4 @@ exports.domElement = domElement;
|
|
|
674
725
|
exports.getController = getController;
|
|
675
726
|
exports.gridCollisionDetector = gridCollisionDetector;
|
|
676
727
|
exports.registerController = registerController;
|
|
728
|
+
exports.snapMove = snapMove;
|
package/dist/index.d.cts
CHANGED
|
@@ -200,6 +200,55 @@ declare function getController(manager: object | null | undefined, id: string):
|
|
|
200
200
|
/** Ensure the engine is attached to `manager`; returns a detach (ref-decrement) fn. */
|
|
201
201
|
declare function attachEngine(manager: DragDropManager): () => void;
|
|
202
202
|
//#endregion
|
|
203
|
+
//#region src/snapMove.d.ts
|
|
204
|
+
/**
|
|
205
|
+
* The 2-D grid analog of dnd-kit's `move(items, event)` helper — call it from your
|
|
206
|
+
* own `onDragOver`/`onDragEnd` to place the dragged item into a grid's `Layout` at
|
|
207
|
+
* the cell under the pointer (with compaction), and get the new layout back.
|
|
208
|
+
*
|
|
209
|
+
* This is the consumer-facing reducer for **interop with the wider dnd-kit
|
|
210
|
+
* ecosystem** — e.g. dragging a `useSortable` card into a grid, or a grid tile
|
|
211
|
+
* between a grid and a sortable list. At a cross-parent seam (grid ⇄ list) you
|
|
212
|
+
* MUST reduce live in `onDragOver` (dnd-kit reparents the node mid-drag; reducing
|
|
213
|
+
* only on drop desyncs React and throws `removeChild`). Pure snapgrid grids don't
|
|
214
|
+
* need this — their managed engine already handles in-grid and cross-grid drags.
|
|
215
|
+
*
|
|
216
|
+
* The dragged item's size comes from a grid tile's payload (`data.snapGrid.item`)
|
|
217
|
+
* when present, else from `ctx.defaultItem` (default 1×1) for a foreign source.
|
|
218
|
+
*/
|
|
219
|
+
interface SnapMoveContext {
|
|
220
|
+
positionParams: PositionParams;
|
|
221
|
+
compactor: Compactor;
|
|
222
|
+
/** Size for a foreign (non-grid) source that carries no snapgrid item. @default {w:1,h:1} */
|
|
223
|
+
defaultItem?: {
|
|
224
|
+
w: number;
|
|
225
|
+
h: number;
|
|
226
|
+
};
|
|
227
|
+
/** Override the grid's client rect (else read from the target droppable's element). */
|
|
228
|
+
gridRect?: {
|
|
229
|
+
left: number;
|
|
230
|
+
top: number;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/** The dnd-kit drag event shape `snapMove` reads (a `dragover`/`dragend` event). */
|
|
234
|
+
interface SnapMoveEvent {
|
|
235
|
+
operation: {
|
|
236
|
+
source: {
|
|
237
|
+
id: string | number;
|
|
238
|
+
data?: unknown;
|
|
239
|
+
} | null;
|
|
240
|
+
target: object | null;
|
|
241
|
+
position: {
|
|
242
|
+
current: {
|
|
243
|
+
x: number;
|
|
244
|
+
y: number;
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/** Place the event's dragged item into `layout` at the pointer cell; returns the new layout. */
|
|
250
|
+
declare function snapMove(layout: Layout, event: SnapMoveEvent, ctx: SnapMoveContext): Layout;
|
|
251
|
+
//#endregion
|
|
203
252
|
//#region src/dnd/collision.d.ts
|
|
204
253
|
/**
|
|
205
254
|
* Marker attribute set on every grid container element. Used by {@link gridDepth}
|
|
@@ -207,11 +256,23 @@ declare function attachEngine(manager: DragDropManager): () => void;
|
|
|
207
256
|
*/
|
|
208
257
|
declare const SNAPGRID_GRID_ATTR = "data-snapgrid-grid";
|
|
209
258
|
/**
|
|
210
|
-
* Collision detector for grid droppables.
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
259
|
+
* Collision detector for grid droppables. Uses **pointer** intersection (not
|
|
260
|
+
* dnd-kit's default, which is pointer-first but falls back to the dragged SHAPE
|
|
261
|
+
* when the pointer leaves a droppable): a grid claims a drag only while the
|
|
262
|
+
* pointer is genuinely inside it. The shape fallback was actively wrong here —
|
|
263
|
+
* the grid's priority boost (below) made a large dragged tile keep winning the
|
|
264
|
+
* grid via mere rect-overlap even after the pointer moved off onto a sibling
|
|
265
|
+
* droppable (e.g. a sortable card beside the grid), so the tile could never
|
|
266
|
+
* leave the grid for that target. Pointer-only also aligns collision with the
|
|
267
|
+
* receive math, which maps the pointer (not the tile rect) to a cell.
|
|
268
|
+
*
|
|
269
|
+
* When the pointer IS inside, rank the grid above the dragged tile's own
|
|
270
|
+
* sortable droppable (so an in-grid move resolves to the container, letting RGL
|
|
271
|
+
* drive it — not dnd-kit's sortable reorder) and above a sibling droppable the
|
|
272
|
+
* pointer also happens to be over. For nested grids whose rects overlap (the
|
|
273
|
+
* pointer is over both an inner grid and its outer one), boost priority by the
|
|
274
|
+
* grid's nesting depth so the **innermost** grid wins; for non-nested grids
|
|
275
|
+
* depth is 0, so priority is unchanged.
|
|
215
276
|
*/
|
|
216
277
|
declare const gridCollisionDetector: CollisionDetector;
|
|
217
278
|
//#endregion
|
|
@@ -257,5 +318,5 @@ declare const NO_FEEDBACK: import("@dnd-kit/abstract").PluginDescriptor<any, any
|
|
|
257
318
|
*/
|
|
258
319
|
declare function buildItemSensors(threshold: number, getDragConfig: () => DragConfig | undefined): Sensors$1;
|
|
259
320
|
//#endregion
|
|
260
|
-
export { type DragConfig, type DragSourceInfo, type DropConfig, type GridCallbacks, GridController, type GridControllerConfig, type GridDropData, type GridEventCallback, type ItemSnapshot, NO_FEEDBACK, RESIZE_HANDLE_ATTR, type ResizeConfig, type ResizeSnapshot, SNAPGRID_GRID_ATTR, type SnapGridDragData, SnapToGrid, attachEngine, buildItemSensors, domElement, getController, gridCollisionDetector, registerController };
|
|
321
|
+
export { type DragConfig, type DragSourceInfo, type DropConfig, type GridCallbacks, GridController, type GridControllerConfig, type GridDropData, type GridEventCallback, type ItemSnapshot, NO_FEEDBACK, RESIZE_HANDLE_ATTR, type ResizeConfig, type ResizeSnapshot, SNAPGRID_GRID_ATTR, type SnapGridDragData, type SnapMoveContext, type SnapMoveEvent, SnapToGrid, attachEngine, buildItemSensors, domElement, getController, gridCollisionDetector, registerController, snapMove };
|
|
261
322
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/dnd/dragData.ts","../src/controller/GridController.ts","../src/controller/registry.ts","../src/dnd/SnapGridEngine.ts","../src/dnd/collision.ts","../src/dnd/snapToGrid.ts","../src/dnd/entity.ts","../src/dndShared.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/dnd/dragData.ts","../src/controller/GridController.ts","../src/controller/registry.ts","../src/dnd/SnapGridEngine.ts","../src/snapMove.ts","../src/dnd/collision.ts","../src/dnd/snapToGrid.ts","../src/dnd/entity.ts","../src/dndShared.ts"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -200,6 +200,55 @@ declare function getController(manager: object | null | undefined, id: string):
|
|
|
200
200
|
/** Ensure the engine is attached to `manager`; returns a detach (ref-decrement) fn. */
|
|
201
201
|
declare function attachEngine(manager: DragDropManager): () => void;
|
|
202
202
|
//#endregion
|
|
203
|
+
//#region src/snapMove.d.ts
|
|
204
|
+
/**
|
|
205
|
+
* The 2-D grid analog of dnd-kit's `move(items, event)` helper — call it from your
|
|
206
|
+
* own `onDragOver`/`onDragEnd` to place the dragged item into a grid's `Layout` at
|
|
207
|
+
* the cell under the pointer (with compaction), and get the new layout back.
|
|
208
|
+
*
|
|
209
|
+
* This is the consumer-facing reducer for **interop with the wider dnd-kit
|
|
210
|
+
* ecosystem** — e.g. dragging a `useSortable` card into a grid, or a grid tile
|
|
211
|
+
* between a grid and a sortable list. At a cross-parent seam (grid ⇄ list) you
|
|
212
|
+
* MUST reduce live in `onDragOver` (dnd-kit reparents the node mid-drag; reducing
|
|
213
|
+
* only on drop desyncs React and throws `removeChild`). Pure snapgrid grids don't
|
|
214
|
+
* need this — their managed engine already handles in-grid and cross-grid drags.
|
|
215
|
+
*
|
|
216
|
+
* The dragged item's size comes from a grid tile's payload (`data.snapGrid.item`)
|
|
217
|
+
* when present, else from `ctx.defaultItem` (default 1×1) for a foreign source.
|
|
218
|
+
*/
|
|
219
|
+
interface SnapMoveContext {
|
|
220
|
+
positionParams: PositionParams;
|
|
221
|
+
compactor: Compactor;
|
|
222
|
+
/** Size for a foreign (non-grid) source that carries no snapgrid item. @default {w:1,h:1} */
|
|
223
|
+
defaultItem?: {
|
|
224
|
+
w: number;
|
|
225
|
+
h: number;
|
|
226
|
+
};
|
|
227
|
+
/** Override the grid's client rect (else read from the target droppable's element). */
|
|
228
|
+
gridRect?: {
|
|
229
|
+
left: number;
|
|
230
|
+
top: number;
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/** The dnd-kit drag event shape `snapMove` reads (a `dragover`/`dragend` event). */
|
|
234
|
+
interface SnapMoveEvent {
|
|
235
|
+
operation: {
|
|
236
|
+
source: {
|
|
237
|
+
id: string | number;
|
|
238
|
+
data?: unknown;
|
|
239
|
+
} | null;
|
|
240
|
+
target: object | null;
|
|
241
|
+
position: {
|
|
242
|
+
current: {
|
|
243
|
+
x: number;
|
|
244
|
+
y: number;
|
|
245
|
+
};
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/** Place the event's dragged item into `layout` at the pointer cell; returns the new layout. */
|
|
250
|
+
declare function snapMove(layout: Layout, event: SnapMoveEvent, ctx: SnapMoveContext): Layout;
|
|
251
|
+
//#endregion
|
|
203
252
|
//#region src/dnd/collision.d.ts
|
|
204
253
|
/**
|
|
205
254
|
* Marker attribute set on every grid container element. Used by {@link gridDepth}
|
|
@@ -207,11 +256,23 @@ declare function attachEngine(manager: DragDropManager): () => void;
|
|
|
207
256
|
*/
|
|
208
257
|
declare const SNAPGRID_GRID_ATTR = "data-snapgrid-grid";
|
|
209
258
|
/**
|
|
210
|
-
* Collision detector for grid droppables.
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
259
|
+
* Collision detector for grid droppables. Uses **pointer** intersection (not
|
|
260
|
+
* dnd-kit's default, which is pointer-first but falls back to the dragged SHAPE
|
|
261
|
+
* when the pointer leaves a droppable): a grid claims a drag only while the
|
|
262
|
+
* pointer is genuinely inside it. The shape fallback was actively wrong here —
|
|
263
|
+
* the grid's priority boost (below) made a large dragged tile keep winning the
|
|
264
|
+
* grid via mere rect-overlap even after the pointer moved off onto a sibling
|
|
265
|
+
* droppable (e.g. a sortable card beside the grid), so the tile could never
|
|
266
|
+
* leave the grid for that target. Pointer-only also aligns collision with the
|
|
267
|
+
* receive math, which maps the pointer (not the tile rect) to a cell.
|
|
268
|
+
*
|
|
269
|
+
* When the pointer IS inside, rank the grid above the dragged tile's own
|
|
270
|
+
* sortable droppable (so an in-grid move resolves to the container, letting RGL
|
|
271
|
+
* drive it — not dnd-kit's sortable reorder) and above a sibling droppable the
|
|
272
|
+
* pointer also happens to be over. For nested grids whose rects overlap (the
|
|
273
|
+
* pointer is over both an inner grid and its outer one), boost priority by the
|
|
274
|
+
* grid's nesting depth so the **innermost** grid wins; for non-nested grids
|
|
275
|
+
* depth is 0, so priority is unchanged.
|
|
215
276
|
*/
|
|
216
277
|
declare const gridCollisionDetector: CollisionDetector;
|
|
217
278
|
//#endregion
|
|
@@ -257,5 +318,5 @@ declare const NO_FEEDBACK: import("@dnd-kit/abstract").PluginDescriptor<any, any
|
|
|
257
318
|
*/
|
|
258
319
|
declare function buildItemSensors(threshold: number, getDragConfig: () => DragConfig | undefined): Sensors$1;
|
|
259
320
|
//#endregion
|
|
260
|
-
export { type DragConfig, type DragSourceInfo, type DropConfig, type GridCallbacks, GridController, type GridControllerConfig, type GridDropData, type GridEventCallback, type ItemSnapshot, NO_FEEDBACK, RESIZE_HANDLE_ATTR, type ResizeConfig, type ResizeSnapshot, SNAPGRID_GRID_ATTR, type SnapGridDragData, SnapToGrid, attachEngine, buildItemSensors, domElement, getController, gridCollisionDetector, registerController };
|
|
321
|
+
export { type DragConfig, type DragSourceInfo, type DropConfig, type GridCallbacks, GridController, type GridControllerConfig, type GridDropData, type GridEventCallback, type ItemSnapshot, NO_FEEDBACK, RESIZE_HANDLE_ATTR, type ResizeConfig, type ResizeSnapshot, SNAPGRID_GRID_ATTR, type SnapGridDragData, type SnapMoveContext, type SnapMoveEvent, SnapToGrid, attachEngine, buildItemSensors, domElement, getController, gridCollisionDetector, registerController, snapMove };
|
|
261
322
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/dnd/dragData.ts","../src/controller/GridController.ts","../src/controller/registry.ts","../src/dnd/SnapGridEngine.ts","../src/dnd/collision.ts","../src/dnd/snapToGrid.ts","../src/dnd/entity.ts","../src/dndShared.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/dnd/dragData.ts","../src/controller/GridController.ts","../src/controller/registry.ts","../src/dnd/SnapGridEngine.ts","../src/snapMove.ts","../src/dnd/collision.ts","../src/dnd/snapToGrid.ts","../src/dnd/entity.ts","../src/dndShared.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { beginDrag, beginReceive, beginResize, calcGridColWidth, calcGridItemPosition, calcXY, commitLayout, dragResize, dragTo, hideActive, nudge, removeItemWithCompactor } from "@snapgridjs/core";
|
|
2
|
-
import {
|
|
1
|
+
import { beginDrag, beginReceive, beginResize, calcGridColWidth, calcGridItemPosition, calcXY, commitLayout, dragResize, dragTo, hideActive, insertItemWithCompactor, nudge, removeItemWithCompactor } from "@snapgridjs/core";
|
|
2
|
+
import { pointerIntersection } from "@dnd-kit/collision";
|
|
3
3
|
import { Modifier } from "@dnd-kit/abstract";
|
|
4
4
|
import { Feedback, KeyboardSensor, PointerActivationConstraints, PointerSensor } from "@dnd-kit/dom";
|
|
5
5
|
//#region src/controller/GridController.ts
|
|
@@ -572,6 +572,45 @@ function attachEngine(manager) {
|
|
|
572
572
|
};
|
|
573
573
|
}
|
|
574
574
|
//#endregion
|
|
575
|
+
//#region src/snapMove.ts
|
|
576
|
+
/** Place the event's dragged item into `layout` at the pointer cell; returns the new layout. */
|
|
577
|
+
function snapMove(layout, event, ctx) {
|
|
578
|
+
const op = event.operation;
|
|
579
|
+
const source = op.source;
|
|
580
|
+
if (!source) return layout;
|
|
581
|
+
const id = String(source.id);
|
|
582
|
+
const data = source.data?.snapGrid;
|
|
583
|
+
const size = data?.kind === "move" ? {
|
|
584
|
+
w: data.item.w,
|
|
585
|
+
h: data.item.h
|
|
586
|
+
} : ctx.defaultItem ?? {
|
|
587
|
+
w: 1,
|
|
588
|
+
h: 1
|
|
589
|
+
};
|
|
590
|
+
const rect = ctx.gridRect ?? domElement(op.target)?.getBoundingClientRect() ?? {
|
|
591
|
+
left: 0,
|
|
592
|
+
top: 0
|
|
593
|
+
};
|
|
594
|
+
const p = op.position.current;
|
|
595
|
+
const cell = receiveCell({
|
|
596
|
+
x: p.x,
|
|
597
|
+
y: p.y
|
|
598
|
+
}, rect, {
|
|
599
|
+
x: 0,
|
|
600
|
+
y: 0
|
|
601
|
+
}, size.w, size.h, ctx.positionParams);
|
|
602
|
+
return insertItemWithCompactor(layout, {
|
|
603
|
+
i: id,
|
|
604
|
+
x: cell.x,
|
|
605
|
+
y: cell.y,
|
|
606
|
+
w: size.w,
|
|
607
|
+
h: size.h
|
|
608
|
+
}, cell.x, cell.y, {
|
|
609
|
+
compactor: ctx.compactor,
|
|
610
|
+
cols: ctx.positionParams.cols
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
//#endregion
|
|
575
614
|
//#region src/dnd/collision.ts
|
|
576
615
|
/**
|
|
577
616
|
* Marker attribute set on every grid container element. Used by {@link gridDepth}
|
|
@@ -595,14 +634,26 @@ function gridDepth(el) {
|
|
|
595
634
|
return depth;
|
|
596
635
|
}
|
|
597
636
|
/**
|
|
598
|
-
* Collision detector for grid droppables.
|
|
599
|
-
*
|
|
600
|
-
*
|
|
601
|
-
*
|
|
602
|
-
*
|
|
637
|
+
* Collision detector for grid droppables. Uses **pointer** intersection (not
|
|
638
|
+
* dnd-kit's default, which is pointer-first but falls back to the dragged SHAPE
|
|
639
|
+
* when the pointer leaves a droppable): a grid claims a drag only while the
|
|
640
|
+
* pointer is genuinely inside it. The shape fallback was actively wrong here —
|
|
641
|
+
* the grid's priority boost (below) made a large dragged tile keep winning the
|
|
642
|
+
* grid via mere rect-overlap even after the pointer moved off onto a sibling
|
|
643
|
+
* droppable (e.g. a sortable card beside the grid), so the tile could never
|
|
644
|
+
* leave the grid for that target. Pointer-only also aligns collision with the
|
|
645
|
+
* receive math, which maps the pointer (not the tile rect) to a cell.
|
|
646
|
+
*
|
|
647
|
+
* When the pointer IS inside, rank the grid above the dragged tile's own
|
|
648
|
+
* sortable droppable (so an in-grid move resolves to the container, letting RGL
|
|
649
|
+
* drive it — not dnd-kit's sortable reorder) and above a sibling droppable the
|
|
650
|
+
* pointer also happens to be over. For nested grids whose rects overlap (the
|
|
651
|
+
* pointer is over both an inner grid and its outer one), boost priority by the
|
|
652
|
+
* grid's nesting depth so the **innermost** grid wins; for non-nested grids
|
|
653
|
+
* depth is 0, so priority is unchanged.
|
|
603
654
|
*/
|
|
604
655
|
const gridCollisionDetector = (input) => {
|
|
605
|
-
const collision =
|
|
656
|
+
const collision = pointerIntersection(input);
|
|
606
657
|
if (!collision) return null;
|
|
607
658
|
return {
|
|
608
659
|
...collision,
|
|
@@ -662,6 +713,6 @@ function buildItemSensors(threshold, getDragConfig) {
|
|
|
662
713
|
}), KeyboardSensor];
|
|
663
714
|
}
|
|
664
715
|
//#endregion
|
|
665
|
-
export { GridController, NO_FEEDBACK, RESIZE_HANDLE_ATTR, SNAPGRID_GRID_ATTR, SnapToGrid, attachEngine, buildItemSensors, domElement, getController, gridCollisionDetector, registerController };
|
|
716
|
+
export { GridController, NO_FEEDBACK, RESIZE_HANDLE_ATTR, SNAPGRID_GRID_ATTR, SnapToGrid, attachEngine, buildItemSensors, domElement, getController, gridCollisionDetector, registerController, snapMove };
|
|
666
717
|
|
|
667
718
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["#committed","#listeners","#session","#rendered","#renderedMapSource","#renderedMap","#indexById","#itemCache","#resizeCache","#emit","#keyboard","#renderedById","#placeholderCache","#nextIndex","#manager","#unsub","#start","#move","#end","#onKeyDown","#source","#dest","#keyboard","#dropSpec","#lastTargetId","#lastDest","#reset","#resolveDest","#setDest","#receiveExternalInto","#receiveInto","#externalSpecFor","#dropCounter"],"sources":["../src/controller/GridController.ts","../src/controller/registry.ts","../src/dnd/dragFlow.ts","../src/dnd/entity.ts","../src/dnd/SnapGridEngine.ts","../src/dnd/collision.ts","../src/dnd/snapToGrid.ts","../src/dndShared.ts"],"sourcesContent":["import type { Modifiers, Sensors } from \"@dnd-kit/abstract\";\nimport type { DragDropManager } from \"@dnd-kit/dom\";\nimport type {\n Compactor,\n DragSession,\n GridConfig,\n Layout,\n LayoutItem,\n PositionParams,\n ResizeHandleAxis,\n} from \"@snapgridjs/core\";\nimport type { DragConfig, DropConfig, GridEventCallback } from \"../types.js\";\n\n/**\n * The per-grid drag/resize callbacks the consumer supplied. Published to the\n * controller so the shared {@link SnapGridEngine} can invoke the RIGHT grid's\n * callbacks at the right phase (the engine is manager-wide; callbacks are per-grid).\n */\nexport interface GridCallbacks {\n onDragStart?: GridEventCallback;\n onDrag?: GridEventCallback;\n onDragStop?: GridEventCallback;\n onResizeStart?: GridEventCallback;\n onResize?: GridEventCallback;\n onResizeStop?: GridEventCallback;\n onLayoutChange?: (layout: Layout) => void;\n onDrop?: (layout: Layout, item: LayoutItem, event: Event | null) => void;\n}\n\n/**\n * Per-grid configuration the container host writes to the controller each render\n * (during render, so items that resolve this controller by `group` read fresh\n * config on the same pass). Also the seam the manager-wide {@link SnapGridEngine}\n * reads per-grid geometry, compaction, gates, and callbacks from.\n */\nexport interface GridControllerConfig {\n positionParams: PositionParams;\n gridConfig: GridConfig;\n width: number;\n autoSize: boolean;\n itemSensors: Sensors;\n itemModifiers: Modifiers;\n isItemDraggable: (id: string) => boolean;\n isItemResizable: (id: string) => boolean;\n resizeHandlesFor: (id: string) => readonly ResizeHandleAxis[];\n // ── Read by SnapGridEngine ──────────────────────────────────────────────\n compactor: Compactor;\n dragConfig?: DragConfig;\n dropConfig?: DropConfig;\n callbacks: GridCallbacks;\n}\n\nexport interface ItemSnapshot {\n item: LayoutItem | undefined;\n isDragging: boolean;\n // True only for a *pointer* drag of this tile. There's no overlay — the tile\n // floats itself — so the host renders it at its committed origin and dnd-kit's\n // float offset composes on top. A keyboard drag has no float, so the tile steps\n // in place instead (hence false here).\n hidden: boolean;\n}\n\nexport interface ResizeSnapshot {\n isResizing: boolean;\n}\n\nfunction sameItem(a: LayoutItem | undefined, b: LayoutItem | undefined): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n // Only the fields that affect what a tile renders/positions. Layout items are\n // immutable, so the compactor may hand back a fresh object for an *unmoved*\n // tile each frame — comparing by value (not identity) is what keeps that tile\n // from re-rendering during someone else's drag.\n return a.i === b.i && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;\n}\n\n/**\n * Live per-grid drag/resize state as a plain observable: the provider writes\n * (`setSession`/`setKeyboard`/`setCommitted`), hooks subscribe to just their own\n * slice via `useSyncExternalStore`. Value-cached snapshots mean a drag re-renders\n * only the tiles whose slice changed, not the whole subtree (the old\n * context-value model re-rendered every tile every frame).\n */\nexport class GridController {\n id: string;\n #committed: Layout;\n #session: DragSession | null = null;\n // True while the active drag was started by the keyboard (no floating overlay\n // → the in-grid tile must stay visible and move in place).\n #keyboard = false;\n #listeners = new Set<() => void>();\n // Per-grid config, written by the container host each render (see setConfig).\n // Non-null once mounted; items only read it after resolving a registered grid.\n config: GridControllerConfig | null = null;\n\n // getSnapshot must return a stable reference while the slice is unchanged\n // (useSyncExternalStore contract, and the basis of the fine-grained re-render).\n #itemCache = new Map<string, ItemSnapshot>();\n #resizeCache = new Map<string, ResizeSnapshot>();\n #placeholderCache: LayoutItem | null = null;\n\n // Rebuilt only when the rendered layout reference changes.\n #renderedMap: Map<string, LayoutItem> | null = null;\n #renderedMapSource: Layout | null = null;\n\n // Stable per-id index for the sortable contract (useGridItem). Assigned on first\n // sight; reclaimed when an item leaves the committed layout (see setCommitted), so\n // the index space stays bounded under item churn. While an item is present its\n // index is stable — the sortable FLIP it would otherwise drive never fires (RGL\n // owns motion).\n #indexById = new Map<string, number>();\n #nextIndex = 0;\n\n /** The dnd-kit manager this grid is registered with (set by useInstance). */\n manager: DragDropManager | undefined;\n\n /**\n * This grid's container element, reported by the host. The engine reads it to\n * map a pointer to a cell when receiving a tile (its `getBoundingClientRect`).\n */\n element: Element | null = null;\n\n constructor(id: string, committed: Layout = [], manager?: DragDropManager) {\n this.id = id;\n this.#committed = committed;\n this.manager = manager;\n }\n\n /** The committed (base) layout — the engine's source of truth during a drag. */\n getCommitted(): Layout {\n return this.#committed;\n }\n\n /** Replace the per-grid config (called by the container host during render). */\n setConfig(config: GridControllerConfig): void {\n this.config = config;\n }\n\n /**\n * Re-point this grid's id. The container host syncs it (during render, before\n * the droppable/group read it) when the controlled `id` prop changes, so the\n * returned `group`, the droppable id, and the registry key never drift apart.\n */\n setId(id: string): void {\n this.id = id;\n }\n\n // Satisfies dnd-kit's `Instance` interface (useInstance calls this in a layout\n // effect). Registry registration is handled by the host hook (it must happen\n // during render so child items resolve this controller on their first render),\n // so there's nothing to do here.\n register = (): void => {};\n\n subscribe = (listener: () => void): (() => void) => {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n };\n\n #emit(): void {\n for (const listener of this.#listeners) listener();\n }\n\n /** The layout currently shown: the drag preview while dragging, else committed. */\n #rendered(): Layout {\n return this.#session ? (this.#session.preview as Layout) : this.#committed;\n }\n\n #renderedById(): Map<string, LayoutItem> {\n const rendered = this.#rendered();\n if (this.#renderedMapSource !== rendered) {\n this.#renderedMap = new Map(rendered.map((it) => [it.i, it]));\n this.#renderedMapSource = rendered;\n }\n return this.#renderedMap!;\n }\n\n /**\n * Sync the committed layout from the controlled `layout` prop. Called during\n * the provider's render, so it must NOT notify — emitting here would update\n * subscribed GridItems mid-render (a React \"setState while rendering\" error).\n * No notify is needed: a `layout` prop change already re-renders the whole\n * provider subtree, so every GridItem re-reads its snapshot on that pass.\n */\n setCommitted(layout: Layout): void {\n if (this.#committed === layout) return;\n this.#committed = layout;\n // Reclaim cached slices/indices for items no longer in the layout, so a\n // long-lived grid whose items churn doesn't grow these maps without bound.\n const present = new Set(layout.map((it) => it.i));\n for (const id of this.#indexById.keys()) if (!present.has(id)) this.#indexById.delete(id);\n for (const id of this.#itemCache.keys()) if (!present.has(id)) this.#itemCache.delete(id);\n for (const id of this.#resizeCache.keys()) if (!present.has(id)) this.#resizeCache.delete(id);\n }\n\n setSession(next: DragSession | null): void {\n this.#session = next;\n this.#emit();\n }\n\n getSession(): DragSession | null {\n return this.#session;\n }\n\n /** Record whether the active drag is keyboard-driven (drives `hidden`). */\n setKeyboard(value: boolean): void {\n if (this.#keyboard === value) return;\n this.#keyboard = value;\n this.#emit();\n }\n\n itemSnapshot = (id: string): ItemSnapshot => {\n const item = this.#renderedById().get(id);\n const isDragging = this.#session?.activeId === id;\n const hidden = isDragging && this.#session?.kind === \"move\" && !this.#keyboard;\n const prev = this.#itemCache.get(id);\n if (\n prev &&\n prev.isDragging === isDragging &&\n prev.hidden === hidden &&\n sameItem(prev.item, item)\n ) {\n return prev;\n }\n const snap: ItemSnapshot = { item, isDragging, hidden };\n this.#itemCache.set(id, snap);\n return snap;\n };\n\n placeholderSnapshot = (): LayoutItem | null => {\n const next = this.#session?.placeholder ?? null;\n if (sameItem(this.#placeholderCache ?? undefined, next ?? undefined)) {\n return this.#placeholderCache;\n }\n this.#placeholderCache = next;\n return next;\n };\n\n resizeSnapshot = (itemId: string): ResizeSnapshot => {\n const isResizing = this.#session?.kind === \"resize\" && this.#session.activeId === itemId;\n const prev = this.#resizeCache.get(itemId);\n if (prev && prev.isResizing === isResizing) return prev;\n const snap: ResizeSnapshot = { isResizing };\n this.#resizeCache.set(itemId, snap);\n return snap;\n };\n\n renderedSnapshot = (): Layout => this.#rendered();\n\n /** A stable index for `id` (see {@link GridController.#indexById}). */\n itemIndex(id: string): number {\n let i = this.#indexById.get(id);\n if (i === undefined) {\n i = this.#nextIndex++;\n this.#indexById.set(id, i);\n }\n return i;\n }\n}\n","import type { GridController } from \"./GridController.js\";\n\n/**\n * Resolves a grid's {@link GridController} by its id, scoped to the dnd-kit\n * manager the grid is registered with. A container registers its controller\n * here (during render, so child items resolve it on their first render); items\n * look it up by their `group` (= the grid id). Replaces the old geometry\n * `GridRegistry` — which grid the pointer is over now comes from the collision\n * target, so the registry's only job is id → controller resolution.\n *\n * Keyed by manager so two apps (or two providers) never collide, and grids in\n * one provider share a map (the cross-grid seam).\n */\nconst byManager = new WeakMap<object, Map<string, GridController>>();\n// Used when there is no manager yet (no <DragDropProvider> above) — degenerate\n// but keeps lookups total instead of throwing.\nconst noManager = new Map<string, GridController>();\n\nfunction mapFor(manager: object | null | undefined): Map<string, GridController> {\n if (!manager) return noManager;\n let map = byManager.get(manager);\n if (!map) {\n map = new Map();\n byManager.set(manager, map);\n }\n return map;\n}\n\n/** Register a controller under `id` for `manager`. Returns an unregister fn. */\nexport function registerController(\n manager: object | null | undefined,\n id: string,\n controller: GridController,\n): () => void {\n const map = mapFor(manager);\n map.set(id, controller);\n return () => {\n if (map.get(id) === controller) map.delete(id);\n };\n}\n\n/** The controller registered under `id` for `manager`, or undefined. */\nexport function getController(\n manager: object | null | undefined,\n id: string,\n): GridController | undefined {\n return mapFor(manager).get(id);\n}\n\n// The active drag's grab offset (pointer position within the dragged tile),\n// shared across grids on the same manager so a *receiving* grid maps the pointer\n// to the cell under the grabbed point, not the tile's corner. One drag at a time\n// per manager, so a single slot keyed by manager suffices.\nconst grabOffsets = new WeakMap<object, { x: number; y: number }>();\nconst noManagerGrab = { current: null as { x: number; y: number } | null };\n\nexport function setGrabOffset(\n manager: object | null | undefined,\n offset: { x: number; y: number } | null,\n): void {\n if (!manager) {\n noManagerGrab.current = offset;\n return;\n }\n if (offset) grabOffsets.set(manager, offset);\n else grabOffsets.delete(manager);\n}\n\nexport function getGrabOffset(manager: object | null | undefined): { x: number; y: number } {\n const offset = manager ? grabOffsets.get(manager) : noManagerGrab.current;\n return offset ?? { x: 0, y: 0 };\n}\n","import { type PositionParams, calcXY } from \"@snapgridjs/core\";\nimport type { DropConfig, GridDropData } from \"../types.js\";\nimport type { SnapGridDragData } from \"./dragData.js\";\n\n/**\n * Pure decision helpers for the drag interaction so the tricky bits — grab-offset\n * cell mapping, the cross-grid drop lifecycle, and external-drop acceptance — are\n * unit-testable without a DOM or dnd-kit.\n */\n\n/** Read snapgrid's payload off a dnd-kit drag source. */\nexport function dragData(event: {\n operation: { source?: { data?: unknown } | null };\n}): SnapGridDragData | undefined {\n const data = event.operation.source?.data as { snapGrid?: SnapGridDragData } | undefined;\n return data?.snapGrid;\n}\n\n/** Size/id spec for an external (non-grid) draggable the grid may accept, or null. */\nexport function externalDropSpec(\n source: { id: string | number; type?: unknown; data?: unknown } | null | undefined,\n dropConfig: DropConfig | undefined,\n): { i?: string; w: number; h: number } | null {\n if (!dropConfig?.enabled || !source) return null;\n const data = source.data as { snapGrid?: unknown; snapGridDrop?: GridDropData } | undefined;\n if (data?.snapGrid) return null; // a grid item, not external\n if (dropConfig.accept && !dropConfig.accept(source)) return null;\n const spec = data?.snapGridDrop;\n return {\n i: spec?.i,\n // Fall back to react-grid-layout's `defaultDropConfig.defaultItem` (1×1) for parity.\n w: spec?.w ?? dropConfig.defaultItem?.w ?? 1,\n h: spec?.h ?? dropConfig.defaultItem?.h ?? 1,\n };\n}\n\n/**\n * Map a client-space pointer to a grid cell, accounting for where *within* the\n * dragged tile the pointer grabbed it. Subtracting the grab offset means the\n * tile's top-left (not the cursor) maps to the cell, so a received tile's\n * placeholder aligns with the floating overlay instead of jumping its corner to\n * the cursor. External drops pass `{ x: 0, y: 0 }` (no meaningful grab point).\n */\nexport function receiveCell(\n pointer: { x: number; y: number },\n gridRect: { left: number; top: number },\n grabOffset: { x: number; y: number },\n w: number,\n h: number,\n pp: PositionParams,\n): { x: number; y: number } {\n return calcXY(\n pp,\n pointer.y - grabOffset.y - gridRect.top,\n pointer.x - grabOffset.x - gridRect.left,\n w,\n h,\n );\n}\n\n/**\n * Map a keyboard event key to a one-cell grid step while a keyboard drag is\n * active, or null for keys snapgrid doesn't own — Enter/Space (drop) and Escape\n * (cancel) fall through to dnd-kit's KeyboardSensor.\n */\nexport function arrowStep(key: string): [number, number] | null {\n switch (key) {\n case \"ArrowLeft\":\n return [-1, 0];\n case \"ArrowRight\":\n return [1, 0];\n case \"ArrowUp\":\n return [0, -1];\n case \"ArrowDown\":\n return [0, 1];\n default:\n return null;\n }\n}\n\n/**\n * Which grid a drop commits to, as fed to {@link classifyDrop} as `dest`. A\n * keyboard drag has no pointer, so it can only ever land in its own grid; a\n * pointer drag lands in whichever grid the collision observer resolved (or none).\n */\nexport function dropDestination(opts: {\n keyboard: boolean;\n targetId: string | number | null | undefined;\n myId: string;\n}): string | null {\n if (opts.keyboard) return opts.myId;\n return opts.targetId != null ? String(opts.targetId) : null;\n}\n\n/** State gathered by the drag-end handler, fed to {@link classifyDrop}. */\nexport interface DropState {\n /** Kind of the in-progress session, or null if there is none. */\n kind: \"move\" | \"resize\" | null;\n /** Whether the drag was canceled (Esc / abort). */\n canceled: boolean;\n /** Does THIS grid own the dragged item (i.e. it is the source)? */\n ownsItem: boolean;\n /** Is the drag source a grid item (vs. an external draggable)? */\n hasData: boolean;\n /** Id of the grid under the drop pointer, or null if none. */\n dest: string | null;\n /** This grid's id. */\n myId: string;\n}\n\n/**\n * What the drag-end handler should do. Each action implies a specific set of\n * callbacks — encoded here so the cross-grid lifecycle contract is explicit and\n * testable:\n * - `commit-in-grid` / `remove-source` / `revert` all fire `onDragStop` (the\n * SOURCE grid owns the drag's start/stop pair);\n * - `commit-dest` fires only `onLayoutChange` — the destination grid never\n * fired `onDragStart`, so emitting `onDragStop` there would be unbalanced.\n */\nexport type DropAction =\n | \"cancel-resize\"\n | \"cancel-move\"\n | \"commit-resize\"\n | \"commit-in-grid\"\n | \"remove-source\"\n | \"revert\"\n | \"commit-dest\"\n | \"external-drop\"\n | \"noop\";\n\n/** Pure classification of a drag end. See {@link DropAction}. */\nexport function classifyDrop(s: DropState): DropAction {\n if (s.canceled) {\n if (s.kind === \"resize\") return \"cancel-resize\";\n if (s.ownsItem) return \"cancel-move\";\n return \"noop\";\n }\n if (s.kind === \"resize\") return \"commit-resize\";\n\n if (s.ownsItem && s.hasData) {\n if (s.dest === s.myId && s.kind === \"move\") return \"commit-in-grid\";\n if (s.dest) return \"remove-source\";\n return \"revert\";\n }\n\n // Not the owner: we can only be a receiving grid, and only with a session.\n if (s.dest === s.myId && s.kind === \"move\") {\n return s.hasData ? \"commit-dest\" : \"external-drop\";\n }\n return \"noop\";\n}\n","/**\n * The DOM element of a dnd-kit entity (a draggable, droppable, or drag source).\n * dnd-kit's abstract types don't expose `element`, but the DOM layer snapgrid\n * runs on always sets it — this centralizes that one assumption (and the cast)\n * in a single place instead of scattering it across the drag code.\n */\nexport function domElement(entity: object | null | undefined): Element | null {\n return (entity as { element?: Element | null } | null | undefined)?.element ?? null;\n}\n","import type { DragDropManager } from \"@dnd-kit/dom\";\nimport {\n type LayoutItem,\n beginDrag,\n beginReceive,\n beginResize,\n calcGridItemPosition,\n commitLayout,\n dragResize,\n dragTo,\n hideActive,\n nudge,\n removeItemWithCompactor,\n} from \"@snapgridjs/core\";\nimport type { GridController } from \"../controller/GridController.js\";\nimport { getController, getGrabOffset, setGrabOffset } from \"../controller/registry.js\";\nimport type { SnapGridDragData } from \"./dragData.js\";\nimport { arrowStep, classifyDrop, dragData, externalDropSpec, receiveCell } from \"./dragFlow.js\";\nimport { domElement } from \"./entity.js\";\n\n/**\n * The drag/resize/receive engine — ONE per dnd-kit manager, driving every grid\n * on it. Previously this logic lived in each grid's `useGridController` (N grids\n * = N monitors); centralizing it makes the brain framework-agnostic (it touches\n * no React) and lets a tile cross grids through one set of handlers. Per-grid\n * geometry, compaction, gates, and callbacks are read from each grid's published\n * {@link GridController} config; which grid the pointer is over comes from the\n * collision target, and the source grid from the drag payload's `group`.\n *\n * Attached via {@link attachEngine} (a per-manager, ref-counted singleton) so it\n * works the same whether the turnkey components own the `DragDropProvider` or a\n * headless consumer supplies their own — no provider plugin registration needed.\n */\n\ntype Point = { x: number; y: number };\ntype DragSource = { id: string | number; type?: unknown; data?: unknown } | null;\n\nconst hasWindow = typeof window !== \"undefined\";\n\nfunction dragCtx(ctrl: GridController) {\n const cfg = ctrl.config!;\n return {\n positionParams: cfg.positionParams,\n compactor: cfg.compactor,\n cols: cfg.gridConfig.cols,\n };\n}\n\n/** Map a client-space pointer to a cell within `ctrl`, via its element rect. */\nfunction cellFromPointer(\n ctrl: GridController,\n pointer: Point,\n item: { w: number; h: number },\n manager: DragDropManager,\n): Point | null {\n const el = ctrl.element;\n const cfg = ctrl.config;\n if (!el || !cfg) return null;\n const rect = el.getBoundingClientRect();\n return receiveCell(pointer, rect, getGrabOffset(manager), item.w, item.h, cfg.positionParams);\n}\n\nclass SnapGridEngine {\n #manager: DragDropManager;\n #unsub: Array<() => void> = [];\n\n // Active-drag state — one drag at a time per manager.\n #source: GridController | null = null; // the owning grid (move/resize)\n #dest: GridController | null = null; // current receiving grid (≠ source), if any\n #keyboard = false;\n #dropSpec: { i: string; w: number; h: number } | null = null; // external draggable\n #dropCounter = 0;\n // Per-drag cache so a continuous drag (pointer over one grid for many frames)\n // doesn't re-resolve the destination controller on every move.\n #lastTargetId: string | number | null = null;\n #lastDest: GridController | undefined = undefined;\n\n constructor(manager: DragDropManager) {\n this.#manager = manager;\n const mon = manager.monitor;\n this.#unsub.push(\n mon.addEventListener(\"dragstart\", (event) => {\n const op = event.operation;\n const p = op.position.current;\n this.#start(\n dragData(event),\n { x: p.x, y: p.y },\n op.source as DragSource,\n op.activatorEvent,\n );\n }),\n mon.addEventListener(\"dragmove\", (event) => {\n const op = event.operation;\n const p = op.position.current;\n this.#move(\n dragData(event),\n { x: p.x, y: p.y },\n op.source as DragSource,\n op.target?.id ?? null,\n op.activatorEvent,\n );\n }),\n mon.addEventListener(\"dragend\", (event) => {\n const op = event.operation;\n this.#end(\n dragData(event),\n op.target?.id ?? null,\n event.nativeEvent ?? null,\n event.canceled,\n );\n }),\n );\n // Keyboard dragging needs a window listener; guard so a framework-agnostic\n // binding can construct the engine in a non-DOM (SSR) context without throwing.\n if (hasWindow) window.addEventListener(\"keydown\", this.#onKeyDown, true);\n }\n\n destroy(): void {\n for (const u of this.#unsub) u();\n this.#unsub = [];\n if (hasWindow) window.removeEventListener(\"keydown\", this.#onKeyDown, true);\n }\n\n #reset(): void {\n this.#source = null;\n this.#dest = null;\n this.#keyboard = false;\n this.#dropSpec = null;\n this.#lastTargetId = null;\n this.#lastDest = undefined;\n }\n\n /** Resolve the grid under the pointer from the collision target id (cached per drag). */\n #resolveDest(targetId: string | number | null): GridController | undefined {\n if (targetId == null) return undefined;\n if (targetId !== this.#lastTargetId) {\n this.#lastTargetId = targetId;\n this.#lastDest = getController(this.#manager, String(targetId));\n }\n return this.#lastDest;\n }\n\n // Switch the current receiving grid, clearing the previous one's preview (unless\n // it's the source grid, whose own session is managed separately).\n #setDest(next: GridController | null): void {\n if (this.#dest && this.#dest !== next && this.#dest !== this.#source) {\n this.#dest.setSession(null);\n }\n this.#dest = next;\n }\n\n #start(\n data: SnapGridDragData | undefined,\n pointer: Point,\n source: DragSource,\n activatorEvent: Event | null,\n ): void {\n this.#reset();\n if (!data) return; // external: spec is minted lazily on move over an accepting grid\n const owner = getController(this.#manager, data.group);\n const cfg = owner?.config;\n if (!owner || !cfg) return;\n const layout = owner.getCommitted();\n const item = layout.find((it) => it.i === data.itemId);\n if (!item) return;\n\n if (data.kind === \"resize\") {\n const rect = calcGridItemPosition(cfg.positionParams, item.x, item.y, item.w, item.h);\n owner.setSession(beginResize(layout, { item, rect, pointer }, data.handle));\n this.#source = owner;\n owner.setKeyboard(false); // clear any stale flag; resize is never keyboard-flagged\n cfg.callbacks.onResizeStart?.(layout, item, item, item, activatorEvent, null);\n return;\n }\n\n const isKeyboard = hasWindow && activatorEvent instanceof KeyboardEvent;\n this.#keyboard = isKeyboard;\n owner.setKeyboard(isKeyboard);\n const rect = calcGridItemPosition(cfg.positionParams, item.x, item.y, item.w, item.h);\n owner.setSession(beginDrag(layout, { item, left: rect.left, top: rect.top, pointer }));\n this.#source = owner;\n // Share the grab offset (pointer within the tile) so a receiving grid maps the\n // pointer to the cell under the grabbed point, not the tile's corner.\n const cr = domElement(source)?.getBoundingClientRect();\n if (cr) setGrabOffset(this.#manager, { x: pointer.x - cr.left, y: pointer.y - cr.top });\n cfg.callbacks.onDragStart?.(layout, item, item, item, activatorEvent, null);\n }\n\n #move(\n data: SnapGridDragData | undefined,\n pointer: Point,\n source: DragSource,\n targetId: string | number | null,\n activatorEvent: Event | null,\n ): void {\n if (this.#keyboard) return; // keyboard moves are driven by the arrow-key handler\n const owner = this.#source;\n\n // Resize: advance the source grid's resize session.\n const ownerSession = owner?.getSession();\n if (owner && ownerSession?.kind === \"resize\") {\n const cfg = owner.config!;\n const next = dragResize(ownerSession, pointer, dragCtx(owner));\n owner.setSession(next);\n cfg.callbacks.onResize?.(\n next.preview,\n next.anchor.item,\n next.placeholder,\n next.placeholder,\n activatorEvent,\n null,\n );\n return;\n }\n\n const destCtrl = this.#resolveDest(targetId);\n\n if (!data) {\n // External (non-grid) draggable: preview where it would land over a grid that accepts it.\n this.#setDest(destCtrl ? this.#receiveExternalInto(destCtrl, source, pointer) : null);\n return;\n }\n if (data.kind !== \"move\") return;\n\n // Moving within the source grid.\n if (owner && destCtrl === owner) {\n this.#setDest(null);\n const cur = owner.getSession();\n if (!cur) return;\n const cfg = owner.config!;\n const next = dragTo(cur, pointer, dragCtx(owner));\n owner.setSession(next);\n cfg.callbacks.onDrag?.(\n next.preview,\n next.anchor.item,\n next.placeholder,\n next.placeholder,\n activatorEvent,\n null,\n );\n return;\n }\n\n // Leaving the source grid (if we resolved one): hide its placeholder, keep its\n // items in place (the dragged tile floats itself across grids — no overlay).\n if (owner) {\n const cur = owner.getSession();\n if (cur) {\n const cfg = owner.config!;\n const hidden = hideActive(cur);\n owner.setSession(hidden);\n cfg.callbacks.onDrag?.(\n hidden.preview,\n hidden.anchor.item,\n null,\n null,\n activatorEvent,\n null,\n );\n }\n }\n // Receive the tile into the destination grid. Independent of whether the source\n // grid resolved, so a desynced source can't block another grid from receiving.\n this.#setDest(\n destCtrl && destCtrl !== owner ? this.#receiveInto(destCtrl, data.item, pointer) : null,\n );\n }\n\n /** Build a receive preview for `foreign` in `dest`; returns `dest` on success, else null. */\n #receiveInto(dest: GridController, foreign: LayoutItem, pointer: Point): GridController | null {\n if (!dest.config) return null;\n const committed = dest.getCommitted();\n const cell = cellFromPointer(dest, pointer, foreign, this.#manager) ?? { x: 0, y: 0 };\n dest.setSession(beginReceive(committed, foreign, cell.x, cell.y, pointer, dragCtx(dest)));\n return dest;\n }\n\n /** Receive an external (non-grid) draggable into `dest`, synthesizing its item. */\n #receiveExternalInto(\n dest: GridController,\n source: DragSource,\n pointer: Point,\n ): GridController | null {\n const spec = this.#externalSpecFor(dest, source);\n if (!spec) return null;\n return this.#receiveInto(dest, { i: spec.i, x: 0, y: 0, w: spec.w, h: spec.h }, pointer);\n }\n\n // Synthesize a stable id/size for an external draggable the first time it's over\n // an accepting grid; re-check acceptance per grid, but keep the id stable so the\n // preview item doesn't churn as the pointer moves between grids.\n #externalSpecFor(\n dest: GridController,\n source: DragSource,\n ): { i: string; w: number; h: number } | null {\n const spec = externalDropSpec(source, dest.config?.dropConfig);\n if (!spec) return null;\n if (!this.#dropSpec) {\n this.#dropCounter += 1;\n this.#dropSpec = {\n i: spec.i ?? `${dest.id}-dropped-${this.#dropCounter}`,\n w: spec.w,\n h: spec.h,\n };\n }\n return this.#dropSpec;\n }\n\n #end(\n data: SnapGridDragData | undefined,\n targetId: string | number | null,\n nativeEvent: Event | null,\n canceled: boolean,\n ): void {\n const source = this.#source;\n const dest = this.#dest;\n try {\n // Source grid (the owner): owns the drag's start/stop pair and the resize path.\n if (source) {\n const cfg = source.config!;\n const cur = source.getSession();\n // The item leaves the source ONLY if a grid actually received it (a live\n // receive session in #dest). Otherwise it's an in-grid move (pointer/keyboard\n // over the source) or a revert — never a remove keyed off a racy drop target\n // that no grid committed (which would lose the tile).\n const destId = dest\n ? dest.id\n : this.#keyboard || (targetId != null && String(targetId) === source.id)\n ? source.id\n : null;\n const action = classifyDrop({\n kind: cur?.kind ?? null,\n canceled,\n ownsItem: true,\n hasData: !!data,\n dest: destId,\n myId: source.id,\n });\n switch (action) {\n case \"cancel-resize\":\n cfg.callbacks.onResizeStop?.(\n source.getCommitted(),\n cur?.anchor.item ?? null,\n null,\n null,\n nativeEvent,\n null,\n );\n break;\n case \"cancel-move\":\n cfg.callbacks.onDragStop?.(\n source.getCommitted(),\n cur?.anchor.item ?? null,\n null,\n null,\n nativeEvent,\n null,\n );\n break;\n case \"commit-resize\":\n if (cur) {\n cfg.callbacks.onLayoutChange?.(commitLayout(cur));\n cfg.callbacks.onResizeStop?.(\n cur.preview,\n cur.anchor.item,\n cur.placeholder,\n cur.placeholder,\n nativeEvent,\n null,\n );\n }\n break;\n case \"commit-in-grid\":\n case \"remove-source\":\n case \"revert\": {\n if (action === \"commit-in-grid\" && cur) {\n cfg.callbacks.onLayoutChange?.(commitLayout(cur));\n } else if (action === \"remove-source\" && data) {\n const { compactor, cols } = dragCtx(source);\n cfg.callbacks.onLayoutChange?.(\n removeItemWithCompactor(source.getCommitted(), data.itemId, { compactor, cols }),\n );\n } // \"revert\" → dropped outside any grid → no layout change.\n cfg.callbacks.onDragStop?.(\n cur?.preview ?? source.getCommitted(),\n cur?.anchor.item ?? null,\n cur?.placeholder ?? null,\n cur?.placeholder ?? null,\n nativeEvent,\n null,\n );\n break;\n }\n }\n }\n\n // Destination grid (receiver): #dest holds the live receive session, so it IS\n // the landing grid — commit it regardless of the (possibly racy) drop target.\n if (dest && dest !== source) {\n const cfg = dest.config!;\n const cur = dest.getSession();\n const action = classifyDrop({\n kind: cur?.kind ?? null,\n canceled,\n ownsItem: false,\n hasData: !!data,\n dest: dest.id,\n myId: dest.id,\n });\n if (action === \"commit-dest\") {\n if (cur) cfg.callbacks.onLayoutChange?.(commitLayout(cur));\n } else if (action === \"external-drop\" && cur) {\n const committed = commitLayout(cur);\n const dropped = committed.find((it) => it.i === cur.activeId);\n if (dropped) cfg.callbacks.onDrop?.(committed, dropped, nativeEvent);\n }\n }\n } finally {\n // Always clean up, even if a consumer callback above threw — otherwise a stale\n // session / keyboard flag / grab offset would leak into the next drag.\n setGrabOffset(this.#manager, null);\n source?.setKeyboard(false);\n source?.setSession(null);\n if (dest && dest !== source) dest.setSession(null);\n this.#reset();\n }\n }\n\n #onKeyDown = (e: KeyboardEvent): void => {\n if (!this.#keyboard) return;\n const source = this.#source;\n const session = source?.getSession();\n if (!source || !session || session.kind !== \"move\") return;\n const step = arrowStep(e.key);\n if (!step) return; // Enter/Space (drop) and Escape (cancel) → dnd-kit's KeyboardSensor\n e.preventDefault();\n // Own the arrow: stop dnd-kit's KeyboardSensor (a document capture listener) from\n // also moving — we run in capture on window, ahead of it.\n e.stopImmediatePropagation();\n source.setSession(nudge(session, step[0], step[1], dragCtx(source)));\n };\n}\n\n// One engine per manager, ref-counted by the number of mounted grids so the\n// monitor + window listeners are torn down when the last grid for a manager\n// unmounts (no leak holding the manager alive via the window keydown listener).\nconst engines = new WeakMap<DragDropManager, { engine: SnapGridEngine; refs: number }>();\n\n/** Ensure the engine is attached to `manager`; returns a detach (ref-decrement) fn. */\nexport function attachEngine(manager: DragDropManager): () => void {\n let entry = engines.get(manager);\n if (!entry) {\n entry = { engine: new SnapGridEngine(manager), refs: 0 };\n engines.set(manager, entry);\n }\n entry.refs += 1;\n // Idempotent: a binding (or a double-invoked effect cleanup) calling detach twice\n // must not over-decrement and tear the engine down while other grids are mounted.\n let detached = false;\n return () => {\n if (detached) return;\n detached = true;\n const e = engines.get(manager);\n if (!e) return;\n e.refs -= 1;\n if (e.refs <= 0) {\n e.engine.destroy();\n engines.delete(manager);\n }\n };\n}\n","import { type CollisionDetector, defaultCollisionDetection } from \"@dnd-kit/collision\";\nimport { domElement } from \"./entity.js\";\n\n/**\n * Marker attribute set on every grid container element. Used by {@link gridDepth}\n * to measure how deeply a grid is nested, purely from the DOM.\n */\nexport const SNAPGRID_GRID_ATTR = \"data-snapgrid-grid\";\n\n// Base priority for a grid droppable. Outranks a dragged tile's own sortable\n// droppable so collision inside a grid resolves to the container (RGL drives the\n// move, not dnd-kit's sortable reorder), and lets a foreign sortable resolve the\n// grid as its drop target. `gridDepth` adds to this so an inner grid outranks its\n// outer one when their rects overlap.\nconst GRID_COLLISION_PRIORITY = 10;\n\n/**\n * How deeply `el`'s grid is nested: the number of ancestor grid containers above\n * it. A top-level grid is 0; a grid rendered inside another grid's tile is 1; and\n * so on. DOM containment is the ground truth, so this is correct regardless of the\n * React tree shape or how priorities are assigned elsewhere.\n */\nexport function gridDepth(el: Element | null | undefined): number {\n let depth = 0;\n let node = el?.parentElement ?? null;\n while (node) {\n if (node.hasAttribute(SNAPGRID_GRID_ATTR)) depth++;\n node = node.parentElement;\n }\n return depth;\n}\n\n/**\n * Collision detector for grid droppables. Runs dnd-kit's default detector, then —\n * when nested grid rects overlap (the pointer is over both an inner grid and its\n * outer one) — ranks the **innermost** grid highest by boosting priority with the\n * grid's nesting depth. Without this, overlapping grids tie on priority and the\n * winner is arbitrary. For non-nested grids depth is 0, so priority is unchanged.\n */\nexport const gridCollisionDetector: CollisionDetector = (input) => {\n const collision = defaultCollisionDetection(input);\n if (!collision) return null;\n return {\n ...collision,\n priority: GRID_COLLISION_PRIORITY + gridDepth(domElement(input.droppable)),\n };\n};\n","import { Modifier } from \"@dnd-kit/abstract\";\nimport type { DragDropManager } from \"@dnd-kit/dom\";\nimport { type PositionParams, calcGridColWidth } from \"@snapgridjs/core\";\n\nexport interface SnapToGridOptions {\n /** Current geometry (changes with container width). Read fresh each apply(). */\n getPositionParams: () => PositionParams;\n /** Whether snapping is currently enabled (dragConfig.snapToGrid). */\n isEnabled: () => boolean;\n}\n\n/**\n * Quantizes the dragged item's transform to whole grid cells, so the floating\n * <DragOverlay> clone jumps cell-to-cell in lockstep with the (always-snapped)\n * placeholder instead of tracking the pointer smoothly. Applied on the item\n * draggable; a no-op unless `dragConfig.snapToGrid` is set.\n */\nexport class SnapToGrid extends Modifier<DragDropManager, SnapToGridOptions> {\n override apply({ transform }: DragDropManager[\"dragOperation\"]) {\n const opts = this.options;\n if (!opts?.isEnabled()) return transform;\n const pp = opts.getPositionParams();\n // A cell step is the column/row size plus the gap to the next cell.\n const colStep = calcGridColWidth(pp) + pp.margin[0];\n const rowStep = pp.rowHeight + pp.margin[1];\n if (colStep <= 0 || rowStep <= 0) return transform; // guard degenerate geometry\n return {\n x: Math.round(transform.x / colStep) * colStep,\n y: Math.round(transform.y / rowStep) * rowStep,\n };\n }\n}\n","import {\n Feedback,\n KeyboardSensor,\n PointerActivationConstraints,\n PointerSensor,\n type Sensors,\n} from \"@dnd-kit/dom\";\nimport type { DragConfig } from \"./types.js\";\n\n/** Marker attribute placed on resize-handle elements. */\nexport const RESIZE_HANDLE_ATTR = \"data-snapgrid-resize-handle\";\n\n// Resize handles are draggables too, but resizing isn't a move — there's no tile\n// to float — so they suppress dnd-kit's visual feedback entirely.\nexport const NO_FEEDBACK = [Feedback.configure({ feedback: \"none\" })];\n\n/**\n * Whether a pointer-down on `target` should NOT start an item move. Pure and\n * exported for testing. Honors three rules, in order:\n * - never start a move from a resize handle;\n * - never start from a region matching `dragConfig.cancel`;\n * - if `dragConfig.handle` is set, only start from within it.\n */\nexport function shouldPreventItemDrag(\n target: EventTarget | null,\n cfg: DragConfig | undefined,\n): boolean {\n if (!(target instanceof Element)) return false;\n if (target.closest(`[${RESIZE_HANDLE_ATTR}]`)) return true;\n if (cfg?.cancel && target.closest(cfg.cancel)) return true;\n if (cfg?.handle && !target.closest(cfg.handle)) return true;\n return false;\n}\n\n/**\n * Sensors for item (move) draggables, built from the drag config: a distance\n * activation threshold (so clicks don't start drags) plus handle/cancel/resize\n * gating, with the keyboard sensor kept for accessibility.\n */\nexport function buildItemSensors(\n threshold: number,\n getDragConfig: () => DragConfig | undefined,\n): Sensors {\n return [\n PointerSensor.configure({\n activationConstraints: () =>\n threshold > 0\n ? [new PointerActivationConstraints.Distance({ value: threshold })]\n : undefined,\n preventActivation: (event: PointerEvent) =>\n shouldPreventItemDrag(event.target, getDragConfig()),\n }),\n KeyboardSensor,\n ];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["#committed","#listeners","#session","#rendered","#renderedMapSource","#renderedMap","#indexById","#itemCache","#resizeCache","#emit","#keyboard","#renderedById","#placeholderCache","#nextIndex","#manager","#unsub","#start","#move","#end","#onKeyDown","#source","#dest","#keyboard","#dropSpec","#lastTargetId","#lastDest","#reset","#resolveDest","#setDest","#receiveExternalInto","#receiveInto","#externalSpecFor","#dropCounter"],"sources":["../src/controller/GridController.ts","../src/controller/registry.ts","../src/dnd/dragFlow.ts","../src/dnd/entity.ts","../src/dnd/SnapGridEngine.ts","../src/snapMove.ts","../src/dnd/collision.ts","../src/dnd/snapToGrid.ts","../src/dndShared.ts"],"sourcesContent":["import type { Modifiers, Sensors } from \"@dnd-kit/abstract\";\nimport type { DragDropManager } from \"@dnd-kit/dom\";\nimport type {\n Compactor,\n DragSession,\n GridConfig,\n Layout,\n LayoutItem,\n PositionParams,\n ResizeHandleAxis,\n} from \"@snapgridjs/core\";\nimport type { DragConfig, DropConfig, GridEventCallback } from \"../types.js\";\n\n/**\n * The per-grid drag/resize callbacks the consumer supplied. Published to the\n * controller so the shared {@link SnapGridEngine} can invoke the RIGHT grid's\n * callbacks at the right phase (the engine is manager-wide; callbacks are per-grid).\n */\nexport interface GridCallbacks {\n onDragStart?: GridEventCallback;\n onDrag?: GridEventCallback;\n onDragStop?: GridEventCallback;\n onResizeStart?: GridEventCallback;\n onResize?: GridEventCallback;\n onResizeStop?: GridEventCallback;\n onLayoutChange?: (layout: Layout) => void;\n onDrop?: (layout: Layout, item: LayoutItem, event: Event | null) => void;\n}\n\n/**\n * Per-grid configuration the container host writes to the controller each render\n * (during render, so items that resolve this controller by `group` read fresh\n * config on the same pass). Also the seam the manager-wide {@link SnapGridEngine}\n * reads per-grid geometry, compaction, gates, and callbacks from.\n */\nexport interface GridControllerConfig {\n positionParams: PositionParams;\n gridConfig: GridConfig;\n width: number;\n autoSize: boolean;\n itemSensors: Sensors;\n itemModifiers: Modifiers;\n isItemDraggable: (id: string) => boolean;\n isItemResizable: (id: string) => boolean;\n resizeHandlesFor: (id: string) => readonly ResizeHandleAxis[];\n // ── Read by SnapGridEngine ──────────────────────────────────────────────\n compactor: Compactor;\n dragConfig?: DragConfig;\n dropConfig?: DropConfig;\n callbacks: GridCallbacks;\n}\n\nexport interface ItemSnapshot {\n item: LayoutItem | undefined;\n isDragging: boolean;\n // True only for a *pointer* drag of this tile. There's no overlay — the tile\n // floats itself — so the host renders it at its committed origin and dnd-kit's\n // float offset composes on top. A keyboard drag has no float, so the tile steps\n // in place instead (hence false here).\n hidden: boolean;\n}\n\nexport interface ResizeSnapshot {\n isResizing: boolean;\n}\n\nfunction sameItem(a: LayoutItem | undefined, b: LayoutItem | undefined): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n // Only the fields that affect what a tile renders/positions. Layout items are\n // immutable, so the compactor may hand back a fresh object for an *unmoved*\n // tile each frame — comparing by value (not identity) is what keeps that tile\n // from re-rendering during someone else's drag.\n return a.i === b.i && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;\n}\n\n/**\n * Live per-grid drag/resize state as a plain observable: the provider writes\n * (`setSession`/`setKeyboard`/`setCommitted`), hooks subscribe to just their own\n * slice via `useSyncExternalStore`. Value-cached snapshots mean a drag re-renders\n * only the tiles whose slice changed, not the whole subtree (the old\n * context-value model re-rendered every tile every frame).\n */\nexport class GridController {\n id: string;\n #committed: Layout;\n #session: DragSession | null = null;\n // True while the active drag was started by the keyboard (no floating overlay\n // → the in-grid tile must stay visible and move in place).\n #keyboard = false;\n #listeners = new Set<() => void>();\n // Per-grid config, written by the container host each render (see setConfig).\n // Non-null once mounted; items only read it after resolving a registered grid.\n config: GridControllerConfig | null = null;\n\n // getSnapshot must return a stable reference while the slice is unchanged\n // (useSyncExternalStore contract, and the basis of the fine-grained re-render).\n #itemCache = new Map<string, ItemSnapshot>();\n #resizeCache = new Map<string, ResizeSnapshot>();\n #placeholderCache: LayoutItem | null = null;\n\n // Rebuilt only when the rendered layout reference changes.\n #renderedMap: Map<string, LayoutItem> | null = null;\n #renderedMapSource: Layout | null = null;\n\n // Stable per-id index for the sortable contract (useGridItem). Assigned on first\n // sight; reclaimed when an item leaves the committed layout (see setCommitted), so\n // the index space stays bounded under item churn. While an item is present its\n // index is stable — the sortable FLIP it would otherwise drive never fires (RGL\n // owns motion).\n #indexById = new Map<string, number>();\n #nextIndex = 0;\n\n /** The dnd-kit manager this grid is registered with (set by useInstance). */\n manager: DragDropManager | undefined;\n\n /**\n * This grid's container element, reported by the host. The engine reads it to\n * map a pointer to a cell when receiving a tile (its `getBoundingClientRect`).\n */\n element: Element | null = null;\n\n constructor(id: string, committed: Layout = [], manager?: DragDropManager) {\n this.id = id;\n this.#committed = committed;\n this.manager = manager;\n }\n\n /** The committed (base) layout — the engine's source of truth during a drag. */\n getCommitted(): Layout {\n return this.#committed;\n }\n\n /** Replace the per-grid config (called by the container host during render). */\n setConfig(config: GridControllerConfig): void {\n this.config = config;\n }\n\n /**\n * Re-point this grid's id. The container host syncs it (during render, before\n * the droppable/group read it) when the controlled `id` prop changes, so the\n * returned `group`, the droppable id, and the registry key never drift apart.\n */\n setId(id: string): void {\n this.id = id;\n }\n\n // Satisfies dnd-kit's `Instance` interface (useInstance calls this in a layout\n // effect). Registry registration is handled by the host hook (it must happen\n // during render so child items resolve this controller on their first render),\n // so there's nothing to do here.\n register = (): void => {};\n\n subscribe = (listener: () => void): (() => void) => {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n };\n\n #emit(): void {\n for (const listener of this.#listeners) listener();\n }\n\n /** The layout currently shown: the drag preview while dragging, else committed. */\n #rendered(): Layout {\n return this.#session ? (this.#session.preview as Layout) : this.#committed;\n }\n\n #renderedById(): Map<string, LayoutItem> {\n const rendered = this.#rendered();\n if (this.#renderedMapSource !== rendered) {\n this.#renderedMap = new Map(rendered.map((it) => [it.i, it]));\n this.#renderedMapSource = rendered;\n }\n return this.#renderedMap!;\n }\n\n /**\n * Sync the committed layout from the controlled `layout` prop. Called during\n * the provider's render, so it must NOT notify — emitting here would update\n * subscribed GridItems mid-render (a React \"setState while rendering\" error).\n * No notify is needed: a `layout` prop change already re-renders the whole\n * provider subtree, so every GridItem re-reads its snapshot on that pass.\n */\n setCommitted(layout: Layout): void {\n if (this.#committed === layout) return;\n this.#committed = layout;\n // Reclaim cached slices/indices for items no longer in the layout, so a\n // long-lived grid whose items churn doesn't grow these maps without bound.\n const present = new Set(layout.map((it) => it.i));\n for (const id of this.#indexById.keys()) if (!present.has(id)) this.#indexById.delete(id);\n for (const id of this.#itemCache.keys()) if (!present.has(id)) this.#itemCache.delete(id);\n for (const id of this.#resizeCache.keys()) if (!present.has(id)) this.#resizeCache.delete(id);\n }\n\n setSession(next: DragSession | null): void {\n this.#session = next;\n this.#emit();\n }\n\n getSession(): DragSession | null {\n return this.#session;\n }\n\n /** Record whether the active drag is keyboard-driven (drives `hidden`). */\n setKeyboard(value: boolean): void {\n if (this.#keyboard === value) return;\n this.#keyboard = value;\n this.#emit();\n }\n\n itemSnapshot = (id: string): ItemSnapshot => {\n const item = this.#renderedById().get(id);\n const isDragging = this.#session?.activeId === id;\n const hidden = isDragging && this.#session?.kind === \"move\" && !this.#keyboard;\n const prev = this.#itemCache.get(id);\n if (\n prev &&\n prev.isDragging === isDragging &&\n prev.hidden === hidden &&\n sameItem(prev.item, item)\n ) {\n return prev;\n }\n const snap: ItemSnapshot = { item, isDragging, hidden };\n this.#itemCache.set(id, snap);\n return snap;\n };\n\n placeholderSnapshot = (): LayoutItem | null => {\n const next = this.#session?.placeholder ?? null;\n if (sameItem(this.#placeholderCache ?? undefined, next ?? undefined)) {\n return this.#placeholderCache;\n }\n this.#placeholderCache = next;\n return next;\n };\n\n resizeSnapshot = (itemId: string): ResizeSnapshot => {\n const isResizing = this.#session?.kind === \"resize\" && this.#session.activeId === itemId;\n const prev = this.#resizeCache.get(itemId);\n if (prev && prev.isResizing === isResizing) return prev;\n const snap: ResizeSnapshot = { isResizing };\n this.#resizeCache.set(itemId, snap);\n return snap;\n };\n\n renderedSnapshot = (): Layout => this.#rendered();\n\n /** A stable index for `id` (see {@link GridController.#indexById}). */\n itemIndex(id: string): number {\n let i = this.#indexById.get(id);\n if (i === undefined) {\n i = this.#nextIndex++;\n this.#indexById.set(id, i);\n }\n return i;\n }\n}\n","import type { GridController } from \"./GridController.js\";\n\n/**\n * Resolves a grid's {@link GridController} by its id, scoped to the dnd-kit\n * manager the grid is registered with. A container registers its controller\n * here (during render, so child items resolve it on their first render); items\n * look it up by their `group` (= the grid id). Replaces the old geometry\n * `GridRegistry` — which grid the pointer is over now comes from the collision\n * target, so the registry's only job is id → controller resolution.\n *\n * Keyed by manager so two apps (or two providers) never collide, and grids in\n * one provider share a map (the cross-grid seam).\n */\nconst byManager = new WeakMap<object, Map<string, GridController>>();\n// Used when there is no manager yet (no <DragDropProvider> above) — degenerate\n// but keeps lookups total instead of throwing.\nconst noManager = new Map<string, GridController>();\n\nfunction mapFor(manager: object | null | undefined): Map<string, GridController> {\n if (!manager) return noManager;\n let map = byManager.get(manager);\n if (!map) {\n map = new Map();\n byManager.set(manager, map);\n }\n return map;\n}\n\n/** Register a controller under `id` for `manager`. Returns an unregister fn. */\nexport function registerController(\n manager: object | null | undefined,\n id: string,\n controller: GridController,\n): () => void {\n const map = mapFor(manager);\n map.set(id, controller);\n return () => {\n if (map.get(id) === controller) map.delete(id);\n };\n}\n\n/** The controller registered under `id` for `manager`, or undefined. */\nexport function getController(\n manager: object | null | undefined,\n id: string,\n): GridController | undefined {\n return mapFor(manager).get(id);\n}\n\n// The active drag's grab offset (pointer position within the dragged tile),\n// shared across grids on the same manager so a *receiving* grid maps the pointer\n// to the cell under the grabbed point, not the tile's corner. One drag at a time\n// per manager, so a single slot keyed by manager suffices.\nconst grabOffsets = new WeakMap<object, { x: number; y: number }>();\nconst noManagerGrab = { current: null as { x: number; y: number } | null };\n\nexport function setGrabOffset(\n manager: object | null | undefined,\n offset: { x: number; y: number } | null,\n): void {\n if (!manager) {\n noManagerGrab.current = offset;\n return;\n }\n if (offset) grabOffsets.set(manager, offset);\n else grabOffsets.delete(manager);\n}\n\nexport function getGrabOffset(manager: object | null | undefined): { x: number; y: number } {\n const offset = manager ? grabOffsets.get(manager) : noManagerGrab.current;\n return offset ?? { x: 0, y: 0 };\n}\n","import { type PositionParams, calcXY } from \"@snapgridjs/core\";\nimport type { DropConfig, GridDropData } from \"../types.js\";\nimport type { SnapGridDragData } from \"./dragData.js\";\n\n/**\n * Pure decision helpers for the drag interaction so the tricky bits — grab-offset\n * cell mapping, the cross-grid drop lifecycle, and external-drop acceptance — are\n * unit-testable without a DOM or dnd-kit.\n */\n\n/** Read snapgrid's payload off a dnd-kit drag source. */\nexport function dragData(event: {\n operation: { source?: { data?: unknown } | null };\n}): SnapGridDragData | undefined {\n const data = event.operation.source?.data as { snapGrid?: SnapGridDragData } | undefined;\n return data?.snapGrid;\n}\n\n/** Size/id spec for an external (non-grid) draggable the grid may accept, or null. */\nexport function externalDropSpec(\n source: { id: string | number; type?: unknown; data?: unknown } | null | undefined,\n dropConfig: DropConfig | undefined,\n): { i?: string; w: number; h: number } | null {\n if (!dropConfig?.enabled || !source) return null;\n const data = source.data as { snapGrid?: unknown; snapGridDrop?: GridDropData } | undefined;\n if (data?.snapGrid) return null; // a grid item, not external\n if (dropConfig.accept && !dropConfig.accept(source)) return null;\n const spec = data?.snapGridDrop;\n return {\n i: spec?.i,\n // Fall back to react-grid-layout's `defaultDropConfig.defaultItem` (1×1) for parity.\n w: spec?.w ?? dropConfig.defaultItem?.w ?? 1,\n h: spec?.h ?? dropConfig.defaultItem?.h ?? 1,\n };\n}\n\n/**\n * Map a client-space pointer to a grid cell, accounting for where *within* the\n * dragged tile the pointer grabbed it. Subtracting the grab offset means the\n * tile's top-left (not the cursor) maps to the cell, so a received tile's\n * placeholder aligns with the floating overlay instead of jumping its corner to\n * the cursor. External drops pass `{ x: 0, y: 0 }` (no meaningful grab point).\n */\nexport function receiveCell(\n pointer: { x: number; y: number },\n gridRect: { left: number; top: number },\n grabOffset: { x: number; y: number },\n w: number,\n h: number,\n pp: PositionParams,\n): { x: number; y: number } {\n return calcXY(\n pp,\n pointer.y - grabOffset.y - gridRect.top,\n pointer.x - grabOffset.x - gridRect.left,\n w,\n h,\n );\n}\n\n/**\n * Map a keyboard event key to a one-cell grid step while a keyboard drag is\n * active, or null for keys snapgrid doesn't own — Enter/Space (drop) and Escape\n * (cancel) fall through to dnd-kit's KeyboardSensor.\n */\nexport function arrowStep(key: string): [number, number] | null {\n switch (key) {\n case \"ArrowLeft\":\n return [-1, 0];\n case \"ArrowRight\":\n return [1, 0];\n case \"ArrowUp\":\n return [0, -1];\n case \"ArrowDown\":\n return [0, 1];\n default:\n return null;\n }\n}\n\n/**\n * Which grid a drop commits to, as fed to {@link classifyDrop} as `dest`. A\n * keyboard drag has no pointer, so it can only ever land in its own grid; a\n * pointer drag lands in whichever grid the collision observer resolved (or none).\n */\nexport function dropDestination(opts: {\n keyboard: boolean;\n targetId: string | number | null | undefined;\n myId: string;\n}): string | null {\n if (opts.keyboard) return opts.myId;\n return opts.targetId != null ? String(opts.targetId) : null;\n}\n\n/** State gathered by the drag-end handler, fed to {@link classifyDrop}. */\nexport interface DropState {\n /** Kind of the in-progress session, or null if there is none. */\n kind: \"move\" | \"resize\" | null;\n /** Whether the drag was canceled (Esc / abort). */\n canceled: boolean;\n /** Does THIS grid own the dragged item (i.e. it is the source)? */\n ownsItem: boolean;\n /** Is the drag source a grid item (vs. an external draggable)? */\n hasData: boolean;\n /** Id of the grid under the drop pointer, or null if none. */\n dest: string | null;\n /** This grid's id. */\n myId: string;\n}\n\n/**\n * What the drag-end handler should do. Each action implies a specific set of\n * callbacks — encoded here so the cross-grid lifecycle contract is explicit and\n * testable:\n * - `commit-in-grid` / `remove-source` / `revert` all fire `onDragStop` (the\n * SOURCE grid owns the drag's start/stop pair);\n * - `commit-dest` fires only `onLayoutChange` — the destination grid never\n * fired `onDragStart`, so emitting `onDragStop` there would be unbalanced.\n */\nexport type DropAction =\n | \"cancel-resize\"\n | \"cancel-move\"\n | \"commit-resize\"\n | \"commit-in-grid\"\n | \"remove-source\"\n | \"revert\"\n | \"commit-dest\"\n | \"external-drop\"\n | \"noop\";\n\n/** Pure classification of a drag end. See {@link DropAction}. */\nexport function classifyDrop(s: DropState): DropAction {\n if (s.canceled) {\n if (s.kind === \"resize\") return \"cancel-resize\";\n if (s.ownsItem) return \"cancel-move\";\n return \"noop\";\n }\n if (s.kind === \"resize\") return \"commit-resize\";\n\n if (s.ownsItem && s.hasData) {\n if (s.dest === s.myId && s.kind === \"move\") return \"commit-in-grid\";\n if (s.dest) return \"remove-source\";\n return \"revert\";\n }\n\n // Not the owner: we can only be a receiving grid, and only with a session.\n if (s.dest === s.myId && s.kind === \"move\") {\n return s.hasData ? \"commit-dest\" : \"external-drop\";\n }\n return \"noop\";\n}\n","/**\n * The DOM element of a dnd-kit entity (a draggable, droppable, or drag source).\n * dnd-kit's abstract types don't expose `element`, but the DOM layer snapgrid\n * runs on always sets it — this centralizes that one assumption (and the cast)\n * in a single place instead of scattering it across the drag code.\n */\nexport function domElement(entity: object | null | undefined): Element | null {\n return (entity as { element?: Element | null } | null | undefined)?.element ?? null;\n}\n","import type { DragDropManager } from \"@dnd-kit/dom\";\nimport {\n type LayoutItem,\n beginDrag,\n beginReceive,\n beginResize,\n calcGridItemPosition,\n commitLayout,\n dragResize,\n dragTo,\n hideActive,\n nudge,\n removeItemWithCompactor,\n} from \"@snapgridjs/core\";\nimport type { GridController } from \"../controller/GridController.js\";\nimport { getController, getGrabOffset, setGrabOffset } from \"../controller/registry.js\";\nimport type { SnapGridDragData } from \"./dragData.js\";\nimport { arrowStep, classifyDrop, dragData, externalDropSpec, receiveCell } from \"./dragFlow.js\";\nimport { domElement } from \"./entity.js\";\n\n/**\n * The drag/resize/receive engine — ONE per dnd-kit manager, driving every grid\n * on it. Previously this logic lived in each grid's `useGridController` (N grids\n * = N monitors); centralizing it makes the brain framework-agnostic (it touches\n * no React) and lets a tile cross grids through one set of handlers. Per-grid\n * geometry, compaction, gates, and callbacks are read from each grid's published\n * {@link GridController} config; which grid the pointer is over comes from the\n * collision target, and the source grid from the drag payload's `group`.\n *\n * Attached via {@link attachEngine} (a per-manager, ref-counted singleton) so it\n * works the same whether the turnkey components own the `DragDropProvider` or a\n * headless consumer supplies their own — no provider plugin registration needed.\n */\n\ntype Point = { x: number; y: number };\ntype DragSource = { id: string | number; type?: unknown; data?: unknown } | null;\n\nconst hasWindow = typeof window !== \"undefined\";\n\nfunction dragCtx(ctrl: GridController) {\n const cfg = ctrl.config!;\n return {\n positionParams: cfg.positionParams,\n compactor: cfg.compactor,\n cols: cfg.gridConfig.cols,\n };\n}\n\n/** Map a client-space pointer to a cell within `ctrl`, via its element rect. */\nfunction cellFromPointer(\n ctrl: GridController,\n pointer: Point,\n item: { w: number; h: number },\n manager: DragDropManager,\n): Point | null {\n const el = ctrl.element;\n const cfg = ctrl.config;\n if (!el || !cfg) return null;\n const rect = el.getBoundingClientRect();\n return receiveCell(pointer, rect, getGrabOffset(manager), item.w, item.h, cfg.positionParams);\n}\n\nclass SnapGridEngine {\n #manager: DragDropManager;\n #unsub: Array<() => void> = [];\n\n // Active-drag state — one drag at a time per manager.\n #source: GridController | null = null; // the owning grid (move/resize)\n #dest: GridController | null = null; // current receiving grid (≠ source), if any\n #keyboard = false;\n #dropSpec: { i: string; w: number; h: number } | null = null; // external draggable\n #dropCounter = 0;\n // Per-drag cache so a continuous drag (pointer over one grid for many frames)\n // doesn't re-resolve the destination controller on every move.\n #lastTargetId: string | number | null = null;\n #lastDest: GridController | undefined = undefined;\n\n constructor(manager: DragDropManager) {\n this.#manager = manager;\n const mon = manager.monitor;\n this.#unsub.push(\n mon.addEventListener(\"dragstart\", (event) => {\n const op = event.operation;\n const p = op.position.current;\n this.#start(\n dragData(event),\n { x: p.x, y: p.y },\n op.source as DragSource,\n op.activatorEvent,\n );\n }),\n mon.addEventListener(\"dragmove\", (event) => {\n const op = event.operation;\n const p = op.position.current;\n this.#move(\n dragData(event),\n { x: p.x, y: p.y },\n op.source as DragSource,\n op.target?.id ?? null,\n op.activatorEvent,\n );\n }),\n mon.addEventListener(\"dragend\", (event) => {\n const op = event.operation;\n this.#end(\n dragData(event),\n op.target?.id ?? null,\n event.nativeEvent ?? null,\n event.canceled,\n );\n }),\n );\n // Keyboard dragging needs a window listener; guard so a framework-agnostic\n // binding can construct the engine in a non-DOM (SSR) context without throwing.\n if (hasWindow) window.addEventListener(\"keydown\", this.#onKeyDown, true);\n }\n\n destroy(): void {\n for (const u of this.#unsub) u();\n this.#unsub = [];\n if (hasWindow) window.removeEventListener(\"keydown\", this.#onKeyDown, true);\n }\n\n #reset(): void {\n this.#source = null;\n this.#dest = null;\n this.#keyboard = false;\n this.#dropSpec = null;\n this.#lastTargetId = null;\n this.#lastDest = undefined;\n }\n\n /** Resolve the grid under the pointer from the collision target id (cached per drag). */\n #resolveDest(targetId: string | number | null): GridController | undefined {\n if (targetId == null) return undefined;\n if (targetId !== this.#lastTargetId) {\n this.#lastTargetId = targetId;\n this.#lastDest = getController(this.#manager, String(targetId));\n }\n return this.#lastDest;\n }\n\n // Switch the current receiving grid, clearing the previous one's preview (unless\n // it's the source grid, whose own session is managed separately).\n #setDest(next: GridController | null): void {\n if (this.#dest && this.#dest !== next && this.#dest !== this.#source) {\n this.#dest.setSession(null);\n }\n this.#dest = next;\n }\n\n #start(\n data: SnapGridDragData | undefined,\n pointer: Point,\n source: DragSource,\n activatorEvent: Event | null,\n ): void {\n this.#reset();\n if (!data) return; // external: spec is minted lazily on move over an accepting grid\n const owner = getController(this.#manager, data.group);\n const cfg = owner?.config;\n if (!owner || !cfg) return;\n const layout = owner.getCommitted();\n const item = layout.find((it) => it.i === data.itemId);\n if (!item) return;\n\n if (data.kind === \"resize\") {\n const rect = calcGridItemPosition(cfg.positionParams, item.x, item.y, item.w, item.h);\n owner.setSession(beginResize(layout, { item, rect, pointer }, data.handle));\n this.#source = owner;\n owner.setKeyboard(false); // clear any stale flag; resize is never keyboard-flagged\n cfg.callbacks.onResizeStart?.(layout, item, item, item, activatorEvent, null);\n return;\n }\n\n const isKeyboard = hasWindow && activatorEvent instanceof KeyboardEvent;\n this.#keyboard = isKeyboard;\n owner.setKeyboard(isKeyboard);\n const rect = calcGridItemPosition(cfg.positionParams, item.x, item.y, item.w, item.h);\n owner.setSession(beginDrag(layout, { item, left: rect.left, top: rect.top, pointer }));\n this.#source = owner;\n // Share the grab offset (pointer within the tile) so a receiving grid maps the\n // pointer to the cell under the grabbed point, not the tile's corner.\n const cr = domElement(source)?.getBoundingClientRect();\n if (cr) setGrabOffset(this.#manager, { x: pointer.x - cr.left, y: pointer.y - cr.top });\n cfg.callbacks.onDragStart?.(layout, item, item, item, activatorEvent, null);\n }\n\n #move(\n data: SnapGridDragData | undefined,\n pointer: Point,\n source: DragSource,\n targetId: string | number | null,\n activatorEvent: Event | null,\n ): void {\n if (this.#keyboard) return; // keyboard moves are driven by the arrow-key handler\n const owner = this.#source;\n\n // Resize: advance the source grid's resize session.\n const ownerSession = owner?.getSession();\n if (owner && ownerSession?.kind === \"resize\") {\n const cfg = owner.config!;\n const next = dragResize(ownerSession, pointer, dragCtx(owner));\n owner.setSession(next);\n cfg.callbacks.onResize?.(\n next.preview,\n next.anchor.item,\n next.placeholder,\n next.placeholder,\n activatorEvent,\n null,\n );\n return;\n }\n\n const destCtrl = this.#resolveDest(targetId);\n\n if (!data) {\n // External (non-grid) draggable: preview where it would land over a grid that accepts it.\n this.#setDest(destCtrl ? this.#receiveExternalInto(destCtrl, source, pointer) : null);\n return;\n }\n if (data.kind !== \"move\") return;\n\n // Moving within the source grid.\n if (owner && destCtrl === owner) {\n this.#setDest(null);\n const cur = owner.getSession();\n if (!cur) return;\n const cfg = owner.config!;\n const next = dragTo(cur, pointer, dragCtx(owner));\n owner.setSession(next);\n cfg.callbacks.onDrag?.(\n next.preview,\n next.anchor.item,\n next.placeholder,\n next.placeholder,\n activatorEvent,\n null,\n );\n return;\n }\n\n // Leaving the source grid (if we resolved one): hide its placeholder, keep its\n // items in place (the dragged tile floats itself across grids — no overlay).\n if (owner) {\n const cur = owner.getSession();\n if (cur) {\n const cfg = owner.config!;\n const hidden = hideActive(cur);\n owner.setSession(hidden);\n cfg.callbacks.onDrag?.(\n hidden.preview,\n hidden.anchor.item,\n null,\n null,\n activatorEvent,\n null,\n );\n }\n }\n // Receive the tile into the destination grid. Independent of whether the source\n // grid resolved, so a desynced source can't block another grid from receiving.\n this.#setDest(\n destCtrl && destCtrl !== owner ? this.#receiveInto(destCtrl, data.item, pointer) : null,\n );\n }\n\n /** Build a receive preview for `foreign` in `dest`; returns `dest` on success, else null. */\n #receiveInto(dest: GridController, foreign: LayoutItem, pointer: Point): GridController | null {\n if (!dest.config) return null;\n const committed = dest.getCommitted();\n const cell = cellFromPointer(dest, pointer, foreign, this.#manager) ?? { x: 0, y: 0 };\n dest.setSession(beginReceive(committed, foreign, cell.x, cell.y, pointer, dragCtx(dest)));\n return dest;\n }\n\n /** Receive an external (non-grid) draggable into `dest`, synthesizing its item. */\n #receiveExternalInto(\n dest: GridController,\n source: DragSource,\n pointer: Point,\n ): GridController | null {\n const spec = this.#externalSpecFor(dest, source);\n if (!spec) return null;\n return this.#receiveInto(dest, { i: spec.i, x: 0, y: 0, w: spec.w, h: spec.h }, pointer);\n }\n\n // Synthesize a stable id/size for an external draggable the first time it's over\n // an accepting grid; re-check acceptance per grid, but keep the id stable so the\n // preview item doesn't churn as the pointer moves between grids.\n #externalSpecFor(\n dest: GridController,\n source: DragSource,\n ): { i: string; w: number; h: number } | null {\n const spec = externalDropSpec(source, dest.config?.dropConfig);\n if (!spec) return null;\n if (!this.#dropSpec) {\n this.#dropCounter += 1;\n this.#dropSpec = {\n i: spec.i ?? `${dest.id}-dropped-${this.#dropCounter}`,\n w: spec.w,\n h: spec.h,\n };\n }\n return this.#dropSpec;\n }\n\n #end(\n data: SnapGridDragData | undefined,\n targetId: string | number | null,\n nativeEvent: Event | null,\n canceled: boolean,\n ): void {\n const source = this.#source;\n const dest = this.#dest;\n try {\n // Source grid (the owner): owns the drag's start/stop pair and the resize path.\n if (source) {\n const cfg = source.config!;\n const cur = source.getSession();\n // The item leaves the source ONLY if a grid actually received it (a live\n // receive session in #dest). Otherwise it's an in-grid move (pointer/keyboard\n // over the source) or a revert — never a remove keyed off a racy drop target\n // that no grid committed (which would lose the tile).\n const destId = dest\n ? dest.id\n : this.#keyboard || (targetId != null && String(targetId) === source.id)\n ? source.id\n : null;\n const action = classifyDrop({\n kind: cur?.kind ?? null,\n canceled,\n ownsItem: true,\n hasData: !!data,\n dest: destId,\n myId: source.id,\n });\n switch (action) {\n case \"cancel-resize\":\n cfg.callbacks.onResizeStop?.(\n source.getCommitted(),\n cur?.anchor.item ?? null,\n null,\n null,\n nativeEvent,\n null,\n );\n break;\n case \"cancel-move\":\n cfg.callbacks.onDragStop?.(\n source.getCommitted(),\n cur?.anchor.item ?? null,\n null,\n null,\n nativeEvent,\n null,\n );\n break;\n case \"commit-resize\":\n if (cur) {\n cfg.callbacks.onLayoutChange?.(commitLayout(cur));\n cfg.callbacks.onResizeStop?.(\n cur.preview,\n cur.anchor.item,\n cur.placeholder,\n cur.placeholder,\n nativeEvent,\n null,\n );\n }\n break;\n case \"commit-in-grid\":\n case \"remove-source\":\n case \"revert\": {\n if (action === \"commit-in-grid\" && cur) {\n cfg.callbacks.onLayoutChange?.(commitLayout(cur));\n } else if (action === \"remove-source\" && data) {\n const { compactor, cols } = dragCtx(source);\n cfg.callbacks.onLayoutChange?.(\n removeItemWithCompactor(source.getCommitted(), data.itemId, { compactor, cols }),\n );\n } // \"revert\" → dropped outside any grid → no layout change.\n cfg.callbacks.onDragStop?.(\n cur?.preview ?? source.getCommitted(),\n cur?.anchor.item ?? null,\n cur?.placeholder ?? null,\n cur?.placeholder ?? null,\n nativeEvent,\n null,\n );\n break;\n }\n }\n }\n\n // Destination grid (receiver): #dest holds the live receive session, so it IS\n // the landing grid — commit it regardless of the (possibly racy) drop target.\n if (dest && dest !== source) {\n const cfg = dest.config!;\n const cur = dest.getSession();\n const action = classifyDrop({\n kind: cur?.kind ?? null,\n canceled,\n ownsItem: false,\n hasData: !!data,\n dest: dest.id,\n myId: dest.id,\n });\n if (action === \"commit-dest\") {\n if (cur) cfg.callbacks.onLayoutChange?.(commitLayout(cur));\n } else if (action === \"external-drop\" && cur) {\n const committed = commitLayout(cur);\n const dropped = committed.find((it) => it.i === cur.activeId);\n if (dropped) cfg.callbacks.onDrop?.(committed, dropped, nativeEvent);\n }\n }\n } finally {\n // Always clean up, even if a consumer callback above threw — otherwise a stale\n // session / keyboard flag / grab offset would leak into the next drag.\n setGrabOffset(this.#manager, null);\n source?.setKeyboard(false);\n source?.setSession(null);\n if (dest && dest !== source) dest.setSession(null);\n this.#reset();\n }\n }\n\n #onKeyDown = (e: KeyboardEvent): void => {\n if (!this.#keyboard) return;\n const source = this.#source;\n const session = source?.getSession();\n if (!source || !session || session.kind !== \"move\") return;\n const step = arrowStep(e.key);\n if (!step) return; // Enter/Space (drop) and Escape (cancel) → dnd-kit's KeyboardSensor\n e.preventDefault();\n // Own the arrow: stop dnd-kit's KeyboardSensor (a document capture listener) from\n // also moving — we run in capture on window, ahead of it.\n e.stopImmediatePropagation();\n source.setSession(nudge(session, step[0], step[1], dragCtx(source)));\n };\n}\n\n// One engine per manager, ref-counted by the number of mounted grids so the\n// monitor + window listeners are torn down when the last grid for a manager\n// unmounts (no leak holding the manager alive via the window keydown listener).\nconst engines = new WeakMap<DragDropManager, { engine: SnapGridEngine; refs: number }>();\n\n/** Ensure the engine is attached to `manager`; returns a detach (ref-decrement) fn. */\nexport function attachEngine(manager: DragDropManager): () => void {\n let entry = engines.get(manager);\n if (!entry) {\n entry = { engine: new SnapGridEngine(manager), refs: 0 };\n engines.set(manager, entry);\n }\n entry.refs += 1;\n // Idempotent: a binding (or a double-invoked effect cleanup) calling detach twice\n // must not over-decrement and tear the engine down while other grids are mounted.\n let detached = false;\n return () => {\n if (detached) return;\n detached = true;\n const e = engines.get(manager);\n if (!e) return;\n e.refs -= 1;\n if (e.refs <= 0) {\n e.engine.destroy();\n engines.delete(manager);\n }\n };\n}\n","import {\n type Compactor,\n type Layout,\n type LayoutItem,\n type PositionParams,\n insertItemWithCompactor,\n} from \"@snapgridjs/core\";\nimport type { SnapGridDragData } from \"./dnd/dragData.js\";\nimport { receiveCell } from \"./dnd/dragFlow.js\";\nimport { domElement } from \"./dnd/entity.js\";\n\n/**\n * The 2-D grid analog of dnd-kit's `move(items, event)` helper — call it from your\n * own `onDragOver`/`onDragEnd` to place the dragged item into a grid's `Layout` at\n * the cell under the pointer (with compaction), and get the new layout back.\n *\n * This is the consumer-facing reducer for **interop with the wider dnd-kit\n * ecosystem** — e.g. dragging a `useSortable` card into a grid, or a grid tile\n * between a grid and a sortable list. At a cross-parent seam (grid ⇄ list) you\n * MUST reduce live in `onDragOver` (dnd-kit reparents the node mid-drag; reducing\n * only on drop desyncs React and throws `removeChild`). Pure snapgrid grids don't\n * need this — their managed engine already handles in-grid and cross-grid drags.\n *\n * The dragged item's size comes from a grid tile's payload (`data.snapGrid.item`)\n * when present, else from `ctx.defaultItem` (default 1×1) for a foreign source.\n */\nexport interface SnapMoveContext {\n positionParams: PositionParams;\n compactor: Compactor;\n /** Size for a foreign (non-grid) source that carries no snapgrid item. @default {w:1,h:1} */\n defaultItem?: { w: number; h: number };\n /** Override the grid's client rect (else read from the target droppable's element). */\n gridRect?: { left: number; top: number };\n}\n\n/** The dnd-kit drag event shape `snapMove` reads (a `dragover`/`dragend` event). */\nexport interface SnapMoveEvent {\n operation: {\n source: { id: string | number; data?: unknown } | null;\n target: object | null;\n position: { current: { x: number; y: number } };\n };\n}\n\n/** Place the event's dragged item into `layout` at the pointer cell; returns the new layout. */\nexport function snapMove(layout: Layout, event: SnapMoveEvent, ctx: SnapMoveContext): Layout {\n const op = event.operation;\n const source = op.source;\n if (!source) return layout;\n\n const id = String(source.id);\n const data = (source.data as { snapGrid?: SnapGridDragData } | undefined)?.snapGrid;\n const size =\n data?.kind === \"move\"\n ? { w: data.item.w, h: data.item.h }\n : (ctx.defaultItem ?? { w: 1, h: 1 });\n\n const rect = ctx.gridRect ??\n domElement(op.target)?.getBoundingClientRect() ?? { left: 0, top: 0 };\n const p = op.position.current;\n const cell = receiveCell(\n { x: p.x, y: p.y },\n rect,\n { x: 0, y: 0 },\n size.w,\n size.h,\n ctx.positionParams,\n );\n\n const item: LayoutItem = { i: id, x: cell.x, y: cell.y, w: size.w, h: size.h };\n // insertItemWithCompactor moves the item if it already exists in `layout`, or\n // inserts it (displacing the occupant of the target cell) if it's new.\n return insertItemWithCompactor(layout, item, cell.x, cell.y, {\n compactor: ctx.compactor,\n cols: ctx.positionParams.cols,\n });\n}\n","import { type CollisionDetector, pointerIntersection } from \"@dnd-kit/collision\";\nimport { domElement } from \"./entity.js\";\n\n/**\n * Marker attribute set on every grid container element. Used by {@link gridDepth}\n * to measure how deeply a grid is nested, purely from the DOM.\n */\nexport const SNAPGRID_GRID_ATTR = \"data-snapgrid-grid\";\n\n// Base priority for a grid droppable. Outranks a dragged tile's own sortable\n// droppable so collision inside a grid resolves to the container (RGL drives the\n// move, not dnd-kit's sortable reorder), and lets a foreign sortable resolve the\n// grid as its drop target. `gridDepth` adds to this so an inner grid outranks its\n// outer one when their rects overlap.\nconst GRID_COLLISION_PRIORITY = 10;\n\n/**\n * How deeply `el`'s grid is nested: the number of ancestor grid containers above\n * it. A top-level grid is 0; a grid rendered inside another grid's tile is 1; and\n * so on. DOM containment is the ground truth, so this is correct regardless of the\n * React tree shape or how priorities are assigned elsewhere.\n */\nexport function gridDepth(el: Element | null | undefined): number {\n let depth = 0;\n let node = el?.parentElement ?? null;\n while (node) {\n if (node.hasAttribute(SNAPGRID_GRID_ATTR)) depth++;\n node = node.parentElement;\n }\n return depth;\n}\n\n/**\n * Collision detector for grid droppables. Uses **pointer** intersection (not\n * dnd-kit's default, which is pointer-first but falls back to the dragged SHAPE\n * when the pointer leaves a droppable): a grid claims a drag only while the\n * pointer is genuinely inside it. The shape fallback was actively wrong here —\n * the grid's priority boost (below) made a large dragged tile keep winning the\n * grid via mere rect-overlap even after the pointer moved off onto a sibling\n * droppable (e.g. a sortable card beside the grid), so the tile could never\n * leave the grid for that target. Pointer-only also aligns collision with the\n * receive math, which maps the pointer (not the tile rect) to a cell.\n *\n * When the pointer IS inside, rank the grid above the dragged tile's own\n * sortable droppable (so an in-grid move resolves to the container, letting RGL\n * drive it — not dnd-kit's sortable reorder) and above a sibling droppable the\n * pointer also happens to be over. For nested grids whose rects overlap (the\n * pointer is over both an inner grid and its outer one), boost priority by the\n * grid's nesting depth so the **innermost** grid wins; for non-nested grids\n * depth is 0, so priority is unchanged.\n */\nexport const gridCollisionDetector: CollisionDetector = (input) => {\n const collision = pointerIntersection(input);\n if (!collision) return null;\n return {\n ...collision,\n priority: GRID_COLLISION_PRIORITY + gridDepth(domElement(input.droppable)),\n };\n};\n","import { Modifier } from \"@dnd-kit/abstract\";\nimport type { DragDropManager } from \"@dnd-kit/dom\";\nimport { type PositionParams, calcGridColWidth } from \"@snapgridjs/core\";\n\nexport interface SnapToGridOptions {\n /** Current geometry (changes with container width). Read fresh each apply(). */\n getPositionParams: () => PositionParams;\n /** Whether snapping is currently enabled (dragConfig.snapToGrid). */\n isEnabled: () => boolean;\n}\n\n/**\n * Quantizes the dragged item's transform to whole grid cells, so the floating\n * <DragOverlay> clone jumps cell-to-cell in lockstep with the (always-snapped)\n * placeholder instead of tracking the pointer smoothly. Applied on the item\n * draggable; a no-op unless `dragConfig.snapToGrid` is set.\n */\nexport class SnapToGrid extends Modifier<DragDropManager, SnapToGridOptions> {\n override apply({ transform }: DragDropManager[\"dragOperation\"]) {\n const opts = this.options;\n if (!opts?.isEnabled()) return transform;\n const pp = opts.getPositionParams();\n // A cell step is the column/row size plus the gap to the next cell.\n const colStep = calcGridColWidth(pp) + pp.margin[0];\n const rowStep = pp.rowHeight + pp.margin[1];\n if (colStep <= 0 || rowStep <= 0) return transform; // guard degenerate geometry\n return {\n x: Math.round(transform.x / colStep) * colStep,\n y: Math.round(transform.y / rowStep) * rowStep,\n };\n }\n}\n","import {\n Feedback,\n KeyboardSensor,\n PointerActivationConstraints,\n PointerSensor,\n type Sensors,\n} from \"@dnd-kit/dom\";\nimport type { DragConfig } from \"./types.js\";\n\n/** Marker attribute placed on resize-handle elements. */\nexport const RESIZE_HANDLE_ATTR = \"data-snapgrid-resize-handle\";\n\n// Resize handles are draggables too, but resizing isn't a move — there's no tile\n// to float — so they suppress dnd-kit's visual feedback entirely.\nexport const NO_FEEDBACK = [Feedback.configure({ feedback: \"none\" })];\n\n/**\n * Whether a pointer-down on `target` should NOT start an item move. Pure and\n * exported for testing. Honors three rules, in order:\n * - never start a move from a resize handle;\n * - never start from a region matching `dragConfig.cancel`;\n * - if `dragConfig.handle` is set, only start from within it.\n */\nexport function shouldPreventItemDrag(\n target: EventTarget | null,\n cfg: DragConfig | undefined,\n): boolean {\n if (!(target instanceof Element)) return false;\n if (target.closest(`[${RESIZE_HANDLE_ATTR}]`)) return true;\n if (cfg?.cancel && target.closest(cfg.cancel)) return true;\n if (cfg?.handle && !target.closest(cfg.handle)) return true;\n return false;\n}\n\n/**\n * Sensors for item (move) draggables, built from the drag config: a distance\n * activation threshold (so clicks don't start drags) plus handle/cancel/resize\n * gating, with the keyboard sensor kept for accessibility.\n */\nexport function buildItemSensors(\n threshold: number,\n getDragConfig: () => DragConfig | undefined,\n): Sensors {\n return [\n PointerSensor.configure({\n activationConstraints: () =>\n threshold > 0\n ? [new PointerActivationConstraints.Distance({ value: threshold })]\n : undefined,\n preventActivation: (event: PointerEvent) =>\n shouldPreventItemDrag(event.target, getDragConfig()),\n }),\n KeyboardSensor,\n ];\n}\n"],"mappings":";;;;;AAkEA,SAAS,SAAS,GAA2B,GAAoC;CAC/E,IAAI,MAAM,GAAG,OAAO;CACpB,IAAI,CAAC,KAAK,CAAC,GAAG,OAAO;CAKrB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;AAC/E;;;;;;;;AASA,IAAa,iBAAb,MAA4B;CAC1B;CACA;CACA,WAA+B;CAG/B,YAAY;CACZ,6BAAa,IAAI,IAAgB;CAGjC,SAAsC;CAItC,6BAAa,IAAI,IAA0B;CAC3C,+BAAe,IAAI,IAA4B;CAC/C,oBAAuC;CAGvC,eAA+C;CAC/C,qBAAoC;CAOpC,6BAAa,IAAI,IAAoB;CACrC,aAAa;;CAGb;;;;;CAMA,UAA0B;CAE1B,YAAY,IAAY,YAAoB,CAAC,GAAG,SAA2B;EACzE,KAAK,KAAK;EACV,KAAKA,aAAa;EAClB,KAAK,UAAU;CACjB;;CAGA,eAAuB;EACrB,OAAO,KAAKA;CACd;;CAGA,UAAU,QAAoC;EAC5C,KAAK,SAAS;CAChB;;;;;;CAOA,MAAM,IAAkB;EACtB,KAAK,KAAK;CACZ;CAMA,iBAAuB,CAAC;CAExB,aAAa,aAAuC;EAClD,KAAKC,WAAW,IAAI,QAAQ;EAC5B,aAAa;GACX,KAAKA,WAAW,OAAO,QAAQ;EACjC;CACF;CAEA,QAAc;EACZ,KAAK,MAAM,YAAY,KAAKA,YAAY,SAAS;CACnD;;CAGA,YAAoB;EAClB,OAAO,KAAKC,WAAY,KAAKA,SAAS,UAAqB,KAAKF;CAClE;CAEA,gBAAyC;EACvC,MAAM,WAAW,KAAKG,UAAU;EAChC,IAAI,KAAKC,uBAAuB,UAAU;GACxC,KAAKC,eAAe,IAAI,IAAI,SAAS,KAAK,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;GAC5D,KAAKD,qBAAqB;EAC5B;EACA,OAAO,KAAKC;CACd;;;;;;;;CASA,aAAa,QAAsB;EACjC,IAAI,KAAKL,eAAe,QAAQ;EAChC,KAAKA,aAAa;EAGlB,MAAM,UAAU,IAAI,IAAI,OAAO,KAAK,OAAO,GAAG,CAAC,CAAC;EAChD,KAAK,MAAM,MAAM,KAAKM,WAAW,KAAK,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,GAAG,KAAKA,WAAW,OAAO,EAAE;EACxF,KAAK,MAAM,MAAM,KAAKC,WAAW,KAAK,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,GAAG,KAAKA,WAAW,OAAO,EAAE;EACxF,KAAK,MAAM,MAAM,KAAKC,aAAa,KAAK,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,GAAG,KAAKA,aAAa,OAAO,EAAE;CAC9F;CAEA,WAAW,MAAgC;EACzC,KAAKN,WAAW;EAChB,KAAKO,MAAM;CACb;CAEA,aAAiC;EAC/B,OAAO,KAAKP;CACd;;CAGA,YAAY,OAAsB;EAChC,IAAI,KAAKQ,cAAc,OAAO;EAC9B,KAAKA,YAAY;EACjB,KAAKD,MAAM;CACb;CAEA,gBAAgB,OAA6B;EAC3C,MAAM,OAAO,KAAKE,cAAc,EAAE,IAAI,EAAE;EACxC,MAAM,aAAa,KAAKT,UAAU,aAAa;EAC/C,MAAM,SAAS,cAAc,KAAKA,UAAU,SAAS,UAAU,CAAC,KAAKQ;EACrE,MAAM,OAAO,KAAKH,WAAW,IAAI,EAAE;EACnC,IACE,QACA,KAAK,eAAe,cACpB,KAAK,WAAW,UAChB,SAAS,KAAK,MAAM,IAAI,GAExB,OAAO;EAET,MAAM,OAAqB;GAAE;GAAM;GAAY;EAAO;EACtD,KAAKA,WAAW,IAAI,IAAI,IAAI;EAC5B,OAAO;CACT;CAEA,4BAA+C;EAC7C,MAAM,OAAO,KAAKL,UAAU,eAAe;EAC3C,IAAI,SAAS,KAAKU,qBAAqB,KAAA,GAAW,QAAQ,KAAA,CAAS,GACjE,OAAO,KAAKA;EAEd,KAAKA,oBAAoB;EACzB,OAAO;CACT;CAEA,kBAAkB,WAAmC;EACnD,MAAM,aAAa,KAAKV,UAAU,SAAS,YAAY,KAAKA,SAAS,aAAa;EAClF,MAAM,OAAO,KAAKM,aAAa,IAAI,MAAM;EACzC,IAAI,QAAQ,KAAK,eAAe,YAAY,OAAO;EACnD,MAAM,OAAuB,EAAE,WAAW;EAC1C,KAAKA,aAAa,IAAI,QAAQ,IAAI;EAClC,OAAO;CACT;CAEA,yBAAiC,KAAKL,UAAU;;CAGhD,UAAU,IAAoB;EAC5B,IAAI,IAAI,KAAKG,WAAW,IAAI,EAAE;EAC9B,IAAI,MAAM,KAAA,GAAW;GACnB,IAAI,KAAKO;GACT,KAAKP,WAAW,IAAI,IAAI,CAAC;EAC3B;EACA,OAAO;CACT;AACF;;;;;;;;;;;;;;ACtPA,MAAM,4BAAY,IAAI,QAA6C;AAGnE,MAAM,4BAAY,IAAI,IAA4B;AAElD,SAAS,OAAO,SAAiE;CAC/E,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI,MAAM,UAAU,IAAI,OAAO;CAC/B,IAAI,CAAC,KAAK;EACR,sBAAM,IAAI,IAAI;EACd,UAAU,IAAI,SAAS,GAAG;CAC5B;CACA,OAAO;AACT;;AAGA,SAAgB,mBACd,SACA,IACA,YACY;CACZ,MAAM,MAAM,OAAO,OAAO;CAC1B,IAAI,IAAI,IAAI,UAAU;CACtB,aAAa;EACX,IAAI,IAAI,IAAI,EAAE,MAAM,YAAY,IAAI,OAAO,EAAE;CAC/C;AACF;;AAGA,SAAgB,cACd,SACA,IAC4B;CAC5B,OAAO,OAAO,OAAO,EAAE,IAAI,EAAE;AAC/B;AAMA,MAAM,8BAAc,IAAI,QAA0C;AAClE,MAAM,gBAAgB,EAAE,SAAS,KAAwC;AAEzE,SAAgB,cACd,SACA,QACM;CACN,IAAI,CAAC,SAAS;EACZ,cAAc,UAAU;EACxB;CACF;CACA,IAAI,QAAQ,YAAY,IAAI,SAAS,MAAM;MACtC,YAAY,OAAO,OAAO;AACjC;AAEA,SAAgB,cAAc,SAA8D;CAE1F,QADe,UAAU,YAAY,IAAI,OAAO,IAAI,cAAc,YACjD;EAAE,GAAG;EAAG,GAAG;CAAE;AAChC;;;;;;;;;AC5DA,SAAgB,SAAS,OAEQ;CAE/B,QADa,MAAM,UAAU,QAAQ,OACxB;AACf;;AAGA,SAAgB,iBACd,QACA,YAC6C;CAC7C,IAAI,CAAC,YAAY,WAAW,CAAC,QAAQ,OAAO;CAC5C,MAAM,OAAO,OAAO;CACpB,IAAI,MAAM,UAAU,OAAO;CAC3B,IAAI,WAAW,UAAU,CAAC,WAAW,OAAO,MAAM,GAAG,OAAO;CAC5D,MAAM,OAAO,MAAM;CACnB,OAAO;EACL,GAAG,MAAM;EAET,GAAG,MAAM,KAAK,WAAW,aAAa,KAAK;EAC3C,GAAG,MAAM,KAAK,WAAW,aAAa,KAAK;CAC7C;AACF;;;;;;;;AASA,SAAgB,YACd,SACA,UACA,YACA,GACA,GACA,IAC0B;CAC1B,OAAO,OACL,IACA,QAAQ,IAAI,WAAW,IAAI,SAAS,KACpC,QAAQ,IAAI,WAAW,IAAI,SAAS,MACpC,GACA,CACF;AACF;;;;;;AAOA,SAAgB,UAAU,KAAsC;CAC9D,QAAQ,KAAR;EACE,KAAK,aACH,OAAO,CAAC,IAAI,CAAC;EACf,KAAK,cACH,OAAO,CAAC,GAAG,CAAC;EACd,KAAK,WACH,OAAO,CAAC,GAAG,EAAE;EACf,KAAK,aACH,OAAO,CAAC,GAAG,CAAC;EACd,SACE,OAAO;CACX;AACF;;AAqDA,SAAgB,aAAa,GAA0B;CACrD,IAAI,EAAE,UAAU;EACd,IAAI,EAAE,SAAS,UAAU,OAAO;EAChC,IAAI,EAAE,UAAU,OAAO;EACvB,OAAO;CACT;CACA,IAAI,EAAE,SAAS,UAAU,OAAO;CAEhC,IAAI,EAAE,YAAY,EAAE,SAAS;EAC3B,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,QAAQ,OAAO;EACnD,IAAI,EAAE,MAAM,OAAO;EACnB,OAAO;CACT;CAGA,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,QAClC,OAAO,EAAE,UAAU,gBAAgB;CAErC,OAAO;AACT;;;;;;;;;AChJA,SAAgB,WAAW,QAAmD;CAC5E,OAAQ,QAA4D,WAAW;AACjF;;;AC6BA,MAAM,YAAY,OAAO,WAAW;AAEpC,SAAS,QAAQ,MAAsB;CACrC,MAAM,MAAM,KAAK;CACjB,OAAO;EACL,gBAAgB,IAAI;EACpB,WAAW,IAAI;EACf,MAAM,IAAI,WAAW;CACvB;AACF;;AAGA,SAAS,gBACP,MACA,SACA,MACA,SACc;CACd,MAAM,KAAK,KAAK;CAChB,MAAM,MAAM,KAAK;CACjB,IAAI,CAAC,MAAM,CAAC,KAAK,OAAO;CAExB,OAAO,YAAY,SADN,GAAG,sBACe,GAAG,cAAc,OAAO,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,cAAc;AAC9F;AAEA,IAAM,iBAAN,MAAqB;CACnB;CACA,SAA4B,CAAC;CAG7B,UAAiC;CACjC,QAA+B;CAC/B,YAAY;CACZ,YAAwD;CACxD,eAAe;CAGf,gBAAwC;CACxC,YAAwC,KAAA;CAExC,YAAY,SAA0B;EACpC,KAAKQ,WAAW;EAChB,MAAM,MAAM,QAAQ;EACpB,KAAKC,OAAO,KACV,IAAI,iBAAiB,cAAc,UAAU;GAC3C,MAAM,KAAK,MAAM;GACjB,MAAM,IAAI,GAAG,SAAS;GACtB,KAAKC,OACH,SAAS,KAAK,GACd;IAAE,GAAG,EAAE;IAAG,GAAG,EAAE;GAAE,GACjB,GAAG,QACH,GAAG,cACL;EACF,CAAC,GACD,IAAI,iBAAiB,aAAa,UAAU;GAC1C,MAAM,KAAK,MAAM;GACjB,MAAM,IAAI,GAAG,SAAS;GACtB,KAAKC,MACH,SAAS,KAAK,GACd;IAAE,GAAG,EAAE;IAAG,GAAG,EAAE;GAAE,GACjB,GAAG,QACH,GAAG,QAAQ,MAAM,MACjB,GAAG,cACL;EACF,CAAC,GACD,IAAI,iBAAiB,YAAY,UAAU;GACzC,MAAM,KAAK,MAAM;GACjB,KAAKC,KACH,SAAS,KAAK,GACd,GAAG,QAAQ,MAAM,MACjB,MAAM,eAAe,MACrB,MAAM,QACR;EACF,CAAC,CACH;EAGA,IAAI,WAAW,OAAO,iBAAiB,WAAW,KAAKC,YAAY,IAAI;CACzE;CAEA,UAAgB;EACd,KAAK,MAAM,KAAK,KAAKJ,QAAQ,EAAE;EAC/B,KAAKA,SAAS,CAAC;EACf,IAAI,WAAW,OAAO,oBAAoB,WAAW,KAAKI,YAAY,IAAI;CAC5E;CAEA,SAAe;EACb,KAAKC,UAAU;EACf,KAAKC,QAAQ;EACb,KAAKC,YAAY;EACjB,KAAKC,YAAY;EACjB,KAAKC,gBAAgB;EACrB,KAAKC,YAAY,KAAA;CACnB;;CAGA,aAAa,UAA8D;EACzE,IAAI,YAAY,MAAM,OAAO,KAAA;EAC7B,IAAI,aAAa,KAAKD,eAAe;GACnC,KAAKA,gBAAgB;GACrB,KAAKC,YAAY,cAAc,KAAKX,UAAU,OAAO,QAAQ,CAAC;EAChE;EACA,OAAO,KAAKW;CACd;CAIA,SAAS,MAAmC;EAC1C,IAAI,KAAKJ,SAAS,KAAKA,UAAU,QAAQ,KAAKA,UAAU,KAAKD,SAC3D,KAAKC,MAAM,WAAW,IAAI;EAE5B,KAAKA,QAAQ;CACf;CAEA,OACE,MACA,SACA,QACA,gBACM;EACN,KAAKK,OAAO;EACZ,IAAI,CAAC,MAAM;EACX,MAAM,QAAQ,cAAc,KAAKZ,UAAU,KAAK,KAAK;EACrD,MAAM,MAAM,OAAO;EACnB,IAAI,CAAC,SAAS,CAAC,KAAK;EACpB,MAAM,SAAS,MAAM,aAAa;EAClC,MAAM,OAAO,OAAO,MAAM,OAAO,GAAG,MAAM,KAAK,MAAM;EACrD,IAAI,CAAC,MAAM;EAEX,IAAI,KAAK,SAAS,UAAU;GAC1B,MAAM,OAAO,qBAAqB,IAAI,gBAAgB,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;GACpF,MAAM,WAAW,YAAY,QAAQ;IAAE;IAAM;IAAM;GAAQ,GAAG,KAAK,MAAM,CAAC;GAC1E,KAAKM,UAAU;GACf,MAAM,YAAY,KAAK;GACvB,IAAI,UAAU,gBAAgB,QAAQ,MAAM,MAAM,MAAM,gBAAgB,IAAI;GAC5E;EACF;EAEA,MAAM,aAAa,aAAa,0BAA0B;EAC1D,KAAKE,YAAY;EACjB,MAAM,YAAY,UAAU;EAC5B,MAAM,OAAO,qBAAqB,IAAI,gBAAgB,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;EACpF,MAAM,WAAW,UAAU,QAAQ;GAAE;GAAM,MAAM,KAAK;GAAM,KAAK,KAAK;GAAK;EAAQ,CAAC,CAAC;EACrF,KAAKF,UAAU;EAGf,MAAM,KAAK,WAAW,MAAM,GAAG,sBAAsB;EACrD,IAAI,IAAI,cAAc,KAAKN,UAAU;GAAE,GAAG,QAAQ,IAAI,GAAG;GAAM,GAAG,QAAQ,IAAI,GAAG;EAAI,CAAC;EACtF,IAAI,UAAU,cAAc,QAAQ,MAAM,MAAM,MAAM,gBAAgB,IAAI;CAC5E;CAEA,MACE,MACA,SACA,QACA,UACA,gBACM;EACN,IAAI,KAAKQ,WAAW;EACpB,MAAM,QAAQ,KAAKF;EAGnB,MAAM,eAAe,OAAO,WAAW;EACvC,IAAI,SAAS,cAAc,SAAS,UAAU;GAC5C,MAAM,MAAM,MAAM;GAClB,MAAM,OAAO,WAAW,cAAc,SAAS,QAAQ,KAAK,CAAC;GAC7D,MAAM,WAAW,IAAI;GACrB,IAAI,UAAU,WACZ,KAAK,SACL,KAAK,OAAO,MACZ,KAAK,aACL,KAAK,aACL,gBACA,IACF;GACA;EACF;EAEA,MAAM,WAAW,KAAKO,aAAa,QAAQ;EAE3C,IAAI,CAAC,MAAM;GAET,KAAKC,SAAS,WAAW,KAAKC,qBAAqB,UAAU,QAAQ,OAAO,IAAI,IAAI;GACpF;EACF;EACA,IAAI,KAAK,SAAS,QAAQ;EAG1B,IAAI,SAAS,aAAa,OAAO;GAC/B,KAAKD,SAAS,IAAI;GAClB,MAAM,MAAM,MAAM,WAAW;GAC7B,IAAI,CAAC,KAAK;GACV,MAAM,MAAM,MAAM;GAClB,MAAM,OAAO,OAAO,KAAK,SAAS,QAAQ,KAAK,CAAC;GAChD,MAAM,WAAW,IAAI;GACrB,IAAI,UAAU,SACZ,KAAK,SACL,KAAK,OAAO,MACZ,KAAK,aACL,KAAK,aACL,gBACA,IACF;GACA;EACF;EAIA,IAAI,OAAO;GACT,MAAM,MAAM,MAAM,WAAW;GAC7B,IAAI,KAAK;IACP,MAAM,MAAM,MAAM;IAClB,MAAM,SAAS,WAAW,GAAG;IAC7B,MAAM,WAAW,MAAM;IACvB,IAAI,UAAU,SACZ,OAAO,SACP,OAAO,OAAO,MACd,MACA,MACA,gBACA,IACF;GACF;EACF;EAGA,KAAKA,SACH,YAAY,aAAa,QAAQ,KAAKE,aAAa,UAAU,KAAK,MAAM,OAAO,IAAI,IACrF;CACF;;CAGA,aAAa,MAAsB,SAAqB,SAAuC;EAC7F,IAAI,CAAC,KAAK,QAAQ,OAAO;EACzB,MAAM,YAAY,KAAK,aAAa;EACpC,MAAM,OAAO,gBAAgB,MAAM,SAAS,SAAS,KAAKhB,QAAQ,KAAK;GAAE,GAAG;GAAG,GAAG;EAAE;EACpF,KAAK,WAAW,aAAa,WAAW,SAAS,KAAK,GAAG,KAAK,GAAG,SAAS,QAAQ,IAAI,CAAC,CAAC;EACxF,OAAO;CACT;;CAGA,qBACE,MACA,QACA,SACuB;EACvB,MAAM,OAAO,KAAKiB,iBAAiB,MAAM,MAAM;EAC/C,IAAI,CAAC,MAAM,OAAO;EAClB,OAAO,KAAKD,aAAa,MAAM;GAAE,GAAG,KAAK;GAAG,GAAG;GAAG,GAAG;GAAG,GAAG,KAAK;GAAG,GAAG,KAAK;EAAE,GAAG,OAAO;CACzF;CAKA,iBACE,MACA,QAC4C;EAC5C,MAAM,OAAO,iBAAiB,QAAQ,KAAK,QAAQ,UAAU;EAC7D,IAAI,CAAC,MAAM,OAAO;EAClB,IAAI,CAAC,KAAKP,WAAW;GACnB,KAAKS,gBAAgB;GACrB,KAAKT,YAAY;IACf,GAAG,KAAK,KAAK,GAAG,KAAK,GAAG,WAAW,KAAKS;IACxC,GAAG,KAAK;IACR,GAAG,KAAK;GACV;EACF;EACA,OAAO,KAAKT;CACd;CAEA,KACE,MACA,UACA,aACA,UACM;EACN,MAAM,SAAS,KAAKH;EACpB,MAAM,OAAO,KAAKC;EAClB,IAAI;GAEF,IAAI,QAAQ;IACV,MAAM,MAAM,OAAO;IACnB,MAAM,MAAM,OAAO,WAAW;IAK9B,MAAM,SAAS,OACX,KAAK,KACL,KAAKC,aAAc,YAAY,QAAQ,OAAO,QAAQ,MAAM,OAAO,KACjE,OAAO,KACP;IACN,MAAM,SAAS,aAAa;KAC1B,MAAM,KAAK,QAAQ;KACnB;KACA,UAAU;KACV,SAAS,CAAC,CAAC;KACX,MAAM;KACN,MAAM,OAAO;IACf,CAAC;IACD,QAAQ,QAAR;KACE,KAAK;MACH,IAAI,UAAU,eACZ,OAAO,aAAa,GACpB,KAAK,OAAO,QAAQ,MACpB,MACA,MACA,aACA,IACF;MACA;KACF,KAAK;MACH,IAAI,UAAU,aACZ,OAAO,aAAa,GACpB,KAAK,OAAO,QAAQ,MACpB,MACA,MACA,aACA,IACF;MACA;KACF,KAAK;MACH,IAAI,KAAK;OACP,IAAI,UAAU,iBAAiB,aAAa,GAAG,CAAC;OAChD,IAAI,UAAU,eACZ,IAAI,SACJ,IAAI,OAAO,MACX,IAAI,aACJ,IAAI,aACJ,aACA,IACF;MACF;MACA;KACF,KAAK;KACL,KAAK;KACL,KAAK;MACH,IAAI,WAAW,oBAAoB,KACjC,IAAI,UAAU,iBAAiB,aAAa,GAAG,CAAC;WAC3C,IAAI,WAAW,mBAAmB,MAAM;OAC7C,MAAM,EAAE,WAAW,SAAS,QAAQ,MAAM;OAC1C,IAAI,UAAU,iBACZ,wBAAwB,OAAO,aAAa,GAAG,KAAK,QAAQ;QAAE;QAAW;OAAK,CAAC,CACjF;MACF;MACA,IAAI,UAAU,aACZ,KAAK,WAAW,OAAO,aAAa,GACpC,KAAK,OAAO,QAAQ,MACpB,KAAK,eAAe,MACpB,KAAK,eAAe,MACpB,aACA,IACF;MACA;IAEJ;GACF;GAIA,IAAI,QAAQ,SAAS,QAAQ;IAC3B,MAAM,MAAM,KAAK;IACjB,MAAM,MAAM,KAAK,WAAW;IAC5B,MAAM,SAAS,aAAa;KAC1B,MAAM,KAAK,QAAQ;KACnB;KACA,UAAU;KACV,SAAS,CAAC,CAAC;KACX,MAAM,KAAK;KACX,MAAM,KAAK;IACb,CAAC;IACD,IAAI,WAAW;SACT,KAAK,IAAI,UAAU,iBAAiB,aAAa,GAAG,CAAC;IAAA,OACpD,IAAI,WAAW,mBAAmB,KAAK;KAC5C,MAAM,YAAY,aAAa,GAAG;KAClC,MAAM,UAAU,UAAU,MAAM,OAAO,GAAG,MAAM,IAAI,QAAQ;KAC5D,IAAI,SAAS,IAAI,UAAU,SAAS,WAAW,SAAS,WAAW;IACrE;GACF;EACF,UAAU;GAGR,cAAc,KAAKR,UAAU,IAAI;GACjC,QAAQ,YAAY,KAAK;GACzB,QAAQ,WAAW,IAAI;GACvB,IAAI,QAAQ,SAAS,QAAQ,KAAK,WAAW,IAAI;GACjD,KAAKY,OAAO;EACd;CACF;CAEA,cAAc,MAA2B;EACvC,IAAI,CAAC,KAAKJ,WAAW;EACrB,MAAM,SAAS,KAAKF;EACpB,MAAM,UAAU,QAAQ,WAAW;EACnC,IAAI,CAAC,UAAU,CAAC,WAAW,QAAQ,SAAS,QAAQ;EACpD,MAAM,OAAO,UAAU,EAAE,GAAG;EAC5B,IAAI,CAAC,MAAM;EACX,EAAE,eAAe;EAGjB,EAAE,yBAAyB;EAC3B,OAAO,WAAW,MAAM,SAAS,KAAK,IAAI,KAAK,IAAI,QAAQ,MAAM,CAAC,CAAC;CACrE;AACF;AAKA,MAAM,0BAAU,IAAI,QAAmE;;AAGvF,SAAgB,aAAa,SAAsC;CACjE,IAAI,QAAQ,QAAQ,IAAI,OAAO;CAC/B,IAAI,CAAC,OAAO;EACV,QAAQ;GAAE,QAAQ,IAAI,eAAe,OAAO;GAAG,MAAM;EAAE;EACvD,QAAQ,IAAI,SAAS,KAAK;CAC5B;CACA,MAAM,QAAQ;CAGd,IAAI,WAAW;CACf,aAAa;EACX,IAAI,UAAU;EACd,WAAW;EACX,MAAM,IAAI,QAAQ,IAAI,OAAO;EAC7B,IAAI,CAAC,GAAG;EACR,EAAE,QAAQ;EACV,IAAI,EAAE,QAAQ,GAAG;GACf,EAAE,OAAO,QAAQ;GACjB,QAAQ,OAAO,OAAO;EACxB;CACF;AACF;;;;ACzaA,SAAgB,SAAS,QAAgB,OAAsB,KAA8B;CAC3F,MAAM,KAAK,MAAM;CACjB,MAAM,SAAS,GAAG;CAClB,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,KAAK,OAAO,OAAO,EAAE;CAC3B,MAAM,OAAQ,OAAO,MAAsD;CAC3E,MAAM,OACJ,MAAM,SAAS,SACX;EAAE,GAAG,KAAK,KAAK;EAAG,GAAG,KAAK,KAAK;CAAE,IAChC,IAAI,eAAe;EAAE,GAAG;EAAG,GAAG;CAAE;CAEvC,MAAM,OAAO,IAAI,YACf,WAAW,GAAG,MAAM,GAAG,sBAAsB,KAAK;EAAE,MAAM;EAAG,KAAK;CAAE;CACtE,MAAM,IAAI,GAAG,SAAS;CACtB,MAAM,OAAO,YACX;EAAE,GAAG,EAAE;EAAG,GAAG,EAAE;CAAE,GACjB,MACA;EAAE,GAAG;EAAG,GAAG;CAAE,GACb,KAAK,GACL,KAAK,GACL,IAAI,cACN;CAKA,OAAO,wBAAwB,QAAQ;EAHZ,GAAG;EAAI,GAAG,KAAK;EAAG,GAAG,KAAK;EAAG,GAAG,KAAK;EAAG,GAAG,KAAK;CAGjC,GAAG,KAAK,GAAG,KAAK,GAAG;EAC3D,WAAW,IAAI;EACf,MAAM,IAAI,eAAe;CAC3B,CAAC;AACH;;;;;;;ACrEA,MAAa,qBAAqB;AAOlC,MAAM,0BAA0B;;;;;;;AAQhC,SAAgB,UAAU,IAAwC;CAChE,IAAI,QAAQ;CACZ,IAAI,OAAO,IAAI,iBAAiB;CAChC,OAAO,MAAM;EACX,IAAI,KAAK,aAAA,oBAA+B,GAAG;EAC3C,OAAO,KAAK;CACd;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,yBAA4C,UAAU;CACjE,MAAM,YAAY,oBAAoB,KAAK;CAC3C,IAAI,CAAC,WAAW,OAAO;CACvB,OAAO;EACL,GAAG;EACH,UAAU,0BAA0B,UAAU,WAAW,MAAM,SAAS,CAAC;CAC3E;AACF;;;;;;;;;ACzCA,IAAa,aAAb,cAAgC,SAA6C;CAC3E,MAAe,EAAE,aAA+C;EAC9D,MAAM,OAAO,KAAK;EAClB,IAAI,CAAC,MAAM,UAAU,GAAG,OAAO;EAC/B,MAAM,KAAK,KAAK,kBAAkB;EAElC,MAAM,UAAU,iBAAiB,EAAE,IAAI,GAAG,OAAO;EACjD,MAAM,UAAU,GAAG,YAAY,GAAG,OAAO;EACzC,IAAI,WAAW,KAAK,WAAW,GAAG,OAAO;EACzC,OAAO;GACL,GAAG,KAAK,MAAM,UAAU,IAAI,OAAO,IAAI;GACvC,GAAG,KAAK,MAAM,UAAU,IAAI,OAAO,IAAI;EACzC;CACF;AACF;;;;ACrBA,MAAa,qBAAqB;AAIlC,MAAa,cAAc,CAAC,SAAS,UAAU,EAAE,UAAU,OAAO,CAAC,CAAC;;;;;;;;AASpE,SAAgB,sBACd,QACA,KACS;CACT,IAAI,EAAE,kBAAkB,UAAU,OAAO;CACzC,IAAI,OAAO,QAAQ,+BAAyB,GAAG,OAAO;CACtD,IAAI,KAAK,UAAU,OAAO,QAAQ,IAAI,MAAM,GAAG,OAAO;CACtD,IAAI,KAAK,UAAU,CAAC,OAAO,QAAQ,IAAI,MAAM,GAAG,OAAO;CACvD,OAAO;AACT;;;;;;AAOA,SAAgB,iBACd,WACA,eACS;CACT,OAAO,CACL,cAAc,UAAU;EACtB,6BACE,YAAY,IACR,CAAC,IAAI,6BAA6B,SAAS,EAAE,OAAO,UAAU,CAAC,CAAC,IAChE,KAAA;EACN,oBAAoB,UAClB,sBAAsB,MAAM,QAAQ,cAAc,CAAC;CACvD,CAAC,GACD,cACF;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snapgridjs/dnd",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Framework-agnostic dnd-kit grid engine for snapgrid — the shared drag/resize/cross-grid brain consumed by @snapgridjs/react (and future Vue/Solid bindings).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Edmond Leung",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"module": "./dist/index.mjs",
|
|
47
47
|
"types": "./dist/index.d.mts",
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@snapgridjs/core": "0.
|
|
49
|
+
"@snapgridjs/core": "0.6.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@dnd-kit/abstract": "^0.4.0",
|