react-grid-layout 1.3.4 → 1.4.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 -0
- package/.prettierignore +2 -1
- package/.prettierrc +0 -1
- package/CHANGELOG.md +36 -0
- package/README.md +35 -6
- package/build/GridItem.js +483 -493
- package/build/ReactGridLayout.js +534 -592
- package/build/ReactGridLayoutPropTypes.js +43 -48
- package/build/ResponsiveReactGridLayout.js +144 -238
- package/build/calculateUtils.js +76 -115
- package/build/components/WidthProvider.js +79 -122
- package/build/responsiveUtils.js +33 -63
- package/build/utils.js +402 -442
- package/css/styles.css +8 -3
- package/dist/react-grid-layout.min.js +1 -1
- package/dist/react-grid-layout.min.js.map +1 -1
- package/index.js +1 -0
- package/lib/GridItem.jsx +71 -70
- package/lib/ReactGridLayout.jsx +64 -23
- package/lib/ReactGridLayoutPropTypes.js +2 -10
- package/lib/ResponsiveReactGridLayout.jsx +4 -4
- package/lib/calculateUtils.js +20 -4
- package/lib/components/WidthProvider.jsx +18 -16
- package/lib/utils.js +208 -22
- package/package.json +43 -36
package/lib/GridItem.jsx
CHANGED
|
@@ -3,7 +3,13 @@ import React from "react";
|
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { DraggableCore } from "react-draggable";
|
|
5
5
|
import { Resizable } from "react-resizable";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
fastPositionEqual,
|
|
8
|
+
perc,
|
|
9
|
+
resizeItemInDirection,
|
|
10
|
+
setTopLeft,
|
|
11
|
+
setTransform
|
|
12
|
+
} from "./utils";
|
|
7
13
|
import {
|
|
8
14
|
calcGridItemPosition,
|
|
9
15
|
calcGridItemWHPx,
|
|
@@ -24,15 +30,12 @@ import type {
|
|
|
24
30
|
GridDragEvent,
|
|
25
31
|
GridResizeEvent,
|
|
26
32
|
DroppingPosition,
|
|
27
|
-
Position
|
|
33
|
+
Position,
|
|
34
|
+
ResizeHandleAxis
|
|
28
35
|
} from "./utils";
|
|
29
36
|
|
|
30
37
|
import type { PositionParams } from "./calculateUtils";
|
|
31
|
-
import type {
|
|
32
|
-
ResizeHandleAxis,
|
|
33
|
-
ResizeHandle,
|
|
34
|
-
ReactRef
|
|
35
|
-
} from "./ReactGridLayoutPropTypes";
|
|
38
|
+
import type { ResizeHandle, ReactRef } from "./ReactGridLayoutPropTypes";
|
|
36
39
|
|
|
37
40
|
type PartialPosition = { top: number, left: number };
|
|
38
41
|
type GridItemCallback<Data: GridDragEvent | GridResizeEvent> = (
|
|
@@ -42,8 +45,20 @@ type GridItemCallback<Data: GridDragEvent | GridResizeEvent> = (
|
|
|
42
45
|
Data
|
|
43
46
|
) => void;
|
|
44
47
|
|
|
48
|
+
type ResizeCallbackData = {
|
|
49
|
+
node: HTMLElement,
|
|
50
|
+
size: Position,
|
|
51
|
+
handle: ResizeHandleAxis
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type GridItemResizeCallback = (
|
|
55
|
+
e: Event,
|
|
56
|
+
data: ResizeCallbackData,
|
|
57
|
+
position: Position
|
|
58
|
+
) => void;
|
|
59
|
+
|
|
45
60
|
type State = {
|
|
46
|
-
resizing: ?{ width: number, height: number },
|
|
61
|
+
resizing: ?{ top: number, left: number, width: number, height: number },
|
|
47
62
|
dragging: ?{ top: number, left: number },
|
|
48
63
|
className: string
|
|
49
64
|
};
|
|
@@ -356,6 +371,15 @@ export default class GridItem extends React.Component<Props, State> {
|
|
|
356
371
|
);
|
|
357
372
|
}
|
|
358
373
|
|
|
374
|
+
/**
|
|
375
|
+
* Utility function to setup callback handler definitions for
|
|
376
|
+
* similarily structured resize events.
|
|
377
|
+
*/
|
|
378
|
+
curryResizeHandler(position: Position, handler: Function): Function {
|
|
379
|
+
return (e: Event, data: ResizeCallbackData): Function =>
|
|
380
|
+
handler(e, data, position);
|
|
381
|
+
}
|
|
382
|
+
|
|
359
383
|
/**
|
|
360
384
|
* Mix a Resizable instance into a child.
|
|
361
385
|
* @param {Element} child Child element.
|
|
@@ -369,7 +393,6 @@ export default class GridItem extends React.Component<Props, State> {
|
|
|
369
393
|
): ReactElement<any> {
|
|
370
394
|
const {
|
|
371
395
|
cols,
|
|
372
|
-
x,
|
|
373
396
|
minW,
|
|
374
397
|
minH,
|
|
375
398
|
maxW,
|
|
@@ -381,13 +404,7 @@ export default class GridItem extends React.Component<Props, State> {
|
|
|
381
404
|
const positionParams = this.getPositionParams();
|
|
382
405
|
|
|
383
406
|
// This is the max possible width - doesn't go to infinity because of the width of the window
|
|
384
|
-
const maxWidth = calcGridItemPosition(
|
|
385
|
-
positionParams,
|
|
386
|
-
0,
|
|
387
|
-
0,
|
|
388
|
-
cols - x,
|
|
389
|
-
0
|
|
390
|
-
).width;
|
|
407
|
+
const maxWidth = calcGridItemPosition(positionParams, 0, 0, cols, 0).width;
|
|
391
408
|
|
|
392
409
|
// Calculate min/max constraints using our min & maxes
|
|
393
410
|
const mins = calcGridItemPosition(positionParams, 0, 0, minW, minH);
|
|
@@ -408,9 +425,9 @@ export default class GridItem extends React.Component<Props, State> {
|
|
|
408
425
|
height={position.height}
|
|
409
426
|
minConstraints={minConstraints}
|
|
410
427
|
maxConstraints={maxConstraints}
|
|
411
|
-
onResizeStop={this.onResizeStop}
|
|
412
|
-
onResizeStart={this.onResizeStart}
|
|
413
|
-
onResize={this.onResize}
|
|
428
|
+
onResizeStop={this.curryResizeHandler(position, this.onResizeStop)}
|
|
429
|
+
onResizeStart={this.curryResizeHandler(position, this.onResizeStart)}
|
|
430
|
+
onResize={this.curryResizeHandler(position, this.onResize)}
|
|
414
431
|
transformScale={transformScale}
|
|
415
432
|
resizeHandles={resizeHandles}
|
|
416
433
|
handle={resizeHandle}
|
|
@@ -541,77 +558,61 @@ export default class GridItem extends React.Component<Props, State> {
|
|
|
541
558
|
* @param {Event} e event data
|
|
542
559
|
* @param {Object} callbackData an object with node and size information
|
|
543
560
|
*/
|
|
544
|
-
onResizeStop: (
|
|
545
|
-
e,
|
|
546
|
-
callbackData
|
|
547
|
-
) => {
|
|
548
|
-
this.onResizeHandler(e, callbackData, "onResizeStop");
|
|
549
|
-
};
|
|
561
|
+
onResizeStop: GridItemResizeCallback = (e, callbackData, position) =>
|
|
562
|
+
this.onResizeHandler(e, callbackData, position, "onResizeStop");
|
|
550
563
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
* @param {Object} callbackData an object with node and size information
|
|
555
|
-
*/
|
|
556
|
-
onResizeStart: (Event, { node: HTMLElement, size: Position }) => void = (
|
|
557
|
-
e,
|
|
558
|
-
callbackData
|
|
559
|
-
) => {
|
|
560
|
-
this.onResizeHandler(e, callbackData, "onResizeStart");
|
|
561
|
-
};
|
|
564
|
+
// onResizeStart event handler
|
|
565
|
+
onResizeStart: GridItemResizeCallback = (e, callbackData, position) =>
|
|
566
|
+
this.onResizeHandler(e, callbackData, position, "onResizeStart");
|
|
562
567
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
* @param {Object} callbackData an object with node and size information
|
|
567
|
-
*/
|
|
568
|
-
onResize: (Event, { node: HTMLElement, size: Position }) => void = (
|
|
569
|
-
e,
|
|
570
|
-
callbackData
|
|
571
|
-
) => {
|
|
572
|
-
this.onResizeHandler(e, callbackData, "onResize");
|
|
573
|
-
};
|
|
568
|
+
// onResize event handler
|
|
569
|
+
onResize: GridItemResizeCallback = (e, callbackData, position) =>
|
|
570
|
+
this.onResizeHandler(e, callbackData, position, "onResize");
|
|
574
571
|
|
|
575
572
|
/**
|
|
576
|
-
* Wrapper around
|
|
577
|
-
* All drag events call the function with the given handler name,
|
|
578
|
-
* with the signature (index, x, y).
|
|
579
|
-
*
|
|
580
|
-
* @param {String} handlerName Handler name to wrap.
|
|
581
|
-
* @return {Function} Handler function.
|
|
573
|
+
* Wrapper around resize events to provide more useful data.
|
|
582
574
|
*/
|
|
583
575
|
onResizeHandler(
|
|
584
576
|
e: Event,
|
|
585
|
-
{ node, size }:
|
|
577
|
+
{ node, size, handle }: ResizeCallbackData, // 'size' is updated position
|
|
578
|
+
position: Position, // existing position
|
|
586
579
|
handlerName: string
|
|
587
580
|
): void {
|
|
588
581
|
const handler = this.props[handlerName];
|
|
589
582
|
if (!handler) return;
|
|
590
|
-
const {
|
|
591
|
-
|
|
583
|
+
const { x, y, i, maxH, minH, containerWidth } = this.props;
|
|
584
|
+
const { minW, maxW } = this.props;
|
|
585
|
+
|
|
586
|
+
// Clamping of dimensions based on resize direction
|
|
587
|
+
let updatedSize = size;
|
|
588
|
+
if (node) {
|
|
589
|
+
updatedSize = resizeItemInDirection(
|
|
590
|
+
handle,
|
|
591
|
+
position,
|
|
592
|
+
size,
|
|
593
|
+
containerWidth
|
|
594
|
+
);
|
|
595
|
+
this.setState({
|
|
596
|
+
resizing: handlerName === "onResizeStop" ? null : updatedSize
|
|
597
|
+
});
|
|
598
|
+
}
|
|
592
599
|
|
|
593
|
-
// Get new XY
|
|
600
|
+
// Get new XY based on pixel size
|
|
594
601
|
let { w, h } = calcWH(
|
|
595
602
|
this.getPositionParams(),
|
|
596
|
-
|
|
597
|
-
|
|
603
|
+
updatedSize.width,
|
|
604
|
+
updatedSize.height,
|
|
598
605
|
x,
|
|
599
|
-
y
|
|
606
|
+
y,
|
|
607
|
+
handle
|
|
600
608
|
);
|
|
601
609
|
|
|
610
|
+
// Min/max capping.
|
|
602
611
|
// minW should be at least 1 (TODO propTypes validation?)
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
// maxW should be at most (cols - x)
|
|
606
|
-
maxW = Math.min(maxW, cols - x);
|
|
607
|
-
|
|
608
|
-
// Min/max capping
|
|
609
|
-
w = clamp(w, minW, maxW);
|
|
612
|
+
w = clamp(w, Math.max(minW, 1), maxW);
|
|
610
613
|
h = clamp(h, minH, maxH);
|
|
611
614
|
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
handler.call(this, i, w, h, { e, node, size });
|
|
615
|
+
handler.call(this, i, w, h, { e, node, size: updatedSize, handle });
|
|
615
616
|
}
|
|
616
617
|
|
|
617
618
|
render(): ReactNode {
|
package/lib/ReactGridLayout.jsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import { deepEqual } from "fast-equals";
|
|
5
5
|
import clsx from "clsx";
|
|
6
6
|
import {
|
|
7
7
|
bottom,
|
|
@@ -47,6 +47,7 @@ type State = {
|
|
|
47
47
|
oldDragItem: ?LayoutItem,
|
|
48
48
|
oldLayout: ?Layout,
|
|
49
49
|
oldResizeItem: ?LayoutItem,
|
|
50
|
+
resizing: boolean,
|
|
50
51
|
droppingDOMNode: ?ReactElement<any>,
|
|
51
52
|
droppingPosition?: DroppingPosition,
|
|
52
53
|
// Mirrored props
|
|
@@ -132,6 +133,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
132
133
|
oldDragItem: null,
|
|
133
134
|
oldLayout: null,
|
|
134
135
|
oldResizeItem: null,
|
|
136
|
+
resizing: false,
|
|
135
137
|
droppingDOMNode: null,
|
|
136
138
|
children: []
|
|
137
139
|
};
|
|
@@ -158,7 +160,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
158
160
|
// Legacy support for compactType
|
|
159
161
|
// Allow parent to set layout directly.
|
|
160
162
|
if (
|
|
161
|
-
!
|
|
163
|
+
!deepEqual(nextProps.layout, prevState.propsLayout) ||
|
|
162
164
|
nextProps.compactType !== prevState.compactType
|
|
163
165
|
) {
|
|
164
166
|
newLayoutBase = nextProps.layout;
|
|
@@ -198,7 +200,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
198
200
|
// from SCU is if the user intentionally memoizes children. If they do, and they can
|
|
199
201
|
// handle changes properly, performance will increase.
|
|
200
202
|
this.props.children !== nextProps.children ||
|
|
201
|
-
!fastRGLPropsEqual(this.props, nextProps,
|
|
203
|
+
!fastRGLPropsEqual(this.props, nextProps, deepEqual) ||
|
|
202
204
|
this.state.activeDrag !== nextState.activeDrag ||
|
|
203
205
|
this.state.mounted !== nextState.mounted ||
|
|
204
206
|
this.state.droppingPosition !== nextState.droppingPosition
|
|
@@ -348,12 +350,13 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
348
350
|
allowOverlap
|
|
349
351
|
);
|
|
350
352
|
|
|
351
|
-
this.props.onDragStop(layout, oldDragItem, l, null, e, node);
|
|
352
|
-
|
|
353
353
|
// Set state
|
|
354
354
|
const newLayout = allowOverlap
|
|
355
355
|
? layout
|
|
356
356
|
: compact(layout, compactType(this.props), cols);
|
|
357
|
+
|
|
358
|
+
this.props.onDragStop(newLayout, oldDragItem, l, null, e, node);
|
|
359
|
+
|
|
357
360
|
const { oldLayout } = this.state;
|
|
358
361
|
this.setState({
|
|
359
362
|
activeDrag: null,
|
|
@@ -368,7 +371,7 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
368
371
|
onLayoutMaybeChanged(newLayout: Layout, oldLayout: ?Layout) {
|
|
369
372
|
if (!oldLayout) oldLayout = this.state.layout;
|
|
370
373
|
|
|
371
|
-
if (!
|
|
374
|
+
if (!deepEqual(oldLayout, newLayout)) {
|
|
372
375
|
this.props.onLayoutChange(newLayout);
|
|
373
376
|
}
|
|
374
377
|
}
|
|
@@ -385,7 +388,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
385
388
|
|
|
386
389
|
this.setState({
|
|
387
390
|
oldResizeItem: cloneLayoutItem(l),
|
|
388
|
-
oldLayout: this.state.layout
|
|
391
|
+
oldLayout: this.state.layout,
|
|
392
|
+
resizing: true
|
|
389
393
|
});
|
|
390
394
|
|
|
391
395
|
this.props.onResizeStart(layout, l, l, null, e, node);
|
|
@@ -395,9 +399,10 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
395
399
|
i,
|
|
396
400
|
w,
|
|
397
401
|
h,
|
|
398
|
-
{ e, node }
|
|
402
|
+
{ e, node, size, handle }
|
|
399
403
|
) => {
|
|
400
|
-
const {
|
|
404
|
+
const { oldResizeItem } = this.state;
|
|
405
|
+
let { layout } = this.state;
|
|
401
406
|
const { cols, preventCollision, allowOverlap } = this.props;
|
|
402
407
|
|
|
403
408
|
const [newLayout, l] = withLayoutItem(layout, i, l => {
|
|
@@ -425,18 +430,49 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
425
430
|
}
|
|
426
431
|
}
|
|
427
432
|
|
|
428
|
-
if (!hasCollisions) {
|
|
429
|
-
// Set new width and height.
|
|
430
|
-
l.w = w;
|
|
431
|
-
l.h = h;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
433
|
return l;
|
|
435
434
|
});
|
|
436
435
|
|
|
437
436
|
// Shouldn't ever happen, but typechecking makes it necessary
|
|
438
437
|
if (!l) return;
|
|
439
438
|
|
|
439
|
+
let finalLayout;
|
|
440
|
+
if (["sw", "w", "nw", "n", "ne"].indexOf(handle) !== -1) {
|
|
441
|
+
let x = l.x;
|
|
442
|
+
let y = l.y;
|
|
443
|
+
if (["sw", "nw", "w"].indexOf(handle) !== -1) {
|
|
444
|
+
x = l.x + (l.w - w);
|
|
445
|
+
w = l.x !== x && x < 0 ? l.w : w;
|
|
446
|
+
x = x < 0 ? 0 : x;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (["ne", "n", "nw"].indexOf(handle) !== -1) {
|
|
450
|
+
y = l.y + (l.h - h);
|
|
451
|
+
h = l.y !== y && y < 0 ? l.h : h;
|
|
452
|
+
y = y < 0 ? 0 : y;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
l.w = w;
|
|
456
|
+
l.h = h;
|
|
457
|
+
// Move the element to the new position.
|
|
458
|
+
const isUserAction = true;
|
|
459
|
+
finalLayout = moveElement(
|
|
460
|
+
newLayout,
|
|
461
|
+
l,
|
|
462
|
+
x,
|
|
463
|
+
y,
|
|
464
|
+
isUserAction,
|
|
465
|
+
this.props.preventCollision,
|
|
466
|
+
compactType(this.props),
|
|
467
|
+
cols,
|
|
468
|
+
allowOverlap
|
|
469
|
+
);
|
|
470
|
+
} else {
|
|
471
|
+
l.w = w;
|
|
472
|
+
l.h = h;
|
|
473
|
+
finalLayout = newLayout;
|
|
474
|
+
}
|
|
475
|
+
|
|
440
476
|
// Create placeholder element (display only)
|
|
441
477
|
const placeholder = {
|
|
442
478
|
w: l.w,
|
|
@@ -447,13 +483,13 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
447
483
|
i: i
|
|
448
484
|
};
|
|
449
485
|
|
|
450
|
-
this.props.onResize(
|
|
486
|
+
this.props.onResize(finalLayout, oldResizeItem, l, placeholder, e, node);
|
|
451
487
|
|
|
452
488
|
// Re-compact the newLayout and set the drag placeholder.
|
|
453
489
|
this.setState({
|
|
454
490
|
layout: allowOverlap
|
|
455
|
-
?
|
|
456
|
-
: compact(
|
|
491
|
+
? finalLayout
|
|
492
|
+
: compact(finalLayout, compactType(this.props), cols),
|
|
457
493
|
activeDrag: placeholder
|
|
458
494
|
});
|
|
459
495
|
};
|
|
@@ -468,18 +504,20 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
468
504
|
const { cols, allowOverlap } = this.props;
|
|
469
505
|
const l = getLayoutItem(layout, i);
|
|
470
506
|
|
|
471
|
-
this.props.onResizeStop(layout, oldResizeItem, l, null, e, node);
|
|
472
|
-
|
|
473
507
|
// Set state
|
|
474
508
|
const newLayout = allowOverlap
|
|
475
509
|
? layout
|
|
476
510
|
: compact(layout, compactType(this.props), cols);
|
|
511
|
+
|
|
512
|
+
this.props.onResizeStop(newLayout, oldResizeItem, l, null, e, node);
|
|
513
|
+
|
|
477
514
|
const { oldLayout } = this.state;
|
|
478
515
|
this.setState({
|
|
479
516
|
activeDrag: null,
|
|
480
517
|
layout: newLayout,
|
|
481
518
|
oldResizeItem: null,
|
|
482
|
-
oldLayout: null
|
|
519
|
+
oldLayout: null,
|
|
520
|
+
resizing: false
|
|
483
521
|
});
|
|
484
522
|
|
|
485
523
|
this.onLayoutMaybeChanged(newLayout, oldLayout);
|
|
@@ -511,7 +549,9 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
511
549
|
x={activeDrag.x}
|
|
512
550
|
y={activeDrag.y}
|
|
513
551
|
i={activeDrag.i}
|
|
514
|
-
className=
|
|
552
|
+
className={`react-grid-placeholder ${
|
|
553
|
+
this.state.resizing ? "placeholder-resizing" : ""
|
|
554
|
+
}`}
|
|
515
555
|
containerWidth={width}
|
|
516
556
|
cols={cols}
|
|
517
557
|
margin={margin}
|
|
@@ -713,7 +753,8 @@ export default class ReactGridLayout extends React.Component<Props, State> {
|
|
|
713
753
|
const newLayout = compact(
|
|
714
754
|
layout.filter(l => l.i !== droppingItem.i),
|
|
715
755
|
compactType(this.props),
|
|
716
|
-
cols
|
|
756
|
+
cols,
|
|
757
|
+
this.props.allowOverlap
|
|
717
758
|
);
|
|
718
759
|
|
|
719
760
|
this.setState({
|
|
@@ -11,7 +11,8 @@ import type {
|
|
|
11
11
|
EventCallback,
|
|
12
12
|
CompactType,
|
|
13
13
|
Layout,
|
|
14
|
-
LayoutItem
|
|
14
|
+
LayoutItem,
|
|
15
|
+
ResizeHandleAxis
|
|
15
16
|
} from "./utils";
|
|
16
17
|
|
|
17
18
|
// util
|
|
@@ -19,15 +20,6 @@ export type ReactRef<T: HTMLElement> = {|
|
|
|
19
20
|
+current: T | null
|
|
20
21
|
|};
|
|
21
22
|
|
|
22
|
-
export type ResizeHandleAxis =
|
|
23
|
-
| "s"
|
|
24
|
-
| "w"
|
|
25
|
-
| "e"
|
|
26
|
-
| "n"
|
|
27
|
-
| "sw"
|
|
28
|
-
| "nw"
|
|
29
|
-
| "se"
|
|
30
|
-
| "ne";
|
|
31
23
|
export type ResizeHandle =
|
|
32
24
|
| ReactElement<any>
|
|
33
25
|
| ((
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import
|
|
4
|
+
import { deepEqual } from "fast-equals";
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
cloneLayout,
|
|
@@ -203,7 +203,7 @@ export default class ResponsiveReactGridLayout extends React.Component<
|
|
|
203
203
|
nextProps: Props<*>,
|
|
204
204
|
prevState: State
|
|
205
205
|
): ?$Shape<State> {
|
|
206
|
-
if (!
|
|
206
|
+
if (!deepEqual(nextProps.layouts, prevState.layouts)) {
|
|
207
207
|
// Allow parent to set layouts directly.
|
|
208
208
|
const { breakpoint, cols } = prevState;
|
|
209
209
|
|
|
@@ -228,8 +228,8 @@ export default class ResponsiveReactGridLayout extends React.Component<
|
|
|
228
228
|
if (
|
|
229
229
|
this.props.width != prevProps.width ||
|
|
230
230
|
this.props.breakpoint !== prevProps.breakpoint ||
|
|
231
|
-
!
|
|
232
|
-
!
|
|
231
|
+
!deepEqual(this.props.breakpoints, prevProps.breakpoints) ||
|
|
232
|
+
!deepEqual(this.props.cols, prevProps.cols)
|
|
233
233
|
) {
|
|
234
234
|
this.onWidthChange(prevProps);
|
|
235
235
|
}
|
package/lib/calculateUtils.js
CHANGED
|
@@ -71,6 +71,14 @@ export function calcGridItemPosition(
|
|
|
71
71
|
if (state && state.dragging) {
|
|
72
72
|
out.top = Math.round(state.dragging.top);
|
|
73
73
|
out.left = Math.round(state.dragging.left);
|
|
74
|
+
} else if (
|
|
75
|
+
state &&
|
|
76
|
+
state.resizing &&
|
|
77
|
+
typeof state.resizing.top === "number" &&
|
|
78
|
+
typeof state.resizing.left === "number"
|
|
79
|
+
) {
|
|
80
|
+
out.top = Math.round(state.resizing.top);
|
|
81
|
+
out.left = Math.round(state.resizing.left);
|
|
74
82
|
}
|
|
75
83
|
// Otherwise, calculate from grid units.
|
|
76
84
|
else {
|
|
@@ -123,6 +131,7 @@ export function calcXY(
|
|
|
123
131
|
* @param {Number} width Width in pixels.
|
|
124
132
|
* @param {Number} x X coordinate in grid units.
|
|
125
133
|
* @param {Number} y Y coordinate in grid units.
|
|
134
|
+
* @param {String} handle Resize Handle.
|
|
126
135
|
* @return {Object} w, h as grid units.
|
|
127
136
|
*/
|
|
128
137
|
export function calcWH(
|
|
@@ -130,7 +139,8 @@ export function calcWH(
|
|
|
130
139
|
width: number,
|
|
131
140
|
height: number,
|
|
132
141
|
x: number,
|
|
133
|
-
y: number
|
|
142
|
+
y: number,
|
|
143
|
+
handle: string
|
|
134
144
|
): { w: number, h: number } {
|
|
135
145
|
const { margin, maxRows, cols, rowHeight } = positionParams;
|
|
136
146
|
const colWidth = calcGridColWidth(positionParams);
|
|
@@ -142,9 +152,15 @@ export function calcWH(
|
|
|
142
152
|
let h = Math.round((height + margin[1]) / (rowHeight + margin[1]));
|
|
143
153
|
|
|
144
154
|
// Capping
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
155
|
+
let _w = clamp(w, 0, cols - x);
|
|
156
|
+
let _h = clamp(h, 0, maxRows - y);
|
|
157
|
+
if (["sw", "w", "nw"].indexOf(handle) !== -1) {
|
|
158
|
+
_w = clamp(w, 0, cols);
|
|
159
|
+
}
|
|
160
|
+
if (["nw", "n", "ne"].indexOf(handle) !== -1) {
|
|
161
|
+
_h = clamp(h, 0, maxRows);
|
|
162
|
+
}
|
|
163
|
+
return { w: _w, h: _h };
|
|
148
164
|
}
|
|
149
165
|
|
|
150
166
|
// Similar to _.clamp
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
+
import ResizeObserver from "resize-observer-polyfill";
|
|
4
5
|
import clsx from "clsx";
|
|
5
6
|
import type { ReactRef } from "../ReactGridLayoutPropTypes";
|
|
6
7
|
|
|
@@ -58,30 +59,31 @@ export default function WidthProvideRGL<Config>(
|
|
|
58
59
|
|
|
59
60
|
elementRef: ReactRef<HTMLDivElement> = React.createRef();
|
|
60
61
|
mounted: boolean = false;
|
|
62
|
+
resizeObserver: ResizeObserver;
|
|
61
63
|
|
|
62
64
|
componentDidMount() {
|
|
63
65
|
this.mounted = true;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
this.resizeObserver = new ResizeObserver(entries => {
|
|
67
|
+
const node = this.elementRef.current;
|
|
68
|
+
if (node instanceof HTMLElement) {
|
|
69
|
+
const width = entries[0].contentRect.width;
|
|
70
|
+
this.setState({ width });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const node = this.elementRef.current;
|
|
74
|
+
if (node instanceof HTMLElement) {
|
|
75
|
+
this.resizeObserver.observe(node);
|
|
76
|
+
}
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
componentWillUnmount() {
|
|
72
80
|
this.mounted = false;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
onWindowResize = () => {
|
|
77
|
-
if (!this.mounted) return;
|
|
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
|
-
this.setState({ width: node.offsetWidth });
|
|
81
|
+
const node = this.elementRef.current;
|
|
82
|
+
if (node instanceof HTMLElement) {
|
|
83
|
+
this.resizeObserver.unobserve(node);
|
|
83
84
|
}
|
|
84
|
-
|
|
85
|
+
this.resizeObserver.disconnect();
|
|
86
|
+
}
|
|
85
87
|
|
|
86
88
|
render() {
|
|
87
89
|
const { measureBeforeMount, ...rest } = this.props;
|