react-grid-layout 1.2.3 → 1.3.1
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/.flowconfig +1 -3
- package/CHANGELOG.md +48 -0
- package/README.md +56 -16
- package/build/GridItem.js +12 -12
- package/build/ReactGridLayout.js +306 -325
- package/build/ReactGridLayoutPropTypes.js +11 -5
- package/build/ResponsiveReactGridLayout.js +16 -10
- package/build/calculateUtils.js +8 -8
- package/build/components/WidthProvider.js +30 -17
- package/build/fastRGLPropsEqual.js +1 -1
- package/build/responsiveUtils.js +1 -1
- package/build/utils.js +47 -43
- package/dist/react-grid-layout.min.js +1 -2
- package/dist/react-grid-layout.min.js.map +1 -1
- package/foo.html +388 -0
- package/lib/GridItem.jsx +7 -7
- package/lib/ReactGridLayout.jsx +101 -62
- package/lib/ReactGridLayoutPropTypes.js +38 -17
- package/lib/ResponsiveReactGridLayout.jsx +7 -1
- package/lib/components/WidthProvider.jsx +17 -3
- package/lib/utils.js +44 -25
- package/package.json +31 -29
- package/.husky/pre-commit +0 -6
- package/.travis.yml +0 -9
- package/dist/react-grid-layout.min.js.LICENSE.txt +0 -5
package/lib/ReactGridLayout.jsx
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
|
|
4
4
|
import isEqual from "lodash.isequal";
|
|
5
|
-
import
|
|
5
|
+
import clsx from "clsx";
|
|
6
6
|
import {
|
|
7
|
-
autoBindHandlers,
|
|
8
7
|
bottom,
|
|
9
8
|
childrenEqual,
|
|
10
9
|
cloneLayoutItem,
|
|
@@ -95,6 +94,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
95
94
|
isBounded: false,
|
|
96
95
|
isDraggable: true,
|
|
97
96
|
isResizable: true,
|
|
97
|
+
allowOverlap: false,
|
|
98
98
|
isDroppable: false,
|
|
99
99
|
useCSSTransforms: true,
|
|
100
100
|
transformScale: 1,
|
|
@@ -114,7 +114,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
114
114
|
onResizeStart: noop,
|
|
115
115
|
onResize: noop,
|
|
116
116
|
onResizeStop: noop,
|
|
117
|
-
onDrop: noop
|
|
117
|
+
onDrop: noop,
|
|
118
|
+
onDropDragOver: noop
|
|
118
119
|
};
|
|
119
120
|
|
|
120
121
|
state: State = {
|
|
@@ -124,7 +125,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
124
125
|
this.props.children,
|
|
125
126
|
this.props.cols,
|
|
126
127
|
// Legacy support for verticalCompact: false
|
|
127
|
-
compactType(this.props)
|
|
128
|
+
compactType(this.props),
|
|
129
|
+
this.props.allowOverlap
|
|
128
130
|
),
|
|
129
131
|
mounted: false,
|
|
130
132
|
oldDragItem: null,
|
|
@@ -136,18 +138,6 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
136
138
|
|
|
137
139
|
dragEnterCounter: number = 0;
|
|
138
140
|
|
|
139
|
-
constructor(props: Props, context: any): void {
|
|
140
|
-
super(props, context);
|
|
141
|
-
autoBindHandlers(this, [
|
|
142
|
-
"onDragStart",
|
|
143
|
-
"onDrag",
|
|
144
|
-
"onDragStop",
|
|
145
|
-
"onResizeStart",
|
|
146
|
-
"onResize",
|
|
147
|
-
"onResizeStop"
|
|
148
|
-
]);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
141
|
componentDidMount() {
|
|
152
142
|
this.setState({ mounted: true });
|
|
153
143
|
// Possibly call back with layout on mount. This should be done after correcting the layout width
|
|
@@ -185,7 +175,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
185
175
|
newLayoutBase,
|
|
186
176
|
nextProps.children,
|
|
187
177
|
nextProps.cols,
|
|
188
|
-
compactType(nextProps)
|
|
178
|
+
compactType(nextProps),
|
|
179
|
+
nextProps.allowOverlap
|
|
189
180
|
);
|
|
190
181
|
|
|
191
182
|
return {
|
|
@@ -249,23 +240,23 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
249
240
|
* @param {Event} e The mousedown event
|
|
250
241
|
* @param {Element} node The current dragging DOM element
|
|
251
242
|
*/
|
|
252
|
-
onDragStart(
|
|
243
|
+
onDragStart: (i: string, x: number, y: number, GridDragEvent) => void = (
|
|
253
244
|
i: string,
|
|
254
245
|
x: number,
|
|
255
246
|
y: number,
|
|
256
247
|
{ e, node }: GridDragEvent
|
|
257
|
-
)
|
|
248
|
+
) => {
|
|
258
249
|
const { layout } = this.state;
|
|
259
250
|
const l = getLayoutItem(layout, i);
|
|
260
251
|
if (!l) return;
|
|
261
252
|
|
|
262
253
|
this.setState({
|
|
263
254
|
oldDragItem: cloneLayoutItem(l),
|
|
264
|
-
oldLayout:
|
|
255
|
+
oldLayout: layout
|
|
265
256
|
});
|
|
266
257
|
|
|
267
258
|
return this.props.onDragStart(layout, l, l, null, e, node);
|
|
268
|
-
}
|
|
259
|
+
};
|
|
269
260
|
|
|
270
261
|
/**
|
|
271
262
|
* Each drag movement create a new dragelement and move the element to the dragged location
|
|
@@ -275,10 +266,15 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
275
266
|
* @param {Event} e The mousedown event
|
|
276
267
|
* @param {Element} node The current dragging DOM element
|
|
277
268
|
*/
|
|
278
|
-
onDrag(i: string, x: number, y: number,
|
|
269
|
+
onDrag: (i: string, x: number, y: number, GridDragEvent) => void = (
|
|
270
|
+
i,
|
|
271
|
+
x,
|
|
272
|
+
y,
|
|
273
|
+
{ e, node }
|
|
274
|
+
) => {
|
|
279
275
|
const { oldDragItem } = this.state;
|
|
280
276
|
let { layout } = this.state;
|
|
281
|
-
const { cols } = this.props;
|
|
277
|
+
const { cols, allowOverlap, preventCollision } = this.props;
|
|
282
278
|
const l = getLayoutItem(layout, i);
|
|
283
279
|
if (!l) return;
|
|
284
280
|
|
|
@@ -300,18 +296,21 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
300
296
|
x,
|
|
301
297
|
y,
|
|
302
298
|
isUserAction,
|
|
303
|
-
|
|
299
|
+
preventCollision,
|
|
304
300
|
compactType(this.props),
|
|
305
|
-
cols
|
|
301
|
+
cols,
|
|
302
|
+
allowOverlap
|
|
306
303
|
);
|
|
307
304
|
|
|
308
305
|
this.props.onDrag(layout, oldDragItem, l, placeholder, e, node);
|
|
309
306
|
|
|
310
307
|
this.setState({
|
|
311
|
-
layout:
|
|
308
|
+
layout: allowOverlap
|
|
309
|
+
? layout
|
|
310
|
+
: compact(layout, compactType(this.props), cols),
|
|
312
311
|
activeDrag: placeholder
|
|
313
312
|
});
|
|
314
|
-
}
|
|
313
|
+
};
|
|
315
314
|
|
|
316
315
|
/**
|
|
317
316
|
* When dragging stops, figure out which position the element is closest to and update its x and y.
|
|
@@ -321,17 +320,17 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
321
320
|
* @param {Event} e The mousedown event
|
|
322
321
|
* @param {Element} node The current dragging DOM element
|
|
323
322
|
*/
|
|
324
|
-
onDragStop(
|
|
325
|
-
i
|
|
326
|
-
x
|
|
327
|
-
y
|
|
328
|
-
{ e, node }
|
|
329
|
-
)
|
|
323
|
+
onDragStop: (i: string, x: number, y: number, GridDragEvent) => void = (
|
|
324
|
+
i,
|
|
325
|
+
x,
|
|
326
|
+
y,
|
|
327
|
+
{ e, node }
|
|
328
|
+
) => {
|
|
330
329
|
if (!this.state.activeDrag) return;
|
|
331
330
|
|
|
332
331
|
const { oldDragItem } = this.state;
|
|
333
332
|
let { layout } = this.state;
|
|
334
|
-
const { cols, preventCollision } = this.props;
|
|
333
|
+
const { cols, preventCollision, allowOverlap } = this.props;
|
|
335
334
|
const l = getLayoutItem(layout, i);
|
|
336
335
|
if (!l) return;
|
|
337
336
|
|
|
@@ -345,13 +344,16 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
345
344
|
isUserAction,
|
|
346
345
|
preventCollision,
|
|
347
346
|
compactType(this.props),
|
|
348
|
-
cols
|
|
347
|
+
cols,
|
|
348
|
+
allowOverlap
|
|
349
349
|
);
|
|
350
350
|
|
|
351
351
|
this.props.onDragStop(layout, oldDragItem, l, null, e, node);
|
|
352
352
|
|
|
353
353
|
// Set state
|
|
354
|
-
const newLayout =
|
|
354
|
+
const newLayout = allowOverlap
|
|
355
|
+
? layout
|
|
356
|
+
: compact(layout, compactType(this.props), cols);
|
|
355
357
|
const { oldLayout } = this.state;
|
|
356
358
|
this.setState({
|
|
357
359
|
activeDrag: null,
|
|
@@ -361,7 +363,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
361
363
|
});
|
|
362
364
|
|
|
363
365
|
this.onLayoutMaybeChanged(newLayout, oldLayout);
|
|
364
|
-
}
|
|
366
|
+
};
|
|
365
367
|
|
|
366
368
|
onLayoutMaybeChanged(newLayout: Layout, oldLayout: ?Layout) {
|
|
367
369
|
if (!oldLayout) oldLayout = this.state.layout;
|
|
@@ -371,7 +373,12 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
371
373
|
}
|
|
372
374
|
}
|
|
373
375
|
|
|
374
|
-
onResizeStart(i: string, w: number, h: number,
|
|
376
|
+
onResizeStart: (i: string, w: number, h: number, GridResizeEvent) => void = (
|
|
377
|
+
i,
|
|
378
|
+
w,
|
|
379
|
+
h,
|
|
380
|
+
{ e, node }
|
|
381
|
+
) => {
|
|
375
382
|
const { layout } = this.state;
|
|
376
383
|
const l = getLayoutItem(layout, i);
|
|
377
384
|
if (!l) return;
|
|
@@ -382,17 +389,22 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
382
389
|
});
|
|
383
390
|
|
|
384
391
|
this.props.onResizeStart(layout, l, l, null, e, node);
|
|
385
|
-
}
|
|
392
|
+
};
|
|
386
393
|
|
|
387
|
-
onResize(i: string, w: number, h: number,
|
|
394
|
+
onResize: (i: string, w: number, h: number, GridResizeEvent) => void = (
|
|
395
|
+
i,
|
|
396
|
+
w,
|
|
397
|
+
h,
|
|
398
|
+
{ e, node }
|
|
399
|
+
) => {
|
|
388
400
|
const { layout, oldResizeItem } = this.state;
|
|
389
|
-
const { cols, preventCollision } = this.props;
|
|
401
|
+
const { cols, preventCollision, allowOverlap } = this.props;
|
|
390
402
|
|
|
391
403
|
const [newLayout, l] = withLayoutItem(layout, i, l => {
|
|
392
404
|
// Something like quad tree should be used
|
|
393
405
|
// to find collisions faster
|
|
394
406
|
let hasCollisions;
|
|
395
|
-
if (preventCollision) {
|
|
407
|
+
if (preventCollision && !allowOverlap) {
|
|
396
408
|
const collisions = getAllCollisions(layout, { ...l, w, h }).filter(
|
|
397
409
|
layoutItem => layoutItem.i !== l.i
|
|
398
410
|
);
|
|
@@ -439,20 +451,29 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
439
451
|
|
|
440
452
|
// Re-compact the newLayout and set the drag placeholder.
|
|
441
453
|
this.setState({
|
|
442
|
-
layout:
|
|
454
|
+
layout: allowOverlap
|
|
455
|
+
? newLayout
|
|
456
|
+
: compact(newLayout, compactType(this.props), cols),
|
|
443
457
|
activeDrag: placeholder
|
|
444
458
|
});
|
|
445
|
-
}
|
|
459
|
+
};
|
|
446
460
|
|
|
447
|
-
onResizeStop(i: string, w: number, h: number,
|
|
461
|
+
onResizeStop: (i: string, w: number, h: number, GridResizeEvent) => void = (
|
|
462
|
+
i,
|
|
463
|
+
w,
|
|
464
|
+
h,
|
|
465
|
+
{ e, node }
|
|
466
|
+
) => {
|
|
448
467
|
const { layout, oldResizeItem } = this.state;
|
|
449
|
-
const { cols } = this.props;
|
|
468
|
+
const { cols, allowOverlap } = this.props;
|
|
450
469
|
const l = getLayoutItem(layout, i);
|
|
451
470
|
|
|
452
471
|
this.props.onResizeStop(layout, oldResizeItem, l, null, e, node);
|
|
453
472
|
|
|
454
473
|
// Set state
|
|
455
|
-
const newLayout =
|
|
474
|
+
const newLayout = allowOverlap
|
|
475
|
+
? layout
|
|
476
|
+
: compact(layout, compactType(this.props), cols);
|
|
456
477
|
const { oldLayout } = this.state;
|
|
457
478
|
this.setState({
|
|
458
479
|
activeDrag: null,
|
|
@@ -462,7 +483,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
462
483
|
});
|
|
463
484
|
|
|
464
485
|
this.onLayoutMaybeChanged(newLayout, oldLayout);
|
|
465
|
-
}
|
|
486
|
+
};
|
|
466
487
|
|
|
467
488
|
/**
|
|
468
489
|
* Create a placeholder object.
|
|
@@ -599,6 +620,9 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
599
620
|
// Called while dragging an element. Part of browser native drag/drop API.
|
|
600
621
|
// Native event target might be the layout itself, or an element within the layout.
|
|
601
622
|
onDragOver: DragOverEvent => void | false = e => {
|
|
623
|
+
e.preventDefault(); // Prevent any browser native action
|
|
624
|
+
e.stopPropagation();
|
|
625
|
+
|
|
602
626
|
// we should ignore events from layout's children in Firefox
|
|
603
627
|
// to avoid unpredictable jumping of a dropping placeholder
|
|
604
628
|
// FIXME remove this hack
|
|
@@ -607,24 +631,39 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
607
631
|
// $FlowIgnore can't figure this out
|
|
608
632
|
!e.nativeEvent.target?.classList.contains(layoutClassName)
|
|
609
633
|
) {
|
|
610
|
-
// without this Firefox will not allow drop if currently over droppingItem
|
|
611
|
-
e.preventDefault();
|
|
612
634
|
return false;
|
|
613
635
|
}
|
|
614
636
|
|
|
615
637
|
const {
|
|
616
638
|
droppingItem,
|
|
639
|
+
onDropDragOver,
|
|
617
640
|
margin,
|
|
618
641
|
cols,
|
|
619
642
|
rowHeight,
|
|
620
643
|
maxRows,
|
|
621
644
|
width,
|
|
622
|
-
containerPadding
|
|
645
|
+
containerPadding,
|
|
646
|
+
transformScale
|
|
623
647
|
} = this.props;
|
|
648
|
+
// Allow user to customize the dropping item or short-circuit the drop based on the results
|
|
649
|
+
// of the `onDragOver(e: Event)` callback.
|
|
650
|
+
const onDragOverResult = onDropDragOver?.(e);
|
|
651
|
+
if (onDragOverResult === false) {
|
|
652
|
+
if (this.state.droppingDOMNode) {
|
|
653
|
+
this.removeDroppingPlaceholder();
|
|
654
|
+
}
|
|
655
|
+
return false;
|
|
656
|
+
}
|
|
657
|
+
const finalDroppingItem = { ...droppingItem, ...onDragOverResult };
|
|
658
|
+
|
|
624
659
|
const { layout } = this.state;
|
|
625
660
|
// This is relative to the DOM element that this event fired for.
|
|
626
661
|
const { layerX, layerY } = e.nativeEvent;
|
|
627
|
-
const droppingPosition = {
|
|
662
|
+
const droppingPosition = {
|
|
663
|
+
left: layerX / transformScale,
|
|
664
|
+
top: layerY / transformScale,
|
|
665
|
+
e
|
|
666
|
+
};
|
|
628
667
|
|
|
629
668
|
if (!this.state.droppingDOMNode) {
|
|
630
669
|
const positionParams: PositionParams = {
|
|
@@ -640,17 +679,17 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
640
679
|
positionParams,
|
|
641
680
|
layerY,
|
|
642
681
|
layerX,
|
|
643
|
-
|
|
644
|
-
|
|
682
|
+
finalDroppingItem.w,
|
|
683
|
+
finalDroppingItem.h
|
|
645
684
|
);
|
|
646
685
|
|
|
647
686
|
this.setState({
|
|
648
|
-
droppingDOMNode: <div key={
|
|
687
|
+
droppingDOMNode: <div key={finalDroppingItem.i} />,
|
|
649
688
|
droppingPosition,
|
|
650
689
|
layout: [
|
|
651
690
|
...layout,
|
|
652
691
|
{
|
|
653
|
-
...
|
|
692
|
+
...finalDroppingItem,
|
|
654
693
|
x: calculatedPosition.x,
|
|
655
694
|
y: calculatedPosition.y,
|
|
656
695
|
static: false,
|
|
@@ -665,9 +704,6 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
665
704
|
this.setState({ droppingPosition });
|
|
666
705
|
}
|
|
667
706
|
}
|
|
668
|
-
|
|
669
|
-
e.stopPropagation();
|
|
670
|
-
e.preventDefault();
|
|
671
707
|
};
|
|
672
708
|
|
|
673
709
|
removeDroppingPlaceholder: () => void = () => {
|
|
@@ -688,7 +724,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
688
724
|
});
|
|
689
725
|
};
|
|
690
726
|
|
|
691
|
-
onDragLeave:
|
|
727
|
+
onDragLeave: EventHandler = e => {
|
|
728
|
+
e.preventDefault(); // Prevent any browser native action
|
|
692
729
|
this.dragEnterCounter--;
|
|
693
730
|
|
|
694
731
|
// onDragLeave can be triggered on each layout's child.
|
|
@@ -701,11 +738,13 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
701
738
|
}
|
|
702
739
|
};
|
|
703
740
|
|
|
704
|
-
onDragEnter:
|
|
741
|
+
onDragEnter: EventHandler = e => {
|
|
742
|
+
e.preventDefault(); // Prevent any browser native action
|
|
705
743
|
this.dragEnterCounter++;
|
|
706
744
|
};
|
|
707
745
|
|
|
708
746
|
onDrop: EventHandler = (e: Event) => {
|
|
747
|
+
e.preventDefault(); // Prevent any browser native action
|
|
709
748
|
const { droppingItem } = this.props;
|
|
710
749
|
const { layout } = this.state;
|
|
711
750
|
const item = layout.find(l => l.i === droppingItem.i);
|
|
@@ -721,7 +760,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
721
760
|
render(): React.Element<"div"> {
|
|
722
761
|
const { className, style, isDroppable, innerRef } = this.props;
|
|
723
762
|
|
|
724
|
-
const mergedClassName =
|
|
763
|
+
const mergedClassName = clsx(layoutClassName, className);
|
|
725
764
|
const mergedStyle = {
|
|
726
765
|
height: this.containerHeight(),
|
|
727
766
|
...style
|
|
@@ -6,19 +6,35 @@ import type {
|
|
|
6
6
|
ChildrenArray as ReactChildrenArray,
|
|
7
7
|
Element as ReactElement
|
|
8
8
|
} from "react";
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
import type {
|
|
10
|
+
DragOverEvent,
|
|
11
|
+
EventCallback,
|
|
12
|
+
CompactType,
|
|
13
|
+
Layout,
|
|
14
|
+
LayoutItem
|
|
15
|
+
} from "./utils";
|
|
16
16
|
|
|
17
17
|
// util
|
|
18
18
|
export type ReactRef<T: HTMLElement> = {|
|
|
19
19
|
+current: T | null
|
|
20
20
|
|};
|
|
21
21
|
|
|
22
|
+
export type ResizeHandleAxis =
|
|
23
|
+
| "s"
|
|
24
|
+
| "w"
|
|
25
|
+
| "e"
|
|
26
|
+
| "n"
|
|
27
|
+
| "sw"
|
|
28
|
+
| "nw"
|
|
29
|
+
| "se"
|
|
30
|
+
| "ne";
|
|
31
|
+
export type ResizeHandle =
|
|
32
|
+
| ReactElement<any>
|
|
33
|
+
| ((
|
|
34
|
+
resizeHandleAxis: ResizeHandleAxis,
|
|
35
|
+
ref: ReactRef<HTMLElement>
|
|
36
|
+
) => ReactElement<any>);
|
|
37
|
+
|
|
22
38
|
// Defines which resize handles should be rendered (default: 'se')
|
|
23
39
|
// Allows for any combination of:
|
|
24
40
|
// 's' - South handle (bottom-center)
|
|
@@ -29,13 +45,13 @@ export type ReactRef<T: HTMLElement> = {|
|
|
|
29
45
|
// 'nw' - Northwest handle (top-left)
|
|
30
46
|
// 'se' - Southeast handle (bottom-right)
|
|
31
47
|
// 'ne' - Northeast handle (top-right)
|
|
32
|
-
export const
|
|
33
|
-
PropTypes.
|
|
34
|
-
)
|
|
48
|
+
export const resizeHandleAxesType: ReactPropsChainableTypeChecker =
|
|
49
|
+
PropTypes.arrayOf(
|
|
50
|
+
PropTypes.oneOf(["s", "w", "e", "n", "sw", "nw", "se", "ne"])
|
|
51
|
+
);
|
|
35
52
|
// Custom component for resize handles
|
|
36
|
-
export const resizeHandleType: ReactPropsChainableTypeChecker =
|
|
37
|
-
[PropTypes.node, PropTypes.func]
|
|
38
|
-
);
|
|
53
|
+
export const resizeHandleType: ReactPropsChainableTypeChecker =
|
|
54
|
+
PropTypes.oneOfType([PropTypes.node, PropTypes.func]);
|
|
39
55
|
|
|
40
56
|
export type Props = {|
|
|
41
57
|
className: string,
|
|
@@ -60,8 +76,9 @@ export type Props = {|
|
|
|
60
76
|
useCSSTransforms: boolean,
|
|
61
77
|
transformScale: number,
|
|
62
78
|
droppingItem: $Shape<LayoutItem>,
|
|
63
|
-
resizeHandles:
|
|
79
|
+
resizeHandles: ResizeHandleAxis[],
|
|
64
80
|
resizeHandle?: ResizeHandle,
|
|
81
|
+
allowOverlap: boolean,
|
|
65
82
|
|
|
66
83
|
// Callbacks
|
|
67
84
|
onLayoutChange: Layout => void,
|
|
@@ -71,6 +88,7 @@ export type Props = {|
|
|
|
71
88
|
onResize: EventCallback,
|
|
72
89
|
onResizeStart: EventCallback,
|
|
73
90
|
onResizeStop: EventCallback,
|
|
91
|
+
onDropDragOver: (e: DragOverEvent) => ?({| w?: number, h?: number |} | false),
|
|
74
92
|
onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void,
|
|
75
93
|
children: ReactChildrenArray<ReactElement<any>>,
|
|
76
94
|
innerRef?: Ref<"div">
|
|
@@ -159,6 +177,8 @@ export default {
|
|
|
159
177
|
isBounded: PropTypes.bool,
|
|
160
178
|
isDraggable: PropTypes.bool,
|
|
161
179
|
isResizable: PropTypes.bool,
|
|
180
|
+
// If true, grid can be placed one over the other.
|
|
181
|
+
allowOverlap: PropTypes.bool,
|
|
162
182
|
// If true, grid items won't change position when being dragged over.
|
|
163
183
|
preventCollision: PropTypes.bool,
|
|
164
184
|
// Use CSS transforms instead of top/left
|
|
@@ -169,7 +189,7 @@ export default {
|
|
|
169
189
|
isDroppable: PropTypes.bool,
|
|
170
190
|
|
|
171
191
|
// Resize handle options
|
|
172
|
-
resizeHandles:
|
|
192
|
+
resizeHandles: resizeHandleAxesType,
|
|
173
193
|
resizeHandle: resizeHandleType,
|
|
174
194
|
|
|
175
195
|
//
|
|
@@ -207,11 +227,12 @@ export default {
|
|
|
207
227
|
|
|
208
228
|
// Children must not have duplicate keys.
|
|
209
229
|
children: function (props: Props, propName: string) {
|
|
210
|
-
|
|
230
|
+
const children = props[propName];
|
|
211
231
|
|
|
212
232
|
// Check children keys for duplicates. Throw if found.
|
|
213
|
-
|
|
233
|
+
const keys = {};
|
|
214
234
|
React.Children.forEach(children, function (child) {
|
|
235
|
+
if (child?.key == null) return;
|
|
215
236
|
if (keys[child.key]) {
|
|
216
237
|
throw new Error(
|
|
217
238
|
'Duplicate child key "' +
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from "./responsiveUtils";
|
|
22
22
|
import ReactGridLayout from "./ReactGridLayout";
|
|
23
23
|
|
|
24
|
+
// $FlowFixMe[method-unbinding]
|
|
24
25
|
const type = obj => Object.prototype.toString.call(obj);
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -74,6 +75,7 @@ type Props<Breakpoint: string = string> = {|
|
|
|
74
75
|
type DefaultProps = Pick<
|
|
75
76
|
Props<>,
|
|
76
77
|
{|
|
|
78
|
+
allowOverlap: 0,
|
|
77
79
|
breakpoints: 0,
|
|
78
80
|
cols: 0,
|
|
79
81
|
containerPadding: 0,
|
|
@@ -103,6 +105,8 @@ export default class ResponsiveReactGridLayout extends React.Component<
|
|
|
103
105
|
// {name: pxVal}, e.g. {lg: 1200, md: 996, sm: 768, xs: 480}
|
|
104
106
|
breakpoints: PropTypes.object,
|
|
105
107
|
|
|
108
|
+
allowOverlap: PropTypes.bool,
|
|
109
|
+
|
|
106
110
|
// # of cols. This is a breakpoint -> cols map
|
|
107
111
|
cols: PropTypes.object,
|
|
108
112
|
|
|
@@ -162,6 +166,7 @@ export default class ResponsiveReactGridLayout extends React.Component<
|
|
|
162
166
|
containerPadding: { lg: null, md: null, sm: null, xs: null, xxs: null },
|
|
163
167
|
layouts: {},
|
|
164
168
|
margin: [10, 10],
|
|
169
|
+
allowOverlap: false,
|
|
165
170
|
onBreakpointChange: noop,
|
|
166
171
|
onLayoutChange: noop,
|
|
167
172
|
onWidthChange: noop
|
|
@@ -277,7 +282,8 @@ export default class ResponsiveReactGridLayout extends React.Component<
|
|
|
277
282
|
layout,
|
|
278
283
|
this.props.children,
|
|
279
284
|
newCols,
|
|
280
|
-
compactType
|
|
285
|
+
compactType,
|
|
286
|
+
this.props.allowOverlap
|
|
281
287
|
);
|
|
282
288
|
|
|
283
289
|
// Store the new layout.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
+
import clsx from "clsx";
|
|
4
5
|
import type { ReactRef } from "../ReactGridLayoutPropTypes";
|
|
5
6
|
|
|
6
7
|
type WPDefaultProps = {|
|
|
@@ -26,6 +27,8 @@ type ComposedProps<Config> = {|
|
|
|
26
27
|
width?: number
|
|
27
28
|
|};
|
|
28
29
|
|
|
30
|
+
const layoutClassName = "react-grid-layout";
|
|
31
|
+
|
|
29
32
|
/*
|
|
30
33
|
* A simple HOC that provides facility for listening to container resizes.
|
|
31
34
|
*
|
|
@@ -54,8 +57,10 @@ export default function WidthProvideRGL<Config>(
|
|
|
54
57
|
};
|
|
55
58
|
|
|
56
59
|
elementRef: ReactRef<HTMLDivElement> = React.createRef();
|
|
60
|
+
mounted: boolean = false;
|
|
57
61
|
|
|
58
62
|
componentDidMount() {
|
|
63
|
+
this.mounted = true;
|
|
59
64
|
window.addEventListener("resize", this.onWindowResize);
|
|
60
65
|
// Call to properly set the breakpoint and resize the elements.
|
|
61
66
|
// Note that if you're doing a full-width element, this can get a little wonky if a scrollbar
|
|
@@ -64,21 +69,30 @@ export default function WidthProvideRGL<Config>(
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
componentWillUnmount() {
|
|
72
|
+
this.mounted = false;
|
|
67
73
|
window.removeEventListener("resize", this.onWindowResize);
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
onWindowResize = () => {
|
|
77
|
+
if (!this.mounted) return;
|
|
71
78
|
const node = this.elementRef.current; // Flow casts this to Text | Element
|
|
72
|
-
|
|
79
|
+
// fix: grid position error when node or parentNode display is none by window resize
|
|
80
|
+
// #924 #1084
|
|
81
|
+
if (node instanceof HTMLElement && node.offsetWidth) {
|
|
73
82
|
this.setState({ width: node.offsetWidth });
|
|
74
83
|
}
|
|
75
84
|
};
|
|
76
85
|
|
|
77
86
|
render() {
|
|
78
87
|
const { measureBeforeMount, ...rest } = this.props;
|
|
79
|
-
if (measureBeforeMount && !this.
|
|
88
|
+
if (measureBeforeMount && !this.mounted) {
|
|
80
89
|
return (
|
|
81
|
-
<div
|
|
90
|
+
<div
|
|
91
|
+
className={clsx(this.props.className, layoutClassName)}
|
|
92
|
+
style={this.props.style}
|
|
93
|
+
// $FlowIgnore ref types
|
|
94
|
+
ref={this.elementRef}
|
|
95
|
+
/>
|
|
82
96
|
);
|
|
83
97
|
}
|
|
84
98
|
|