react-grid-layout 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { defaultConstraints, setTransform, setTopLeft, perc, applyPositionConstraints, resizeItemInDirection, applySizeConstraints, defaultPositionStrategy, defaultGridConfig, defaultDragConfig, defaultResizeConfig, defaultDropConfig, getCompactor, compact, getBreakpointFromWidth, getColsFromBreakpoint, findOrGenerateResponsiveLayout, getIndentationValue } from './chunk-FLITZMQC.mjs';
1
+ import { defaultConstraints, setTransform, setTopLeft, perc, applyPositionConstraints, resizeItemInDirection, applySizeConstraints, defaultPositionStrategy, defaultGridConfig, defaultDragConfig, defaultResizeConfig, defaultDropConfig, getCompactor, getBreakpointFromWidth, getColsFromBreakpoint, findOrGenerateResponsiveLayout, compact, getIndentationValue } from './chunk-OH26KG7Y.mjs';
2
2
  import { calcXYRaw, calcGridItemWHPx, clamp, calcGridColWidth, calcWHRaw, calcGridItemPosition, bottom, getLayoutItem, cloneLayoutItem, moveElement, withLayoutItem, getAllCollisions, calcXY, cloneLayout, correctBounds } from './chunk-AWM66AWF.mjs';
3
3
  import React2, { useState, useRef, useMemo, useCallback, useEffect } from 'react';
4
4
  import { DraggableCore } from 'react-draggable';
@@ -23,6 +23,8 @@ function GridItem(props) {
23
23
  useCSSTransforms = true,
24
24
  usePercentages = false,
25
25
  transformScale = 1,
26
+ positionStrategy,
27
+ dragThreshold = 0,
26
28
  droppingPosition,
27
29
  className = "",
28
30
  style,
@@ -62,6 +64,11 @@ function GridItem(props) {
62
64
  const prevDroppingPositionRef = useRef(
63
65
  void 0
64
66
  );
67
+ const layoutRef = useRef(layout);
68
+ layoutRef.current = layout;
69
+ const dragPendingRef = useRef(false);
70
+ const initialDragClientRef = useRef({ x: 0, y: 0 });
71
+ const thresholdExceededRef = useRef(false);
65
72
  const positionParams = useMemo(
66
73
  () => ({
67
74
  cols,
@@ -82,9 +89,18 @@ function GridItem(props) {
82
89
  // Auto-height grids don't have a fixed container height
83
90
  rowHeight,
84
91
  margin,
85
- layout
92
+ // Use empty layout here - the actual layout will be accessed via layoutRef when needed
93
+ // This prevents the context from changing when layout changes, avoiding callback recreation
94
+ layout: []
95
+ }),
96
+ [cols, maxRows, containerWidth, rowHeight, margin]
97
+ );
98
+ const getConstraintContext = useCallback(
99
+ () => ({
100
+ ...constraintContext,
101
+ layout: layoutRef.current
86
102
  }),
87
- [cols, maxRows, containerWidth, rowHeight, margin, layout]
103
+ [constraintContext]
88
104
  );
89
105
  const effectiveLayoutItem = useMemo(
90
106
  () => layoutItem ?? {
@@ -102,6 +118,9 @@ function GridItem(props) {
102
118
  );
103
119
  const createStyle = useCallback(
104
120
  (pos2) => {
121
+ if (positionStrategy?.calcStyle) {
122
+ return positionStrategy.calcStyle(pos2);
123
+ }
105
124
  if (useCSSTransforms) {
106
125
  return setTransform(pos2);
107
126
  }
@@ -115,7 +134,7 @@ function GridItem(props) {
115
134
  }
116
135
  return styleObj;
117
136
  },
118
- [useCSSTransforms, usePercentages, containerWidth]
137
+ [positionStrategy, useCSSTransforms, usePercentages, containerWidth]
119
138
  );
120
139
  const onDragStart = useCallback(
121
140
  (e, { node }) => {
@@ -128,11 +147,33 @@ function GridItem(props) {
128
147
  const pLeft = parentRect.left / transformScale;
129
148
  const cTop = clientRect.top / transformScale;
130
149
  const pTop = parentRect.top / transformScale;
131
- const newPosition = {
132
- left: cLeft - pLeft + offsetParent.scrollLeft,
133
- top: cTop - pTop + offsetParent.scrollTop
134
- };
150
+ let newPosition;
151
+ if (positionStrategy?.calcDragPosition) {
152
+ const mouseEvent = e;
153
+ newPosition = positionStrategy.calcDragPosition(
154
+ mouseEvent.clientX,
155
+ mouseEvent.clientY,
156
+ mouseEvent.clientX - clientRect.left,
157
+ mouseEvent.clientY - clientRect.top
158
+ );
159
+ } else {
160
+ newPosition = {
161
+ left: cLeft - pLeft + offsetParent.scrollLeft,
162
+ top: cTop - pTop + offsetParent.scrollTop
163
+ };
164
+ }
135
165
  dragPositionRef.current = newPosition;
166
+ if (dragThreshold > 0) {
167
+ const mouseEvent = e;
168
+ initialDragClientRef.current = {
169
+ x: mouseEvent.clientX,
170
+ y: mouseEvent.clientY
171
+ };
172
+ dragPendingRef.current = true;
173
+ thresholdExceededRef.current = false;
174
+ setDragging(true);
175
+ return;
176
+ }
136
177
  setDragging(true);
137
178
  const rawPos = calcXYRaw(
138
179
  positionParams,
@@ -144,7 +185,7 @@ function GridItem(props) {
144
185
  effectiveLayoutItem,
145
186
  rawPos.x,
146
187
  rawPos.y,
147
- constraintContext
188
+ getConstraintContext()
148
189
  );
149
190
  onDragStartProp(i, newX, newY, {
150
191
  e,
@@ -156,15 +197,47 @@ function GridItem(props) {
156
197
  onDragStartProp,
157
198
  transformScale,
158
199
  positionParams,
200
+ positionStrategy,
201
+ dragThreshold,
159
202
  constraints,
160
203
  effectiveLayoutItem,
161
- constraintContext,
204
+ getConstraintContext,
162
205
  i
163
206
  ]
164
207
  );
165
208
  const onDrag = useCallback(
166
209
  (e, { node, deltaX, deltaY }) => {
167
210
  if (!onDragProp || !dragging) return;
211
+ const mouseEvent = e;
212
+ if (dragPendingRef.current && !thresholdExceededRef.current) {
213
+ const dx = mouseEvent.clientX - initialDragClientRef.current.x;
214
+ const dy = mouseEvent.clientY - initialDragClientRef.current.y;
215
+ const distance = Math.hypot(dx, dy);
216
+ if (distance < dragThreshold) {
217
+ return;
218
+ }
219
+ thresholdExceededRef.current = true;
220
+ dragPendingRef.current = false;
221
+ if (onDragStartProp) {
222
+ const rawPos2 = calcXYRaw(
223
+ positionParams,
224
+ dragPositionRef.current.top,
225
+ dragPositionRef.current.left
226
+ );
227
+ const { x: startX, y: startY } = applyPositionConstraints(
228
+ constraints,
229
+ effectiveLayoutItem,
230
+ rawPos2.x,
231
+ rawPos2.y,
232
+ getConstraintContext()
233
+ );
234
+ onDragStartProp(i, startX, startY, {
235
+ e,
236
+ node,
237
+ newPosition: dragPositionRef.current
238
+ });
239
+ }
240
+ }
168
241
  let top = dragPositionRef.current.top + deltaY;
169
242
  let left = dragPositionRef.current.left + deltaX;
170
243
  if (isBounded) {
@@ -185,7 +258,7 @@ function GridItem(props) {
185
258
  effectiveLayoutItem,
186
259
  rawPos.x,
187
260
  rawPos.y,
188
- constraintContext
261
+ getConstraintContext()
189
262
  );
190
263
  onDragProp(i, newX, newY, {
191
264
  e,
@@ -195,7 +268,9 @@ function GridItem(props) {
195
268
  },
196
269
  [
197
270
  onDragProp,
271
+ onDragStartProp,
198
272
  dragging,
273
+ dragThreshold,
199
274
  isBounded,
200
275
  h,
201
276
  rowHeight,
@@ -206,12 +281,21 @@ function GridItem(props) {
206
281
  i,
207
282
  constraints,
208
283
  effectiveLayoutItem,
209
- constraintContext
284
+ getConstraintContext
210
285
  ]
211
286
  );
212
287
  const onDragStop = useCallback(
213
288
  (e, { node }) => {
214
289
  if (!onDragStopProp || !dragging) return;
290
+ const wasPending = dragPendingRef.current;
291
+ dragPendingRef.current = false;
292
+ thresholdExceededRef.current = false;
293
+ initialDragClientRef.current = { x: 0, y: 0 };
294
+ if (wasPending) {
295
+ setDragging(false);
296
+ dragPositionRef.current = { left: 0, top: 0 };
297
+ return;
298
+ }
215
299
  const { left, top } = dragPositionRef.current;
216
300
  const newPosition = { top, left };
217
301
  setDragging(false);
@@ -222,7 +306,7 @@ function GridItem(props) {
222
306
  effectiveLayoutItem,
223
307
  rawPos.x,
224
308
  rawPos.y,
225
- constraintContext
309
+ getConstraintContext()
226
310
  );
227
311
  onDragStopProp(i, newX, newY, {
228
312
  e,
@@ -236,7 +320,7 @@ function GridItem(props) {
236
320
  positionParams,
237
321
  constraints,
238
322
  effectiveLayoutItem,
239
- constraintContext,
323
+ getConstraintContext,
240
324
  i
241
325
  ]
242
326
  );
@@ -271,7 +355,7 @@ function GridItem(props) {
271
355
  rawSize.w,
272
356
  rawSize.h,
273
357
  resizeHandle2,
274
- constraintContext
358
+ getConstraintContext()
275
359
  );
276
360
  handler(i, newW, newH, {
277
361
  e: e.nativeEvent,
@@ -286,12 +370,10 @@ function GridItem(props) {
286
370
  onResizeStopProp,
287
371
  containerWidth,
288
372
  positionParams,
289
- x,
290
- y,
291
373
  i,
292
374
  constraints,
293
375
  effectiveLayoutItem,
294
- constraintContext
376
+ getConstraintContext
295
377
  ]
296
378
  );
297
379
  const handleResizeStart = useCallback(
@@ -455,7 +537,7 @@ function childrenEqual(a, b) {
455
537
  }
456
538
  return true;
457
539
  }
458
- function synchronizeLayoutWithChildren(initialLayout, children, cols, compactType, allowOverlap) {
540
+ function synchronizeLayoutWithChildren(initialLayout, children, cols, compactor) {
459
541
  const layout = [];
460
542
  const childKeys = /* @__PURE__ */ new Set();
461
543
  React2.Children.forEach(children, (child) => {
@@ -497,7 +579,7 @@ function synchronizeLayoutWithChildren(initialLayout, children, cols, compactTyp
497
579
  }
498
580
  });
499
581
  const corrected = correctBounds(layout, { cols });
500
- return compact(corrected, compactType, cols, allowOverlap);
582
+ return compactor.compact(corrected, cols);
501
583
  }
502
584
  function GridLayout(props) {
503
585
  const {
@@ -552,14 +634,19 @@ function GridLayout(props) {
552
634
  enabled: isDraggable,
553
635
  bounded: isBounded,
554
636
  handle: draggableHandle,
555
- cancel: draggableCancel
637
+ cancel: draggableCancel,
638
+ threshold: dragThreshold
556
639
  } = dragConfig;
557
640
  const {
558
641
  enabled: isResizable,
559
642
  handles: resizeHandles,
560
643
  handleComponent: resizeHandle
561
644
  } = resizeConfig;
562
- const { enabled: isDroppable, defaultItem: defaultDropItem } = dropConfig;
645
+ const {
646
+ enabled: isDroppable,
647
+ defaultItem: defaultDropItem,
648
+ onDragOver: dropConfigOnDragOver
649
+ } = dropConfig;
563
650
  const compactor = compactorProp ?? getCompactor("vertical");
564
651
  const compactType = compactor.type;
565
652
  const allowOverlap = compactor.allowOverlap;
@@ -576,13 +663,7 @@ function GridLayout(props) {
576
663
  const effectiveContainerPadding = containerPadding ?? margin;
577
664
  const [mounted, setMounted] = useState(false);
578
665
  const [layout, setLayout] = useState(
579
- () => synchronizeLayoutWithChildren(
580
- propsLayout,
581
- children,
582
- cols,
583
- compactType,
584
- allowOverlap
585
- )
666
+ () => synchronizeLayoutWithChildren(propsLayout, children, cols, compactor)
586
667
  );
587
668
  const [activeDrag, setActiveDrag] = useState(null);
588
669
  const [resizing, setResizing] = useState(false);
@@ -618,8 +699,7 @@ function GridLayout(props) {
618
699
  baseLayout,
619
700
  children,
620
701
  cols,
621
- compactType,
622
- allowOverlap
702
+ compactor
623
703
  );
624
704
  setLayout(newLayout);
625
705
  }
@@ -631,7 +711,7 @@ function GridLayout(props) {
631
711
  children,
632
712
  cols,
633
713
  compactType,
634
- allowOverlap,
714
+ compactor,
635
715
  activeDrag,
636
716
  droppingDOMNode,
637
717
  layout
@@ -692,12 +772,10 @@ function GridLayout(props) {
692
772
  allowOverlap
693
773
  );
694
774
  onDragProp(newLayout, oldDragItem, l, placeholder, data.e, data.node);
695
- setLayout(
696
- allowOverlap ? newLayout : compact(newLayout, compactType, cols)
697
- );
775
+ setLayout(compactor.compact(newLayout, cols));
698
776
  setActiveDrag(placeholder);
699
777
  },
700
- [preventCollision, compactType, cols, allowOverlap, onDragProp]
778
+ [preventCollision, compactType, cols, allowOverlap, compactor, onDragProp]
701
779
  );
702
780
  const onDragStop = useCallback(
703
781
  (i, x, y, data) => {
@@ -717,7 +795,7 @@ function GridLayout(props) {
717
795
  cols,
718
796
  allowOverlap
719
797
  );
720
- const finalLayout = allowOverlap ? newLayout : compact(newLayout, compactType, cols);
798
+ const finalLayout = compactor.compact(newLayout, cols);
721
799
  onDragStopProp(finalLayout, oldDragItem, l, null, data.e, data.node);
722
800
  const oldLayout = oldLayoutRef.current;
723
801
  oldDragItemRef.current = null;
@@ -734,6 +812,7 @@ function GridLayout(props) {
734
812
  compactType,
735
813
  cols,
736
814
  allowOverlap,
815
+ compactor,
737
816
  onDragStopProp,
738
817
  onLayoutChange
739
818
  ]
@@ -825,19 +904,17 @@ function GridLayout(props) {
825
904
  data.e,
826
905
  data.node
827
906
  );
828
- setLayout(
829
- allowOverlap ? finalLayout : compact(finalLayout, compactType, cols)
830
- );
907
+ setLayout(compactor.compact(finalLayout, cols));
831
908
  setActiveDrag(placeholder);
832
909
  },
833
- [preventCollision, allowOverlap, compactType, cols, onResizeProp]
910
+ [preventCollision, compactType, cols, allowOverlap, compactor, onResizeProp]
834
911
  );
835
912
  const onResizeStop = useCallback(
836
913
  (i, _w, _h, data) => {
837
914
  const currentLayout = layoutRef.current;
838
915
  const oldResizeItem = oldResizeItemRef.current;
839
916
  const l = getLayoutItem(currentLayout, i);
840
- const finalLayout = allowOverlap ? currentLayout : compact(currentLayout, compactType, cols);
917
+ const finalLayout = compactor.compact(currentLayout, cols);
841
918
  onResizeStopProp(
842
919
  finalLayout,
843
920
  oldResizeItem,
@@ -856,21 +933,19 @@ function GridLayout(props) {
856
933
  onLayoutChange(finalLayout);
857
934
  }
858
935
  },
859
- [allowOverlap, compactType, cols, onResizeStopProp, onLayoutChange]
936
+ [cols, compactor, onResizeStopProp, onLayoutChange]
860
937
  );
861
938
  const removeDroppingPlaceholder = useCallback(() => {
862
939
  const currentLayout = layoutRef.current;
863
- const newLayout = compact(
940
+ const newLayout = compactor.compact(
864
941
  currentLayout.filter((l) => l.i !== droppingItem.i),
865
- compactType,
866
- cols,
867
- allowOverlap
942
+ cols
868
943
  );
869
944
  setLayout(newLayout);
870
945
  setDroppingDOMNode(null);
871
946
  setActiveDrag(null);
872
947
  setDroppingPosition(void 0);
873
- }, [droppingItem.i, compactType, cols, allowOverlap]);
948
+ }, [droppingItem.i, cols, compactor]);
874
949
  const handleDragOver = useCallback(
875
950
  (e) => {
876
951
  e.preventDefault();
@@ -880,7 +955,7 @@ function GridLayout(props) {
880
955
  )) {
881
956
  return false;
882
957
  }
883
- const rawResult = onDropDragOverProp(e);
958
+ const rawResult = dropConfigOnDragOver ? dropConfigOnDragOver(e.nativeEvent) : onDropDragOverProp(e);
884
959
  if (rawResult === false) {
885
960
  if (droppingDOMNode) {
886
961
  removeDroppingPlaceholder();
@@ -955,6 +1030,7 @@ function GridLayout(props) {
955
1030
  droppingDOMNode,
956
1031
  droppingPosition,
957
1032
  droppingItem,
1033
+ dropConfigOnDragOver,
958
1034
  onDropDragOverProp,
959
1035
  removeDroppingPlaceholder,
960
1036
  transformScale,
@@ -1027,6 +1103,8 @@ function GridLayout(props) {
1027
1103
  useCSSTransforms: useCSSTransforms && mounted,
1028
1104
  usePercentages: !mounted,
1029
1105
  transformScale,
1106
+ positionStrategy,
1107
+ dragThreshold,
1030
1108
  w: l.w,
1031
1109
  h: l.h,
1032
1110
  x: l.x,
@@ -1070,6 +1148,8 @@ function GridLayout(props) {
1070
1148
  useCSSTransforms,
1071
1149
  mounted,
1072
1150
  transformScale,
1151
+ positionStrategy,
1152
+ dragThreshold,
1073
1153
  droppingPosition,
1074
1154
  resizeHandles,
1075
1155
  resizeHandle,
@@ -1414,5 +1494,5 @@ function ResponsiveGridLayout(props) {
1414
1494
  }
1415
1495
 
1416
1496
  export { GridItem, GridLayout, ResponsiveGridLayout };
1417
- //# sourceMappingURL=chunk-PLWMASMX.mjs.map
1418
- //# sourceMappingURL=chunk-PLWMASMX.mjs.map
1497
+ //# sourceMappingURL=chunk-OWK47QTG.mjs.map
1498
+ //# sourceMappingURL=chunk-OWK47QTG.mjs.map