@snapgridjs/react 0.5.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 CHANGED
@@ -19,6 +19,7 @@ Draggable, resizable, responsive grid layouts for React — with pluggable packi
19
19
  - **Pluggable packing** — `vertical` / `horizontal` / `none`, plus `masonry` / `gravity` / `shelf` from [`@snapgridjs/extras`](https://www.npmjs.com/package/@snapgridjs/extras), or your own `Compactor`.
20
20
  - **Cross-grid dragging** — wrap grids in a `<SnapGridGroup>` and drag tiles between them.
21
21
  - **Nested grids** — drop a grid inside a tile of another grid and drag tiles between levels; isolate a sub-grid with its own provider when you want it contained.
22
+ - **dnd-kit interop** — drag between a grid and a dnd-kit `useSortable` list or board (cards in, tiles out, both reorder) under one provider, via `snapMove`.
22
23
  - **Responsive** — per-breakpoint layouts with `<ResponsiveGridLayout>`.
23
24
  - **Keyboard accessible** — Enter/Space to pick up, arrow keys to move, Esc to cancel.
24
25
  - **SSR-safe** and **TypeScript-first** (types included).
package/dist/index.cjs CHANGED
@@ -143,7 +143,8 @@ function useGridContainer(opts) {
143
143
  const srcEl = (0, _snapgridjs_dnd.domElement)(source);
144
144
  if (srcEl && gridElRef.current && srcEl.contains(gridElRef.current)) return false;
145
145
  if (source.type === "grid-item") return true;
146
- return source.data?.snapGridDrop != null;
146
+ if (source.data?.snapGridDrop != null) return true;
147
+ return opts.accept?.(source) ?? false;
147
148
  },
148
149
  collisionDetector: _snapgridjs_dnd.gridCollisionDetector
149
150
  });
@@ -171,6 +172,7 @@ function useGridContainer(opts) {
171
172
  }
172
173
  const REFLOW_EASING = "ease";
173
174
  const REFLOW_TRANSITION = `transform 150ms ${REFLOW_EASING}, width 150ms ${REFLOW_EASING}, height 150ms ${REFLOW_EASING}`;
175
+ const TILE_TRANSITION = `width 150ms ${REFLOW_EASING}, height 150ms ${REFLOW_EASING}`;
174
176
  //#endregion
175
177
  //#region src/hooks/useResolveController.ts
176
178
  /**
@@ -191,6 +193,7 @@ const ITEM_FEEDBACK = [_dnd_kit_dom.Feedback.configure({
191
193
  feedback: (_source, manager) => (0, _dnd_kit_dom_utilities.isKeyboardEvent)(manager.dragOperation.activatorEvent) ? "none" : "default",
192
194
  dropAnimation: null
193
195
  })];
196
+ const tileNeverTarget = () => null;
194
197
  /**
195
198
  * Headless hook for a single grid tile. The tile is a real `useSortable` (a
196
199
  * draggable + droppable carrying `group`/`index`/`type`/`accept`), so it
@@ -201,10 +204,18 @@ const ITEM_FEEDBACK = [_dnd_kit_dom.Feedback.configure({
201
204
  * element you render — you own the tag, className, content, and cosmetic styling.
202
205
  *
203
206
  * The dragged tile floats itself via dnd-kit's default feedback (no `<DragOverlay>`):
204
- * the active tile renders at its committed origin so the float offset composes, and
205
- * reflow is animated on the compositor via the Web Animations API — both so it stays
206
- * smooth in Safari, where the float's popover top-layer repaint would jank a
207
- * CSS-transition reflow.
207
+ * the active tile renders at its committed origin and dnd-kit's float follows the
208
+ * pointer from there, while reflow is animated on the compositor via the Web
209
+ * Animations API (a FLIP) — both so it stays smooth in Safari, where the float's
210
+ * popover top-layer repaint would jank a CSS-transition reflow.
211
+ *
212
+ * Tiles are positioned with `left`/`top` (not `transform`). dnd-kit's self-float
213
+ * measures the source element's rect ignoring transforms and re-applies its current
214
+ * transform each frame; a transform-positioned tile leans on that, but the
215
+ * compensation is lost the instant the dragged element is swapped for a foreign one
216
+ * mid-drag (grid → sortable interop — the tile becomes a flow card), which would
217
+ * make the float jump by the tile's grid offset. Plain left/top has nothing to lose
218
+ * on the swap, matching how dnd-kit's own flow-positioned sortables hand off cleanly.
208
219
  */
209
220
  function useGridItem(id, group) {
210
221
  const controller = useResolveController(group);
@@ -232,6 +243,7 @@ function useGridItem(id, group) {
232
243
  group,
233
244
  type: "grid-item",
234
245
  accept: "grid-item",
246
+ collisionDetector: tileNeverTarget,
235
247
  disabled: !config.isItemDraggable(id),
236
248
  sensors: config.itemSensors,
237
249
  modifiers: config.itemModifiers,
@@ -251,6 +263,7 @@ function useGridItem(id, group) {
251
263
  const posTop = pos?.top;
252
264
  const prev = (0, react.useRef)(null);
253
265
  const reflowAnim = (0, react.useRef)(null);
266
+ const settleAnchor = (0, react.useRef)(null);
254
267
  (0, react.useLayoutEffect)(() => {
255
268
  const cur = posLeft != null && posTop != null ? {
256
269
  left: posLeft,
@@ -259,17 +272,31 @@ function useGridItem(id, group) {
259
272
  const before = prev.current;
260
273
  prev.current = cur;
261
274
  const el = elRef.current;
262
- if (!el || !cur || !before || active || justDropped || !dragging) return;
275
+ if (!el || !cur) return;
276
+ if (active) {
277
+ settleAnchor.current = cur;
278
+ reflowAnim.current?.cancel();
279
+ return;
280
+ }
281
+ if (dragging) settleAnchor.current = null;
282
+ else if (settleAnchor.current) {
283
+ const a = settleAnchor.current;
284
+ reflowAnim.current?.cancel();
285
+ if (cur.left !== a.left || cur.top !== a.top) settleAnchor.current = null;
286
+ return;
287
+ }
288
+ if (!before || justDropped) return;
263
289
  if (before.left === cur.left && before.top === cur.top) return;
290
+ if (typeof el.animate !== "function") return;
264
291
  let fromX = before.left;
265
292
  let fromY = before.top;
266
293
  if (reflowAnim.current?.playState === "running") {
267
294
  const m = new DOMMatrix(getComputedStyle(el).transform);
268
- fromX = m.m41;
269
- fromY = m.m42;
295
+ fromX = before.left + m.m41;
296
+ fromY = before.top + m.m42;
270
297
  }
271
298
  reflowAnim.current?.cancel();
272
- reflowAnim.current = el.animate([{ transform: `translate(${fromX}px, ${fromY}px)` }, { transform: `translate(${cur.left}px, ${cur.top}px)` }], {
299
+ reflowAnim.current = el.animate([{ transform: `translate(${fromX - cur.left}px, ${fromY - cur.top}px)` }, { transform: "translate(0px, 0px)" }], {
273
300
  duration: 150,
274
301
  easing: REFLOW_EASING
275
302
  });
@@ -286,12 +313,11 @@ function useGridItem(id, group) {
286
313
  handleRef,
287
314
  style: pos ? {
288
315
  position: "absolute",
289
- left: 0,
290
- top: 0,
316
+ left: pos.left,
317
+ top: pos.top,
291
318
  width: pos.width,
292
319
  height: pos.height,
293
- transform: `translate(${pos.left}px, ${pos.top}px)`,
294
- transition: active || justDropped || dragging ? "none" : REFLOW_TRANSITION,
320
+ transition: justDropped || dragging ? "none" : TILE_TRANSITION,
295
321
  touchAction: "none"
296
322
  } : {
297
323
  position: "absolute",
@@ -689,6 +715,12 @@ Object.defineProperty(exports, "PointerSensor", {
689
715
  });
690
716
  exports.ResponsiveGridLayout = ResponsiveGridLayout;
691
717
  exports.SnapGridGroup = SnapGridGroup;
718
+ Object.defineProperty(exports, "defaultGridConfig", {
719
+ enumerable: true,
720
+ get: function() {
721
+ return _snapgridjs_core.defaultGridConfig;
722
+ }
723
+ });
692
724
  Object.defineProperty(exports, "getCompactor", {
693
725
  enumerable: true,
694
726
  get: function() {
@@ -701,12 +733,36 @@ Object.defineProperty(exports, "horizontalCompactor", {
701
733
  return _snapgridjs_core.horizontalCompactor;
702
734
  }
703
735
  });
736
+ Object.defineProperty(exports, "insertItemWithCompactor", {
737
+ enumerable: true,
738
+ get: function() {
739
+ return _snapgridjs_core.insertItemWithCompactor;
740
+ }
741
+ });
704
742
  Object.defineProperty(exports, "noCompactor", {
705
743
  enumerable: true,
706
744
  get: function() {
707
745
  return _snapgridjs_core.noCompactor;
708
746
  }
709
747
  });
748
+ Object.defineProperty(exports, "removeItemWithCompactor", {
749
+ enumerable: true,
750
+ get: function() {
751
+ return _snapgridjs_core.removeItemWithCompactor;
752
+ }
753
+ });
754
+ Object.defineProperty(exports, "snapMove", {
755
+ enumerable: true,
756
+ get: function() {
757
+ return _snapgridjs_dnd.snapMove;
758
+ }
759
+ });
760
+ Object.defineProperty(exports, "toPositionParams", {
761
+ enumerable: true,
762
+ get: function() {
763
+ return _snapgridjs_core.toPositionParams;
764
+ }
765
+ });
710
766
  exports.useContainerWidth = useContainerWidth;
711
767
  Object.defineProperty(exports, "useDraggable", {
712
768
  enumerable: true,
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
- import { DragConfig, DragConfig as DragConfig$1, DragSourceInfo, DropConfig, DropConfig as DropConfig$1, GridController, GridDropData, GridEventCallback, GridEventCallback as GridEventCallback$1, RESIZE_HANDLE_ATTR, ResizeConfig, ResizeConfig as ResizeConfig$1 } from "@snapgridjs/dnd";
1
+ import { DragConfig, DragConfig as DragConfig$1, DragSourceInfo, DragSourceInfo as DragSourceInfo$1, DropConfig, DropConfig as DropConfig$1, GridController, GridDropData, GridEventCallback, GridEventCallback as GridEventCallback$1, RESIZE_HANDLE_ATTR, ResizeConfig, ResizeConfig as ResizeConfig$1, SnapMoveContext, SnapMoveEvent, snapMove } from "@snapgridjs/dnd";
2
2
  import { CSSProperties, ReactNode } from "react";
3
- import { BreakpointCols, BreakpointCols as BreakpointCols$1, Breakpoints, Breakpoints as Breakpoints$1, CompactType, Compactor, Compactor as Compactor$1, GridConfig, GridConfig as GridConfig$1, Layout, Layout as Layout$1, LayoutItem, LayoutItem as LayoutItem$1, PositionParams, ResizeHandleAxis, ResizeHandleAxis as ResizeHandleAxis$1, ResponsiveLayouts, ResponsiveLayouts as ResponsiveLayouts$1, getCompactor, horizontalCompactor, noCompactor, verticalCompactor } from "@snapgridjs/core";
3
+ import { BreakpointCols, BreakpointCols as BreakpointCols$1, Breakpoints, Breakpoints as Breakpoints$1, CompactType, Compactor, Compactor as Compactor$1, GridConfig, GridConfig as GridConfig$1, Layout, Layout as Layout$1, LayoutItem, LayoutItem as LayoutItem$1, PositionParams, ResizeHandleAxis, ResizeHandleAxis as ResizeHandleAxis$1, ResponsiveLayouts, ResponsiveLayouts as ResponsiveLayouts$1, defaultGridConfig, getCompactor, horizontalCompactor, insertItemWithCompactor, noCompactor, removeItemWithCompactor, toPositionParams, verticalCompactor } from "@snapgridjs/core";
4
4
  import { DragOverlay, useDraggable, useDroppable } from "@dnd-kit/react";
5
5
  import { Feedback, KeyboardSensor, PointerSensor } from "@dnd-kit/dom";
6
6
 
@@ -18,6 +18,13 @@ interface UseGridControllerOptions {
18
18
  dragConfig?: DragConfig$1;
19
19
  resizeConfig?: ResizeConfig$1;
20
20
  dropConfig?: DropConfig$1;
21
+ /**
22
+ * Accept additional (non-grid) dnd-kit draggables as drop targets — e.g. a
23
+ * `useSortable` card from a sibling list, for interop. Extends the built-in
24
+ * acceptance (grid tiles + `snapGridDrop` externals); the ancestry guard still
25
+ * applies. You drive the actual receive in your own `onDragOver` with `snapMove`.
26
+ */
27
+ accept?: (source: DragSourceInfo$1) => boolean;
21
28
  compactor?: Compactor$1;
22
29
  isDraggable?: boolean;
23
30
  isResizable?: boolean;
@@ -85,10 +92,18 @@ interface UseGridItemResult {
85
92
  * element you render — you own the tag, className, content, and cosmetic styling.
86
93
  *
87
94
  * The dragged tile floats itself via dnd-kit's default feedback (no `<DragOverlay>`):
88
- * the active tile renders at its committed origin so the float offset composes, and
89
- * reflow is animated on the compositor via the Web Animations API — both so it stays
90
- * smooth in Safari, where the float's popover top-layer repaint would jank a
91
- * CSS-transition reflow.
95
+ * the active tile renders at its committed origin and dnd-kit's float follows the
96
+ * pointer from there, while reflow is animated on the compositor via the Web
97
+ * Animations API (a FLIP) — both so it stays smooth in Safari, where the float's
98
+ * popover top-layer repaint would jank a CSS-transition reflow.
99
+ *
100
+ * Tiles are positioned with `left`/`top` (not `transform`). dnd-kit's self-float
101
+ * measures the source element's rect ignoring transforms and re-applies its current
102
+ * transform each frame; a transform-positioned tile leans on that, but the
103
+ * compensation is lost the instant the dragged element is swapped for a foreign one
104
+ * mid-drag (grid → sortable interop — the tile becomes a flow card), which would
105
+ * make the float jump by the tile's grid offset. Plain left/top has nothing to lose
106
+ * on the swap, matching how dnd-kit's own flow-positioned sortables hand off cleanly.
92
107
  */
93
108
  declare function useGridItem(id: string, group: string): UseGridItemResult;
94
109
  //#endregion
@@ -299,5 +314,5 @@ interface UseContainerWidthResult {
299
314
  */
300
315
  declare function useContainerWidth(options?: UseContainerWidthOptions): UseContainerWidthResult;
301
316
  //#endregion
302
- export { type BreakpointCols, type Breakpoints, type CompactType, type Compactor, DEFAULT_BREAKPOINTS, DEFAULT_BREAKPOINT_COLS, type DragConfig, DragOverlay, type DragSourceInfo, type DropConfig, Feedback, type GridConfig, type GridContainerProps, type GridDropData, type GridEventCallback, GridItem, type GridItemProps, GridLayout, type GridLayoutProps, GridPlaceholder, type GridPlaceholderInfo, type GridPlaceholderProps, KeyboardSensor, type Layout, type LayoutItem, PointerSensor, type PositionParams, type ResizeConfig, type ResizeHandleAxis, ResponsiveGridLayout, type ResponsiveGridLayoutProps, type ResponsiveLayouts, SnapGridGroup, type UseContainerWidthOptions, type UseContainerWidthResult, type UseGridContainerResult, type UseGridControllerOptions, type UseGridItemResult, type UseGridResizeHandleResult, type UseResponsiveLayoutOptions, type UseResponsiveLayoutResult, getCompactor, horizontalCompactor, noCompactor, useContainerWidth, useDraggable, useDroppable, useGridContainer, useGridItem, useGridPlaceholder, useGridResizeHandle, useResponsiveLayout, verticalCompactor };
317
+ export { type BreakpointCols, type Breakpoints, type CompactType, type Compactor, DEFAULT_BREAKPOINTS, DEFAULT_BREAKPOINT_COLS, type DragConfig, DragOverlay, type DragSourceInfo, type DropConfig, Feedback, type GridConfig, type GridContainerProps, type GridDropData, type GridEventCallback, GridItem, type GridItemProps, GridLayout, type GridLayoutProps, GridPlaceholder, type GridPlaceholderInfo, type GridPlaceholderProps, KeyboardSensor, type Layout, type LayoutItem, PointerSensor, type PositionParams, type ResizeConfig, type ResizeHandleAxis, ResponsiveGridLayout, type ResponsiveGridLayoutProps, type ResponsiveLayouts, SnapGridGroup, type SnapMoveContext, type SnapMoveEvent, type UseContainerWidthOptions, type UseContainerWidthResult, type UseGridContainerResult, type UseGridControllerOptions, type UseGridItemResult, type UseGridResizeHandleResult, type UseResponsiveLayoutOptions, type UseResponsiveLayoutResult, defaultGridConfig, getCompactor, horizontalCompactor, insertItemWithCompactor, noCompactor, removeItemWithCompactor, snapMove, toPositionParams, useContainerWidth, useDraggable, useDroppable, useGridContainer, useGridItem, useGridPlaceholder, useGridResizeHandle, useResponsiveLayout, verticalCompactor };
303
318
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/hooks/useGridController.ts","../src/hooks/useGridContainer.ts","../src/hooks/useGridItem.ts","../src/hooks/useGridPlaceholder.ts","../src/hooks/useGridResizeHandle.ts","../src/hooks/useResponsiveLayout.ts","../src/components/GridLayout.tsx","../src/components/ResponsiveGridLayout.tsx","../src/components/GridItem.tsx","../src/components/GridPlaceholder.tsx","../src/hooks/useContainerWidth.ts"],"mappings":";;;;;;;;UAkCiB,wBAAA;;EAEf,EAAA;;EAEA,KAAA;EAJuC;EAMvC,MAAA,EAAQ,QAAA;EACR,cAAA,IAAkB,MAAA,EAAQ,QAAA;EAC1B,UAAA,GAAa,OAAA,CAAQ,YAAA;EACrB,UAAA,GAAa,YAAA;EACb,YAAA,GAAe,cAAA;EACf,UAAA,GAAa,YAAA;EACb,SAAA,GAAY,WAAA;EACZ,WAAA;EACA,WAAA;EACA,QAAA;EACA,WAAA,GAAc,mBAAA;EACd,MAAA,GAAS,mBAAA;EACT,UAAA,GAAa,mBAAA;EACb,aAAA,GAAgB,mBAAA;EAChB,QAAA,GAAW,mBAAA;EACX,YAAA,GAAe,mBAAA;EACf,MAAA,IAAU,MAAA,EAAQ,QAAA,EAAQ,IAAA,EAAM,YAAA,EAAY,KAAA,EAAO,KAAA;AAAA;;;UC7CpC,kBAAA;;EAEf,GAAA,GAAM,OAAA,EAAS,OAAA;;EAEf,KAAA,EAAO,aAAa;EDmBmB;ECjBvC,kBAAA;AAAA;AAAA,UAGe,sBAAA;EDsBM;ECpBrB,cAAA,EAAgB,kBAAA;EDqBH;ECnBb,YAAA;EDqBa;ECnBb,KAAA;EDwBc;ECtBd,UAAA,EAAY,cAAc;AAAA;;;;;;;iBAgBZ,gBAAA,CAAiB,IAAA,EAAM,wBAAA,GAA2B,sBAAsB;;;UCjBvE,iBAAA;;EAEf,GAAA,GAAM,OAAA,EAAS,OAAA;;;AFKjB;;;EECE,SAAA,GAAY,OAAA,EAAS,OAAA;EFMK;EEJ1B,KAAA,EAAO,aAAA;EFKM;EEHb,UAAA;EFKe;EEHf,IAAA,EAAM,YAAA;AAAA;;;;;;;;;;;;;;;;iBAkBQ,WAAA,CAAY,EAAA,UAAY,KAAA,WAAgB,iBAAiB;;;UCvDxD,mBAAA;;EAEf,IAAA,EAAM,YAAA;;EAEN,KAAA,EAAO,aAAa;AAAA;;;;;;iBAQN,kBAAA,CAAmB,KAAA,WAAgB,mBAAmB;;;UCVrD,yBAAA;;EAEf,GAAA,GAAM,OAAA,EAAS,OAAA;;EAEf,WAAA;IAAA,CAAgB,kBAAkB;EAAA;;EAElC,UAAA;AAAA;;;;;;;iBASc,mBAAA,CACd,MAAA,UACA,MAAA,EAAQ,kBAAA,EACR,KAAA,WACC,yBAAyB;;;;cCXf,mBAAA,EAAqB,aAA6D;AAAA,cAClF,uBAAA,EAAyB,gBAAyD;AAAA,UAE9E,0BAAA;;EAEf,KAAA;ELee;EKbf,OAAA,EAAS,mBAAA;;EAET,WAAA,GAAc,aAAA;ELkBY;EKhB1B,IAAA,GAAO,gBAAA;ELiBM;EKfb,SAAA,GAAY,WAAA;ELiBG;EKff,cAAA,IAAkB,MAAA,EAAQ,QAAA,EAAQ,OAAA,EAAS,mBAAA;ELiB/B;EKfZ,kBAAA,IAAsB,UAAA,UAAoB,IAAA;AAAA;AAAA,UAG3B,yBAAA;ELmBC;EKjBhB,UAAA;ELmBe;EKjBf,IAAA;ELkBgC;EKhBhC,MAAA,EAAQ,QAAA;ELgBgD;EKdxD,cAAA,GAAiB,MAAA,EAAQ,QAAM;AAAA;;;;;;iBAQjB,mBAAA,CACd,OAAA,EAAS,0BAAA,GACR,yBAAyB;;;UCtCX,eAAA,SAAwB,wBAAA;EACvC,QAAA,EAAU,SAAA;;EAEV,SAAA;;EAEA,KAAA,GAAQ,aAAA;AAAA;;;;;;;;;;;iBA4CM,UAAA,CAAW,KAAA,EAAO,eAAA,GAAkB,KAAA,CAAM,GAAA,CAAI,OAAO;;;;;;;iBAiBrD,aAAA,CAAA;EAAgB;AAAA;EAAc,QAAA,EAAU,SAAA;AAAA,IAAc,KAAA,CAAM,GAAA,CAAI,OAAA;;;UCpE/D,yBAAA;;EAEf,KAAA;;EAEA,OAAA,EAAS,mBAAA;EPkB8B;EOhBvC,cAAA,IAAkB,MAAA,EAAQ,QAAA,EAAQ,OAAA,EAAS,mBAAA;EPsBnC;EOpBR,kBAAA,IAAsB,UAAA,UAAoB,IAAA;EPsBrB;EOpBrB,WAAA,GAAc,aAAA;EPqBD;EOnBb,IAAA,GAAO,gBAAA;EACP,SAAA;EACA,MAAA;EACA,gBAAA;EACA,SAAA,GAAY,WAAA;EACZ,UAAA,GAAa,YAAA;EACb,YAAA,GAAe,cAAA;EACf,WAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EACA,KAAA,GAAQ,aAAA;EACR,QAAA,EAAU,SAAA;AAAA;;;;;;;iBASI,oBAAA,CAAqB,KAAA,EAAO,yBAAA,GAA4B,KAAA,CAAM,GAAA,CAAI,OAAO;;;UCvCxE,aAAA;;EAEf,EAAA;;EAEA,KAAA;EACA,QAAA,EAAU,SAAA;ERuBK;EQrBf,SAAA;;EAEA,KAAA,GAAQ,aAAa;AAAA;;;;;;;;;;;;iBAgEd,YAAA,CAAA;EAAe,EAAA;EAAI,KAAA;EAAO,QAAA;EAAU,SAAA;EAAW;AAAA,GAAS,aAAA,+BAAa,GAAA,CAAA,OAAA;AAAA,cAqBjE,QAAA,kBAAQ,mBAAA,QAAA,YAAA;;;UChGJ,oBAAA;;EAEf,KAAA;;EAEA,SAAA;;EAEA,KAAA,GAAQ,aAAa;AAAA;;;;;;iBAiBP,eAAA,CAAA;EAAkB,KAAA;EAAO,SAAA;EAAW;AAAA,GAAS,oBAAA,+BAAoB,GAAA,CAAA,OAAA;;;UCnBhE,wBAAA;;EAEf,YAAY;AAAA;AAAA,UAGG,uBAAA;;EAEf,KAAA;EVmBe;EUjBf,OAAA;;EAEA,YAAA,GAAe,OAAA,EAAS,WAAW;AAAA;;;;;iBAOrB,iBAAA,CAAkB,OAAA,GAAS,wBAAA,GAAgC,uBAAuB"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/hooks/useGridController.ts","../src/hooks/useGridContainer.ts","../src/hooks/useGridItem.ts","../src/hooks/useGridPlaceholder.ts","../src/hooks/useGridResizeHandle.ts","../src/hooks/useResponsiveLayout.ts","../src/components/GridLayout.tsx","../src/components/ResponsiveGridLayout.tsx","../src/components/GridItem.tsx","../src/components/GridPlaceholder.tsx","../src/hooks/useContainerWidth.ts"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DragOverlay, useDraggable, useDroppable } from "@dnd-kit/react";
2
- import { BreakpointCols, BreakpointCols as BreakpointCols$1, Breakpoints, Breakpoints as Breakpoints$1, CompactType, Compactor, Compactor as Compactor$1, GridConfig, GridConfig as GridConfig$1, Layout, Layout as Layout$1, LayoutItem, LayoutItem as LayoutItem$1, PositionParams, ResizeHandleAxis, ResizeHandleAxis as ResizeHandleAxis$1, ResponsiveLayouts, ResponsiveLayouts as ResponsiveLayouts$1, getCompactor, horizontalCompactor, noCompactor, verticalCompactor } from "@snapgridjs/core";
3
- import { DragConfig, DragConfig as DragConfig$1, DragSourceInfo, DropConfig, DropConfig as DropConfig$1, GridController, GridDropData, GridEventCallback, GridEventCallback as GridEventCallback$1, RESIZE_HANDLE_ATTR, ResizeConfig, ResizeConfig as ResizeConfig$1 } from "@snapgridjs/dnd";
2
+ import { BreakpointCols, BreakpointCols as BreakpointCols$1, Breakpoints, Breakpoints as Breakpoints$1, CompactType, Compactor, Compactor as Compactor$1, GridConfig, GridConfig as GridConfig$1, Layout, Layout as Layout$1, LayoutItem, LayoutItem as LayoutItem$1, PositionParams, ResizeHandleAxis, ResizeHandleAxis as ResizeHandleAxis$1, ResponsiveLayouts, ResponsiveLayouts as ResponsiveLayouts$1, defaultGridConfig, getCompactor, horizontalCompactor, insertItemWithCompactor, noCompactor, removeItemWithCompactor, toPositionParams, verticalCompactor } from "@snapgridjs/core";
3
+ import { DragConfig, DragConfig as DragConfig$1, DragSourceInfo, DragSourceInfo as DragSourceInfo$1, DropConfig, DropConfig as DropConfig$1, GridController, GridDropData, GridEventCallback, GridEventCallback as GridEventCallback$1, RESIZE_HANDLE_ATTR, ResizeConfig, ResizeConfig as ResizeConfig$1, SnapMoveContext, SnapMoveEvent, snapMove } from "@snapgridjs/dnd";
4
4
  import { CSSProperties, ReactNode } from "react";
5
5
  import { Feedback, KeyboardSensor, PointerSensor } from "@dnd-kit/dom";
6
6
 
@@ -18,6 +18,13 @@ interface UseGridControllerOptions {
18
18
  dragConfig?: DragConfig$1;
19
19
  resizeConfig?: ResizeConfig$1;
20
20
  dropConfig?: DropConfig$1;
21
+ /**
22
+ * Accept additional (non-grid) dnd-kit draggables as drop targets — e.g. a
23
+ * `useSortable` card from a sibling list, for interop. Extends the built-in
24
+ * acceptance (grid tiles + `snapGridDrop` externals); the ancestry guard still
25
+ * applies. You drive the actual receive in your own `onDragOver` with `snapMove`.
26
+ */
27
+ accept?: (source: DragSourceInfo$1) => boolean;
21
28
  compactor?: Compactor$1;
22
29
  isDraggable?: boolean;
23
30
  isResizable?: boolean;
@@ -85,10 +92,18 @@ interface UseGridItemResult {
85
92
  * element you render — you own the tag, className, content, and cosmetic styling.
86
93
  *
87
94
  * The dragged tile floats itself via dnd-kit's default feedback (no `<DragOverlay>`):
88
- * the active tile renders at its committed origin so the float offset composes, and
89
- * reflow is animated on the compositor via the Web Animations API — both so it stays
90
- * smooth in Safari, where the float's popover top-layer repaint would jank a
91
- * CSS-transition reflow.
95
+ * the active tile renders at its committed origin and dnd-kit's float follows the
96
+ * pointer from there, while reflow is animated on the compositor via the Web
97
+ * Animations API (a FLIP) — both so it stays smooth in Safari, where the float's
98
+ * popover top-layer repaint would jank a CSS-transition reflow.
99
+ *
100
+ * Tiles are positioned with `left`/`top` (not `transform`). dnd-kit's self-float
101
+ * measures the source element's rect ignoring transforms and re-applies its current
102
+ * transform each frame; a transform-positioned tile leans on that, but the
103
+ * compensation is lost the instant the dragged element is swapped for a foreign one
104
+ * mid-drag (grid → sortable interop — the tile becomes a flow card), which would
105
+ * make the float jump by the tile's grid offset. Plain left/top has nothing to lose
106
+ * on the swap, matching how dnd-kit's own flow-positioned sortables hand off cleanly.
92
107
  */
93
108
  declare function useGridItem(id: string, group: string): UseGridItemResult;
94
109
  //#endregion
@@ -299,5 +314,5 @@ interface UseContainerWidthResult {
299
314
  */
300
315
  declare function useContainerWidth(options?: UseContainerWidthOptions): UseContainerWidthResult;
301
316
  //#endregion
302
- export { type BreakpointCols, type Breakpoints, type CompactType, type Compactor, DEFAULT_BREAKPOINTS, DEFAULT_BREAKPOINT_COLS, type DragConfig, DragOverlay, type DragSourceInfo, type DropConfig, Feedback, type GridConfig, type GridContainerProps, type GridDropData, type GridEventCallback, GridItem, type GridItemProps, GridLayout, type GridLayoutProps, GridPlaceholder, type GridPlaceholderInfo, type GridPlaceholderProps, KeyboardSensor, type Layout, type LayoutItem, PointerSensor, type PositionParams, type ResizeConfig, type ResizeHandleAxis, ResponsiveGridLayout, type ResponsiveGridLayoutProps, type ResponsiveLayouts, SnapGridGroup, type UseContainerWidthOptions, type UseContainerWidthResult, type UseGridContainerResult, type UseGridControllerOptions, type UseGridItemResult, type UseGridResizeHandleResult, type UseResponsiveLayoutOptions, type UseResponsiveLayoutResult, getCompactor, horizontalCompactor, noCompactor, useContainerWidth, useDraggable, useDroppable, useGridContainer, useGridItem, useGridPlaceholder, useGridResizeHandle, useResponsiveLayout, verticalCompactor };
317
+ export { type BreakpointCols, type Breakpoints, type CompactType, type Compactor, DEFAULT_BREAKPOINTS, DEFAULT_BREAKPOINT_COLS, type DragConfig, DragOverlay, type DragSourceInfo, type DropConfig, Feedback, type GridConfig, type GridContainerProps, type GridDropData, type GridEventCallback, GridItem, type GridItemProps, GridLayout, type GridLayoutProps, GridPlaceholder, type GridPlaceholderInfo, type GridPlaceholderProps, KeyboardSensor, type Layout, type LayoutItem, PointerSensor, type PositionParams, type ResizeConfig, type ResizeHandleAxis, ResponsiveGridLayout, type ResponsiveGridLayoutProps, type ResponsiveLayouts, SnapGridGroup, type SnapMoveContext, type SnapMoveEvent, type UseContainerWidthOptions, type UseContainerWidthResult, type UseGridContainerResult, type UseGridControllerOptions, type UseGridItemResult, type UseGridResizeHandleResult, type UseResponsiveLayoutOptions, type UseResponsiveLayoutResult, defaultGridConfig, getCompactor, horizontalCompactor, insertItemWithCompactor, noCompactor, removeItemWithCompactor, snapMove, toPositionParams, useContainerWidth, useDraggable, useDroppable, useGridContainer, useGridItem, useGridPlaceholder, useGridResizeHandle, useResponsiveLayout, verticalCompactor };
303
318
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/hooks/useGridController.ts","../src/hooks/useGridContainer.ts","../src/hooks/useGridItem.ts","../src/hooks/useGridPlaceholder.ts","../src/hooks/useGridResizeHandle.ts","../src/hooks/useResponsiveLayout.ts","../src/components/GridLayout.tsx","../src/components/ResponsiveGridLayout.tsx","../src/components/GridItem.tsx","../src/components/GridPlaceholder.tsx","../src/hooks/useContainerWidth.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/hooks/useGridController.ts","../src/hooks/useGridContainer.ts","../src/hooks/useGridItem.ts","../src/hooks/useGridPlaceholder.ts","../src/hooks/useGridResizeHandle.ts","../src/hooks/useResponsiveLayout.ts","../src/components/GridLayout.tsx","../src/components/ResponsiveGridLayout.tsx","../src/components/GridItem.tsx","../src/components/GridPlaceholder.tsx","../src/hooks/useContainerWidth.ts"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { DragDropProvider, DragOverlay, useDragDropManager, useDraggable, useDraggable as useDraggable$1, useDroppable, useDroppable as useDroppable$1, useInstance } from "@dnd-kit/react";
2
- import { bottom, calcGridItemPosition, defaultGridConfig, findOrGenerateResponsiveLayout, getBreakpointFromWidth, getColsFromBreakpoint, getCompactor, horizontalCompactor, noCompactor, toPositionParams, verticalCompactor, verticalCompactor as verticalCompactor$1 } from "@snapgridjs/core";
3
- import { GridController, NO_FEEDBACK, RESIZE_HANDLE_ATTR, SNAPGRID_GRID_ATTR, SnapToGrid, attachEngine, buildItemSensors, domElement, getController, gridCollisionDetector, registerController } from "@snapgridjs/dnd";
2
+ import { bottom, calcGridItemPosition, defaultGridConfig, defaultGridConfig as defaultGridConfig$1, findOrGenerateResponsiveLayout, getBreakpointFromWidth, getColsFromBreakpoint, getCompactor, horizontalCompactor, insertItemWithCompactor, noCompactor, removeItemWithCompactor, toPositionParams, toPositionParams as toPositionParams$1, verticalCompactor, verticalCompactor as verticalCompactor$1 } from "@snapgridjs/core";
3
+ import { GridController, NO_FEEDBACK, RESIZE_HANDLE_ATTR, SNAPGRID_GRID_ATTR, SnapToGrid, attachEngine, buildItemSensors, domElement, getController, gridCollisionDetector, registerController, snapMove } from "@snapgridjs/dnd";
4
4
  import { Children, createContext, isValidElement, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
5
  import { Feedback, Feedback as Feedback$1, KeyboardSensor, PointerSensor } from "@dnd-kit/dom";
6
6
  import { isKeyboardEvent } from "@dnd-kit/dom/utilities";
@@ -27,10 +27,10 @@ function useGridController(opts) {
27
27
  const autoId = useId();
28
28
  const containerId = opts.id ?? autoId;
29
29
  const gridConfig = useMemo(() => ({
30
- ...defaultGridConfig,
30
+ ...defaultGridConfig$1,
31
31
  ...opts.gridConfig
32
32
  }), [opts.gridConfig]);
33
- const positionParams = useMemo(() => toPositionParams(gridConfig, opts.width), [gridConfig, opts.width]);
33
+ const positionParams = useMemo(() => toPositionParams$1(gridConfig, opts.width), [gridConfig, opts.width]);
34
34
  const compactor = opts.compactor ?? verticalCompactor$1;
35
35
  const manager = useDragDropManager();
36
36
  const controller = useInstance((m) => new GridController(containerId, opts.layout, m ?? void 0));
@@ -142,7 +142,8 @@ function useGridContainer(opts) {
142
142
  const srcEl = domElement(source);
143
143
  if (srcEl && gridElRef.current && srcEl.contains(gridElRef.current)) return false;
144
144
  if (source.type === "grid-item") return true;
145
- return source.data?.snapGridDrop != null;
145
+ if (source.data?.snapGridDrop != null) return true;
146
+ return opts.accept?.(source) ?? false;
146
147
  },
147
148
  collisionDetector: gridCollisionDetector
148
149
  });
@@ -170,6 +171,7 @@ function useGridContainer(opts) {
170
171
  }
171
172
  const REFLOW_EASING = "ease";
172
173
  const REFLOW_TRANSITION = `transform 150ms ${REFLOW_EASING}, width 150ms ${REFLOW_EASING}, height 150ms ${REFLOW_EASING}`;
174
+ const TILE_TRANSITION = `width 150ms ${REFLOW_EASING}, height 150ms ${REFLOW_EASING}`;
173
175
  //#endregion
174
176
  //#region src/hooks/useResolveController.ts
175
177
  /**
@@ -190,6 +192,7 @@ const ITEM_FEEDBACK = [Feedback$1.configure({
190
192
  feedback: (_source, manager) => isKeyboardEvent(manager.dragOperation.activatorEvent) ? "none" : "default",
191
193
  dropAnimation: null
192
194
  })];
195
+ const tileNeverTarget = () => null;
193
196
  /**
194
197
  * Headless hook for a single grid tile. The tile is a real `useSortable` (a
195
198
  * draggable + droppable carrying `group`/`index`/`type`/`accept`), so it
@@ -200,10 +203,18 @@ const ITEM_FEEDBACK = [Feedback$1.configure({
200
203
  * element you render — you own the tag, className, content, and cosmetic styling.
201
204
  *
202
205
  * The dragged tile floats itself via dnd-kit's default feedback (no `<DragOverlay>`):
203
- * the active tile renders at its committed origin so the float offset composes, and
204
- * reflow is animated on the compositor via the Web Animations API — both so it stays
205
- * smooth in Safari, where the float's popover top-layer repaint would jank a
206
- * CSS-transition reflow.
206
+ * the active tile renders at its committed origin and dnd-kit's float follows the
207
+ * pointer from there, while reflow is animated on the compositor via the Web
208
+ * Animations API (a FLIP) — both so it stays smooth in Safari, where the float's
209
+ * popover top-layer repaint would jank a CSS-transition reflow.
210
+ *
211
+ * Tiles are positioned with `left`/`top` (not `transform`). dnd-kit's self-float
212
+ * measures the source element's rect ignoring transforms and re-applies its current
213
+ * transform each frame; a transform-positioned tile leans on that, but the
214
+ * compensation is lost the instant the dragged element is swapped for a foreign one
215
+ * mid-drag (grid → sortable interop — the tile becomes a flow card), which would
216
+ * make the float jump by the tile's grid offset. Plain left/top has nothing to lose
217
+ * on the swap, matching how dnd-kit's own flow-positioned sortables hand off cleanly.
207
218
  */
208
219
  function useGridItem(id, group) {
209
220
  const controller = useResolveController(group);
@@ -231,6 +242,7 @@ function useGridItem(id, group) {
231
242
  group,
232
243
  type: "grid-item",
233
244
  accept: "grid-item",
245
+ collisionDetector: tileNeverTarget,
234
246
  disabled: !config.isItemDraggable(id),
235
247
  sensors: config.itemSensors,
236
248
  modifiers: config.itemModifiers,
@@ -250,6 +262,7 @@ function useGridItem(id, group) {
250
262
  const posTop = pos?.top;
251
263
  const prev = useRef(null);
252
264
  const reflowAnim = useRef(null);
265
+ const settleAnchor = useRef(null);
253
266
  useLayoutEffect(() => {
254
267
  const cur = posLeft != null && posTop != null ? {
255
268
  left: posLeft,
@@ -258,17 +271,31 @@ function useGridItem(id, group) {
258
271
  const before = prev.current;
259
272
  prev.current = cur;
260
273
  const el = elRef.current;
261
- if (!el || !cur || !before || active || justDropped || !dragging) return;
274
+ if (!el || !cur) return;
275
+ if (active) {
276
+ settleAnchor.current = cur;
277
+ reflowAnim.current?.cancel();
278
+ return;
279
+ }
280
+ if (dragging) settleAnchor.current = null;
281
+ else if (settleAnchor.current) {
282
+ const a = settleAnchor.current;
283
+ reflowAnim.current?.cancel();
284
+ if (cur.left !== a.left || cur.top !== a.top) settleAnchor.current = null;
285
+ return;
286
+ }
287
+ if (!before || justDropped) return;
262
288
  if (before.left === cur.left && before.top === cur.top) return;
289
+ if (typeof el.animate !== "function") return;
263
290
  let fromX = before.left;
264
291
  let fromY = before.top;
265
292
  if (reflowAnim.current?.playState === "running") {
266
293
  const m = new DOMMatrix(getComputedStyle(el).transform);
267
- fromX = m.m41;
268
- fromY = m.m42;
294
+ fromX = before.left + m.m41;
295
+ fromY = before.top + m.m42;
269
296
  }
270
297
  reflowAnim.current?.cancel();
271
- reflowAnim.current = el.animate([{ transform: `translate(${fromX}px, ${fromY}px)` }, { transform: `translate(${cur.left}px, ${cur.top}px)` }], {
298
+ reflowAnim.current = el.animate([{ transform: `translate(${fromX - cur.left}px, ${fromY - cur.top}px)` }, { transform: "translate(0px, 0px)" }], {
272
299
  duration: 150,
273
300
  easing: REFLOW_EASING
274
301
  });
@@ -285,12 +312,11 @@ function useGridItem(id, group) {
285
312
  handleRef,
286
313
  style: pos ? {
287
314
  position: "absolute",
288
- left: 0,
289
- top: 0,
315
+ left: pos.left,
316
+ top: pos.top,
290
317
  width: pos.width,
291
318
  height: pos.height,
292
- transform: `translate(${pos.left}px, ${pos.top}px)`,
293
- transition: active || justDropped || dragging ? "none" : REFLOW_TRANSITION,
319
+ transition: justDropped || dragging ? "none" : TILE_TRANSITION,
294
320
  touchAction: "none"
295
321
  } : {
296
322
  position: "absolute",
@@ -657,6 +683,6 @@ function useContainerWidth(options = {}) {
657
683
  };
658
684
  }
659
685
  //#endregion
660
- export { DEFAULT_BREAKPOINTS, DEFAULT_BREAKPOINT_COLS, DragOverlay, Feedback, GridItem, GridLayout, GridPlaceholder, KeyboardSensor, PointerSensor, ResponsiveGridLayout, SnapGridGroup, getCompactor, horizontalCompactor, noCompactor, useContainerWidth, useDraggable, useDroppable, useGridContainer, useGridItem, useGridPlaceholder, useGridResizeHandle, useResponsiveLayout, verticalCompactor };
686
+ export { DEFAULT_BREAKPOINTS, DEFAULT_BREAKPOINT_COLS, DragOverlay, Feedback, GridItem, GridLayout, GridPlaceholder, KeyboardSensor, PointerSensor, ResponsiveGridLayout, SnapGridGroup, defaultGridConfig, getCompactor, horizontalCompactor, insertItemWithCompactor, noCompactor, removeItemWithCompactor, snapMove, toPositionParams, useContainerWidth, useDraggable, useDroppable, useGridContainer, useGridItem, useGridPlaceholder, useGridResizeHandle, useResponsiveLayout, verticalCompactor };
661
687
 
662
688
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["verticalCompactor","useDroppable","Feedback","useDraggable","verticalCompactor"],"sources":["../src/hooks/useGridController.ts","../src/hooks/useGridContainer.ts","../src/reflow.ts","../src/hooks/useResolveController.ts","../src/hooks/useGridItem.ts","../src/hooks/useGridPlaceholder.ts","../src/hooks/useGridResizeHandle.ts","../src/hooks/useResponsiveLayout.ts","../src/components/GridItem.tsx","../src/components/GridPlaceholder.tsx","../src/components/GridLayout.tsx","../src/components/ResponsiveGridLayout.tsx","../src/hooks/useContainerWidth.ts"],"sourcesContent":["import { useDragDropManager, useInstance } from \"@dnd-kit/react\";\nimport {\n type Compactor,\n type GridConfig,\n type Layout,\n type LayoutItem,\n type PositionParams,\n defaultGridConfig,\n toPositionParams,\n verticalCompactor,\n} from \"@snapgridjs/core\";\nimport {\n type DragConfig,\n type DropConfig,\n GridController,\n type GridEventCallback,\n type ResizeConfig,\n SnapToGrid,\n attachEngine,\n buildItemSensors,\n registerController,\n} from \"@snapgridjs/dnd\";\nimport { useCallback, useEffect, useId, useMemo, useRef } from \"react\";\n\nconst DEFAULT_HANDLES = [\"se\"] as const;\n\n// Per-item drag/resize gate. Mirrors RGL's engine rule: a `static` item is locked\n// unless its flag (`isDraggable`/`isResizable`) is explicitly `true` (\"pinned\");\n// a non-static item just follows the flag (default `true`).\nfunction itemGateOpen(flag: boolean | undefined, isStatic: boolean | undefined): boolean {\n return isStatic ? flag === true : (flag ?? true);\n}\n\n/** Options the grid host ({@link useGridContainer}) feeds the controller. */\nexport interface UseGridControllerOptions {\n /** Stable id for the grid's droppable surface (auto-generated if omitted). */\n id?: string;\n /** Container width in pixels (e.g. from {@link useContainerWidth}). */\n width: number;\n /** Controlled layout. Never mutated. */\n layout: Layout;\n onLayoutChange?: (layout: Layout) => void;\n gridConfig?: Partial<GridConfig>;\n dragConfig?: DragConfig;\n resizeConfig?: ResizeConfig;\n dropConfig?: DropConfig;\n compactor?: Compactor;\n isDraggable?: boolean;\n isResizable?: boolean;\n autoSize?: boolean;\n onDragStart?: GridEventCallback;\n onDrag?: GridEventCallback;\n onDragStop?: GridEventCallback;\n onResizeStart?: GridEventCallback;\n onResize?: GridEventCallback;\n onResizeStop?: GridEventCallback;\n onDrop?: (layout: Layout, item: LayoutItem, event: Event | null) => void;\n}\n\n/**\n * The grid's React seam: owns the {@link GridController} (an observable render\n * bridge), publishes per-grid config to it each render, registers it for id →\n * controller resolution, and attaches the manager-wide {@link SnapGridEngine}.\n *\n * The drag/resize *orchestration* lives in the engine (one per manager), not\n * here — this hook only wires the React-specific parts: the controller, the item\n * sensors/modifiers descriptors, the draggable/resizable gates, and the config\n * the engine reads. Created by {@link useGridContainer}; items resolve the same\n * controller by their `group` (= this grid's id). Consumes the ambient\n * `DragDropProvider` — it does not mint one.\n */\nexport function useGridController(opts: UseGridControllerOptions): GridController {\n const autoId = useId();\n const containerId = opts.id ?? autoId;\n\n const gridConfig: GridConfig = useMemo(\n () => ({ ...defaultGridConfig, ...opts.gridConfig }),\n [opts.gridConfig],\n );\n const positionParams: PositionParams = useMemo(\n () => toPositionParams(gridConfig, opts.width),\n [gridConfig, opts.width],\n );\n const compactor: Compactor = opts.compactor ?? verticalCompactor;\n\n const manager = useDragDropManager();\n const controller = useInstance<GridController>(\n (m) => new GridController(containerId, opts.layout, m ?? undefined),\n );\n controller.setCommitted(opts.layout);\n // useInstance creates the controller once, freezing its id to the first render's\n // value; re-point it if the controlled `id` prop changes so the group, the\n // droppable id, and the registry key (below) stay in sync. (Read during render,\n // before useGridContainer's droppable/group read controller.id.)\n if (controller.id !== containerId) controller.setId(containerId);\n\n // Live refs for the item sensor/modifier descriptors, which read config lazily\n // (they're built once but must see the latest dragConfig / positionParams).\n const optsRef = useRef(opts);\n optsRef.current = opts;\n const ppRef = useRef(positionParams);\n ppRef.current = positionParams;\n\n // Register the controller so items (and snapMove) resolve it by id, and so the\n // engine can find it as a drag's source/destination. During render so child\n // items resolve it on their first render (children render after the parent but\n // before any layout effect). The effect's cleanup unregisters on unmount / id\n // or manager change.\n registerController(manager, containerId, controller);\n useEffect(\n () => registerController(manager, containerId, controller),\n [manager, containerId, controller],\n );\n\n // Attach the manager-wide drag/resize engine (ref-counted; one per manager,\n // shared by every grid on it). Detaches when the last grid for this manager\n // unmounts. No-op without a manager (no provider above).\n useEffect(() => {\n if (!manager) return;\n return attachEngine(manager);\n }, [manager]);\n\n const committedById = useMemo(\n () => new Map<string, LayoutItem>(opts.layout.map((it) => [it.i, it])),\n [opts.layout],\n );\n\n const dragThreshold = opts.dragConfig?.threshold ?? 3;\n const itemSensors = useMemo(\n () => buildItemSensors(dragThreshold, () => optsRef.current.dragConfig),\n [dragThreshold],\n );\n\n // Snap-to-grid modifier (stable descriptor; reads live refs so it never goes\n // stale). A no-op unless `dragConfig.snapToGrid` is set.\n const itemModifiers = useMemo(\n () => [\n SnapToGrid.configure({\n getPositionParams: () => ppRef.current,\n isEnabled: () => optsRef.current.dragConfig?.snapToGrid ?? false,\n }),\n ],\n [],\n );\n\n const gridDraggable = opts.isDraggable ?? true;\n const dragEnabled = opts.dragConfig?.enabled ?? true;\n const isItemDraggable = useCallback(\n (id: string) => {\n const it = committedById.get(id);\n if (!it) return false;\n return gridDraggable && dragEnabled && itemGateOpen(it.isDraggable, it.static);\n },\n [committedById, gridDraggable, dragEnabled],\n );\n\n const gridResizable = opts.isResizable ?? true;\n const resizeEnabled = opts.resizeConfig?.enabled ?? true;\n const isItemResizable = useCallback(\n (id: string) => {\n const it = committedById.get(id);\n if (!it) return false;\n return gridResizable && resizeEnabled && itemGateOpen(it.isResizable, it.static);\n },\n [committedById, gridResizable, resizeEnabled],\n );\n const defaultHandles = opts.resizeConfig?.handles;\n const resizeHandlesFor = useCallback(\n (id: string) => committedById.get(id)?.resizeHandles ?? defaultHandles ?? DEFAULT_HANDLES,\n [committedById, defaultHandles],\n );\n\n // The per-grid callbacks the engine invokes, memoized so a stable consumer\n // doesn't reallocate the object every render (rebuilt only when one changes).\n const callbacks = useMemo(\n () => ({\n onDragStart: opts.onDragStart,\n onDrag: opts.onDrag,\n onDragStop: opts.onDragStop,\n onResizeStart: opts.onResizeStart,\n onResize: opts.onResize,\n onResizeStop: opts.onResizeStop,\n onLayoutChange: opts.onLayoutChange,\n onDrop: opts.onDrop,\n }),\n [\n opts.onDragStart,\n opts.onDrag,\n opts.onDragStop,\n opts.onResizeStart,\n opts.onResize,\n opts.onResizeStop,\n opts.onLayoutChange,\n opts.onDrop,\n ],\n );\n\n // Publish per-grid config to the controller so items (resolved by group) read\n // fresh geometry/predicates without a React context, and the engine reads this\n // grid's geometry, compaction, gates, and callbacks.\n controller.setConfig({\n positionParams,\n gridConfig,\n width: opts.width,\n autoSize: opts.autoSize ?? true,\n itemSensors,\n itemModifiers,\n isItemDraggable,\n isItemResizable,\n resizeHandlesFor,\n compactor,\n dragConfig: opts.dragConfig,\n dropConfig: opts.dropConfig,\n callbacks,\n });\n\n return controller;\n}\n","import { useDroppable } from \"@dnd-kit/react\";\nimport { type GridConfig, bottom } from \"@snapgridjs/core\";\nimport {\n type GridController,\n SNAPGRID_GRID_ATTR,\n domElement,\n gridCollisionDetector,\n} from \"@snapgridjs/dnd\";\nimport { type CSSProperties, useCallback, useRef, useSyncExternalStore } from \"react\";\nimport { type UseGridControllerOptions, useGridController } from \"./useGridController.js\";\n\nexport interface GridContainerProps {\n /** Attach to your container element. */\n ref: (element: Element | null) => void;\n /** Positioning style (relative + width + auto-sized height). Spread onto your element. */\n style: CSSProperties;\n /** Present while a compatible draggable is over the grid. */\n \"data-drop-target\"?: true;\n}\n\nexport interface UseGridContainerResult {\n /** Spread onto your container element. */\n containerProps: GridContainerProps;\n /** True while a compatible draggable is over the grid. */\n isDropTarget: boolean;\n /** This grid's id — pass as the `group` to {@link useGridItem} for its tiles. */\n group: string;\n /** The grid's controller (for advanced/headless composition). */\n controller: GridController;\n}\n\n/** Total container height in pixels for the given number of occupied rows. */\nfunction containerHeight(rows: number, grid: GridConfig): number {\n const padY = (grid.containerPadding ?? grid.margin)[1];\n if (rows <= 0) return padY * 2;\n return padY * 2 + rows * grid.rowHeight + (rows - 1) * grid.margin[1];\n}\n\n/**\n * The grid host: creates this grid's controller + drag monitor (see\n * {@link useGridController}), registers the droppable surface, and returns props\n * to spread onto your own container element. Render `useGridItem` tiles inside,\n * passing `group` (this grid's id) so they resolve this controller.\n */\nexport function useGridContainer(opts: UseGridControllerOptions): UseGridContainerResult {\n const controller = useGridController(opts);\n const config = controller.config;\n const { width, autoSize, gridConfig } = config!;\n const gridElRef = useRef<Element | null>(null);\n\n const { ref, isDropTarget } = useDroppable({\n id: controller.id,\n type: \"grid\",\n // Accept grid tiles plus external draggables carrying a `snapGridDrop`\n // payload. The latter have no type, so `accept: \"grid-item\"` would reject\n // them and they'd never resolve as a drop target. (The provider still\n // decides whether to actually receive an external source via dropConfig.)\n accept: (source) => {\n // Reject a source whose element CONTAINS this grid — an ancestor tile that\n // hosts this nested grid. Prevents dropping a host tile into the grid it\n // contains (a paradox) now that nested grids can share one manager.\n const srcEl = domElement(source);\n if (srcEl && gridElRef.current && srcEl.contains(gridElRef.current)) return false;\n if (source.type === \"grid-item\") return true;\n const data = source.data as { snapGridDrop?: unknown } | undefined;\n return data?.snapGridDrop != null;\n },\n collisionDetector: gridCollisionDetector,\n });\n\n // Merge dnd-kit's droppable ref with reporting the element to the controller\n // (the engine reads it to map the pointer to a cell when receiving a tile from\n // another grid), and mark the element so nested grids can measure their depth.\n const setRef = useCallback(\n (element: Element | null) => {\n ref(element);\n controller.element = element;\n gridElRef.current = element;\n if (element) element.setAttribute(SNAPGRID_GRID_ATTR, \"\");\n },\n [ref, controller],\n );\n\n // Subscribe to the rendered layout (drag preview while dragging, else\n // committed) so the surface auto-height tracks the content as it reflows.\n const renderedLayout = useSyncExternalStore(\n controller.subscribe,\n controller.renderedSnapshot,\n controller.renderedSnapshot,\n );\n const height = autoSize ? containerHeight(bottom(renderedLayout), gridConfig) : undefined;\n\n return {\n containerProps: {\n ref: setRef,\n style: { position: \"relative\", width, height },\n \"data-drop-target\": isDropTarget || undefined,\n },\n isDropTarget,\n group: controller.id,\n controller,\n };\n}\n","// Shared reflow timing for tiles and the placeholder, so they animate in lockstep\n// when a drag reflows the grid. Used by useGridItem (the tile's WAAPI reflow and\n// its out-of-drag CSS transition) and GridPlaceholder (its default look).\nexport const REFLOW_MS = 150;\nexport const REFLOW_EASING = \"ease\";\nexport const REFLOW_TRANSITION = `transform ${REFLOW_MS}ms ${REFLOW_EASING}, width ${REFLOW_MS}ms ${REFLOW_EASING}, height ${REFLOW_MS}ms ${REFLOW_EASING}`;\n","import { useDragDropManager } from \"@dnd-kit/react\";\nimport { type GridController, getController } from \"@snapgridjs/dnd\";\n\n/**\n * Resolve a grid's controller by its `group` (= the grid's id), scoped to the\n * ambient dnd-kit manager. Items declare `group` (mirroring useSortable); the\n * container registered the controller under that id. Throws a helpful error if\n * unresolved — almost always a missing `group` or a tile rendered outside any\n * grid / `DragDropProvider`.\n */\nexport function useResolveController(group: string): GridController {\n const manager = useDragDropManager();\n const controller = getController(manager, group);\n if (!controller) {\n throw new Error(\n `snapgrid: no grid found for group \"${group}\". A grid item must pass the group returned by its grid's useGridContainer, and render inside a <DragDropProvider> (or use <GridLayout>, which wires this for you).`,\n );\n }\n return controller;\n}\n","import { type Draggable, Feedback } from \"@dnd-kit/dom\";\nimport { isKeyboardEvent } from \"@dnd-kit/dom/utilities\";\nimport { useSortable } from \"@dnd-kit/react/sortable\";\nimport { type LayoutItem, calcGridItemPosition } from \"@snapgridjs/core\";\nimport {\n type CSSProperties,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport { REFLOW_EASING, REFLOW_MS, REFLOW_TRANSITION } from \"../reflow.js\";\nimport { useResolveController } from \"./useResolveController.js\";\n\n// A pointer drag floats the tile via dnd-kit's default feedback; a keyboard drag gets\n// `none` (no pointer — the tile steps in place via the session). The drop tween is\n// disabled so a pointer drop lands at the cell, not the float origin.\nconst ITEM_FEEDBACK = [\n Feedback.configure({\n feedback: (_source: Draggable, manager) =>\n isKeyboardEvent(manager.dragOperation.activatorEvent) ? \"none\" : \"default\",\n dropAnimation: null,\n }),\n];\n\nexport interface UseGridItemResult {\n /** Attach to the element that represents this grid item. */\n ref: (element: Element | null) => void;\n /**\n * Optional drag handle (dnd-kit's native handle). Attach to a child element to\n * restrict **pointer** drag activation to it; leave it unattached and the whole\n * tile drags. Keyboard pickup (Enter/Space on a focused tile) is unaffected.\n */\n handleRef: (element: Element | null) => void;\n /** Positioning style to spread onto your element. */\n style: CSSProperties;\n /** True while this item is the active drag source. */\n isDragging: boolean;\n /** The item's current (possibly reflowed) layout entry. */\n item: LayoutItem | undefined;\n}\n\n/**\n * Headless hook for a single grid tile. The tile is a real `useSortable` (a\n * draggable + droppable carrying `group`/`index`/`type`/`accept`), so it\n * interoperates with the dnd-kit sortable ecosystem, yet it is positioned by RGL\n * via the {@link GridController}. `group` is the owning grid's id (from its\n * {@link useGridContainer}), mirroring `useSortable`'s `group`. Spread the returned\n * `ref`, optional `handleRef`, positioning `style`, and drag state onto whatever\n * element you render — you own the tag, className, content, and cosmetic styling.\n *\n * The dragged tile floats itself via dnd-kit's default feedback (no `<DragOverlay>`):\n * the active tile renders at its committed origin so the float offset composes, and\n * reflow is animated on the compositor via the Web Animations API — both so it stays\n * smooth in Safari, where the float's popover top-layer repaint would jank a\n * CSS-transition reflow.\n */\nexport function useGridItem(id: string, group: string): UseGridItemResult {\n const controller = useResolveController(group);\n // Subscribe to just this item's slice → a drag elsewhere doesn't re-render it.\n const snap = useSyncExternalStore(\n controller.subscribe,\n () => controller.itemSnapshot(id),\n () => controller.itemSnapshot(id),\n );\n const item = snap.item;\n const active = snap.isDragging;\n // The controller's \"pointer move in progress\" signal (false for a keyboard drag).\n // We don't hide the tile (it floats itself) — we use it to decide whether to pin\n // the tile at its origin for the float.\n const hidden = snap.hidden;\n const config = controller.config!;\n\n // True on the single render where the tile goes active → settled (the drop frame):\n // snap to the landed cell instead of sliding there from the committed origin.\n const wasActive = useRef(false);\n const justDropped = wasActive.current && !active;\n wasActive.current = active;\n\n // Stable identity for the drag payload so dnd-kit doesn't churn on it every\n // render; it changes only when this tile's resolved entry does (a reflow).\n // `group` lets the engine resolve this tile's owning grid from the payload.\n const data = useMemo(\n () => ({ snapGrid: { kind: \"move\", itemId: id, item, group } }),\n [id, item, group],\n );\n\n const {\n ref: sortableRef,\n handleRef,\n isDragging,\n } = useSortable({\n id,\n index: controller.itemIndex(id),\n group,\n type: \"grid-item\",\n accept: \"grid-item\",\n disabled: !config.isItemDraggable(id),\n sensors: config.itemSensors,\n modifiers: config.itemModifiers,\n // Keep the sortable defaults (optimistic + keyboard, needed for interop); just\n // append the feedback config.\n plugins: (defaults) => [...defaults, ...ITEM_FEEDBACK],\n // Carry the full item so a receiving grid can render/insert it on a cross-grid drop.\n data,\n });\n\n // Capture the element to drive the WAAPI reflow, while still feeding the sortable's ref.\n const elRef = useRef<Element | null>(null);\n const setRef = useCallback(\n (element: Element | null) => {\n sortableRef(element);\n elRef.current = element;\n },\n [sortableRef],\n );\n\n const session = controller.getSession();\n const dragging = session != null;\n\n // During a POINTER drag the active tile renders at its committed origin so dnd-kit's\n // float offset tracks the pointer; a keyboard drag (and every other tile) renders at\n // the reflowed (preview) cell so it steps with the arrow keys.\n const posItem = item ? (active && hidden ? (session?.anchor.item ?? item) : item) : undefined;\n const pos = posItem\n ? calcGridItemPosition(config.positionParams, posItem.x, posItem.y, posItem.w, posItem.h)\n : undefined;\n const posLeft = pos?.left;\n const posTop = pos?.top;\n\n // While dragging, animate a reflowing tile to its new cell on the compositor (a\n // FLIP from its current visual position, so a mid-flight re-target stays smooth).\n // Compositor animations are immune to the float's popover repaint that janks a CSS\n // transition in Safari; outside a drag the CSS transition below handles changes.\n const prev = useRef<{ left: number; top: number } | null>(null);\n const reflowAnim = useRef<Animation | null>(null);\n useLayoutEffect(() => {\n const cur = posLeft != null && posTop != null ? { left: posLeft, top: posTop } : null;\n const before = prev.current;\n prev.current = cur;\n const el = elRef.current;\n if (!el || !cur || !before || active || justDropped || !dragging) return;\n if (before.left === cur.left && before.top === cur.top) return;\n let fromX = before.left;\n let fromY = before.top;\n if (reflowAnim.current?.playState === \"running\") {\n const m = new DOMMatrix(getComputedStyle(el).transform);\n fromX = m.m41;\n fromY = m.m42;\n }\n reflowAnim.current?.cancel();\n reflowAnim.current = el.animate(\n [\n { transform: `translate(${fromX}px, ${fromY}px)` },\n { transform: `translate(${cur.left}px, ${cur.top}px)` },\n ],\n { duration: REFLOW_MS, easing: REFLOW_EASING },\n );\n }, [posLeft, posTop, active, justDropped, dragging]);\n\n // Cancel any in-flight reflow animation when the tile unmounts (e.g. removed\n // mid-drag during a cross-grid move) so a running Animation can't outlive its node.\n useEffect(() => () => reflowAnim.current?.cancel(), []);\n\n const style: CSSProperties = pos\n ? {\n position: \"absolute\",\n left: 0,\n top: 0,\n width: pos.width,\n height: pos.height,\n transform: `translate(${pos.left}px, ${pos.top}px)`,\n // During a drag the WAAPI animation owns reflow motion; a CSS transition\n // would get janked (Safari) and double up. Outside a drag, keep it for\n // programmatic layout changes. The active/just-dropped tile never transitions.\n transition: active || justDropped || dragging ? \"none\" : REFLOW_TRANSITION,\n touchAction: \"none\",\n }\n : { position: \"absolute\", touchAction: \"none\" };\n\n return { ref: setRef, handleRef, style, isDragging, item };\n}\n","import { type LayoutItem, calcGridItemPosition } from \"@snapgridjs/core\";\nimport { type CSSProperties, useSyncExternalStore } from \"react\";\nimport { useResolveController } from \"./useResolveController.js\";\n\nexport interface GridPlaceholderInfo {\n /** The layout entry marking where the dragged item will land. */\n item: LayoutItem;\n /** Positioning style (left/top/size) to spread onto your placeholder element. */\n style: CSSProperties;\n}\n\n/**\n * Headless hook returning where the drag placeholder should be rendered, or\n * `null` when no drag is in progress. `group` is the owning grid's id (from its\n * {@link useGridContainer}). You render the element however you like.\n */\nexport function useGridPlaceholder(group: string): GridPlaceholderInfo | null {\n const controller = useResolveController(group);\n const placeholder = useSyncExternalStore(\n controller.subscribe,\n controller.placeholderSnapshot,\n controller.placeholderSnapshot,\n );\n if (!placeholder) return null;\n const pos = calcGridItemPosition(\n controller.config!.positionParams,\n placeholder.x,\n placeholder.y,\n placeholder.w,\n placeholder.h,\n );\n const style: CSSProperties = {\n position: \"absolute\",\n // Transform-positioned to match grid items (see useGridItem) — the\n // placeholder slides as a GPU transform, not an animated left/top.\n left: 0,\n top: 0,\n width: pos.width,\n height: pos.height,\n transform: `translate(${pos.left}px, ${pos.top}px)`,\n pointerEvents: \"none\",\n };\n return { item: placeholder, style };\n}\n","import { useDraggable } from \"@dnd-kit/react\";\nimport type { ResizeHandleAxis } from \"@snapgridjs/core\";\nimport { NO_FEEDBACK, RESIZE_HANDLE_ATTR } from \"@snapgridjs/dnd\";\nimport { useSyncExternalStore } from \"react\";\nimport { useResolveController } from \"./useResolveController.js\";\n\nexport interface UseGridResizeHandleResult {\n /** Attach to your resize-handle element. */\n ref: (element: Element | null) => void;\n /** Spread onto the handle element so item drags ignore pointer-downs on it. */\n handleProps: { [RESIZE_HANDLE_ATTR]: true };\n /** True while this item is actively being resized. */\n isResizing: boolean;\n}\n\n/**\n * Headless hook for a single resize handle. Model a handle as its own draggable;\n * dragging it resizes the item from the given edge/corner. `group` is the owning\n * grid's id (from its {@link useGridContainer}). Spread `ref` and `handleProps`\n * onto the handle element you position/style.\n */\nexport function useGridResizeHandle(\n itemId: string,\n handle: ResizeHandleAxis,\n group: string,\n): UseGridResizeHandleResult {\n const controller = useResolveController(group);\n const { ref } = useDraggable({\n id: `${itemId}::resize::${handle}`,\n disabled: !controller.config?.isItemResizable(itemId),\n plugins: NO_FEEDBACK,\n data: { snapGrid: { kind: \"resize\", itemId, handle, group } },\n });\n const { isResizing } = useSyncExternalStore(\n controller.subscribe,\n () => controller.resizeSnapshot(itemId),\n () => controller.resizeSnapshot(itemId),\n );\n return { ref, handleProps: { [RESIZE_HANDLE_ATTR]: true }, isResizing };\n}\n","import {\n type BreakpointCols,\n type Breakpoints,\n type Compactor,\n type Layout,\n type ResponsiveLayouts,\n findOrGenerateResponsiveLayout,\n getBreakpointFromWidth,\n getColsFromBreakpoint,\n verticalCompactor,\n} from \"@snapgridjs/core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\n\n/** react-grid-layout's default breakpoints (px) and column counts. */\nexport const DEFAULT_BREAKPOINTS: Breakpoints = { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 };\nexport const DEFAULT_BREAKPOINT_COLS: BreakpointCols = { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 };\n\nexport interface UseResponsiveLayoutOptions {\n /** Current container width in pixels. */\n width: number;\n /** Controlled per-breakpoint layouts. Missing breakpoints are generated from the nearest one. */\n layouts: ResponsiveLayouts;\n /** Breakpoint → min width (px). @default lg/md/sm/xs/xxs */\n breakpoints?: Breakpoints;\n /** Breakpoint → column count. @default 12/10/6/4/2 */\n cols?: BreakpointCols;\n /** Compaction strategy used when generating a missing breakpoint's layout. */\n compactor?: Compactor;\n /** Called when a layout commits: the active layout and the updated map. */\n onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts) => void;\n /** Called when the active breakpoint changes. */\n onBreakpointChange?: (breakpoint: string, cols: number) => void;\n}\n\nexport interface UseResponsiveLayoutResult {\n /** The active breakpoint name. */\n breakpoint: string;\n /** Column count for the active breakpoint. */\n cols: number;\n /** The resolved layout for the active breakpoint (generated if absent). */\n layout: Layout;\n /** Pass to the grid's `onLayoutChange`; updates the active breakpoint's layout. */\n onLayoutChange: (layout: Layout) => void;\n}\n\n/**\n * Headless responsive layout engine: resolves the active breakpoint and its\n * column count/layout from the container width, generating a layout for the\n * active breakpoint from the nearest one when missing.\n */\nexport function useResponsiveLayout(\n options: UseResponsiveLayoutOptions,\n): UseResponsiveLayoutResult {\n const {\n width,\n layouts,\n breakpoints = DEFAULT_BREAKPOINTS,\n cols = DEFAULT_BREAKPOINT_COLS,\n compactor = verticalCompactor,\n onLayoutChange,\n onBreakpointChange,\n } = options;\n\n const breakpoint = getBreakpointFromWidth(breakpoints, width);\n const colCount = getColsFromBreakpoint(breakpoint, cols);\n\n // Memoized so the clone + compact over every item only runs when an input\n // actually changes (not on every render/width tick). The fallback source for\n // generating a missing breakpoint — used by findOrGenerateResponsiveLayout\n // only when no provided breakpoint sits at/above the target — is the widest\n // provided layout. Derived purely from inputs (no ref mutated in an effect),\n // so generation is a pure function of render inputs (StrictMode/concurrent\n // safe) and no longer depends on the order breakpoints were visited.\n const layout = useMemo(() => {\n let source = breakpoint;\n let sourceWidth = Number.NEGATIVE_INFINITY;\n for (const [bp, minWidth] of Object.entries(breakpoints)) {\n if (layouts[bp] && minWidth > sourceWidth) {\n sourceWidth = minWidth;\n source = bp;\n }\n }\n return findOrGenerateResponsiveLayout(\n layouts,\n breakpoints,\n breakpoint,\n source,\n colCount,\n compactor,\n );\n }, [layouts, breakpoints, breakpoint, colCount, compactor]);\n\n // Fire onBreakpointChange when the active breakpoint actually changes. This ref\n // is written only inside the effect (never read during render), so render stays pure.\n const onBreakpointChangeRef = useRef(onBreakpointChange);\n onBreakpointChangeRef.current = onBreakpointChange;\n const firedBreakpointRef = useRef(breakpoint);\n useEffect(() => {\n if (firedBreakpointRef.current !== breakpoint) {\n firedBreakpointRef.current = breakpoint;\n onBreakpointChangeRef.current?.(breakpoint, colCount);\n }\n }, [breakpoint, colCount]);\n\n const handleLayoutChange = useCallback(\n (next: Layout) => {\n onLayoutChange?.(next, { ...layouts, [breakpoint]: next });\n },\n [onLayoutChange, layouts, breakpoint],\n );\n\n return { breakpoint, cols: colCount, layout, onLayoutChange: handleLayoutChange };\n}\n","import type { ResizeHandleAxis } from \"@snapgridjs/core\";\nimport { type CSSProperties, type ReactNode, memo } from \"react\";\nimport { useGridItem } from \"../hooks/useGridItem.js\";\nimport { useGridResizeHandle } from \"../hooks/useGridResizeHandle.js\";\nimport { useResolveController } from \"../hooks/useResolveController.js\";\n\nexport interface GridItemProps {\n /** Matches the layout item's `i`. */\n id: string;\n /** The owning grid's id (from its useGridContainer). */\n group: string;\n children: ReactNode;\n /** Appended to the default `snapgrid-item` class. */\n className?: string;\n /** Merged over (and able to override) the positioning style. */\n style?: CSSProperties;\n}\n\nconst HANDLE_CURSOR: Record<ResizeHandleAxis, string> = {\n n: \"ns-resize\",\n s: \"ns-resize\",\n e: \"ew-resize\",\n w: \"ew-resize\",\n se: \"nwse-resize\",\n nw: \"nwse-resize\",\n ne: \"nesw-resize\",\n sw: \"nesw-resize\",\n};\n\nconst SIDE = 14;\nfunction handleStyle(handle: ResizeHandleAxis): CSSProperties {\n const s: CSSProperties = {\n position: \"absolute\",\n width: SIDE,\n height: SIDE,\n cursor: HANDLE_CURSOR[handle],\n touchAction: \"none\",\n zIndex: 4,\n };\n if (handle.includes(\"n\")) s.top = -SIDE / 2;\n if (handle.includes(\"s\")) s.bottom = -SIDE / 2;\n if (handle.includes(\"e\")) s.right = -SIDE / 2;\n if (handle.includes(\"w\")) s.left = -SIDE / 2;\n if (handle === \"n\" || handle === \"s\") {\n s.left = `calc(50% - ${SIDE / 2}px)`;\n }\n if (handle === \"e\" || handle === \"w\") {\n s.top = `calc(50% - ${SIDE / 2}px)`;\n }\n return s;\n}\n\nfunction DefaultResizeHandle({\n itemId,\n handle,\n group,\n}: { itemId: string; handle: ResizeHandleAxis; group: string }) {\n const { ref, handleProps } = useGridResizeHandle(itemId, handle, group);\n return (\n <span\n ref={ref}\n {...handleProps}\n className={`snapgrid-resize-handle snapgrid-resize-handle--${handle}`}\n style={handleStyle(handle)}\n />\n );\n}\n\n/**\n * Convenience wrapper over {@link useGridItem}: an absolutely-positioned `<div>`\n * with stable hooks (`.snapgrid-item`, `data-grid-id`, `data-dragging`) and the\n * configured resize handles. `group` is the owning grid's id. For full control,\n * use the hooks directly.\n *\n * Memoized so re-rendering the surface (e.g. its auto-height tracking the drag)\n * doesn't re-render every tile — a tile re-renders only when its own slice\n * changes (via useGridItem's subscription). Keeps a drag's React work scoped to\n * the moved tile (see renderScope.test).\n */\nfunction GridItemImpl({ id, group, children, className, style }: GridItemProps) {\n const controller = useResolveController(group);\n const { ref, style: positionStyle, isDragging } = useGridItem(id, group);\n const config = controller.config;\n const handles = config?.isItemResizable(id) ? config.resizeHandlesFor(id) : [];\n return (\n <div\n ref={ref}\n data-grid-id={id}\n data-dragging={isDragging || undefined}\n className={className ? `snapgrid-item ${className}` : \"snapgrid-item\"}\n style={style ? { ...positionStyle, ...style } : positionStyle}\n >\n {children}\n {handles.map((handle) => (\n <DefaultResizeHandle key={handle} itemId={id} handle={handle} group={group} />\n ))}\n </div>\n );\n}\n\nexport const GridItem = memo(GridItemImpl);\n","import type { CSSProperties } from \"react\";\nimport { useGridPlaceholder } from \"../hooks/useGridPlaceholder.js\";\nimport { REFLOW_TRANSITION } from \"../reflow.js\";\n\nexport interface GridPlaceholderProps {\n /** The owning grid's id (from its useGridContainer). */\n group: string;\n /** Appended to the default `snapgrid-placeholder` class. */\n className?: string;\n /** Merged over (and able to override) the default look. */\n style?: CSSProperties;\n}\n\nconst DEFAULT_LOOK: CSSProperties = {\n background: \"rgba(99, 102, 241, 0.2)\",\n border: \"1px dashed rgba(99, 102, 241, 0.6)\",\n borderRadius: 4,\n boxSizing: \"border-box\",\n zIndex: 2,\n transition: REFLOW_TRANSITION,\n};\n\n/**\n * Convenience placeholder rendered from {@link useGridPlaceholder}. Renders\n * nothing when no drag is active. For a custom placeholder, call the hook\n * directly and render your own element with the returned `style`.\n */\nexport function GridPlaceholder({ group, className, style }: GridPlaceholderProps) {\n const placeholder = useGridPlaceholder(group);\n if (!placeholder) return null;\n return (\n <div\n aria-hidden=\"true\"\n className={className ? `snapgrid-placeholder ${className}` : \"snapgrid-placeholder\"}\n style={{ ...placeholder.style, ...DEFAULT_LOOK, ...style }}\n />\n );\n}\n","import { DragDropProvider } from \"@dnd-kit/react\";\nimport {\n type CSSProperties,\n Children,\n type ReactNode,\n createContext,\n isValidElement,\n useContext,\n} from \"react\";\nimport { useGridContainer } from \"../hooks/useGridContainer.js\";\nimport type { UseGridControllerOptions } from \"../hooks/useGridController.js\";\nimport { GridItem } from \"./GridItem.js\";\nimport { GridPlaceholder } from \"./GridPlaceholder.js\";\n\nexport interface GridLayoutProps extends UseGridControllerOptions {\n children: ReactNode;\n /** Appended to the default `snapgrid` class on the surface. */\n className?: string;\n /** Merged over (and able to override) the surface's positioning style. */\n style?: CSSProperties;\n}\n\n// Marks that a snapgrid-managed <DragDropProvider> already exists above, so a\n// nested GridLayout (or sibling sharing one) doesn't mint a second manager.\nconst InProvider = createContext(false);\n\n/** Strip the namespacing prefix React applies to keys inside `Children.map`. */\nfunction keyToId(key: string): string {\n return key.startsWith(\".$\") ? key.slice(2) : key;\n}\n\n/** The default surface: positioned container + mapped items + placeholder. */\nfunction GridSurface({ className, style, children, ...opts }: GridLayoutProps) {\n const { containerProps, group } = useGridContainer(opts);\n return (\n <div\n {...containerProps}\n className={className ? `snapgrid ${className}` : \"snapgrid\"}\n style={style ? { ...containerProps.style, ...style } : containerProps.style}\n >\n {Children.map(children, (child) => {\n if (!isValidElement(child) || child.key == null) return child;\n return (\n <GridItem key={child.key} id={keyToId(String(child.key))} group={group}>\n {child}\n </GridItem>\n );\n })}\n <GridPlaceholder group={group} />\n </div>\n );\n}\n\n/**\n * Drop-in grid component: a controlled, react-grid-layout v2-compatible layout\n * backed by dnd-kit. A thin shell over {@link useGridContainer} and the headless\n * hooks — children are keyed by their layout item's `i`. For full control over\n * markup/styling, use the hooks directly.\n *\n * Supplies the dnd-kit `DragDropProvider` for the turnkey case so consumers\n * don't manage one. Nest multiple `GridLayout`s and they share one provider\n * (the seam for cross-grid drags); a consumer's own provider is also honored.\n */\nexport function GridLayout(props: GridLayoutProps): React.JSX.Element {\n const inProvider = useContext(InProvider);\n const surface = <GridSurface {...props} />;\n if (inProvider) return surface;\n return (\n <DragDropProvider>\n <InProvider.Provider value={true}>{surface}</InProvider.Provider>\n </DragDropProvider>\n );\n}\n\n/**\n * Share one dnd-kit `DragDropProvider` across several sibling grids so tiles can\n * be dragged between them. (Nested `GridLayout`s already share a provider; this\n * is for siblings.) A thin wrapper over `DragDropProvider` — the cross-grid seam\n * is the shared manager + collision target.\n */\nexport function SnapGridGroup({ children }: { children: ReactNode }): React.JSX.Element {\n const inProvider = useContext(InProvider);\n if (inProvider) return <>{children}</>;\n return (\n <DragDropProvider>\n <InProvider.Provider value={true}>{children}</InProvider.Provider>\n </DragDropProvider>\n );\n}\n","import type {\n BreakpointCols,\n Breakpoints,\n Compactor,\n Layout,\n ResponsiveLayouts,\n} from \"@snapgridjs/core\";\nimport type { DragConfig, ResizeConfig } from \"@snapgridjs/dnd\";\nimport { type CSSProperties, type ReactNode, useMemo } from \"react\";\nimport { useResponsiveLayout } from \"../hooks/useResponsiveLayout.js\";\nimport { GridLayout } from \"./GridLayout.js\";\n\nexport interface ResponsiveGridLayoutProps {\n /** Container width in pixels (e.g. from {@link useContainerWidth}). */\n width: number;\n /** Controlled per-breakpoint layouts. Children are keyed by item `i`. */\n layouts: ResponsiveLayouts;\n /** Called when a layout commits: the active layout and the updated map. */\n onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts) => void;\n /** Called when the active breakpoint changes. */\n onBreakpointChange?: (breakpoint: string, cols: number) => void;\n /** Breakpoint → min width (px). @default lg/md/sm/xs/xxs */\n breakpoints?: Breakpoints;\n /** Breakpoint → column count. @default 12/10/6/4/2 */\n cols?: BreakpointCols;\n rowHeight?: number;\n margin?: [number, number];\n containerPadding?: [number, number] | null;\n compactor?: Compactor;\n dragConfig?: DragConfig;\n resizeConfig?: ResizeConfig;\n isDraggable?: boolean;\n isResizable?: boolean;\n autoSize?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\n/**\n * A responsive grid: switches column count and layout by breakpoint as `width`\n * changes, generating a breakpoint's layout from the nearest one when absent.\n * A thin wrapper over {@link useResponsiveLayout} + {@link GridLayout}; mirrors\n * react-grid-layout v2's `ResponsiveGridLayout`.\n */\nexport function ResponsiveGridLayout(props: ResponsiveGridLayoutProps): React.JSX.Element {\n const { cols, layout, onLayoutChange } = useResponsiveLayout({\n width: props.width,\n layouts: props.layouts,\n breakpoints: props.breakpoints,\n cols: props.cols,\n compactor: props.compactor,\n onLayoutChange: props.onLayoutChange,\n onBreakpointChange: props.onBreakpointChange,\n });\n\n // Stable object identity so the grid host's gridConfig/positionParams memos\n // aren't busted on every render (e.g. each width tick).\n const gridConfig = useMemo(\n () => ({\n cols,\n rowHeight: props.rowHeight ?? 150,\n margin: props.margin ?? ([10, 10] as [number, number]),\n containerPadding: props.containerPadding ?? null,\n }),\n [cols, props.rowHeight, props.margin, props.containerPadding],\n );\n\n return (\n // No explicit `id`: useGridContainer mints a stable per-instance id (useId),\n // which avoids droppable/registry identity churn when the breakpoint changes and\n // keeps two responsive grids in a group from colliding on the same id.\n <GridLayout\n layout={layout}\n width={props.width}\n onLayoutChange={onLayoutChange}\n gridConfig={gridConfig}\n compactor={props.compactor}\n dragConfig={props.dragConfig}\n resizeConfig={props.resizeConfig}\n isDraggable={props.isDraggable}\n isResizable={props.isResizable}\n autoSize={props.autoSize}\n className={props.className}\n style={props.style}\n >\n {props.children}\n </GridLayout>\n );\n}\n","import { useCallback, useEffect, useLayoutEffect, useState } from \"react\";\n\n// useLayoutEffect warns when run on the server; fall back to useEffect there so\n// the hook is SSR-safe (Next.js / Remix). The initial `width` is `initialWidth`\n// on both server and client, so the first render matches and there's no\n// hydration mismatch — the measured width is applied right after mount.\nconst useIsomorphicLayoutEffect = typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\nexport interface UseContainerWidthOptions {\n /** Width to use until the element has been measured. @default 1280 */\n initialWidth?: number;\n}\n\nexport interface UseContainerWidthResult {\n /** Measured container width in pixels (or `initialWidth` before mount). */\n width: number;\n /** Whether the element has been measured at least once. */\n mounted: boolean;\n /** Attach to the element whose width should drive the grid. */\n containerRef: (element: HTMLElement | null) => void;\n}\n\n/**\n * Measure a container's width with a `ResizeObserver`. Replaces react-grid-layout's\n * `WidthProvider` HOC with a hook, mirroring RGL v2's `useContainerWidth`.\n */\nexport function useContainerWidth(options: UseContainerWidthOptions = {}): UseContainerWidthResult {\n const { initialWidth = 1280 } = options;\n const [width, setWidth] = useState(initialWidth);\n const [mounted, setMounted] = useState(false);\n // Track the element in state so the observer effect re-runs when it changes;\n // this is StrictMode-safe (the effect's cleanup disconnects the observer).\n const [element, setElement] = useState<HTMLElement | null>(null);\n const containerRef = useCallback((node: HTMLElement | null) => setElement(node), []);\n\n useIsomorphicLayoutEffect(() => {\n if (!element || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n const next = element.getBoundingClientRect().width;\n if (next > 0) {\n setWidth(next);\n setMounted(true);\n }\n };\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, [element]);\n\n return { width, mounted, containerRef };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["defaultGridConfig","toPositionParams","verticalCompactor","useDroppable","Feedback","useDraggable","verticalCompactor"],"sources":["../src/hooks/useGridController.ts","../src/hooks/useGridContainer.ts","../src/reflow.ts","../src/hooks/useResolveController.ts","../src/hooks/useGridItem.ts","../src/hooks/useGridPlaceholder.ts","../src/hooks/useGridResizeHandle.ts","../src/hooks/useResponsiveLayout.ts","../src/components/GridItem.tsx","../src/components/GridPlaceholder.tsx","../src/components/GridLayout.tsx","../src/components/ResponsiveGridLayout.tsx","../src/hooks/useContainerWidth.ts"],"sourcesContent":["import { useDragDropManager, useInstance } from \"@dnd-kit/react\";\nimport {\n type Compactor,\n type GridConfig,\n type Layout,\n type LayoutItem,\n type PositionParams,\n defaultGridConfig,\n toPositionParams,\n verticalCompactor,\n} from \"@snapgridjs/core\";\nimport {\n type DragConfig,\n type DragSourceInfo,\n type DropConfig,\n GridController,\n type GridEventCallback,\n type ResizeConfig,\n SnapToGrid,\n attachEngine,\n buildItemSensors,\n registerController,\n} from \"@snapgridjs/dnd\";\nimport { useCallback, useEffect, useId, useMemo, useRef } from \"react\";\n\nconst DEFAULT_HANDLES = [\"se\"] as const;\n\n// Per-item drag/resize gate. Mirrors RGL's engine rule: a `static` item is locked\n// unless its flag (`isDraggable`/`isResizable`) is explicitly `true` (\"pinned\");\n// a non-static item just follows the flag (default `true`).\nfunction itemGateOpen(flag: boolean | undefined, isStatic: boolean | undefined): boolean {\n return isStatic ? flag === true : (flag ?? true);\n}\n\n/** Options the grid host ({@link useGridContainer}) feeds the controller. */\nexport interface UseGridControllerOptions {\n /** Stable id for the grid's droppable surface (auto-generated if omitted). */\n id?: string;\n /** Container width in pixels (e.g. from {@link useContainerWidth}). */\n width: number;\n /** Controlled layout. Never mutated. */\n layout: Layout;\n onLayoutChange?: (layout: Layout) => void;\n gridConfig?: Partial<GridConfig>;\n dragConfig?: DragConfig;\n resizeConfig?: ResizeConfig;\n dropConfig?: DropConfig;\n /**\n * Accept additional (non-grid) dnd-kit draggables as drop targets — e.g. a\n * `useSortable` card from a sibling list, for interop. Extends the built-in\n * acceptance (grid tiles + `snapGridDrop` externals); the ancestry guard still\n * applies. You drive the actual receive in your own `onDragOver` with `snapMove`.\n */\n accept?: (source: DragSourceInfo) => boolean;\n compactor?: Compactor;\n isDraggable?: boolean;\n isResizable?: boolean;\n autoSize?: boolean;\n onDragStart?: GridEventCallback;\n onDrag?: GridEventCallback;\n onDragStop?: GridEventCallback;\n onResizeStart?: GridEventCallback;\n onResize?: GridEventCallback;\n onResizeStop?: GridEventCallback;\n onDrop?: (layout: Layout, item: LayoutItem, event: Event | null) => void;\n}\n\n/**\n * The grid's React seam: owns the {@link GridController} (an observable render\n * bridge), publishes per-grid config to it each render, registers it for id →\n * controller resolution, and attaches the manager-wide {@link SnapGridEngine}.\n *\n * The drag/resize *orchestration* lives in the engine (one per manager), not\n * here — this hook only wires the React-specific parts: the controller, the item\n * sensors/modifiers descriptors, the draggable/resizable gates, and the config\n * the engine reads. Created by {@link useGridContainer}; items resolve the same\n * controller by their `group` (= this grid's id). Consumes the ambient\n * `DragDropProvider` — it does not mint one.\n */\nexport function useGridController(opts: UseGridControllerOptions): GridController {\n const autoId = useId();\n const containerId = opts.id ?? autoId;\n\n const gridConfig: GridConfig = useMemo(\n () => ({ ...defaultGridConfig, ...opts.gridConfig }),\n [opts.gridConfig],\n );\n const positionParams: PositionParams = useMemo(\n () => toPositionParams(gridConfig, opts.width),\n [gridConfig, opts.width],\n );\n const compactor: Compactor = opts.compactor ?? verticalCompactor;\n\n const manager = useDragDropManager();\n const controller = useInstance<GridController>(\n (m) => new GridController(containerId, opts.layout, m ?? undefined),\n );\n controller.setCommitted(opts.layout);\n // useInstance creates the controller once, freezing its id to the first render's\n // value; re-point it if the controlled `id` prop changes so the group, the\n // droppable id, and the registry key (below) stay in sync. (Read during render,\n // before useGridContainer's droppable/group read controller.id.)\n if (controller.id !== containerId) controller.setId(containerId);\n\n // Live refs for the item sensor/modifier descriptors, which read config lazily\n // (they're built once but must see the latest dragConfig / positionParams).\n const optsRef = useRef(opts);\n optsRef.current = opts;\n const ppRef = useRef(positionParams);\n ppRef.current = positionParams;\n\n // Register the controller so items (and snapMove) resolve it by id, and so the\n // engine can find it as a drag's source/destination. During render so child\n // items resolve it on their first render (children render after the parent but\n // before any layout effect). The effect's cleanup unregisters on unmount / id\n // or manager change.\n registerController(manager, containerId, controller);\n useEffect(\n () => registerController(manager, containerId, controller),\n [manager, containerId, controller],\n );\n\n // Attach the manager-wide drag/resize engine (ref-counted; one per manager,\n // shared by every grid on it). Detaches when the last grid for this manager\n // unmounts. No-op without a manager (no provider above).\n useEffect(() => {\n if (!manager) return;\n return attachEngine(manager);\n }, [manager]);\n\n const committedById = useMemo(\n () => new Map<string, LayoutItem>(opts.layout.map((it) => [it.i, it])),\n [opts.layout],\n );\n\n const dragThreshold = opts.dragConfig?.threshold ?? 3;\n const itemSensors = useMemo(\n () => buildItemSensors(dragThreshold, () => optsRef.current.dragConfig),\n [dragThreshold],\n );\n\n // Snap-to-grid modifier (stable descriptor; reads live refs so it never goes\n // stale). A no-op unless `dragConfig.snapToGrid` is set.\n const itemModifiers = useMemo(\n () => [\n SnapToGrid.configure({\n getPositionParams: () => ppRef.current,\n isEnabled: () => optsRef.current.dragConfig?.snapToGrid ?? false,\n }),\n ],\n [],\n );\n\n const gridDraggable = opts.isDraggable ?? true;\n const dragEnabled = opts.dragConfig?.enabled ?? true;\n const isItemDraggable = useCallback(\n (id: string) => {\n const it = committedById.get(id);\n if (!it) return false;\n return gridDraggable && dragEnabled && itemGateOpen(it.isDraggable, it.static);\n },\n [committedById, gridDraggable, dragEnabled],\n );\n\n const gridResizable = opts.isResizable ?? true;\n const resizeEnabled = opts.resizeConfig?.enabled ?? true;\n const isItemResizable = useCallback(\n (id: string) => {\n const it = committedById.get(id);\n if (!it) return false;\n return gridResizable && resizeEnabled && itemGateOpen(it.isResizable, it.static);\n },\n [committedById, gridResizable, resizeEnabled],\n );\n const defaultHandles = opts.resizeConfig?.handles;\n const resizeHandlesFor = useCallback(\n (id: string) => committedById.get(id)?.resizeHandles ?? defaultHandles ?? DEFAULT_HANDLES,\n [committedById, defaultHandles],\n );\n\n // The per-grid callbacks the engine invokes, memoized so a stable consumer\n // doesn't reallocate the object every render (rebuilt only when one changes).\n const callbacks = useMemo(\n () => ({\n onDragStart: opts.onDragStart,\n onDrag: opts.onDrag,\n onDragStop: opts.onDragStop,\n onResizeStart: opts.onResizeStart,\n onResize: opts.onResize,\n onResizeStop: opts.onResizeStop,\n onLayoutChange: opts.onLayoutChange,\n onDrop: opts.onDrop,\n }),\n [\n opts.onDragStart,\n opts.onDrag,\n opts.onDragStop,\n opts.onResizeStart,\n opts.onResize,\n opts.onResizeStop,\n opts.onLayoutChange,\n opts.onDrop,\n ],\n );\n\n // Publish per-grid config to the controller so items (resolved by group) read\n // fresh geometry/predicates without a React context, and the engine reads this\n // grid's geometry, compaction, gates, and callbacks.\n controller.setConfig({\n positionParams,\n gridConfig,\n width: opts.width,\n autoSize: opts.autoSize ?? true,\n itemSensors,\n itemModifiers,\n isItemDraggable,\n isItemResizable,\n resizeHandlesFor,\n compactor,\n dragConfig: opts.dragConfig,\n dropConfig: opts.dropConfig,\n callbacks,\n });\n\n return controller;\n}\n","import { useDroppable } from \"@dnd-kit/react\";\nimport { type GridConfig, bottom } from \"@snapgridjs/core\";\nimport {\n type GridController,\n SNAPGRID_GRID_ATTR,\n domElement,\n gridCollisionDetector,\n} from \"@snapgridjs/dnd\";\nimport { type CSSProperties, useCallback, useRef, useSyncExternalStore } from \"react\";\nimport { type UseGridControllerOptions, useGridController } from \"./useGridController.js\";\n\nexport interface GridContainerProps {\n /** Attach to your container element. */\n ref: (element: Element | null) => void;\n /** Positioning style (relative + width + auto-sized height). Spread onto your element. */\n style: CSSProperties;\n /** Present while a compatible draggable is over the grid. */\n \"data-drop-target\"?: true;\n}\n\nexport interface UseGridContainerResult {\n /** Spread onto your container element. */\n containerProps: GridContainerProps;\n /** True while a compatible draggable is over the grid. */\n isDropTarget: boolean;\n /** This grid's id — pass as the `group` to {@link useGridItem} for its tiles. */\n group: string;\n /** The grid's controller (for advanced/headless composition). */\n controller: GridController;\n}\n\n/** Total container height in pixels for the given number of occupied rows. */\nfunction containerHeight(rows: number, grid: GridConfig): number {\n const padY = (grid.containerPadding ?? grid.margin)[1];\n if (rows <= 0) return padY * 2;\n return padY * 2 + rows * grid.rowHeight + (rows - 1) * grid.margin[1];\n}\n\n/**\n * The grid host: creates this grid's controller + drag monitor (see\n * {@link useGridController}), registers the droppable surface, and returns props\n * to spread onto your own container element. Render `useGridItem` tiles inside,\n * passing `group` (this grid's id) so they resolve this controller.\n */\nexport function useGridContainer(opts: UseGridControllerOptions): UseGridContainerResult {\n const controller = useGridController(opts);\n const config = controller.config;\n const { width, autoSize, gridConfig } = config!;\n const gridElRef = useRef<Element | null>(null);\n\n const { ref, isDropTarget } = useDroppable({\n id: controller.id,\n type: \"grid\",\n // Accept grid tiles plus external draggables carrying a `snapGridDrop`\n // payload. The latter have no type, so `accept: \"grid-item\"` would reject\n // them and they'd never resolve as a drop target. (The provider still\n // decides whether to actually receive an external source via dropConfig.)\n accept: (source) => {\n // Reject a source whose element CONTAINS this grid — an ancestor tile that\n // hosts this nested grid. Prevents dropping a host tile into the grid it\n // contains (a paradox) now that nested grids can share one manager.\n const srcEl = domElement(source);\n if (srcEl && gridElRef.current && srcEl.contains(gridElRef.current)) return false;\n if (source.type === \"grid-item\") return true;\n const data = source.data as { snapGridDrop?: unknown } | undefined;\n if (data?.snapGridDrop != null) return true;\n // Consumer extension: accept foreign dnd-kit draggables (e.g. a sortable\n // card) as drop targets for interop; the receive is driven via snapMove.\n return opts.accept?.(source) ?? false;\n },\n collisionDetector: gridCollisionDetector,\n });\n\n // Merge dnd-kit's droppable ref with reporting the element to the controller\n // (the engine reads it to map the pointer to a cell when receiving a tile from\n // another grid), and mark the element so nested grids can measure their depth.\n const setRef = useCallback(\n (element: Element | null) => {\n ref(element);\n controller.element = element;\n gridElRef.current = element;\n if (element) element.setAttribute(SNAPGRID_GRID_ATTR, \"\");\n },\n [ref, controller],\n );\n\n // Subscribe to the rendered layout (drag preview while dragging, else\n // committed) so the surface auto-height tracks the content as it reflows.\n const renderedLayout = useSyncExternalStore(\n controller.subscribe,\n controller.renderedSnapshot,\n controller.renderedSnapshot,\n );\n const height = autoSize ? containerHeight(bottom(renderedLayout), gridConfig) : undefined;\n\n return {\n containerProps: {\n ref: setRef,\n style: { position: \"relative\", width, height },\n \"data-drop-target\": isDropTarget || undefined,\n },\n isDropTarget,\n group: controller.id,\n controller,\n };\n}\n","// Shared reflow timing for tiles and the placeholder, so they animate in lockstep\n// when a drag reflows the grid. Used by useGridItem (the tile's WAAPI reflow FLIP\n// and its out-of-drag CSS transition) and GridPlaceholder (its default look).\nexport const REFLOW_MS = 150;\nexport const REFLOW_EASING = \"ease\";\n// The placeholder is transform-positioned; this transitions its motion.\nexport const REFLOW_TRANSITION = `transform ${REFLOW_MS}ms ${REFLOW_EASING}, width ${REFLOW_MS}ms ${REFLOW_EASING}, height ${REFLOW_MS}ms ${REFLOW_EASING}`;\n// Tiles rest on left/top and animate POSITION via the compositor FLIP in useGridItem,\n// so their CSS transition covers SIZE only: a left/top transition would be copied onto\n// dnd-kit's float clone and fly it in from (0,0) at lift.\nexport const TILE_TRANSITION = `width ${REFLOW_MS}ms ${REFLOW_EASING}, height ${REFLOW_MS}ms ${REFLOW_EASING}`;\n","import { useDragDropManager } from \"@dnd-kit/react\";\nimport { type GridController, getController } from \"@snapgridjs/dnd\";\n\n/**\n * Resolve a grid's controller by its `group` (= the grid's id), scoped to the\n * ambient dnd-kit manager. Items declare `group` (mirroring useSortable); the\n * container registered the controller under that id. Throws a helpful error if\n * unresolved — almost always a missing `group` or a tile rendered outside any\n * grid / `DragDropProvider`.\n */\nexport function useResolveController(group: string): GridController {\n const manager = useDragDropManager();\n const controller = getController(manager, group);\n if (!controller) {\n throw new Error(\n `snapgrid: no grid found for group \"${group}\". A grid item must pass the group returned by its grid's useGridContainer, and render inside a <DragDropProvider> (or use <GridLayout>, which wires this for you).`,\n );\n }\n return controller;\n}\n","import { type Draggable, Feedback } from \"@dnd-kit/dom\";\nimport { isKeyboardEvent } from \"@dnd-kit/dom/utilities\";\nimport { useSortable } from \"@dnd-kit/react/sortable\";\nimport { type LayoutItem, calcGridItemPosition } from \"@snapgridjs/core\";\nimport {\n type CSSProperties,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n} from \"react\";\nimport { REFLOW_EASING, REFLOW_MS, TILE_TRANSITION } from \"../reflow.js\";\nimport { useResolveController } from \"./useResolveController.js\";\n\n// A pointer drag floats the tile via dnd-kit's default feedback; a keyboard drag gets\n// `none` (no pointer — the tile steps in place via the session). The drop tween is\n// disabled so a pointer drop lands at the cell, not the float origin.\nconst ITEM_FEEDBACK = [\n Feedback.configure({\n feedback: (_source: Draggable, manager) =>\n isKeyboardEvent(manager.dragOperation.activatorEvent) ? \"none\" : \"default\",\n dropAnimation: null,\n }),\n];\n\n// A grid tile is never itself a drop target — the grid CONTAINER (a separate,\n// higher-priority droppable) is what a drag resolves onto. Keeping tiles out of the\n// target pool also stops dnd-kit's OptimisticSortingPlugin from reparenting a tile's\n// DOM node mid-drag (it acts only when source AND target are sortables) and then\n// fighting React's commit (`removeChild`).\nconst tileNeverTarget = () => null;\n\nexport interface UseGridItemResult {\n /** Attach to the element that represents this grid item. */\n ref: (element: Element | null) => void;\n /**\n * Optional drag handle (dnd-kit's native handle). Attach to a child element to\n * restrict **pointer** drag activation to it; leave it unattached and the whole\n * tile drags. Keyboard pickup (Enter/Space on a focused tile) is unaffected.\n */\n handleRef: (element: Element | null) => void;\n /** Positioning style to spread onto your element. */\n style: CSSProperties;\n /** True while this item is the active drag source. */\n isDragging: boolean;\n /** The item's current (possibly reflowed) layout entry. */\n item: LayoutItem | undefined;\n}\n\n/**\n * Headless hook for a single grid tile. The tile is a real `useSortable` (a\n * draggable + droppable carrying `group`/`index`/`type`/`accept`), so it\n * interoperates with the dnd-kit sortable ecosystem, yet it is positioned by RGL\n * via the {@link GridController}. `group` is the owning grid's id (from its\n * {@link useGridContainer}), mirroring `useSortable`'s `group`. Spread the returned\n * `ref`, optional `handleRef`, positioning `style`, and drag state onto whatever\n * element you render — you own the tag, className, content, and cosmetic styling.\n *\n * The dragged tile floats itself via dnd-kit's default feedback (no `<DragOverlay>`):\n * the active tile renders at its committed origin and dnd-kit's float follows the\n * pointer from there, while reflow is animated on the compositor via the Web\n * Animations API (a FLIP) — both so it stays smooth in Safari, where the float's\n * popover top-layer repaint would jank a CSS-transition reflow.\n *\n * Tiles are positioned with `left`/`top` (not `transform`). dnd-kit's self-float\n * measures the source element's rect ignoring transforms and re-applies its current\n * transform each frame; a transform-positioned tile leans on that, but the\n * compensation is lost the instant the dragged element is swapped for a foreign one\n * mid-drag (grid → sortable interop — the tile becomes a flow card), which would\n * make the float jump by the tile's grid offset. Plain left/top has nothing to lose\n * on the swap, matching how dnd-kit's own flow-positioned sortables hand off cleanly.\n */\nexport function useGridItem(id: string, group: string): UseGridItemResult {\n const controller = useResolveController(group);\n // Subscribe to just this item's slice → a drag elsewhere doesn't re-render it.\n const snap = useSyncExternalStore(\n controller.subscribe,\n () => controller.itemSnapshot(id),\n () => controller.itemSnapshot(id),\n );\n const item = snap.item;\n const active = snap.isDragging;\n // The controller's \"pointer move in progress\" signal (false for a keyboard drag).\n // We don't hide the tile (it floats itself) — we use it to decide whether to pin\n // the tile at its origin for the float.\n const hidden = snap.hidden;\n const config = controller.config!;\n\n // True on the single render where the tile goes active → settled (the drop frame):\n // snap to the landed cell instead of sliding there from the committed origin.\n const wasActive = useRef(false);\n const justDropped = wasActive.current && !active;\n wasActive.current = active;\n\n // Stable identity for the drag payload so dnd-kit doesn't churn on it every\n // render; it changes only when this tile's resolved entry does (a reflow).\n // `group` lets the engine resolve this tile's owning grid from the payload.\n const data = useMemo(\n () => ({ snapGrid: { kind: \"move\", itemId: id, item, group } }),\n [id, item, group],\n );\n\n const {\n ref: sortableRef,\n handleRef,\n isDragging,\n } = useSortable({\n id,\n index: controller.itemIndex(id),\n group,\n type: \"grid-item\",\n accept: \"grid-item\",\n // The tile is a sortable (so it interops + carries group/index), but never a\n // drop target — the grid container is. See {@link tileNeverTarget}.\n collisionDetector: tileNeverTarget,\n disabled: !config.isItemDraggable(id),\n sensors: config.itemSensors,\n modifiers: config.itemModifiers,\n // Keep the sortable defaults (optimistic + keyboard, needed for interop); just\n // append the feedback config.\n plugins: (defaults) => [...defaults, ...ITEM_FEEDBACK],\n // Carry the full item so a receiving grid can render/insert it on a cross-grid drop.\n data,\n });\n\n // Capture the element to drive the WAAPI reflow, while still feeding the sortable's ref.\n const elRef = useRef<Element | null>(null);\n const setRef = useCallback(\n (element: Element | null) => {\n sortableRef(element);\n elRef.current = element;\n },\n [sortableRef],\n );\n\n const session = controller.getSession();\n const dragging = session != null;\n\n // During a POINTER drag the active tile renders at its committed origin so dnd-kit's\n // float offset tracks the pointer; a keyboard drag (and every other tile) renders at\n // the reflowed (preview) cell so it steps with the arrow keys.\n const posItem = item ? (active && hidden ? (session?.anchor.item ?? item) : item) : undefined;\n const pos = posItem\n ? calcGridItemPosition(config.positionParams, posItem.x, posItem.y, posItem.w, posItem.h)\n : undefined;\n const posLeft = pos?.left;\n const posTop = pos?.top;\n\n // Reflow a tile to its new cell via a compositor FLIP: the resting left/top has\n // already jumped this render, so animate a `transform` delta from the tile's previous\n // visual position back to 0. Drives in-drag reflow AND out-of-drag (responsive /\n // programmatic) changes, and dodges the float's popover repaint that janks a CSS\n // transition in Safari. The drag source settling after a drop is the exception (see\n // the `settleAnchor` branch below).\n const prev = useRef<{ left: number; top: number } | null>(null);\n const reflowAnim = useRef<Animation | null>(null);\n const settleAnchor = useRef<{ left: number; top: number } | null>(null);\n useLayoutEffect(() => {\n const cur = posLeft != null && posTop != null ? { left: posLeft, top: posTop } : null;\n const before = prev.current;\n prev.current = cur;\n const el = elRef.current;\n if (!el || !cur) return;\n\n // Active: dnd-kit owns this tile's motion. Remember the cell it floats from so the\n // post-drop settle can snap instead of FLIP.\n if (active) {\n settleAnchor.current = cur;\n reflowAnim.current?.cancel();\n return;\n }\n // A drag of ANOTHER tile in this grid: this tile reflows normally; drop any stale\n // settle anchor so it FLIPs (it was never floated).\n if (dragging) settleAnchor.current = null;\n // Post-drop settle of the formerly-active source: it was floated, so `before` is the\n // committed origin, not where it visually was — snap (no FLIP) until the committed\n // move lands (cell leaves the anchor). Clearing earlier is unsafe: the drop's commit\n // can arrive a render after `active` clears, and on that frame a pending real move\n // and a no-op drop both read `cur === anchor`. The cost: a true no-op drop leaves the\n // anchor set until the next drag clears it (tiny, accepted — beats reopening the slide).\n else if (settleAnchor.current) {\n const a = settleAnchor.current;\n reflowAnim.current?.cancel();\n if (cur.left !== a.left || cur.top !== a.top) settleAnchor.current = null;\n return;\n }\n\n if (!before || justDropped) return;\n if (before.left === cur.left && before.top === cur.top) return;\n // Web Animations API may be absent (jsdom / SSR / very old browsers): degrade to\n // an instant move (the left/top below already places the tile) rather than throw.\n if (typeof el.animate !== \"function\") return;\n // Previous visual position = the prior resting cell plus any in-flight transform.\n let fromX = before.left;\n let fromY = before.top;\n if (reflowAnim.current?.playState === \"running\") {\n const m = new DOMMatrix(getComputedStyle(el).transform);\n fromX = before.left + m.m41;\n fromY = before.top + m.m42;\n }\n reflowAnim.current?.cancel();\n reflowAnim.current = el.animate(\n [\n { transform: `translate(${fromX - cur.left}px, ${fromY - cur.top}px)` },\n { transform: \"translate(0px, 0px)\" },\n ],\n { duration: REFLOW_MS, easing: REFLOW_EASING },\n );\n }, [posLeft, posTop, active, justDropped, dragging]);\n\n // Cancel any in-flight reflow animation when the tile unmounts (e.g. removed\n // mid-drag during a cross-grid move) so a running Animation can't outlive its node.\n useEffect(() => () => reflowAnim.current?.cancel(), []);\n\n // Tiles rest on left/top (see the hook doc above); position animates via the FLIP\n // above, so the transition is SIZE-only (TILE_TRANSITION) — and \"none\" while dragging\n // (FLIP owns motion) or just-dropped (it snaps). The active tile (⊂ dragging) hits \"none\".\n const style: CSSProperties = pos\n ? {\n position: \"absolute\",\n left: pos.left,\n top: pos.top,\n width: pos.width,\n height: pos.height,\n transition: justDropped || dragging ? \"none\" : TILE_TRANSITION,\n touchAction: \"none\",\n }\n : { position: \"absolute\", touchAction: \"none\" };\n\n return { ref: setRef, handleRef, style, isDragging, item };\n}\n","import { type LayoutItem, calcGridItemPosition } from \"@snapgridjs/core\";\nimport { type CSSProperties, useSyncExternalStore } from \"react\";\nimport { useResolveController } from \"./useResolveController.js\";\n\nexport interface GridPlaceholderInfo {\n /** The layout entry marking where the dragged item will land. */\n item: LayoutItem;\n /** Positioning style (left/top/size) to spread onto your placeholder element. */\n style: CSSProperties;\n}\n\n/**\n * Headless hook returning where the drag placeholder should be rendered, or\n * `null` when no drag is in progress. `group` is the owning grid's id (from its\n * {@link useGridContainer}). You render the element however you like.\n */\nexport function useGridPlaceholder(group: string): GridPlaceholderInfo | null {\n const controller = useResolveController(group);\n const placeholder = useSyncExternalStore(\n controller.subscribe,\n controller.placeholderSnapshot,\n controller.placeholderSnapshot,\n );\n if (!placeholder) return null;\n const pos = calcGridItemPosition(\n controller.config!.positionParams,\n placeholder.x,\n placeholder.y,\n placeholder.w,\n placeholder.h,\n );\n const style: CSSProperties = {\n position: \"absolute\",\n // Transform-positioned to match grid items (see useGridItem) — the\n // placeholder slides as a GPU transform, not an animated left/top.\n left: 0,\n top: 0,\n width: pos.width,\n height: pos.height,\n transform: `translate(${pos.left}px, ${pos.top}px)`,\n pointerEvents: \"none\",\n };\n return { item: placeholder, style };\n}\n","import { useDraggable } from \"@dnd-kit/react\";\nimport type { ResizeHandleAxis } from \"@snapgridjs/core\";\nimport { NO_FEEDBACK, RESIZE_HANDLE_ATTR } from \"@snapgridjs/dnd\";\nimport { useSyncExternalStore } from \"react\";\nimport { useResolveController } from \"./useResolveController.js\";\n\nexport interface UseGridResizeHandleResult {\n /** Attach to your resize-handle element. */\n ref: (element: Element | null) => void;\n /** Spread onto the handle element so item drags ignore pointer-downs on it. */\n handleProps: { [RESIZE_HANDLE_ATTR]: true };\n /** True while this item is actively being resized. */\n isResizing: boolean;\n}\n\n/**\n * Headless hook for a single resize handle. Model a handle as its own draggable;\n * dragging it resizes the item from the given edge/corner. `group` is the owning\n * grid's id (from its {@link useGridContainer}). Spread `ref` and `handleProps`\n * onto the handle element you position/style.\n */\nexport function useGridResizeHandle(\n itemId: string,\n handle: ResizeHandleAxis,\n group: string,\n): UseGridResizeHandleResult {\n const controller = useResolveController(group);\n const { ref } = useDraggable({\n id: `${itemId}::resize::${handle}`,\n disabled: !controller.config?.isItemResizable(itemId),\n plugins: NO_FEEDBACK,\n data: { snapGrid: { kind: \"resize\", itemId, handle, group } },\n });\n const { isResizing } = useSyncExternalStore(\n controller.subscribe,\n () => controller.resizeSnapshot(itemId),\n () => controller.resizeSnapshot(itemId),\n );\n return { ref, handleProps: { [RESIZE_HANDLE_ATTR]: true }, isResizing };\n}\n","import {\n type BreakpointCols,\n type Breakpoints,\n type Compactor,\n type Layout,\n type ResponsiveLayouts,\n findOrGenerateResponsiveLayout,\n getBreakpointFromWidth,\n getColsFromBreakpoint,\n verticalCompactor,\n} from \"@snapgridjs/core\";\nimport { useCallback, useEffect, useMemo, useRef } from \"react\";\n\n/** react-grid-layout's default breakpoints (px) and column counts. */\nexport const DEFAULT_BREAKPOINTS: Breakpoints = { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 };\nexport const DEFAULT_BREAKPOINT_COLS: BreakpointCols = { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 };\n\nexport interface UseResponsiveLayoutOptions {\n /** Current container width in pixels. */\n width: number;\n /** Controlled per-breakpoint layouts. Missing breakpoints are generated from the nearest one. */\n layouts: ResponsiveLayouts;\n /** Breakpoint → min width (px). @default lg/md/sm/xs/xxs */\n breakpoints?: Breakpoints;\n /** Breakpoint → column count. @default 12/10/6/4/2 */\n cols?: BreakpointCols;\n /** Compaction strategy used when generating a missing breakpoint's layout. */\n compactor?: Compactor;\n /** Called when a layout commits: the active layout and the updated map. */\n onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts) => void;\n /** Called when the active breakpoint changes. */\n onBreakpointChange?: (breakpoint: string, cols: number) => void;\n}\n\nexport interface UseResponsiveLayoutResult {\n /** The active breakpoint name. */\n breakpoint: string;\n /** Column count for the active breakpoint. */\n cols: number;\n /** The resolved layout for the active breakpoint (generated if absent). */\n layout: Layout;\n /** Pass to the grid's `onLayoutChange`; updates the active breakpoint's layout. */\n onLayoutChange: (layout: Layout) => void;\n}\n\n/**\n * Headless responsive layout engine: resolves the active breakpoint and its\n * column count/layout from the container width, generating a layout for the\n * active breakpoint from the nearest one when missing.\n */\nexport function useResponsiveLayout(\n options: UseResponsiveLayoutOptions,\n): UseResponsiveLayoutResult {\n const {\n width,\n layouts,\n breakpoints = DEFAULT_BREAKPOINTS,\n cols = DEFAULT_BREAKPOINT_COLS,\n compactor = verticalCompactor,\n onLayoutChange,\n onBreakpointChange,\n } = options;\n\n const breakpoint = getBreakpointFromWidth(breakpoints, width);\n const colCount = getColsFromBreakpoint(breakpoint, cols);\n\n // Memoized so the clone + compact over every item only runs when an input\n // actually changes (not on every render/width tick). The fallback source for\n // generating a missing breakpoint — used by findOrGenerateResponsiveLayout\n // only when no provided breakpoint sits at/above the target — is the widest\n // provided layout. Derived purely from inputs (no ref mutated in an effect),\n // so generation is a pure function of render inputs (StrictMode/concurrent\n // safe) and no longer depends on the order breakpoints were visited.\n const layout = useMemo(() => {\n let source = breakpoint;\n let sourceWidth = Number.NEGATIVE_INFINITY;\n for (const [bp, minWidth] of Object.entries(breakpoints)) {\n if (layouts[bp] && minWidth > sourceWidth) {\n sourceWidth = minWidth;\n source = bp;\n }\n }\n return findOrGenerateResponsiveLayout(\n layouts,\n breakpoints,\n breakpoint,\n source,\n colCount,\n compactor,\n );\n }, [layouts, breakpoints, breakpoint, colCount, compactor]);\n\n // Fire onBreakpointChange when the active breakpoint actually changes. This ref\n // is written only inside the effect (never read during render), so render stays pure.\n const onBreakpointChangeRef = useRef(onBreakpointChange);\n onBreakpointChangeRef.current = onBreakpointChange;\n const firedBreakpointRef = useRef(breakpoint);\n useEffect(() => {\n if (firedBreakpointRef.current !== breakpoint) {\n firedBreakpointRef.current = breakpoint;\n onBreakpointChangeRef.current?.(breakpoint, colCount);\n }\n }, [breakpoint, colCount]);\n\n const handleLayoutChange = useCallback(\n (next: Layout) => {\n onLayoutChange?.(next, { ...layouts, [breakpoint]: next });\n },\n [onLayoutChange, layouts, breakpoint],\n );\n\n return { breakpoint, cols: colCount, layout, onLayoutChange: handleLayoutChange };\n}\n","import type { ResizeHandleAxis } from \"@snapgridjs/core\";\nimport { type CSSProperties, type ReactNode, memo } from \"react\";\nimport { useGridItem } from \"../hooks/useGridItem.js\";\nimport { useGridResizeHandle } from \"../hooks/useGridResizeHandle.js\";\nimport { useResolveController } from \"../hooks/useResolveController.js\";\n\nexport interface GridItemProps {\n /** Matches the layout item's `i`. */\n id: string;\n /** The owning grid's id (from its useGridContainer). */\n group: string;\n children: ReactNode;\n /** Appended to the default `snapgrid-item` class. */\n className?: string;\n /** Merged over (and able to override) the positioning style. */\n style?: CSSProperties;\n}\n\nconst HANDLE_CURSOR: Record<ResizeHandleAxis, string> = {\n n: \"ns-resize\",\n s: \"ns-resize\",\n e: \"ew-resize\",\n w: \"ew-resize\",\n se: \"nwse-resize\",\n nw: \"nwse-resize\",\n ne: \"nesw-resize\",\n sw: \"nesw-resize\",\n};\n\nconst SIDE = 14;\nfunction handleStyle(handle: ResizeHandleAxis): CSSProperties {\n const s: CSSProperties = {\n position: \"absolute\",\n width: SIDE,\n height: SIDE,\n cursor: HANDLE_CURSOR[handle],\n touchAction: \"none\",\n zIndex: 4,\n };\n if (handle.includes(\"n\")) s.top = -SIDE / 2;\n if (handle.includes(\"s\")) s.bottom = -SIDE / 2;\n if (handle.includes(\"e\")) s.right = -SIDE / 2;\n if (handle.includes(\"w\")) s.left = -SIDE / 2;\n if (handle === \"n\" || handle === \"s\") {\n s.left = `calc(50% - ${SIDE / 2}px)`;\n }\n if (handle === \"e\" || handle === \"w\") {\n s.top = `calc(50% - ${SIDE / 2}px)`;\n }\n return s;\n}\n\nfunction DefaultResizeHandle({\n itemId,\n handle,\n group,\n}: { itemId: string; handle: ResizeHandleAxis; group: string }) {\n const { ref, handleProps } = useGridResizeHandle(itemId, handle, group);\n return (\n <span\n ref={ref}\n {...handleProps}\n className={`snapgrid-resize-handle snapgrid-resize-handle--${handle}`}\n style={handleStyle(handle)}\n />\n );\n}\n\n/**\n * Convenience wrapper over {@link useGridItem}: an absolutely-positioned `<div>`\n * with stable hooks (`.snapgrid-item`, `data-grid-id`, `data-dragging`) and the\n * configured resize handles. `group` is the owning grid's id. For full control,\n * use the hooks directly.\n *\n * Memoized so re-rendering the surface (e.g. its auto-height tracking the drag)\n * doesn't re-render every tile — a tile re-renders only when its own slice\n * changes (via useGridItem's subscription). Keeps a drag's React work scoped to\n * the moved tile (see renderScope.test).\n */\nfunction GridItemImpl({ id, group, children, className, style }: GridItemProps) {\n const controller = useResolveController(group);\n const { ref, style: positionStyle, isDragging } = useGridItem(id, group);\n const config = controller.config;\n const handles = config?.isItemResizable(id) ? config.resizeHandlesFor(id) : [];\n return (\n <div\n ref={ref}\n data-grid-id={id}\n data-dragging={isDragging || undefined}\n className={className ? `snapgrid-item ${className}` : \"snapgrid-item\"}\n style={style ? { ...positionStyle, ...style } : positionStyle}\n >\n {children}\n {handles.map((handle) => (\n <DefaultResizeHandle key={handle} itemId={id} handle={handle} group={group} />\n ))}\n </div>\n );\n}\n\nexport const GridItem = memo(GridItemImpl);\n","import type { CSSProperties } from \"react\";\nimport { useGridPlaceholder } from \"../hooks/useGridPlaceholder.js\";\nimport { REFLOW_TRANSITION } from \"../reflow.js\";\n\nexport interface GridPlaceholderProps {\n /** The owning grid's id (from its useGridContainer). */\n group: string;\n /** Appended to the default `snapgrid-placeholder` class. */\n className?: string;\n /** Merged over (and able to override) the default look. */\n style?: CSSProperties;\n}\n\nconst DEFAULT_LOOK: CSSProperties = {\n background: \"rgba(99, 102, 241, 0.2)\",\n border: \"1px dashed rgba(99, 102, 241, 0.6)\",\n borderRadius: 4,\n boxSizing: \"border-box\",\n zIndex: 2,\n transition: REFLOW_TRANSITION,\n};\n\n/**\n * Convenience placeholder rendered from {@link useGridPlaceholder}. Renders\n * nothing when no drag is active. For a custom placeholder, call the hook\n * directly and render your own element with the returned `style`.\n */\nexport function GridPlaceholder({ group, className, style }: GridPlaceholderProps) {\n const placeholder = useGridPlaceholder(group);\n if (!placeholder) return null;\n return (\n <div\n aria-hidden=\"true\"\n className={className ? `snapgrid-placeholder ${className}` : \"snapgrid-placeholder\"}\n style={{ ...placeholder.style, ...DEFAULT_LOOK, ...style }}\n />\n );\n}\n","import { DragDropProvider } from \"@dnd-kit/react\";\nimport {\n type CSSProperties,\n Children,\n type ReactNode,\n createContext,\n isValidElement,\n useContext,\n} from \"react\";\nimport { useGridContainer } from \"../hooks/useGridContainer.js\";\nimport type { UseGridControllerOptions } from \"../hooks/useGridController.js\";\nimport { GridItem } from \"./GridItem.js\";\nimport { GridPlaceholder } from \"./GridPlaceholder.js\";\n\nexport interface GridLayoutProps extends UseGridControllerOptions {\n children: ReactNode;\n /** Appended to the default `snapgrid` class on the surface. */\n className?: string;\n /** Merged over (and able to override) the surface's positioning style. */\n style?: CSSProperties;\n}\n\n// Marks that a snapgrid-managed <DragDropProvider> already exists above, so a\n// nested GridLayout (or sibling sharing one) doesn't mint a second manager.\nconst InProvider = createContext(false);\n\n/** Strip the namespacing prefix React applies to keys inside `Children.map`. */\nfunction keyToId(key: string): string {\n return key.startsWith(\".$\") ? key.slice(2) : key;\n}\n\n/** The default surface: positioned container + mapped items + placeholder. */\nfunction GridSurface({ className, style, children, ...opts }: GridLayoutProps) {\n const { containerProps, group } = useGridContainer(opts);\n return (\n <div\n {...containerProps}\n className={className ? `snapgrid ${className}` : \"snapgrid\"}\n style={style ? { ...containerProps.style, ...style } : containerProps.style}\n >\n {Children.map(children, (child) => {\n if (!isValidElement(child) || child.key == null) return child;\n return (\n <GridItem key={child.key} id={keyToId(String(child.key))} group={group}>\n {child}\n </GridItem>\n );\n })}\n <GridPlaceholder group={group} />\n </div>\n );\n}\n\n/**\n * Drop-in grid component: a controlled, react-grid-layout v2-compatible layout\n * backed by dnd-kit. A thin shell over {@link useGridContainer} and the headless\n * hooks — children are keyed by their layout item's `i`. For full control over\n * markup/styling, use the hooks directly.\n *\n * Supplies the dnd-kit `DragDropProvider` for the turnkey case so consumers\n * don't manage one. Nest multiple `GridLayout`s and they share one provider\n * (the seam for cross-grid drags); a consumer's own provider is also honored.\n */\nexport function GridLayout(props: GridLayoutProps): React.JSX.Element {\n const inProvider = useContext(InProvider);\n const surface = <GridSurface {...props} />;\n if (inProvider) return surface;\n return (\n <DragDropProvider>\n <InProvider.Provider value={true}>{surface}</InProvider.Provider>\n </DragDropProvider>\n );\n}\n\n/**\n * Share one dnd-kit `DragDropProvider` across several sibling grids so tiles can\n * be dragged between them. (Nested `GridLayout`s already share a provider; this\n * is for siblings.) A thin wrapper over `DragDropProvider` — the cross-grid seam\n * is the shared manager + collision target.\n */\nexport function SnapGridGroup({ children }: { children: ReactNode }): React.JSX.Element {\n const inProvider = useContext(InProvider);\n if (inProvider) return <>{children}</>;\n return (\n <DragDropProvider>\n <InProvider.Provider value={true}>{children}</InProvider.Provider>\n </DragDropProvider>\n );\n}\n","import type {\n BreakpointCols,\n Breakpoints,\n Compactor,\n Layout,\n ResponsiveLayouts,\n} from \"@snapgridjs/core\";\nimport type { DragConfig, ResizeConfig } from \"@snapgridjs/dnd\";\nimport { type CSSProperties, type ReactNode, useMemo } from \"react\";\nimport { useResponsiveLayout } from \"../hooks/useResponsiveLayout.js\";\nimport { GridLayout } from \"./GridLayout.js\";\n\nexport interface ResponsiveGridLayoutProps {\n /** Container width in pixels (e.g. from {@link useContainerWidth}). */\n width: number;\n /** Controlled per-breakpoint layouts. Children are keyed by item `i`. */\n layouts: ResponsiveLayouts;\n /** Called when a layout commits: the active layout and the updated map. */\n onLayoutChange?: (layout: Layout, layouts: ResponsiveLayouts) => void;\n /** Called when the active breakpoint changes. */\n onBreakpointChange?: (breakpoint: string, cols: number) => void;\n /** Breakpoint → min width (px). @default lg/md/sm/xs/xxs */\n breakpoints?: Breakpoints;\n /** Breakpoint → column count. @default 12/10/6/4/2 */\n cols?: BreakpointCols;\n rowHeight?: number;\n margin?: [number, number];\n containerPadding?: [number, number] | null;\n compactor?: Compactor;\n dragConfig?: DragConfig;\n resizeConfig?: ResizeConfig;\n isDraggable?: boolean;\n isResizable?: boolean;\n autoSize?: boolean;\n className?: string;\n style?: CSSProperties;\n children: ReactNode;\n}\n\n/**\n * A responsive grid: switches column count and layout by breakpoint as `width`\n * changes, generating a breakpoint's layout from the nearest one when absent.\n * A thin wrapper over {@link useResponsiveLayout} + {@link GridLayout}; mirrors\n * react-grid-layout v2's `ResponsiveGridLayout`.\n */\nexport function ResponsiveGridLayout(props: ResponsiveGridLayoutProps): React.JSX.Element {\n const { cols, layout, onLayoutChange } = useResponsiveLayout({\n width: props.width,\n layouts: props.layouts,\n breakpoints: props.breakpoints,\n cols: props.cols,\n compactor: props.compactor,\n onLayoutChange: props.onLayoutChange,\n onBreakpointChange: props.onBreakpointChange,\n });\n\n // Stable object identity so the grid host's gridConfig/positionParams memos\n // aren't busted on every render (e.g. each width tick).\n const gridConfig = useMemo(\n () => ({\n cols,\n rowHeight: props.rowHeight ?? 150,\n margin: props.margin ?? ([10, 10] as [number, number]),\n containerPadding: props.containerPadding ?? null,\n }),\n [cols, props.rowHeight, props.margin, props.containerPadding],\n );\n\n return (\n // No explicit `id`: useGridContainer mints a stable per-instance id (useId),\n // which avoids droppable/registry identity churn when the breakpoint changes and\n // keeps two responsive grids in a group from colliding on the same id.\n <GridLayout\n layout={layout}\n width={props.width}\n onLayoutChange={onLayoutChange}\n gridConfig={gridConfig}\n compactor={props.compactor}\n dragConfig={props.dragConfig}\n resizeConfig={props.resizeConfig}\n isDraggable={props.isDraggable}\n isResizable={props.isResizable}\n autoSize={props.autoSize}\n className={props.className}\n style={props.style}\n >\n {props.children}\n </GridLayout>\n );\n}\n","import { useCallback, useEffect, useLayoutEffect, useState } from \"react\";\n\n// useLayoutEffect warns when run on the server; fall back to useEffect there so\n// the hook is SSR-safe (Next.js / Remix). The initial `width` is `initialWidth`\n// on both server and client, so the first render matches and there's no\n// hydration mismatch — the measured width is applied right after mount.\nconst useIsomorphicLayoutEffect = typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\nexport interface UseContainerWidthOptions {\n /** Width to use until the element has been measured. @default 1280 */\n initialWidth?: number;\n}\n\nexport interface UseContainerWidthResult {\n /** Measured container width in pixels (or `initialWidth` before mount). */\n width: number;\n /** Whether the element has been measured at least once. */\n mounted: boolean;\n /** Attach to the element whose width should drive the grid. */\n containerRef: (element: HTMLElement | null) => void;\n}\n\n/**\n * Measure a container's width with a `ResizeObserver`. Replaces react-grid-layout's\n * `WidthProvider` HOC with a hook, mirroring RGL v2's `useContainerWidth`.\n */\nexport function useContainerWidth(options: UseContainerWidthOptions = {}): UseContainerWidthResult {\n const { initialWidth = 1280 } = options;\n const [width, setWidth] = useState(initialWidth);\n const [mounted, setMounted] = useState(false);\n // Track the element in state so the observer effect re-runs when it changes;\n // this is StrictMode-safe (the effect's cleanup disconnects the observer).\n const [element, setElement] = useState<HTMLElement | null>(null);\n const containerRef = useCallback((node: HTMLElement | null) => setElement(node), []);\n\n useIsomorphicLayoutEffect(() => {\n if (!element || typeof ResizeObserver === \"undefined\") return;\n const measure = () => {\n const next = element.getBoundingClientRect().width;\n if (next > 0) {\n setWidth(next);\n setMounted(true);\n }\n };\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, [element]);\n\n return { width, mounted, containerRef };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapgridjs/react",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "React grid-layout components built on dnd-kit — a react-grid-layout v2 alternative.",
5
5
  "license": "MIT",
6
6
  "author": "Edmond Leung",
@@ -51,8 +51,8 @@
51
51
  "module": "./dist/index.mjs",
52
52
  "types": "./dist/index.d.mts",
53
53
  "dependencies": {
54
- "@snapgridjs/core": "0.5.0",
55
- "@snapgridjs/dnd": "0.5.0"
54
+ "@snapgridjs/core": "0.6.0",
55
+ "@snapgridjs/dnd": "0.6.0"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "react": ">=18",