react-grid-layout 1.2.5 → 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.
@@ -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
- ): void {
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, { e, node }: GridDragEvent): void {
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: compact(layout, compactType(this.props), cols),
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: string,
326
- x: number,
327
- y: number,
328
- { e, node }: GridDragEvent
329
- ): void {
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 = compact(layout, compactType(this.props), cols);
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, { e, node }: GridResizeEvent) {
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, { e, node }: GridResizeEvent) {
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: compact(newLayout, compactType(this.props), cols),
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, { e, node }: GridResizeEvent) {
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 = compact(layout, compactType(this.props), cols);
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
- droppingItem.w,
644
- droppingItem.h
678
+ finalDroppingItem.w,
679
+ finalDroppingItem.h
645
680
  );
646
681
 
647
682
  this.setState({
648
- droppingDOMNode: <div key={droppingItem.i} />,
683
+ droppingDOMNode: <div key={finalDroppingItem.i} />,
649
684
  droppingPosition,
650
685
  layout: [
651
686
  ...layout,
652
687
  {
653
- ...droppingItem,
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: () => void = () => {
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: () => void = () => {
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,18 +6,34 @@ import type {
6
6
  ChildrenArray as ReactChildrenArray,
7
7
  Element as ReactElement
8
8
  } from "react";
9
- import type { EventCallback, CompactType, Layout, LayoutItem } from "./utils";
9
+ import type {
10
+ DragOverEvent,
11
+ EventCallback,
12
+ CompactType,
13
+ Layout,
14
+ LayoutItem
15
+ } from "./utils";
10
16
 
11
17
  // util
12
18
  export type ReactRef<T: HTMLElement> = {|
13
19
  +current: T | null
14
20
  |};
15
21
 
16
- export type ResizeHandleAxis = "s" | "w" | "e" | "n" | "sw" | "nw" | "se" | "ne";
22
+ export type ResizeHandleAxis =
23
+ | "s"
24
+ | "w"
25
+ | "e"
26
+ | "n"
27
+ | "sw"
28
+ | "nw"
29
+ | "se"
30
+ | "ne";
17
31
  export type ResizeHandle =
18
32
  | ReactElement<any>
19
- | ((resizeHandleAxis: ResizeHandleAxis, ref: ReactRef<HTMLElement>) => ReactElement<any>);
20
-
33
+ | ((
34
+ resizeHandleAxis: ResizeHandleAxis,
35
+ ref: ReactRef<HTMLElement>
36
+ ) => ReactElement<any>);
21
37
 
22
38
  // Defines which resize handles should be rendered (default: 'se')
23
39
  // Allows for any combination of:
@@ -29,13 +45,13 @@ export type ResizeHandle =
29
45
  // 'nw' - Northwest handle (top-left)
30
46
  // 'se' - Southeast handle (bottom-right)
31
47
  // 'ne' - Northeast handle (top-right)
32
- export const resizeHandleAxesType: ReactPropsChainableTypeChecker = PropTypes.arrayOf(
33
- PropTypes.oneOf(["s", "w", "e", "n", "sw", "nw", "se", "ne"])
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 = PropTypes.oneOfType(
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,
@@ -62,6 +78,7 @@ export type Props = {|
62
78
  droppingItem: $Shape<LayoutItem>,
63
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
@@ -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
- var children = props[propName];
230
+ const children = props[propName];
211
231
 
212
232
  // Check children keys for duplicates. Throw if found.
213
- var keys = {};
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.
package/lib/utils.js CHANGED
@@ -159,8 +159,8 @@ export function cloneLayoutItem(layoutItem: LayoutItem): LayoutItem {
159
159
  */
160
160
  export function childrenEqual(a: ReactChildren, b: ReactChildren): boolean {
161
161
  return isEqual(
162
- React.Children.map(a, c => c.key),
163
- React.Children.map(b, c => c.key)
162
+ React.Children.map(a, c => c?.key),
163
+ React.Children.map(b, c => c?.key)
164
164
  );
165
165
  }
166
166
 
@@ -328,11 +328,11 @@ export function compactItem(
328
328
  l.y++;
329
329
  }
330
330
  }
331
-
331
+
332
332
  // Ensure that there are no negative positions
333
333
  l.y = Math.max(l.y, 0);
334
334
  l.x = Math.max(l.x, 0);
335
-
335
+
336
336
  return l;
337
337
  }
338
338
 
@@ -434,7 +434,8 @@ export function moveElement(
434
434
  isUserAction: ?boolean,
435
435
  preventCollision: ?boolean,
436
436
  compactType: CompactType,
437
- cols: number
437
+ cols: number,
438
+ allowOverlap: ?boolean
438
439
  ): Layout {
439
440
  // If this is static and not explicitly enabled as draggable,
440
441
  // no move is possible, so we can short-circuit this immediately.
@@ -471,10 +472,12 @@ export function moveElement(
471
472
 
472
473
  // There was a collision; abort
473
474
  if (preventCollision && collisions.length) {
474
- log(`Collision prevented on ${l.i}, reverting.`);
475
- l.x = oldX;
476
- l.y = oldY;
477
- l.moved = false;
475
+ if (!allowOverlap) {
476
+ log(`Collision prevented on ${l.i}, reverting.`);
477
+ l.x = oldX;
478
+ l.y = oldY;
479
+ l.moved = false;
480
+ }
478
481
  return layout;
479
482
  }
480
483
 
@@ -626,7 +629,8 @@ export function sortLayoutItems(
626
629
  compactType: CompactType
627
630
  ): Layout {
628
631
  if (compactType === "horizontal") return sortLayoutItemsByColRow(layout);
629
- else return sortLayoutItemsByRowCol(layout);
632
+ if (compactType === "vertical") return sortLayoutItemsByRowCol(layout);
633
+ else return layout;
630
634
  }
631
635
 
632
636
  /**
@@ -676,17 +680,21 @@ export function synchronizeLayoutWithChildren(
676
680
  initialLayout: Layout,
677
681
  children: ReactChildren,
678
682
  cols: number,
679
- compactType: CompactType
683
+ compactType: CompactType,
684
+ allowOverlap: ?boolean
680
685
  ): Layout {
681
686
  initialLayout = initialLayout || [];
682
687
 
683
688
  // Generate one layout item per child.
684
689
  const layout: LayoutItem[] = [];
685
- React.Children.forEach(children, (child: ReactElement<any>, i: number) => {
690
+ React.Children.forEach(children, (child: ReactElement<any>) => {
691
+ // Child may not exist
692
+ if (child?.key == null) return;
693
+
686
694
  // Don't overwrite if it already exists.
687
695
  const exists = getLayoutItem(initialLayout, String(child.key));
688
696
  if (exists) {
689
- layout[i] = cloneLayoutItem(exists);
697
+ layout.push(cloneLayoutItem(exists));
690
698
  } else {
691
699
  if (!isProduction && child.props._grid) {
692
700
  console.warn(
@@ -702,24 +710,26 @@ export function synchronizeLayoutWithChildren(
702
710
  validateLayout([g], "ReactGridLayout.children");
703
711
  }
704
712
  // FIXME clone not really necessary here
705
- layout[i] = cloneLayoutItem({ ...g, i: child.key });
713
+ layout.push(cloneLayoutItem({ ...g, i: child.key }));
706
714
  } else {
707
715
  // Nothing provided: ensure this is added to the bottom
708
716
  // FIXME clone not really necessary here
709
- layout[i] = cloneLayoutItem({
717
+ layout.push(cloneLayoutItem({
710
718
  w: 1,
711
719
  h: 1,
712
720
  x: 0,
713
721
  y: bottom(layout),
714
722
  i: String(child.key)
715
- });
723
+ }));
716
724
  }
717
725
  }
718
726
  });
719
727
 
720
728
  // Correct the layout.
721
729
  const correctedLayout = correctBounds(layout, { cols: cols });
722
- return compact(correctedLayout, compactType, cols);
730
+ return allowOverlap
731
+ ? correctedLayout
732
+ : compact(correctedLayout, compactType, cols);
723
733
  }
724
734
 
725
735
  /**
@@ -776,11 +786,6 @@ export function compactType(
776
786
  return verticalCompact === false ? null : compactType;
777
787
  }
778
788
 
779
- // Flow can't really figure this out, so we just use Object
780
- export function autoBindHandlers(el: Object, fns: Array<string>): void {
781
- fns.forEach(key => (el[key] = el[key].bind(el)));
782
- }
783
-
784
789
  function log(...args) {
785
790
  if (!DEBUG) return;
786
791
  // eslint-disable-next-line no-console