react-grid-layout 2.2.3 → 2.3.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.
Files changed (40) hide show
  1. package/README.md +5 -0
  2. package/dist/{ResponsiveGridLayout-BjVraYMQ.d.mts → ResponsiveGridLayout-BSYEMZ9d.d.ts} +4 -4
  3. package/dist/{ResponsiveGridLayout-BrhkSyZk.d.ts → ResponsiveGridLayout-RNuyRTPe.d.mts} +4 -4
  4. package/dist/{calculate-DH4EVtn1.d.mts → calculate-BXoe3Mfz.d.mts} +1 -1
  5. package/dist/{calculate-rP3DHexe.d.ts → calculate-Tc1WkIxl.d.ts} +1 -1
  6. package/dist/{chunk-BPZQUJ7Y.js → chunk-CUP5Y2ZG.js} +500 -155
  7. package/dist/{chunk-55DQUWLA.js → chunk-QAIA5KAO.js} +33 -22
  8. package/dist/{chunk-7MZZ6T4J.js → chunk-SL4EZ2NU.js} +67 -38
  9. package/dist/{chunk-PZLKKWSX.mjs → chunk-TW4BCTKD.mjs} +37 -8
  10. package/dist/{chunk-KDANGDDL.mjs → chunk-VBU6B7II.mjs} +13 -2
  11. package/dist/{chunk-A5WIFECI.js → chunk-VJJIA3HC.js} +7 -3
  12. package/dist/{chunk-WGL5FSZH.mjs → chunk-Z6CWRR74.mjs} +431 -86
  13. package/dist/{chunk-76RTO6EO.mjs → chunk-ZYNFVPDS.mjs} +7 -3
  14. package/dist/core.d.mts +5 -5
  15. package/dist/core.d.ts +5 -5
  16. package/dist/core.js +67 -67
  17. package/dist/core.mjs +2 -2
  18. package/dist/extras.d.mts +2 -2
  19. package/dist/extras.d.ts +2 -2
  20. package/dist/extras.js +8 -8
  21. package/dist/extras.mjs +1 -1
  22. package/dist/index.d.mts +5 -5
  23. package/dist/index.d.ts +5 -5
  24. package/dist/index.js +39 -39
  25. package/dist/index.mjs +4 -4
  26. package/dist/legacy.d.mts +18 -9
  27. package/dist/legacy.d.ts +18 -9
  28. package/dist/legacy.js +35 -25
  29. package/dist/legacy.mjs +18 -9
  30. package/dist/{position-CSgQSjwQ.d.ts → position-VdYnMJql.d.ts} +1 -1
  31. package/dist/{position-BV-g3Ezg.d.mts → position-iPly-ecb.d.mts} +1 -1
  32. package/dist/react.d.mts +24 -6
  33. package/dist/react.d.ts +24 -6
  34. package/dist/react.js +25 -25
  35. package/dist/react.mjs +4 -4
  36. package/dist/{responsive-BrTV_0tK.d.mts → responsive-BVtXrrTF.d.mts} +1 -1
  37. package/dist/{responsive-C_YtBQYq.d.ts → responsive-C6s9JAJU.d.ts} +1 -1
  38. package/dist/{types-jd8MiKM1.d.mts → types-DlzNckle.d.mts} +22 -0
  39. package/dist/{types-jd8MiKM1.d.ts → types-DlzNckle.d.ts} +22 -0
  40. package/package.json +3 -2
@@ -1,13 +1,77 @@
1
- import { defaultConstraints, setTransform, setTopLeft, perc, applyPositionConstraints, resizeItemInDirection, applySizeConstraints, defaultPositionStrategy, defaultGridConfig, defaultDragConfig, defaultResizeConfig, defaultDropConfig, getCompactor, getBreakpointFromWidth, getColsFromBreakpoint, findOrGenerateResponsiveLayout, getIndentationValue } from './chunk-KDANGDDL.mjs';
2
- import { calcXYRaw, calcGridItemWHPx, clamp, calcGridColWidth, calcWHRaw, calcGridItemPosition, bottom, getLayoutItem, cloneLayoutItem, moveElement, withLayoutItem, getAllCollisions, calcXY, cloneLayout, correctBounds } from './chunk-76RTO6EO.mjs';
3
- import React2, { useState, useRef, useMemo, useCallback, useEffect } from 'react';
1
+ import { defaultConstraints, setTransform, setTopLeft, perc, applyPositionConstraints, resizeItemInDirection, applySizeConstraints, getCompactor, getBreakpointFromWidth, getColsFromBreakpoint, findOrGenerateResponsiveLayout, getIndentationValue, defaultPositionStrategy, defaultGridConfig, defaultDragConfig, defaultResizeConfig, defaultDropConfig } from './chunk-VBU6B7II.mjs';
2
+ import { calcXYRaw, calcGridItemWHPx, clamp, calcGridColWidth, calcWHRaw, calcGridItemPosition, cloneLayout, bottom, correctBounds, getLayoutItem, cloneLayoutItem, moveElement, withLayoutItem, getAllCollisions, calcXY } from './chunk-ZYNFVPDS.mjs';
3
+ import React2, { useState, useRef, useMemo, useCallback, useEffect, useLayoutEffect } from 'react';
4
4
  import { DraggableCore } from 'react-draggable';
5
5
  import { Resizable } from 'react-resizable';
6
6
  import clsx from 'clsx';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';
8
8
  import { deepEqual } from 'fast-equals';
9
9
 
10
- function GridItem(props) {
10
+ // src/react/components/edgeScroll.ts
11
+ var EDGE_THRESHOLD = 50;
12
+ var SCROLL_STEP = 12;
13
+ function getNearestScrollable(node) {
14
+ let el = node;
15
+ while (el) {
16
+ const style = window.getComputedStyle(el);
17
+ const overflowY = style.overflowY;
18
+ const scrollable = (overflowY === "auto" || overflowY === "scroll") && el.scrollHeight > el.clientHeight;
19
+ if (scrollable) return el;
20
+ el = el.parentElement;
21
+ }
22
+ return null;
23
+ }
24
+ function createEdgeScrollController(node) {
25
+ const scrollContainer = getNearestScrollable(node);
26
+ let rafId = null;
27
+ let lastX = 0;
28
+ let lastY = 0;
29
+ let running = false;
30
+ function step() {
31
+ const container = scrollContainer;
32
+ if (!container) return;
33
+ const rect = container.getBoundingClientRect();
34
+ const { clientHeight, scrollTop, scrollHeight } = container;
35
+ const { scrollLeft, scrollWidth, clientWidth } = container;
36
+ let dy = 0;
37
+ let dx = 0;
38
+ if (lastY < rect.top + EDGE_THRESHOLD && scrollTop > 0) {
39
+ dy = -SCROLL_STEP;
40
+ } else if (lastY > rect.bottom - EDGE_THRESHOLD && scrollTop + clientHeight < scrollHeight) {
41
+ dy = SCROLL_STEP;
42
+ }
43
+ if (lastX < rect.left + EDGE_THRESHOLD && scrollLeft > 0) {
44
+ dx = -SCROLL_STEP;
45
+ } else if (lastX > rect.right - EDGE_THRESHOLD && scrollLeft + clientWidth < scrollWidth) {
46
+ dx = SCROLL_STEP;
47
+ }
48
+ if (dy !== 0 || dx !== 0) {
49
+ container.scrollTop += dy;
50
+ container.scrollLeft += dx;
51
+ }
52
+ if (running) {
53
+ rafId = requestAnimationFrame(step);
54
+ }
55
+ }
56
+ return {
57
+ feed(clientX, clientY) {
58
+ lastX = clientX;
59
+ lastY = clientY;
60
+ if (!running) {
61
+ running = true;
62
+ rafId = requestAnimationFrame(step);
63
+ }
64
+ },
65
+ stop() {
66
+ running = false;
67
+ if (rafId !== null) {
68
+ cancelAnimationFrame(rafId);
69
+ rafId = null;
70
+ }
71
+ }
72
+ };
73
+ }
74
+ function GridItemInner(props) {
11
75
  const {
12
76
  children,
13
77
  cols,
@@ -19,6 +83,7 @@ function GridItem(props) {
19
83
  isDraggable,
20
84
  isResizable,
21
85
  isBounded,
86
+ allowMobileScroll,
22
87
  static: isStatic,
23
88
  useCSSTransforms = true,
24
89
  usePercentages = false,
@@ -71,6 +136,7 @@ function GridItem(props) {
71
136
  const dragPendingRef = useRef(false);
72
137
  const initialDragClientRef = useRef({ x: 0, y: 0 });
73
138
  const thresholdExceededRef = useRef(false);
139
+ const edgeScrollRef = useRef(null);
74
140
  const positionParams = useMemo(
75
141
  () => ({
76
142
  cols,
@@ -88,7 +154,7 @@ function GridItem(props) {
88
154
  maxRows,
89
155
  containerWidth,
90
156
  containerHeight: 0,
91
- // Auto-height grids don't have a fixed container height
157
+ // Overridden per-interaction with the measured container height
92
158
  rowHeight,
93
159
  margin,
94
160
  // Use empty layout here - the actual layout will be accessed via layoutRef when needed
@@ -98,8 +164,9 @@ function GridItem(props) {
98
164
  [cols, maxRows, containerWidth, rowHeight, margin]
99
165
  );
100
166
  const getConstraintContext = useCallback(
101
- () => ({
167
+ (containerHeight) => ({
102
168
  ...constraintContext,
169
+ containerHeight: containerHeight ?? constraintContext.containerHeight,
103
170
  layout: layoutRef.current
104
171
  }),
105
172
  [constraintContext]
@@ -165,6 +232,11 @@ function GridItem(props) {
165
232
  };
166
233
  }
167
234
  dragPositionRef.current = newPosition;
235
+ if (!edgeScrollRef.current) {
236
+ edgeScrollRef.current = createEdgeScrollController(
237
+ node instanceof HTMLElement ? node : null
238
+ );
239
+ }
168
240
  if (dragThreshold > 0) {
169
241
  const mouseEvent = e;
170
242
  initialDragClientRef.current = {
@@ -240,6 +312,7 @@ function GridItem(props) {
240
312
  });
241
313
  }
242
314
  }
315
+ edgeScrollRef.current?.feed(mouseEvent.clientX, mouseEvent.clientY);
243
316
  let top = dragPositionRef.current.top + deltaY;
244
317
  let left = dragPositionRef.current.left + deltaX;
245
318
  if (isBounded) {
@@ -289,6 +362,8 @@ function GridItem(props) {
289
362
  const onDragStop = useCallback(
290
363
  (e, { node }) => {
291
364
  if (!onDragStopProp || !dragging) return;
365
+ edgeScrollRef.current?.stop();
366
+ edgeScrollRef.current = null;
292
367
  const wasPending = dragPendingRef.current;
293
368
  dragPendingRef.current = false;
294
369
  thresholdExceededRef.current = false;
@@ -348,6 +423,7 @@ function GridItem(props) {
348
423
  };
349
424
  }
350
425
  resizePositionRef.current = updatedSize;
426
+ const containerHeight = node?.offsetParent?.clientHeight ?? 0;
351
427
  const rawSize = calcWHRaw(
352
428
  positionParams,
353
429
  updatedSize.width,
@@ -359,10 +435,14 @@ function GridItem(props) {
359
435
  rawSize.w,
360
436
  rawSize.h,
361
437
  resizeHandle2,
362
- getConstraintContext()
438
+ getConstraintContext(containerHeight)
363
439
  );
364
440
  handler(i, newW, newH, {
365
- e: e.nativeEvent,
441
+ // react-resizable forwards react-draggable's callback event, which is
442
+ // already a native MouseEvent/TouchEvent and has no `nativeEvent`.
443
+ // Reading it unconditionally handed consumers `undefined` (#2264).
444
+ // The drag handlers above pass the raw event for the same reason.
445
+ e: e.nativeEvent ?? e,
366
446
  node,
367
447
  size: updatedSize,
368
448
  handle: resizeHandle2
@@ -525,12 +605,104 @@ function GridItem(props) {
525
605
  handle,
526
606
  cancel: ".react-resizable-handle" + (cancel ? "," + cancel : ""),
527
607
  scale: transformScale,
608
+ allowMobileScroll,
528
609
  nodeRef: elementRef,
529
610
  children: newChild
530
611
  }
531
612
  );
532
613
  return newChild;
533
614
  }
615
+ var GridItem = React2.memo(GridItemInner, (prev, next) => {
616
+ if (prev.x !== next.x || prev.y !== next.y) return false;
617
+ if (prev.w !== next.w || prev.h !== next.h) return false;
618
+ if (prev.minW !== next.minW || prev.maxW !== next.maxW) return false;
619
+ if (prev.minH !== next.minH || prev.maxH !== next.maxH) return false;
620
+ if (prev.cols !== next.cols) return false;
621
+ if (prev.containerWidth !== next.containerWidth) return false;
622
+ if (prev.rowHeight !== next.rowHeight) return false;
623
+ if (prev.maxRows !== next.maxRows) return false;
624
+ if (prev.margin !== next.margin) return false;
625
+ if (prev.containerPadding !== next.containerPadding) return false;
626
+ if (prev.transformScale !== next.transformScale) return false;
627
+ if (prev.isDraggable !== next.isDraggable) return false;
628
+ if (prev.isResizable !== next.isResizable) return false;
629
+ if (prev.isBounded !== next.isBounded) return false;
630
+ if (prev.allowMobileScroll !== next.allowMobileScroll) return false;
631
+ if (prev.useCSSTransforms !== next.useCSSTransforms) return false;
632
+ if (prev.usePercentages !== next.usePercentages) return false;
633
+ if (prev.children !== next.children) return false;
634
+ if (prev.onDrag !== next.onDrag) return false;
635
+ if (prev.onDragStop !== next.onDragStop) return false;
636
+ if (prev.onResize !== next.onResize) return false;
637
+ if (prev.onResizeStop !== next.onResizeStop) return false;
638
+ if (prev.droppingPosition !== next.droppingPosition) return false;
639
+ return true;
640
+ });
641
+ GridItem.displayName = "GridItem";
642
+
643
+ // src/react/components/dropMath.ts
644
+ function computeDropPosition(input) {
645
+ const {
646
+ clientX,
647
+ clientY,
648
+ gridElement,
649
+ droppingItem,
650
+ event,
651
+ dragOffsetX = 0,
652
+ dragOffsetY = 0,
653
+ transformScale,
654
+ cols,
655
+ margin,
656
+ maxRows,
657
+ rowHeight,
658
+ width,
659
+ containerPadding
660
+ } = input;
661
+ const gridRect = gridElement.getBoundingClientRect();
662
+ const positionParams = {
663
+ cols,
664
+ margin,
665
+ maxRows,
666
+ rowHeight,
667
+ containerWidth: width,
668
+ containerPadding
669
+ };
670
+ const actualColWidth = calcGridColWidth(positionParams);
671
+ const itemPixelWidth = calcGridItemWHPx(
672
+ droppingItem.w,
673
+ actualColWidth,
674
+ margin[0]
675
+ );
676
+ const itemPixelHeight = calcGridItemWHPx(
677
+ droppingItem.h,
678
+ rowHeight,
679
+ margin[1]
680
+ );
681
+ const itemCenterOffsetX = itemPixelWidth / 2;
682
+ const itemCenterOffsetY = itemPixelHeight / 2;
683
+ const scrollLeft = gridElement.scrollLeft ?? 0;
684
+ const scrollTop = gridElement.scrollTop ?? 0;
685
+ const rawGridX = clientX - gridRect.left + scrollLeft + dragOffsetX - itemCenterOffsetX;
686
+ const rawGridY = clientY - gridRect.top + scrollTop + dragOffsetY - itemCenterOffsetY;
687
+ const clampedGridX = Math.max(0, rawGridX);
688
+ const clampedGridY = Math.max(0, rawGridY);
689
+ const newDroppingPosition = {
690
+ left: clampedGridX / transformScale,
691
+ top: clampedGridY / transformScale,
692
+ e: event
693
+ };
694
+ const calculatedXY = calcXY(
695
+ positionParams,
696
+ clampedGridY,
697
+ clampedGridX,
698
+ droppingItem.w,
699
+ droppingItem.h
700
+ );
701
+ return {
702
+ newDroppingPosition,
703
+ calculatedXY
704
+ };
705
+ }
534
706
  var noop = () => {
535
707
  };
536
708
  var layoutClassName = "react-grid-layout";
@@ -648,7 +820,8 @@ function GridLayout(props) {
648
820
  bounded: isBounded,
649
821
  handle: draggableHandle,
650
822
  cancel: draggableCancel,
651
- threshold: dragThreshold
823
+ threshold: dragThreshold,
824
+ allowMobileScroll: dragAllowMobileScroll
652
825
  } = dragConfig;
653
826
  const {
654
827
  enabled: isResizable,
@@ -658,7 +831,9 @@ function GridLayout(props) {
658
831
  const {
659
832
  enabled: isDroppable,
660
833
  defaultItem: defaultDropItem,
661
- onDragOver: dropConfigOnDragOver
834
+ onDragOver: dropConfigOnDragOver,
835
+ touchEnabled = true,
836
+ touchDragSource = "[data-rgl-draggable]"
662
837
  } = dropConfig;
663
838
  const compactor = compactorProp ?? getCompactor("vertical");
664
839
  const compactType = compactor.type;
@@ -684,6 +859,8 @@ function GridLayout(props) {
684
859
  null
685
860
  );
686
861
  const [droppingPosition, setDroppingPosition] = useState();
862
+ const droppingPositionRef = useRef(void 0);
863
+ droppingPositionRef.current = droppingPosition;
687
864
  const oldDragItemRef = useRef(null);
688
865
  const oldResizeItemRef = useRef(null);
689
866
  const oldLayoutRef = useRef(null);
@@ -692,6 +869,15 @@ function GridLayout(props) {
692
869
  const prevPropsLayoutRef = useRef(propsLayout);
693
870
  const prevChildrenRef = useRef(children);
694
871
  const prevCompactTypeRef = useRef(compactType);
872
+ const gridContainerRef = useRef(null);
873
+ const touchDragActiveRef = useRef(false);
874
+ const activeTouchIdRef = useRef(null);
875
+ const droppingDOMNodeRef = useRef(null);
876
+ droppingDOMNodeRef.current = droppingDOMNode;
877
+ const onDropPropRef = useRef(onDropProp);
878
+ useLayoutEffect(() => {
879
+ onDropPropRef.current = onDropProp;
880
+ });
695
881
  const layoutRef = useRef(layout);
696
882
  layoutRef.current = layout;
697
883
  useEffect(() => {
@@ -732,12 +918,12 @@ function GridLayout(props) {
732
918
  layout
733
919
  ]);
734
920
  useEffect(() => {
735
- if (!activeDrag && !deepEqual(layout, prevLayoutRef.current)) {
921
+ if (!activeDrag && !droppingDOMNode && !deepEqual(layout, prevLayoutRef.current)) {
736
922
  prevLayoutRef.current = layout;
737
923
  const publicLayout = layout.filter((l) => l.i !== droppingItem.i);
738
924
  onLayoutChange(publicLayout);
739
925
  }
740
- }, [layout, activeDrag, onLayoutChange, droppingItem.i]);
926
+ }, [layout, activeDrag, droppingDOMNode, onLayoutChange, droppingItem.i]);
741
927
  const containerHeight = useMemo(() => {
742
928
  if (!autoSize) return void 0;
743
929
  const nbRow = bottom(layout);
@@ -795,7 +981,7 @@ function GridLayout(props) {
795
981
  );
796
982
  const onDragStop = useCallback(
797
983
  (i, x, y, data) => {
798
- if (!activeDrag) return;
984
+ if (!oldDragItemRef.current) return;
799
985
  const currentLayout = layoutRef.current;
800
986
  const oldDragItem = oldDragItemRef.current;
801
987
  const l = getLayoutItem(currentLayout, i);
@@ -823,7 +1009,6 @@ function GridLayout(props) {
823
1009
  }
824
1010
  },
825
1011
  [
826
- activeDrag,
827
1012
  preventCollision,
828
1013
  compactType,
829
1014
  cols,
@@ -887,6 +1072,9 @@ function GridLayout(props) {
887
1072
  }
888
1073
  item.w = w;
889
1074
  item.h = h;
1075
+ if (handle === "n" || handle === "nw" || handle === "ne") {
1076
+ item.y = newY ?? item.y;
1077
+ }
890
1078
  return item;
891
1079
  });
892
1080
  if (!l) return;
@@ -920,7 +1108,14 @@ function GridLayout(props) {
920
1108
  data.e,
921
1109
  data.node
922
1110
  );
923
- setLayout(compactor.compact(finalLayout, cols));
1111
+ const compactedLayout = compactor.compact(finalLayout, cols);
1112
+ if (handle === "n" || handle === "nw" || handle === "ne") {
1113
+ const resized = compactedLayout.find((item) => item.i === i);
1114
+ if (resized) {
1115
+ resized.y = l.y;
1116
+ }
1117
+ }
1118
+ setLayout(compactedLayout);
924
1119
  setActiveDrag(placeholder);
925
1120
  },
926
1121
  [preventCollision, compactType, cols, allowOverlap, compactor, onResizeProp]
@@ -951,6 +1146,73 @@ function GridLayout(props) {
951
1146
  },
952
1147
  [cols, compactor, onResizeStopProp, onLayoutChange]
953
1148
  );
1149
+ const placeDroppingItem = useCallback(
1150
+ (itemToPlace, newDroppingPosition, calculatedXY, hasPlaceholder) => {
1151
+ if (!hasPlaceholder) {
1152
+ setDroppingDOMNode(/* @__PURE__ */ jsx("div", {}, itemToPlace.i));
1153
+ setDroppingPosition(newDroppingPosition);
1154
+ const baseLayout = layoutRef.current.filter((l) => l.i !== itemToPlace.i);
1155
+ setLayout([
1156
+ ...baseLayout,
1157
+ {
1158
+ ...itemToPlace,
1159
+ x: calculatedXY.x,
1160
+ y: calculatedXY.y,
1161
+ static: false,
1162
+ isDraggable: true
1163
+ }
1164
+ ]);
1165
+ } else if (droppingPositionRef.current) {
1166
+ const shouldUpdate = droppingPositionRef.current.left !== newDroppingPosition.left || droppingPositionRef.current.top !== newDroppingPosition.top;
1167
+ if (shouldUpdate) {
1168
+ setDroppingPosition(newDroppingPosition);
1169
+ setLayout(
1170
+ (currentLayout) => currentLayout.map(
1171
+ (item) => item.i === itemToPlace.i && (item.x !== calculatedXY.x || item.y !== calculatedXY.y) ? { ...item, x: calculatedXY.x, y: calculatedXY.y } : item
1172
+ )
1173
+ );
1174
+ }
1175
+ }
1176
+ },
1177
+ []
1178
+ );
1179
+ const applyTouchDropPosition = useCallback(
1180
+ (clientX, clientY, nativeEvent) => {
1181
+ const gridEl = gridContainerRef.current;
1182
+ if (!gridEl) return;
1183
+ const { newDroppingPosition, calculatedXY } = computeDropPosition({
1184
+ clientX,
1185
+ clientY,
1186
+ gridElement: gridEl,
1187
+ droppingItem,
1188
+ event: nativeEvent,
1189
+ transformScale,
1190
+ cols,
1191
+ margin,
1192
+ maxRows,
1193
+ rowHeight,
1194
+ width,
1195
+ containerPadding: effectiveContainerPadding
1196
+ });
1197
+ placeDroppingItem(
1198
+ droppingItem,
1199
+ newDroppingPosition,
1200
+ calculatedXY,
1201
+ !!droppingDOMNodeRef.current
1202
+ );
1203
+ },
1204
+ [
1205
+ droppingItem,
1206
+ transformScale,
1207
+ cols,
1208
+ margin,
1209
+ maxRows,
1210
+ rowHeight,
1211
+ width,
1212
+ effectiveContainerPadding,
1213
+ placeDroppingItem
1214
+ ]
1215
+ );
954
1216
  const removeDroppingPlaceholder = useCallback(() => {
955
1217
  const currentLayout = layoutRef.current;
956
1218
  const hasDroppingItem = currentLayout.some((l) => l.i === droppingItem.i);
@@ -991,74 +1253,36 @@ function GridLayout(props) {
991
1253
  ...onDragOverResult
992
1254
  } = rawResult ?? {};
993
1255
  const finalDroppingItem = { ...droppingItem, ...onDragOverResult };
994
- const gridRect = e.currentTarget.getBoundingClientRect();
995
- const positionParams = {
1256
+ const { newDroppingPosition, calculatedXY } = computeDropPosition({
1257
+ clientX: e.clientX,
1258
+ clientY: e.clientY,
1259
+ gridElement: e.currentTarget,
1260
+ droppingItem: finalDroppingItem,
1261
+ event: e.nativeEvent,
1262
+ dragOffsetX,
1263
+ dragOffsetY,
1264
+ transformScale,
996
1265
  cols,
997
1266
  margin,
998
1267
  maxRows,
999
1268
  rowHeight,
1000
- containerWidth: width,
1269
+ width,
1001
1270
  containerPadding: effectiveContainerPadding
1002
- };
1003
- const actualColWidth = calcGridColWidth(positionParams);
1004
- const itemPixelWidth = calcGridItemWHPx(
1005
- finalDroppingItem.w,
1006
- actualColWidth,
1007
- margin[0]
1008
- );
1009
- const itemPixelHeight = calcGridItemWHPx(
1010
- finalDroppingItem.h,
1011
- rowHeight,
1012
- margin[1]
1271
+ });
1272
+ placeDroppingItem(
1273
+ finalDroppingItem,
1274
+ newDroppingPosition,
1275
+ calculatedXY,
1276
+ !!droppingDOMNode
1013
1277
  );
1014
- const itemCenterOffsetX = itemPixelWidth / 2;
1015
- const itemCenterOffsetY = itemPixelHeight / 2;
1016
- const rawGridX = e.clientX - gridRect.left + dragOffsetX - itemCenterOffsetX;
1017
- const rawGridY = e.clientY - gridRect.top + dragOffsetY - itemCenterOffsetY;
1018
- const clampedGridX = Math.max(0, rawGridX);
1019
- const clampedGridY = Math.max(0, rawGridY);
1020
- const newDroppingPosition = {
1021
- left: clampedGridX / transformScale,
1022
- top: clampedGridY / transformScale,
1023
- e: e.nativeEvent
1024
- };
1025
- if (!droppingDOMNode) {
1026
- const calculatedPosition = calcXY(
1027
- positionParams,
1028
- clampedGridY,
1029
- clampedGridX,
1030
- finalDroppingItem.w,
1031
- finalDroppingItem.h
1032
- );
1033
- setDroppingDOMNode(/* @__PURE__ */ jsx("div", {}, finalDroppingItem.i));
1034
- setDroppingPosition(newDroppingPosition);
1035
- const baseLayout = layoutRef.current.filter(
1036
- (l) => l.i !== finalDroppingItem.i
1037
- );
1038
- setLayout([
1039
- ...baseLayout,
1040
- {
1041
- ...finalDroppingItem,
1042
- x: calculatedPosition.x,
1043
- y: calculatedPosition.y,
1044
- static: false,
1045
- isDraggable: true
1046
- }
1047
- ]);
1048
- } else if (droppingPosition) {
1049
- const shouldUpdate = droppingPosition.left !== newDroppingPosition.left || droppingPosition.top !== newDroppingPosition.top;
1050
- if (shouldUpdate) {
1051
- setDroppingPosition(newDroppingPosition);
1052
- }
1053
- }
1054
1278
  },
1055
1279
  [
1056
1280
  droppingDOMNode,
1057
- droppingPosition,
1058
1281
  droppingItem,
1059
1282
  dropConfigOnDragOver,
1060
1283
  onDropDragOverProp,
1061
1284
  removeDroppingPlaceholder,
1285
+ placeDroppingItem,
1062
1286
  transformScale,
1063
1287
  cols,
1064
1288
  margin,
@@ -1087,18 +1311,106 @@ function GridLayout(props) {
1087
1311
  e.stopPropagation();
1088
1312
  dragEnterCounterRef.current++;
1089
1313
  }, []);
1314
+ const commitDrop = useCallback(
1315
+ (nativeEvent) => {
1316
+ const currentLayout = layoutRef.current;
1317
+ const item = currentLayout.find((l) => l.i === droppingItem.i);
1318
+ removeDroppingPlaceholder();
1319
+ onDropPropRef.current(currentLayout, item, nativeEvent);
1320
+ },
1321
+ [droppingItem.i, removeDroppingPlaceholder]
1322
+ );
1090
1323
  const handleDrop = useCallback(
1091
1324
  (e) => {
1092
1325
  e.preventDefault();
1093
1326
  e.stopPropagation();
1094
- const currentLayout = layoutRef.current;
1095
- const item = currentLayout.find((l) => l.i === droppingItem.i);
1096
1327
  dragEnterCounterRef.current = 0;
1097
- removeDroppingPlaceholder();
1098
- onDropProp(currentLayout, item, e.nativeEvent);
1328
+ commitDrop(e.nativeEvent);
1099
1329
  },
1100
- [droppingItem.i, removeDroppingPlaceholder, onDropProp]
1330
+ [commitDrop]
1101
1331
  );
1332
+ useEffect(() => {
1333
+ if (!isDroppable || !touchEnabled) return;
1334
+ const gridEl = gridContainerRef.current;
1335
+ if (!gridEl) return;
1336
+ const isOverGrid = (clientX, clientY) => {
1337
+ const el = document.elementFromPoint(clientX, clientY);
1338
+ return el ? gridEl.contains(el) : false;
1339
+ };
1340
+ const isSourceElement = (target) => {
1341
+ if (!(target instanceof HTMLElement)) return false;
1342
+ return target.closest(touchDragSource) !== null;
1343
+ };
1344
+ const getTouch = (e) => {
1345
+ const touches = e.changedTouches;
1346
+ if (!touches || touches.length === 0) return void 0;
1347
+ const id = activeTouchIdRef.current;
1348
+ if (id === null) return touches[0];
1349
+ for (let i = 0; i < touches.length; i++) {
1350
+ const touch = touches[i];
1351
+ if (touch && touch.identifier === id) return touch;
1352
+ }
1353
+ return void 0;
1354
+ };
1355
+ const handleTouchStart = (e) => {
1356
+ if (!isSourceElement(e.target)) return;
1357
+ if (activeTouchIdRef.current !== null) return;
1358
+ e.preventDefault();
1359
+ const touch = e.changedTouches?.[0];
1360
+ if (!touch) return;
1361
+ activeTouchIdRef.current = touch.identifier;
1362
+ touchDragActiveRef.current = true;
1363
+ };
1364
+ const handleTouchMove = (e) => {
1365
+ if (!touchDragActiveRef.current) return;
1366
+ e.preventDefault();
1367
+ const touch = getTouch(e);
1368
+ if (!touch) return;
1369
+ if (!isOverGrid(touch.clientX, touch.clientY)) {
1370
+ if (droppingDOMNodeRef.current) removeDroppingPlaceholder();
1371
+ return;
1372
+ }
1373
+ applyTouchDropPosition(touch.clientX, touch.clientY, e);
1374
+ };
1375
+ const handleTouchEnd = (e) => {
1376
+ if (!touchDragActiveRef.current) return;
1377
+ e.preventDefault();
1378
+ const touch = getTouch(e);
1379
+ touchDragActiveRef.current = false;
1380
+ activeTouchIdRef.current = null;
1381
+ if (!touch) return;
1382
+ if (!isOverGrid(touch.clientX, touch.clientY)) {
1383
+ removeDroppingPlaceholder();
1384
+ return;
1385
+ }
1386
+ commitDrop(e);
1387
+ };
1388
+ const handleTouchCancel = () => {
1389
+ if (!touchDragActiveRef.current) return;
1390
+ touchDragActiveRef.current = false;
1391
+ activeTouchIdRef.current = null;
1392
+ removeDroppingPlaceholder();
1393
+ };
1394
+ const opts = { passive: false };
1395
+ document.addEventListener("touchstart", handleTouchStart, opts);
1396
+ document.addEventListener("touchmove", handleTouchMove, opts);
1397
+ document.addEventListener("touchend", handleTouchEnd, opts);
1398
+ document.addEventListener("touchcancel", handleTouchCancel, opts);
1399
+ return () => {
1400
+ document.removeEventListener("touchstart", handleTouchStart, opts);
1401
+ document.removeEventListener("touchmove", handleTouchMove, opts);
1402
+ document.removeEventListener("touchend", handleTouchEnd, opts);
1403
+ document.removeEventListener("touchcancel", handleTouchCancel, opts);
1404
+ };
1405
+ }, [
1406
+ isDroppable,
1407
+ touchEnabled,
1408
+ touchDragSource,
1409
+ applyTouchDropPosition,
1410
+ removeDroppingPlaceholder,
1411
+ commitDrop,
1412
+ droppingItem.i
1413
+ ]);
1102
1414
  const processGridItem = useCallback(
1103
1415
  (child, isDroppingItem) => {
1104
1416
  if (!child || !child.key) return null;
@@ -1129,6 +1441,7 @@ function GridLayout(props) {
1129
1441
  isDraggable: draggable,
1130
1442
  isResizable: resizable,
1131
1443
  isBounded: bounded,
1444
+ allowMobileScroll: dragAllowMobileScroll,
1132
1445
  useCSSTransforms: useCSSTransforms && mounted,
1133
1446
  usePercentages: !mounted,
1134
1447
  transformScale,
@@ -1213,6 +1526,17 @@ function GridLayout(props) {
1213
1526
  }
1214
1527
  );
1215
1528
  };
1529
+ const setGridRef = useCallback(
1530
+ (node) => {
1531
+ gridContainerRef.current = node;
1532
+ if (typeof innerRef === "function") {
1533
+ innerRef(node);
1534
+ } else if (innerRef && "current" in innerRef) {
1535
+ innerRef.current = node;
1536
+ }
1537
+ },
1538
+ [innerRef]
1539
+ );
1216
1540
  const mergedClassName = clsx(layoutClassName, className);
1217
1541
  const mergedStyle = {
1218
1542
  height: containerHeight,
@@ -1221,7 +1545,7 @@ function GridLayout(props) {
1221
1545
  return /* @__PURE__ */ jsxs(
1222
1546
  "div",
1223
1547
  {
1224
- ref: innerRef,
1548
+ ref: setGridRef,
1225
1549
  className: mergedClassName,
1226
1550
  style: mergedStyle,
1227
1551
  onDrop: isDroppable ? handleDrop : void 0,
@@ -1255,20 +1579,33 @@ var DEFAULT_COLS = {
1255
1579
  };
1256
1580
  var noop2 = () => {
1257
1581
  };
1258
- function synchronizeLayoutWithChildren2(initialLayout, children, cols, compactor) {
1582
+ function synchronizeLayoutWithChildren2(initialLayout, children, cols, compactor, reSeedFromDataGrid = false) {
1259
1583
  const layout = [];
1260
1584
  React2.Children.forEach(children, (child) => {
1261
1585
  if (!React2.isValidElement(child) || child.key === null) return;
1262
1586
  const key = String(child.key);
1587
+ const childProps = child.props;
1588
+ const dataGrid = childProps["data-grid"];
1263
1589
  const existingItem = initialLayout.find((l) => l.i === key);
1264
1590
  if (existingItem) {
1265
- layout.push({
1266
- ...existingItem,
1267
- i: key
1268
- });
1591
+ if (reSeedFromDataGrid && dataGrid) {
1592
+ layout.push({
1593
+ ...existingItem,
1594
+ i: key,
1595
+ w: dataGrid.w ?? existingItem.w,
1596
+ h: dataGrid.h ?? existingItem.h,
1597
+ minW: dataGrid.minW ?? existingItem.minW,
1598
+ maxW: dataGrid.maxW ?? existingItem.maxW,
1599
+ minH: dataGrid.minH ?? existingItem.minH,
1600
+ maxH: dataGrid.maxH ?? existingItem.maxH
1601
+ });
1602
+ } else {
1603
+ layout.push({
1604
+ ...existingItem,
1605
+ i: key
1606
+ });
1607
+ }
1269
1608
  } else {
1270
- const childProps = child.props;
1271
- const dataGrid = childProps["data-grid"];
1272
1609
  if (dataGrid) {
1273
1610
  layout.push({
1274
1611
  i: key,
@@ -1300,7 +1637,7 @@ function synchronizeLayoutWithChildren2(initialLayout, children, cols, compactor
1300
1637
  const corrected = correctBounds(layout, { cols });
1301
1638
  return compactor.compact(corrected, cols);
1302
1639
  }
1303
- function ResponsiveGridLayout(props) {
1640
+ function ResponsiveGridLayoutInner(props) {
1304
1641
  const {
1305
1642
  children,
1306
1643
  width,
@@ -1420,11 +1757,13 @@ function ResponsiveGridLayout(props) {
1420
1757
  newCols,
1421
1758
  compactor
1422
1759
  );
1760
+ const layoutWasGenerated = !newLayouts[newBreakpoint];
1423
1761
  newLayout = synchronizeLayoutWithChildren2(
1424
1762
  newLayout,
1425
1763
  children,
1426
1764
  newCols,
1427
- compactor
1765
+ compactor,
1766
+ layoutWasGenerated
1428
1767
  );
1429
1768
  newLayouts[newBreakpoint] = newLayout;
1430
1769
  setBreakpoint(newBreakpoint);
@@ -1517,5 +1856,11 @@ function ResponsiveGridLayout(props) {
1517
1856
  }
1518
1857
  );
1519
1858
  }
1859
+ var ResponsiveGridLayoutWithRef = React2.forwardRef(function ResponsiveGridLayoutForwardRef(props, ref) {
1860
+ const { innerRef, ...rest } = props;
1861
+ const effectiveInnerRef = innerRef ?? ref;
1862
+ return /* @__PURE__ */ jsx(ResponsiveGridLayoutInner, { ...rest, innerRef: effectiveInnerRef });
1863
+ });
1864
+ ResponsiveGridLayoutWithRef.displayName = "ResponsiveGridLayout";
1520
1865
 
1521
- export { GridItem, GridLayout, ResponsiveGridLayout };
1866
+ export { GridItem, GridLayout, ResponsiveGridLayoutWithRef };