react-grid-layout 1.2.2 → 1.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.
- package/.flowconfig +1 -3
- package/CHANGELOG.md +55 -0
- package/README.md +55 -16
- package/build/GridItem.js +14 -20
- package/build/ReactGridLayout.js +299 -319
- package/build/ReactGridLayoutPropTypes.js +11 -5
- package/build/ResponsiveReactGridLayout.js +12 -6
- package/build/calculateUtils.js +6 -6
- package/build/components/WidthProvider.js +31 -25
- package/build/fastRGLPropsEqual.js +1 -1
- package/build/utils.js +29 -32
- package/dist/react-grid-layout.min.js +1 -1
- package/dist/react-grid-layout.min.js.LICENSE.txt +1 -1
- package/dist/react-grid-layout.min.js.map +1 -1
- package/foo.html +388 -0
- package/lib/GridItem.jsx +18 -14
- package/lib/ReactGridLayout.jsx +93 -58
- package/lib/ReactGridLayoutPropTypes.js +40 -14
- package/lib/ResponsiveReactGridLayout.jsx +7 -1
- package/lib/components/WidthProvider.jsx +35 -23
- package/lib/utils.js +30 -20
- package/package.json +35 -29
- package/.husky/pre-commit +0 -6
- package/.travis.yml +0 -9
package/lib/ReactGridLayout.jsx
CHANGED
|
@@ -4,7 +4,6 @@ import * as React from "react";
|
|
|
4
4
|
import isEqual from "lodash.isequal";
|
|
5
5
|
import classNames from "classnames";
|
|
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,12 +240,12 @@ 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;
|
|
@@ -265,7 +256,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
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 } = this.props;
|
|
282
278
|
const l = getLayoutItem(layout, i);
|
|
283
279
|
if (!l) return;
|
|
284
280
|
|
|
@@ -302,16 +298,19 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
302
298
|
isUserAction,
|
|
303
299
|
this.props.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,35 @@ 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 = { left: layerX, top: layerY, e };
|
|
662
|
+
const droppingPosition = { left: layerX / transformScale, top: layerY / transformScale, e };
|
|
628
663
|
|
|
629
664
|
if (!this.state.droppingDOMNode) {
|
|
630
665
|
const positionParams: PositionParams = {
|
|
@@ -640,17 +675,17 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
640
675
|
positionParams,
|
|
641
676
|
layerY,
|
|
642
677
|
layerX,
|
|
643
|
-
|
|
644
|
-
|
|
678
|
+
finalDroppingItem.w,
|
|
679
|
+
finalDroppingItem.h
|
|
645
680
|
);
|
|
646
681
|
|
|
647
682
|
this.setState({
|
|
648
|
-
droppingDOMNode: <div key={
|
|
683
|
+
droppingDOMNode: <div key={finalDroppingItem.i} />,
|
|
649
684
|
droppingPosition,
|
|
650
685
|
layout: [
|
|
651
686
|
...layout,
|
|
652
687
|
{
|
|
653
|
-
...
|
|
688
|
+
...finalDroppingItem,
|
|
654
689
|
x: calculatedPosition.x,
|
|
655
690
|
y: calculatedPosition.y,
|
|
656
691
|
static: false,
|
|
@@ -665,9 +700,6 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
665
700
|
this.setState({ droppingPosition });
|
|
666
701
|
}
|
|
667
702
|
}
|
|
668
|
-
|
|
669
|
-
e.stopPropagation();
|
|
670
|
-
e.preventDefault();
|
|
671
703
|
};
|
|
672
704
|
|
|
673
705
|
removeDroppingPlaceholder: () => void = () => {
|
|
@@ -688,7 +720,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
688
720
|
});
|
|
689
721
|
};
|
|
690
722
|
|
|
691
|
-
onDragLeave:
|
|
723
|
+
onDragLeave: EventHandler = e => {
|
|
724
|
+
e.preventDefault(); // Prevent any browser native action
|
|
692
725
|
this.dragEnterCounter--;
|
|
693
726
|
|
|
694
727
|
// onDragLeave can be triggered on each layout's child.
|
|
@@ -701,11 +734,13 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
701
734
|
}
|
|
702
735
|
};
|
|
703
736
|
|
|
704
|
-
onDragEnter:
|
|
737
|
+
onDragEnter: EventHandler = e => {
|
|
738
|
+
e.preventDefault(); // Prevent any browser native action
|
|
705
739
|
this.dragEnterCounter++;
|
|
706
740
|
};
|
|
707
741
|
|
|
708
742
|
onDrop: EventHandler = (e: Event) => {
|
|
743
|
+
e.preventDefault(); // Prevent any browser native action
|
|
709
744
|
const { droppingItem } = this.props;
|
|
710
745
|
const { layout } = this.state;
|
|
711
746
|
const item = layout.find(l => l.i === droppingItem.i);
|
|
@@ -6,13 +6,34 @@ import type {
|
|
|
6
6
|
ChildrenArray as ReactChildrenArray,
|
|
7
7
|
Element as ReactElement
|
|
8
8
|
} from "react";
|
|
9
|
-
import type {
|
|
9
|
+
import type {
|
|
10
|
+
DragOverEvent,
|
|
11
|
+
EventCallback,
|
|
12
|
+
CompactType,
|
|
13
|
+
Layout,
|
|
14
|
+
LayoutItem
|
|
15
|
+
} from "./utils";
|
|
16
|
+
|
|
17
|
+
// util
|
|
18
|
+
export type ReactRef<T: HTMLElement> = {|
|
|
19
|
+
+current: T | null
|
|
20
|
+
|};
|
|
10
21
|
|
|
11
|
-
type ResizeHandleAxis =
|
|
12
|
-
|
|
22
|
+
export type ResizeHandleAxis =
|
|
23
|
+
| "s"
|
|
24
|
+
| "w"
|
|
25
|
+
| "e"
|
|
26
|
+
| "n"
|
|
27
|
+
| "sw"
|
|
28
|
+
| "nw"
|
|
29
|
+
| "se"
|
|
30
|
+
| "ne";
|
|
13
31
|
export type ResizeHandle =
|
|
14
32
|
| ReactElement<any>
|
|
15
|
-
| ((
|
|
33
|
+
| ((
|
|
34
|
+
resizeHandleAxis: ResizeHandleAxis,
|
|
35
|
+
ref: ReactRef<HTMLElement>
|
|
36
|
+
) => ReactElement<any>);
|
|
16
37
|
|
|
17
38
|
// Defines which resize handles should be rendered (default: 'se')
|
|
18
39
|
// Allows for any combination of:
|
|
@@ -24,13 +45,13 @@ export type ResizeHandle =
|
|
|
24
45
|
// 'nw' - Northwest handle (top-left)
|
|
25
46
|
// 'se' - Southeast handle (bottom-right)
|
|
26
47
|
// 'ne' - Northeast handle (top-right)
|
|
27
|
-
export const
|
|
28
|
-
PropTypes.
|
|
29
|
-
)
|
|
48
|
+
export const resizeHandleAxesType: ReactPropsChainableTypeChecker =
|
|
49
|
+
PropTypes.arrayOf(
|
|
50
|
+
PropTypes.oneOf(["s", "w", "e", "n", "sw", "nw", "se", "ne"])
|
|
51
|
+
);
|
|
30
52
|
// Custom component for resize handles
|
|
31
|
-
export const resizeHandleType: ReactPropsChainableTypeChecker =
|
|
32
|
-
[PropTypes.node, PropTypes.func]
|
|
33
|
-
);
|
|
53
|
+
export const resizeHandleType: ReactPropsChainableTypeChecker =
|
|
54
|
+
PropTypes.oneOfType([PropTypes.node, PropTypes.func]);
|
|
34
55
|
|
|
35
56
|
export type Props = {|
|
|
36
57
|
className: string,
|
|
@@ -55,8 +76,9 @@ export type Props = {|
|
|
|
55
76
|
useCSSTransforms: boolean,
|
|
56
77
|
transformScale: number,
|
|
57
78
|
droppingItem: $Shape<LayoutItem>,
|
|
58
|
-
resizeHandles:
|
|
79
|
+
resizeHandles: ResizeHandleAxis[],
|
|
59
80
|
resizeHandle?: ResizeHandle,
|
|
81
|
+
allowOverlap: boolean,
|
|
60
82
|
|
|
61
83
|
// Callbacks
|
|
62
84
|
onLayoutChange: Layout => void,
|
|
@@ -66,6 +88,7 @@ export type Props = {|
|
|
|
66
88
|
onResize: EventCallback,
|
|
67
89
|
onResizeStart: EventCallback,
|
|
68
90
|
onResizeStop: EventCallback,
|
|
91
|
+
onDropDragOver: (e: DragOverEvent) => ?({| w?: number, h?: number |} | false),
|
|
69
92
|
onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void,
|
|
70
93
|
children: ReactChildrenArray<ReactElement<any>>,
|
|
71
94
|
innerRef?: Ref<"div">
|
|
@@ -154,6 +177,8 @@ export default {
|
|
|
154
177
|
isBounded: PropTypes.bool,
|
|
155
178
|
isDraggable: PropTypes.bool,
|
|
156
179
|
isResizable: PropTypes.bool,
|
|
180
|
+
// If true, grid can be placed one over the other.
|
|
181
|
+
allowOverlap: PropTypes.bool,
|
|
157
182
|
// If true, grid items won't change position when being dragged over.
|
|
158
183
|
preventCollision: PropTypes.bool,
|
|
159
184
|
// Use CSS transforms instead of top/left
|
|
@@ -164,7 +189,7 @@ export default {
|
|
|
164
189
|
isDroppable: PropTypes.bool,
|
|
165
190
|
|
|
166
191
|
// Resize handle options
|
|
167
|
-
resizeHandles:
|
|
192
|
+
resizeHandles: resizeHandleAxesType,
|
|
168
193
|
resizeHandle: resizeHandleType,
|
|
169
194
|
|
|
170
195
|
//
|
|
@@ -202,11 +227,12 @@ export default {
|
|
|
202
227
|
|
|
203
228
|
// Children must not have duplicate keys.
|
|
204
229
|
children: function (props: Props, propName: string) {
|
|
205
|
-
|
|
230
|
+
const children = props[propName];
|
|
206
231
|
|
|
207
232
|
// Check children keys for duplicates. Throw if found.
|
|
208
|
-
|
|
233
|
+
const keys = {};
|
|
209
234
|
React.Children.forEach(children, function (child) {
|
|
235
|
+
if (child?.key == null) return;
|
|
210
236
|
if (keys[child.key]) {
|
|
211
237
|
throw new Error(
|
|
212
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,7 +1,8 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import
|
|
4
|
+
import classNames from "classnames";
|
|
5
|
+
import type { ReactRef } from "../ReactGridLayoutPropTypes";
|
|
5
6
|
|
|
6
7
|
type WPDefaultProps = {|
|
|
7
8
|
measureBeforeMount: boolean
|
|
@@ -18,29 +19,27 @@ type WPState = {|
|
|
|
18
19
|
width: number
|
|
19
20
|
|};
|
|
20
21
|
|
|
22
|
+
type ComposedProps<Config> = {|
|
|
23
|
+
...Config,
|
|
24
|
+
measureBeforeMount?: boolean,
|
|
25
|
+
className?: string,
|
|
26
|
+
style?: Object,
|
|
27
|
+
width?: number
|
|
28
|
+
|};
|
|
29
|
+
|
|
30
|
+
const layoutClassName = "react-grid-layout";
|
|
31
|
+
|
|
21
32
|
/*
|
|
22
33
|
* A simple HOC that provides facility for listening to container resizes.
|
|
23
34
|
*
|
|
24
35
|
* The Flow type is pretty janky here. I can't just spread `WPProps` into this returned object - I wish I could - but it triggers
|
|
25
36
|
* a flow bug of some sort that causes it to stop typechecking.
|
|
26
37
|
*/
|
|
27
|
-
export default function
|
|
38
|
+
export default function WidthProvideRGL<Config>(
|
|
28
39
|
ComposedComponent: React.AbstractComponent<Config>
|
|
29
|
-
): React.AbstractComponent<{
|
|
30
|
-
...Config,
|
|
31
|
-
measureBeforeMount?: boolean,
|
|
32
|
-
className?: string,
|
|
33
|
-
style?: Object,
|
|
34
|
-
width?: number
|
|
35
|
-
|}> {
|
|
40
|
+
): React.AbstractComponent<ComposedProps<Config>> {
|
|
36
41
|
return class WidthProvider extends React.Component<
|
|
37
|
-
|
|
38
|
-
...Config,
|
|
39
|
-
measureBeforeMount?: boolean,
|
|
40
|
-
className?: string,
|
|
41
|
-
style?: Object,
|
|
42
|
-
width?: number
|
|
43
|
-
|},
|
|
42
|
+
ComposedProps<Config>,
|
|
44
43
|
WPState
|
|
45
44
|
> {
|
|
46
45
|
static defaultProps: WPDefaultProps = {
|
|
@@ -53,15 +52,15 @@ export default function WidthProvider<Config>(
|
|
|
53
52
|
measureBeforeMount: PropTypes.bool
|
|
54
53
|
};
|
|
55
54
|
|
|
56
|
-
state = {
|
|
55
|
+
state: WPState = {
|
|
57
56
|
width: 1280
|
|
58
57
|
};
|
|
59
58
|
|
|
59
|
+
elementRef: ReactRef<HTMLDivElement> = React.createRef();
|
|
60
60
|
mounted: boolean = false;
|
|
61
61
|
|
|
62
62
|
componentDidMount() {
|
|
63
63
|
this.mounted = true;
|
|
64
|
-
|
|
65
64
|
window.addEventListener("resize", this.onWindowResize);
|
|
66
65
|
// Call to properly set the breakpoint and resize the elements.
|
|
67
66
|
// Note that if you're doing a full-width element, this can get a little wonky if a scrollbar
|
|
@@ -76,21 +75,34 @@ export default function WidthProvider<Config>(
|
|
|
76
75
|
|
|
77
76
|
onWindowResize = () => {
|
|
78
77
|
if (!this.mounted) return;
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
const node = this.elementRef.current; // Flow casts this to Text | Element
|
|
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) {
|
|
82
82
|
this.setState({ width: node.offsetWidth });
|
|
83
|
+
}
|
|
83
84
|
};
|
|
84
85
|
|
|
85
86
|
render() {
|
|
86
87
|
const { measureBeforeMount, ...rest } = this.props;
|
|
87
88
|
if (measureBeforeMount && !this.mounted) {
|
|
88
89
|
return (
|
|
89
|
-
<div
|
|
90
|
+
<div
|
|
91
|
+
className={classNames(this.props.className, layoutClassName)}
|
|
92
|
+
style={this.props.style}
|
|
93
|
+
// $FlowIgnore ref types
|
|
94
|
+
ref={this.elementRef}
|
|
95
|
+
/>
|
|
90
96
|
);
|
|
91
97
|
}
|
|
92
98
|
|
|
93
|
-
return
|
|
99
|
+
return (
|
|
100
|
+
<ComposedComponent
|
|
101
|
+
innerRef={this.elementRef}
|
|
102
|
+
{...rest}
|
|
103
|
+
{...this.state}
|
|
104
|
+
/>
|
|
105
|
+
);
|
|
94
106
|
}
|
|
95
107
|
};
|
|
96
108
|
}
|