react-grid-layout 1.5.2 → 2.0.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/README.md +1075 -432
- package/css/styles.css +6 -4
- package/dist/ResponsiveGridLayout-CH4s0tKj.d.ts +124 -0
- package/dist/ResponsiveGridLayout-D6lFRE3f.d.mts +124 -0
- package/dist/calculate-CwYDW8na.d.mts +168 -0
- package/dist/calculate-mgLpNJ5O.d.ts +168 -0
- package/dist/chunk-2KUHNJXF.mjs +90 -0
- package/dist/chunk-2KUHNJXF.mjs.map +1 -0
- package/dist/chunk-3WO4SAYB.js +868 -0
- package/dist/chunk-3WO4SAYB.js.map +1 -0
- package/dist/chunk-4HNUMWQK.mjs +822 -0
- package/dist/chunk-4HNUMWQK.mjs.map +1 -0
- package/dist/chunk-BFTKGAP3.js +1309 -0
- package/dist/chunk-BFTKGAP3.js.map +1 -0
- package/dist/chunk-F6NQPYKT.js +98 -0
- package/dist/chunk-F6NQPYKT.js.map +1 -0
- package/dist/chunk-H5KMDLY3.js +434 -0
- package/dist/chunk-H5KMDLY3.js.map +1 -0
- package/dist/chunk-PBQSHIID.js +4 -0
- package/dist/chunk-PBQSHIID.js.map +1 -0
- package/dist/chunk-R35HZZTA.mjs +1300 -0
- package/dist/chunk-R35HZZTA.mjs.map +1 -0
- package/dist/chunk-ZCXE6SR5.mjs +428 -0
- package/dist/chunk-ZCXE6SR5.mjs.map +1 -0
- package/dist/chunk-ZWN22PS2.mjs +3 -0
- package/dist/chunk-ZWN22PS2.mjs.map +1 -0
- package/dist/core.d.mts +33 -0
- package/dist/core.d.ts +33 -0
- package/dist/core.js +218 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +5 -0
- package/dist/core.mjs.map +1 -0
- package/dist/extras.d.mts +78 -0
- package/dist/extras.d.ts +78 -0
- package/dist/extras.js +91 -0
- package/dist/extras.js.map +1 -0
- package/dist/extras.mjs +89 -0
- package/dist/extras.mjs.map +1 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +154 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +7 -0
- package/dist/index.mjs.map +1 -0
- package/dist/legacy.d.mts +163 -0
- package/dist/legacy.d.ts +163 -0
- package/dist/legacy.js +319 -0
- package/dist/legacy.js.map +1 -0
- package/dist/legacy.mjs +307 -0
- package/dist/legacy.mjs.map +1 -0
- package/dist/position-BmN1z36J.d.mts +319 -0
- package/dist/position-Dk2b4ZMS.d.ts +319 -0
- package/dist/react.d.mts +351 -0
- package/dist/react.d.ts +351 -0
- package/dist/react.js +96 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +7 -0
- package/dist/react.mjs.map +1 -0
- package/dist/responsive-C4L1ESlm.d.ts +145 -0
- package/dist/responsive-CJxefsYw.d.mts +145 -0
- package/dist/types-Cxf4nHNr.d.mts +375 -0
- package/dist/types-Cxf4nHNr.d.ts +375 -0
- package/index-dev.js +8 -0
- package/package.json +132 -39
- package/.babelrc.js +0 -22
- package/.browserslistrc +0 -3
- package/.eslintignore +0 -4
- package/.flowconfig +0 -20
- package/.prettierignore +0 -4
- package/.prettierrc +0 -17
- package/CHANGELOG.md +0 -985
- package/build/GridItem.js +0 -640
- package/build/ReactGridLayout.js +0 -744
- package/build/ReactGridLayoutPropTypes.js +0 -210
- package/build/ResponsiveReactGridLayout.js +0 -294
- package/build/calculateUtils.js +0 -165
- package/build/components/WidthProvider.js +0 -111
- package/build/fastRGLPropsEqual.js +0 -5
- package/build/responsiveUtils.js +0 -101
- package/build/utils.js +0 -834
- package/dist/react-grid-layout.min.js +0 -2
- package/dist/react-grid-layout.min.js.map +0 -1
- package/index.js.flow +0 -8
- package/ip_fetcher +0 -0
- package/ip_fetcher.c +0 -47
- package/lib/GridItem.jsx +0 -689
- package/lib/ReactGridLayout.jsx +0 -855
- package/lib/ReactGridLayoutPropTypes.js +0 -241
- package/lib/ResponsiveReactGridLayout.jsx +0 -349
- package/lib/calculateUtils.js +0 -169
- package/lib/components/WidthProvider.jsx +0 -110
- package/lib/fastRGLPropsEqual.js +0 -46
- package/lib/responsiveUtils.js +0 -118
- package/lib/utils.js +0 -979
package/lib/ReactGridLayout.jsx
DELETED
|
@@ -1,855 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
|
|
4
|
-
import { deepEqual } from "fast-equals";
|
|
5
|
-
import clsx from "clsx";
|
|
6
|
-
import {
|
|
7
|
-
bottom,
|
|
8
|
-
childrenEqual,
|
|
9
|
-
cloneLayoutItem,
|
|
10
|
-
compact,
|
|
11
|
-
compactType,
|
|
12
|
-
fastRGLPropsEqual,
|
|
13
|
-
getAllCollisions,
|
|
14
|
-
getLayoutItem,
|
|
15
|
-
moveElement,
|
|
16
|
-
noop,
|
|
17
|
-
synchronizeLayoutWithChildren,
|
|
18
|
-
withLayoutItem
|
|
19
|
-
} from "./utils";
|
|
20
|
-
|
|
21
|
-
import { calcXY } from "./calculateUtils";
|
|
22
|
-
|
|
23
|
-
import GridItem from "./GridItem";
|
|
24
|
-
import ReactGridLayoutPropTypes from "./ReactGridLayoutPropTypes";
|
|
25
|
-
import type {
|
|
26
|
-
ChildrenArray as ReactChildrenArray,
|
|
27
|
-
Element as ReactElement
|
|
28
|
-
} from "react";
|
|
29
|
-
|
|
30
|
-
// Types
|
|
31
|
-
import type {
|
|
32
|
-
CompactType,
|
|
33
|
-
GridResizeEvent,
|
|
34
|
-
GridDragEvent,
|
|
35
|
-
DragOverEvent,
|
|
36
|
-
Layout,
|
|
37
|
-
DroppingPosition,
|
|
38
|
-
LayoutItem
|
|
39
|
-
} from "./utils";
|
|
40
|
-
|
|
41
|
-
import type { PositionParams } from "./calculateUtils";
|
|
42
|
-
|
|
43
|
-
type State = {
|
|
44
|
-
activeDrag: ?LayoutItem,
|
|
45
|
-
layout: Layout,
|
|
46
|
-
mounted: boolean,
|
|
47
|
-
oldDragItem: ?LayoutItem,
|
|
48
|
-
oldLayout: ?Layout,
|
|
49
|
-
oldResizeItem: ?LayoutItem,
|
|
50
|
-
resizing: boolean,
|
|
51
|
-
droppingDOMNode: ?ReactElement<any>,
|
|
52
|
-
droppingPosition?: DroppingPosition,
|
|
53
|
-
// Mirrored props
|
|
54
|
-
children: ReactChildrenArray<ReactElement<any>>,
|
|
55
|
-
compactType?: CompactType,
|
|
56
|
-
propsLayout?: Layout
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
import type { Props, DefaultProps } from "./ReactGridLayoutPropTypes";
|
|
60
|
-
|
|
61
|
-
// End Types
|
|
62
|
-
|
|
63
|
-
const layoutClassName = "react-grid-layout";
|
|
64
|
-
let isFirefox = false;
|
|
65
|
-
// Try...catch will protect from navigator not existing (e.g. node) or a bad implementation of navigator
|
|
66
|
-
try {
|
|
67
|
-
isFirefox = /firefox/i.test(navigator.userAgent);
|
|
68
|
-
} catch (e) {
|
|
69
|
-
/* Ignore */
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* A reactive, fluid grid layout with draggable, resizable components.
|
|
74
|
-
*/
|
|
75
|
-
|
|
76
|
-
export default class ReactGridLayout extends React.Component<Props, State> {
|
|
77
|
-
// TODO publish internal ReactClass displayName transform
|
|
78
|
-
static displayName: ?string = "ReactGridLayout";
|
|
79
|
-
|
|
80
|
-
// Refactored to another module to make way for preval
|
|
81
|
-
static propTypes = ReactGridLayoutPropTypes;
|
|
82
|
-
|
|
83
|
-
static defaultProps: DefaultProps = {
|
|
84
|
-
autoSize: true,
|
|
85
|
-
cols: 12,
|
|
86
|
-
className: "",
|
|
87
|
-
style: {},
|
|
88
|
-
draggableHandle: "",
|
|
89
|
-
draggableCancel: "",
|
|
90
|
-
containerPadding: null,
|
|
91
|
-
rowHeight: 150,
|
|
92
|
-
maxRows: Infinity, // infinite vertical growth
|
|
93
|
-
layout: [],
|
|
94
|
-
margin: [10, 10],
|
|
95
|
-
isBounded: false,
|
|
96
|
-
isDraggable: true,
|
|
97
|
-
isResizable: true,
|
|
98
|
-
allowOverlap: false,
|
|
99
|
-
isDroppable: false,
|
|
100
|
-
useCSSTransforms: true,
|
|
101
|
-
transformScale: 1,
|
|
102
|
-
verticalCompact: true,
|
|
103
|
-
compactType: "vertical",
|
|
104
|
-
preventCollision: false,
|
|
105
|
-
droppingItem: {
|
|
106
|
-
i: "__dropping-elem__",
|
|
107
|
-
h: 1,
|
|
108
|
-
w: 1
|
|
109
|
-
},
|
|
110
|
-
resizeHandles: ["se"],
|
|
111
|
-
onLayoutChange: noop,
|
|
112
|
-
onDragStart: noop,
|
|
113
|
-
onDrag: noop,
|
|
114
|
-
onDragStop: noop,
|
|
115
|
-
onResizeStart: noop,
|
|
116
|
-
onResize: noop,
|
|
117
|
-
onResizeStop: noop,
|
|
118
|
-
onDrop: noop,
|
|
119
|
-
onDropDragOver: noop
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
state: State = {
|
|
123
|
-
activeDrag: null,
|
|
124
|
-
layout: synchronizeLayoutWithChildren(
|
|
125
|
-
this.props.layout,
|
|
126
|
-
this.props.children,
|
|
127
|
-
this.props.cols,
|
|
128
|
-
// Legacy support for verticalCompact: false
|
|
129
|
-
compactType(this.props),
|
|
130
|
-
this.props.allowOverlap
|
|
131
|
-
),
|
|
132
|
-
mounted: false,
|
|
133
|
-
oldDragItem: null,
|
|
134
|
-
oldLayout: null,
|
|
135
|
-
oldResizeItem: null,
|
|
136
|
-
resizing: false,
|
|
137
|
-
droppingDOMNode: null,
|
|
138
|
-
children: []
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
dragEnterCounter: number = 0;
|
|
142
|
-
|
|
143
|
-
componentDidMount() {
|
|
144
|
-
this.setState({ mounted: true });
|
|
145
|
-
// Possibly call back with layout on mount. This should be done after correcting the layout width
|
|
146
|
-
// to ensure we don't rerender with the wrong width.
|
|
147
|
-
this.onLayoutMaybeChanged(this.state.layout, this.props.layout);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
static getDerivedStateFromProps(
|
|
151
|
-
nextProps: Props,
|
|
152
|
-
prevState: State
|
|
153
|
-
): $Shape<State> | null {
|
|
154
|
-
let newLayoutBase;
|
|
155
|
-
|
|
156
|
-
if (prevState.activeDrag) {
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Legacy support for compactType
|
|
161
|
-
// Allow parent to set layout directly.
|
|
162
|
-
if (
|
|
163
|
-
!deepEqual(nextProps.layout, prevState.propsLayout) ||
|
|
164
|
-
nextProps.compactType !== prevState.compactType
|
|
165
|
-
) {
|
|
166
|
-
newLayoutBase = nextProps.layout;
|
|
167
|
-
} else if (!childrenEqual(nextProps.children, prevState.children)) {
|
|
168
|
-
// If children change, also regenerate the layout. Use our state
|
|
169
|
-
// as the base in case because it may be more up to date than
|
|
170
|
-
// what is in props.
|
|
171
|
-
newLayoutBase = prevState.layout;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// We need to regenerate the layout.
|
|
175
|
-
if (newLayoutBase) {
|
|
176
|
-
const newLayout = synchronizeLayoutWithChildren(
|
|
177
|
-
newLayoutBase,
|
|
178
|
-
nextProps.children,
|
|
179
|
-
nextProps.cols,
|
|
180
|
-
compactType(nextProps),
|
|
181
|
-
nextProps.allowOverlap
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
layout: newLayout,
|
|
186
|
-
// We need to save these props to state for using
|
|
187
|
-
// getDerivedStateFromProps instead of componentDidMount (in which we would get extra rerender)
|
|
188
|
-
compactType: nextProps.compactType,
|
|
189
|
-
children: nextProps.children,
|
|
190
|
-
propsLayout: nextProps.layout
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
shouldComponentUpdate(nextProps: Props, nextState: State): boolean {
|
|
198
|
-
return (
|
|
199
|
-
// NOTE: this is almost always unequal. Therefore the only way to get better performance
|
|
200
|
-
// from SCU is if the user intentionally memoizes children. If they do, and they can
|
|
201
|
-
// handle changes properly, performance will increase.
|
|
202
|
-
this.props.children !== nextProps.children ||
|
|
203
|
-
!fastRGLPropsEqual(this.props, nextProps, deepEqual) ||
|
|
204
|
-
this.state.activeDrag !== nextState.activeDrag ||
|
|
205
|
-
this.state.mounted !== nextState.mounted ||
|
|
206
|
-
this.state.droppingPosition !== nextState.droppingPosition
|
|
207
|
-
);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
componentDidUpdate(prevProps: Props, prevState: State) {
|
|
211
|
-
if (!this.state.activeDrag) {
|
|
212
|
-
const newLayout = this.state.layout;
|
|
213
|
-
const oldLayout = prevState.layout;
|
|
214
|
-
|
|
215
|
-
this.onLayoutMaybeChanged(newLayout, oldLayout);
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Calculates a pixel value for the container.
|
|
221
|
-
* @return {String} Container height in pixels.
|
|
222
|
-
*/
|
|
223
|
-
containerHeight(): ?string {
|
|
224
|
-
if (!this.props.autoSize) return;
|
|
225
|
-
const nbRow = bottom(this.state.layout);
|
|
226
|
-
const containerPaddingY = this.props.containerPadding
|
|
227
|
-
? this.props.containerPadding[1]
|
|
228
|
-
: this.props.margin[1];
|
|
229
|
-
return (
|
|
230
|
-
nbRow * this.props.rowHeight +
|
|
231
|
-
(nbRow - 1) * this.props.margin[1] +
|
|
232
|
-
containerPaddingY * 2 +
|
|
233
|
-
"px"
|
|
234
|
-
);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* When dragging starts
|
|
239
|
-
* @param {String} i Id of the child
|
|
240
|
-
* @param {Number} x X position of the move
|
|
241
|
-
* @param {Number} y Y position of the move
|
|
242
|
-
* @param {Event} e The mousedown event
|
|
243
|
-
* @param {Element} node The current dragging DOM element
|
|
244
|
-
*/
|
|
245
|
-
onDragStart: (i: string, x: number, y: number, GridDragEvent) => void = (
|
|
246
|
-
i: string,
|
|
247
|
-
x: number,
|
|
248
|
-
y: number,
|
|
249
|
-
{ e, node }: GridDragEvent
|
|
250
|
-
) => {
|
|
251
|
-
const { layout } = this.state;
|
|
252
|
-
const l = getLayoutItem(layout, i);
|
|
253
|
-
if (!l) return;
|
|
254
|
-
|
|
255
|
-
// Create placeholder (display only)
|
|
256
|
-
const placeholder = {
|
|
257
|
-
w: l.w,
|
|
258
|
-
h: l.h,
|
|
259
|
-
x: l.x,
|
|
260
|
-
y: l.y,
|
|
261
|
-
placeholder: true,
|
|
262
|
-
i: i
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
this.setState({
|
|
266
|
-
oldDragItem: cloneLayoutItem(l),
|
|
267
|
-
oldLayout: layout,
|
|
268
|
-
activeDrag: placeholder
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
return this.props.onDragStart(layout, l, l, null, e, node);
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Each drag movement create a new dragelement and move the element to the dragged location
|
|
276
|
-
* @param {String} i Id of the child
|
|
277
|
-
* @param {Number} x X position of the move
|
|
278
|
-
* @param {Number} y Y position of the move
|
|
279
|
-
* @param {Event} e The mousedown event
|
|
280
|
-
* @param {Element} node The current dragging DOM element
|
|
281
|
-
*/
|
|
282
|
-
onDrag: (i: string, x: number, y: number, GridDragEvent) => void = (
|
|
283
|
-
i,
|
|
284
|
-
x,
|
|
285
|
-
y,
|
|
286
|
-
{ e, node }
|
|
287
|
-
) => {
|
|
288
|
-
const { oldDragItem } = this.state;
|
|
289
|
-
let { layout } = this.state;
|
|
290
|
-
const { cols, allowOverlap, preventCollision } = this.props;
|
|
291
|
-
const l = getLayoutItem(layout, i);
|
|
292
|
-
if (!l) return;
|
|
293
|
-
|
|
294
|
-
// Create placeholder (display only)
|
|
295
|
-
const placeholder = {
|
|
296
|
-
w: l.w,
|
|
297
|
-
h: l.h,
|
|
298
|
-
x: l.x,
|
|
299
|
-
y: l.y,
|
|
300
|
-
placeholder: true,
|
|
301
|
-
i: i
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
// Move the element to the dragged location.
|
|
305
|
-
const isUserAction = true;
|
|
306
|
-
layout = moveElement(
|
|
307
|
-
layout,
|
|
308
|
-
l,
|
|
309
|
-
x,
|
|
310
|
-
y,
|
|
311
|
-
isUserAction,
|
|
312
|
-
preventCollision,
|
|
313
|
-
compactType(this.props),
|
|
314
|
-
cols,
|
|
315
|
-
allowOverlap
|
|
316
|
-
);
|
|
317
|
-
|
|
318
|
-
this.props.onDrag(layout, oldDragItem, l, placeholder, e, node);
|
|
319
|
-
|
|
320
|
-
this.setState({
|
|
321
|
-
layout: allowOverlap
|
|
322
|
-
? layout
|
|
323
|
-
: compact(layout, compactType(this.props), cols),
|
|
324
|
-
activeDrag: placeholder
|
|
325
|
-
});
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* When dragging stops, figure out which position the element is closest to and update its x and y.
|
|
330
|
-
* @param {String} i Index of the child.
|
|
331
|
-
* @param {Number} x X position of the move
|
|
332
|
-
* @param {Number} y Y position of the move
|
|
333
|
-
* @param {Event} e The mousedown event
|
|
334
|
-
* @param {Element} node The current dragging DOM element
|
|
335
|
-
*/
|
|
336
|
-
onDragStop: (i: string, x: number, y: number, GridDragEvent) => void = (
|
|
337
|
-
i,
|
|
338
|
-
x,
|
|
339
|
-
y,
|
|
340
|
-
{ e, node }
|
|
341
|
-
) => {
|
|
342
|
-
if (!this.state.activeDrag) return;
|
|
343
|
-
|
|
344
|
-
const { oldDragItem } = this.state;
|
|
345
|
-
let { layout } = this.state;
|
|
346
|
-
const { cols, preventCollision, allowOverlap } = this.props;
|
|
347
|
-
const l = getLayoutItem(layout, i);
|
|
348
|
-
if (!l) return;
|
|
349
|
-
|
|
350
|
-
// Move the element here
|
|
351
|
-
const isUserAction = true;
|
|
352
|
-
layout = moveElement(
|
|
353
|
-
layout,
|
|
354
|
-
l,
|
|
355
|
-
x,
|
|
356
|
-
y,
|
|
357
|
-
isUserAction,
|
|
358
|
-
preventCollision,
|
|
359
|
-
compactType(this.props),
|
|
360
|
-
cols,
|
|
361
|
-
allowOverlap
|
|
362
|
-
);
|
|
363
|
-
|
|
364
|
-
// Set state
|
|
365
|
-
const newLayout = allowOverlap
|
|
366
|
-
? layout
|
|
367
|
-
: compact(layout, compactType(this.props), cols);
|
|
368
|
-
|
|
369
|
-
this.props.onDragStop(newLayout, oldDragItem, l, null, e, node);
|
|
370
|
-
|
|
371
|
-
const { oldLayout } = this.state;
|
|
372
|
-
this.setState({
|
|
373
|
-
activeDrag: null,
|
|
374
|
-
layout: newLayout,
|
|
375
|
-
oldDragItem: null,
|
|
376
|
-
oldLayout: null
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
this.onLayoutMaybeChanged(newLayout, oldLayout);
|
|
380
|
-
};
|
|
381
|
-
|
|
382
|
-
onLayoutMaybeChanged(newLayout: Layout, oldLayout: ?Layout) {
|
|
383
|
-
if (!oldLayout) oldLayout = this.state.layout;
|
|
384
|
-
|
|
385
|
-
if (!deepEqual(oldLayout, newLayout)) {
|
|
386
|
-
this.props.onLayoutChange(newLayout);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
onResizeStart: (i: string, w: number, h: number, GridResizeEvent) => void = (
|
|
391
|
-
i,
|
|
392
|
-
w,
|
|
393
|
-
h,
|
|
394
|
-
{ e, node }
|
|
395
|
-
) => {
|
|
396
|
-
const { layout } = this.state;
|
|
397
|
-
const l = getLayoutItem(layout, i);
|
|
398
|
-
if (!l) return;
|
|
399
|
-
|
|
400
|
-
this.setState({
|
|
401
|
-
oldResizeItem: cloneLayoutItem(l),
|
|
402
|
-
oldLayout: this.state.layout,
|
|
403
|
-
resizing: true
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
this.props.onResizeStart(layout, l, l, null, e, node);
|
|
407
|
-
};
|
|
408
|
-
|
|
409
|
-
onResize: (i: string, w: number, h: number, GridResizeEvent) => void = (
|
|
410
|
-
i,
|
|
411
|
-
w,
|
|
412
|
-
h,
|
|
413
|
-
{ e, node, size, handle }
|
|
414
|
-
) => {
|
|
415
|
-
const { oldResizeItem } = this.state;
|
|
416
|
-
const { layout } = this.state;
|
|
417
|
-
const { cols, preventCollision, allowOverlap } = this.props;
|
|
418
|
-
|
|
419
|
-
let shouldMoveItem = false;
|
|
420
|
-
let finalLayout;
|
|
421
|
-
let x;
|
|
422
|
-
let y;
|
|
423
|
-
|
|
424
|
-
const [newLayout, l] = withLayoutItem(layout, i, l => {
|
|
425
|
-
let hasCollisions;
|
|
426
|
-
x = l.x;
|
|
427
|
-
y = l.y;
|
|
428
|
-
if (["sw", "w", "nw", "n", "ne"].indexOf(handle) !== -1) {
|
|
429
|
-
if (["sw", "nw", "w"].indexOf(handle) !== -1) {
|
|
430
|
-
x = l.x + (l.w - w);
|
|
431
|
-
w = l.x !== x && x < 0 ? l.w : w;
|
|
432
|
-
x = x < 0 ? 0 : x;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
if (["ne", "n", "nw"].indexOf(handle) !== -1) {
|
|
436
|
-
y = l.y + (l.h - h);
|
|
437
|
-
h = l.y !== y && y < 0 ? l.h : h;
|
|
438
|
-
y = y < 0 ? 0 : y;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
shouldMoveItem = true;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// Something like quad tree should be used
|
|
445
|
-
// to find collisions faster
|
|
446
|
-
if (preventCollision && !allowOverlap) {
|
|
447
|
-
const collisions = getAllCollisions(layout, {
|
|
448
|
-
...l,
|
|
449
|
-
w,
|
|
450
|
-
h,
|
|
451
|
-
x,
|
|
452
|
-
y
|
|
453
|
-
}).filter(layoutItem => layoutItem.i !== l.i);
|
|
454
|
-
hasCollisions = collisions.length > 0;
|
|
455
|
-
|
|
456
|
-
// If we're colliding, we need adjust the placeholder.
|
|
457
|
-
if (hasCollisions) {
|
|
458
|
-
// Reset layoutItem dimensions if there were collisions
|
|
459
|
-
y = l.y;
|
|
460
|
-
h = l.h;
|
|
461
|
-
x = l.x;
|
|
462
|
-
w = l.w;
|
|
463
|
-
shouldMoveItem = false;
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
l.w = w;
|
|
468
|
-
l.h = h;
|
|
469
|
-
|
|
470
|
-
return l;
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
// Shouldn't ever happen, but typechecking makes it necessary
|
|
474
|
-
if (!l) return;
|
|
475
|
-
|
|
476
|
-
finalLayout = newLayout;
|
|
477
|
-
if (shouldMoveItem) {
|
|
478
|
-
// Move the element to the new position.
|
|
479
|
-
const isUserAction = true;
|
|
480
|
-
finalLayout = moveElement(
|
|
481
|
-
newLayout,
|
|
482
|
-
l,
|
|
483
|
-
x,
|
|
484
|
-
y,
|
|
485
|
-
isUserAction,
|
|
486
|
-
this.props.preventCollision,
|
|
487
|
-
compactType(this.props),
|
|
488
|
-
cols,
|
|
489
|
-
allowOverlap
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// Create placeholder element (display only)
|
|
494
|
-
const placeholder = {
|
|
495
|
-
w: l.w,
|
|
496
|
-
h: l.h,
|
|
497
|
-
x: l.x,
|
|
498
|
-
y: l.y,
|
|
499
|
-
static: true,
|
|
500
|
-
i: i
|
|
501
|
-
};
|
|
502
|
-
|
|
503
|
-
this.props.onResize(finalLayout, oldResizeItem, l, placeholder, e, node);
|
|
504
|
-
|
|
505
|
-
// Re-compact the newLayout and set the drag placeholder.
|
|
506
|
-
this.setState({
|
|
507
|
-
layout: allowOverlap
|
|
508
|
-
? finalLayout
|
|
509
|
-
: compact(finalLayout, compactType(this.props), cols),
|
|
510
|
-
activeDrag: placeholder
|
|
511
|
-
});
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
onResizeStop: (i: string, w: number, h: number, GridResizeEvent) => void = (
|
|
515
|
-
i,
|
|
516
|
-
w,
|
|
517
|
-
h,
|
|
518
|
-
{ e, node }
|
|
519
|
-
) => {
|
|
520
|
-
const { layout, oldResizeItem } = this.state;
|
|
521
|
-
const { cols, allowOverlap } = this.props;
|
|
522
|
-
const l = getLayoutItem(layout, i);
|
|
523
|
-
|
|
524
|
-
// Set state
|
|
525
|
-
const newLayout = allowOverlap
|
|
526
|
-
? layout
|
|
527
|
-
: compact(layout, compactType(this.props), cols);
|
|
528
|
-
|
|
529
|
-
this.props.onResizeStop(newLayout, oldResizeItem, l, null, e, node);
|
|
530
|
-
|
|
531
|
-
const { oldLayout } = this.state;
|
|
532
|
-
this.setState({
|
|
533
|
-
activeDrag: null,
|
|
534
|
-
layout: newLayout,
|
|
535
|
-
oldResizeItem: null,
|
|
536
|
-
oldLayout: null,
|
|
537
|
-
resizing: false
|
|
538
|
-
});
|
|
539
|
-
|
|
540
|
-
this.onLayoutMaybeChanged(newLayout, oldLayout);
|
|
541
|
-
};
|
|
542
|
-
|
|
543
|
-
/**
|
|
544
|
-
* Create a placeholder object.
|
|
545
|
-
* @return {Element} Placeholder div.
|
|
546
|
-
*/
|
|
547
|
-
placeholder(): ?ReactElement<any> {
|
|
548
|
-
const { activeDrag } = this.state;
|
|
549
|
-
if (!activeDrag) return null;
|
|
550
|
-
const {
|
|
551
|
-
width,
|
|
552
|
-
cols,
|
|
553
|
-
margin,
|
|
554
|
-
containerPadding,
|
|
555
|
-
rowHeight,
|
|
556
|
-
maxRows,
|
|
557
|
-
useCSSTransforms,
|
|
558
|
-
transformScale
|
|
559
|
-
} = this.props;
|
|
560
|
-
|
|
561
|
-
// {...this.state.activeDrag} is pretty slow, actually
|
|
562
|
-
return (
|
|
563
|
-
<GridItem
|
|
564
|
-
w={activeDrag.w}
|
|
565
|
-
h={activeDrag.h}
|
|
566
|
-
x={activeDrag.x}
|
|
567
|
-
y={activeDrag.y}
|
|
568
|
-
i={activeDrag.i}
|
|
569
|
-
className={`react-grid-placeholder ${
|
|
570
|
-
this.state.resizing ? "placeholder-resizing" : ""
|
|
571
|
-
}`}
|
|
572
|
-
containerWidth={width}
|
|
573
|
-
cols={cols}
|
|
574
|
-
margin={margin}
|
|
575
|
-
containerPadding={containerPadding || margin}
|
|
576
|
-
maxRows={maxRows}
|
|
577
|
-
rowHeight={rowHeight}
|
|
578
|
-
isDraggable={false}
|
|
579
|
-
isResizable={false}
|
|
580
|
-
isBounded={false}
|
|
581
|
-
useCSSTransforms={useCSSTransforms}
|
|
582
|
-
transformScale={transformScale}
|
|
583
|
-
>
|
|
584
|
-
<div />
|
|
585
|
-
</GridItem>
|
|
586
|
-
);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
/**
|
|
590
|
-
* Given a grid item, set its style attributes & surround in a <Draggable>.
|
|
591
|
-
* @param {Element} child React element.
|
|
592
|
-
* @return {Element} Element wrapped in draggable and properly placed.
|
|
593
|
-
*/
|
|
594
|
-
processGridItem(
|
|
595
|
-
child: ReactElement<any>,
|
|
596
|
-
isDroppingItem?: boolean
|
|
597
|
-
): ?ReactElement<any> {
|
|
598
|
-
if (!child || !child.key) return;
|
|
599
|
-
const l = getLayoutItem(this.state.layout, String(child.key));
|
|
600
|
-
if (!l) return null;
|
|
601
|
-
const {
|
|
602
|
-
width,
|
|
603
|
-
cols,
|
|
604
|
-
margin,
|
|
605
|
-
containerPadding,
|
|
606
|
-
rowHeight,
|
|
607
|
-
maxRows,
|
|
608
|
-
isDraggable,
|
|
609
|
-
isResizable,
|
|
610
|
-
isBounded,
|
|
611
|
-
useCSSTransforms,
|
|
612
|
-
transformScale,
|
|
613
|
-
draggableCancel,
|
|
614
|
-
draggableHandle,
|
|
615
|
-
resizeHandles,
|
|
616
|
-
resizeHandle
|
|
617
|
-
} = this.props;
|
|
618
|
-
const { mounted, droppingPosition } = this.state;
|
|
619
|
-
|
|
620
|
-
// Determine user manipulations possible.
|
|
621
|
-
// If an item is static, it can't be manipulated by default.
|
|
622
|
-
// Any properties defined directly on the grid item will take precedence.
|
|
623
|
-
const draggable =
|
|
624
|
-
typeof l.isDraggable === "boolean"
|
|
625
|
-
? l.isDraggable
|
|
626
|
-
: !l.static && isDraggable;
|
|
627
|
-
const resizable =
|
|
628
|
-
typeof l.isResizable === "boolean"
|
|
629
|
-
? l.isResizable
|
|
630
|
-
: !l.static && isResizable;
|
|
631
|
-
const resizeHandlesOptions = l.resizeHandles || resizeHandles;
|
|
632
|
-
|
|
633
|
-
// isBounded set on child if set on parent, and child is not explicitly false
|
|
634
|
-
const bounded = draggable && isBounded && l.isBounded !== false;
|
|
635
|
-
|
|
636
|
-
return (
|
|
637
|
-
<GridItem
|
|
638
|
-
containerWidth={width}
|
|
639
|
-
cols={cols}
|
|
640
|
-
margin={margin}
|
|
641
|
-
containerPadding={containerPadding || margin}
|
|
642
|
-
maxRows={maxRows}
|
|
643
|
-
rowHeight={rowHeight}
|
|
644
|
-
cancel={draggableCancel}
|
|
645
|
-
handle={draggableHandle}
|
|
646
|
-
onDragStop={this.onDragStop}
|
|
647
|
-
onDragStart={this.onDragStart}
|
|
648
|
-
onDrag={this.onDrag}
|
|
649
|
-
onResizeStart={this.onResizeStart}
|
|
650
|
-
onResize={this.onResize}
|
|
651
|
-
onResizeStop={this.onResizeStop}
|
|
652
|
-
isDraggable={draggable}
|
|
653
|
-
isResizable={resizable}
|
|
654
|
-
isBounded={bounded}
|
|
655
|
-
useCSSTransforms={useCSSTransforms && mounted}
|
|
656
|
-
usePercentages={!mounted}
|
|
657
|
-
transformScale={transformScale}
|
|
658
|
-
w={l.w}
|
|
659
|
-
h={l.h}
|
|
660
|
-
x={l.x}
|
|
661
|
-
y={l.y}
|
|
662
|
-
i={l.i}
|
|
663
|
-
minH={l.minH}
|
|
664
|
-
minW={l.minW}
|
|
665
|
-
maxH={l.maxH}
|
|
666
|
-
maxW={l.maxW}
|
|
667
|
-
static={l.static}
|
|
668
|
-
droppingPosition={isDroppingItem ? droppingPosition : undefined}
|
|
669
|
-
resizeHandles={resizeHandlesOptions}
|
|
670
|
-
resizeHandle={resizeHandle}
|
|
671
|
-
>
|
|
672
|
-
{child}
|
|
673
|
-
</GridItem>
|
|
674
|
-
);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
// Called while dragging an element. Part of browser native drag/drop API.
|
|
678
|
-
// Native event target might be the layout itself, or an element within the layout.
|
|
679
|
-
onDragOver: DragOverEvent => void | false = e => {
|
|
680
|
-
e.preventDefault(); // Prevent any browser native action
|
|
681
|
-
e.stopPropagation();
|
|
682
|
-
|
|
683
|
-
// we should ignore events from layout's children in Firefox
|
|
684
|
-
// to avoid unpredictable jumping of a dropping placeholder
|
|
685
|
-
// FIXME remove this hack
|
|
686
|
-
if (
|
|
687
|
-
isFirefox &&
|
|
688
|
-
// $FlowIgnore can't figure this out
|
|
689
|
-
!e.nativeEvent.target?.classList.contains(layoutClassName)
|
|
690
|
-
) {
|
|
691
|
-
return false;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
const {
|
|
695
|
-
droppingItem,
|
|
696
|
-
onDropDragOver,
|
|
697
|
-
margin,
|
|
698
|
-
cols,
|
|
699
|
-
rowHeight,
|
|
700
|
-
maxRows,
|
|
701
|
-
width,
|
|
702
|
-
containerPadding,
|
|
703
|
-
transformScale
|
|
704
|
-
} = this.props;
|
|
705
|
-
// Allow user to customize the dropping item or short-circuit the drop based on the results
|
|
706
|
-
// of the `onDragOver(e: Event)` callback.
|
|
707
|
-
const onDragOverResult = onDropDragOver?.(e);
|
|
708
|
-
if (onDragOverResult === false) {
|
|
709
|
-
if (this.state.droppingDOMNode) {
|
|
710
|
-
this.removeDroppingPlaceholder();
|
|
711
|
-
}
|
|
712
|
-
return false;
|
|
713
|
-
}
|
|
714
|
-
const finalDroppingItem = { ...droppingItem, ...onDragOverResult };
|
|
715
|
-
|
|
716
|
-
const { layout } = this.state;
|
|
717
|
-
|
|
718
|
-
// $FlowIgnore missing def
|
|
719
|
-
const gridRect = e.currentTarget.getBoundingClientRect(); // The grid's position in the viewport
|
|
720
|
-
|
|
721
|
-
// Calculate the mouse position relative to the grid
|
|
722
|
-
const layerX = e.clientX - gridRect.left;
|
|
723
|
-
const layerY = e.clientY - gridRect.top;
|
|
724
|
-
const droppingPosition = {
|
|
725
|
-
left: layerX / transformScale,
|
|
726
|
-
top: layerY / transformScale,
|
|
727
|
-
e
|
|
728
|
-
};
|
|
729
|
-
|
|
730
|
-
if (!this.state.droppingDOMNode) {
|
|
731
|
-
const positionParams: PositionParams = {
|
|
732
|
-
cols,
|
|
733
|
-
margin,
|
|
734
|
-
maxRows,
|
|
735
|
-
rowHeight,
|
|
736
|
-
containerWidth: width,
|
|
737
|
-
containerPadding: containerPadding || margin
|
|
738
|
-
};
|
|
739
|
-
|
|
740
|
-
const calculatedPosition = calcXY(
|
|
741
|
-
positionParams,
|
|
742
|
-
layerY,
|
|
743
|
-
layerX,
|
|
744
|
-
finalDroppingItem.w,
|
|
745
|
-
finalDroppingItem.h
|
|
746
|
-
);
|
|
747
|
-
|
|
748
|
-
this.setState({
|
|
749
|
-
droppingDOMNode: <div key={finalDroppingItem.i} />,
|
|
750
|
-
droppingPosition,
|
|
751
|
-
layout: [
|
|
752
|
-
...layout,
|
|
753
|
-
{
|
|
754
|
-
...finalDroppingItem,
|
|
755
|
-
x: calculatedPosition.x,
|
|
756
|
-
y: calculatedPosition.y,
|
|
757
|
-
static: false,
|
|
758
|
-
isDraggable: true
|
|
759
|
-
}
|
|
760
|
-
]
|
|
761
|
-
});
|
|
762
|
-
} else if (this.state.droppingPosition) {
|
|
763
|
-
const { left, top } = this.state.droppingPosition;
|
|
764
|
-
const shouldUpdatePosition = left != layerX || top != layerY;
|
|
765
|
-
if (shouldUpdatePosition) {
|
|
766
|
-
this.setState({ droppingPosition });
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
};
|
|
770
|
-
|
|
771
|
-
removeDroppingPlaceholder: () => void = () => {
|
|
772
|
-
const { droppingItem, cols } = this.props;
|
|
773
|
-
const { layout } = this.state;
|
|
774
|
-
|
|
775
|
-
const newLayout = compact(
|
|
776
|
-
layout.filter(l => l.i !== droppingItem.i),
|
|
777
|
-
compactType(this.props),
|
|
778
|
-
cols,
|
|
779
|
-
this.props.allowOverlap
|
|
780
|
-
);
|
|
781
|
-
|
|
782
|
-
this.setState({
|
|
783
|
-
layout: newLayout,
|
|
784
|
-
droppingDOMNode: null,
|
|
785
|
-
activeDrag: null,
|
|
786
|
-
droppingPosition: undefined
|
|
787
|
-
});
|
|
788
|
-
};
|
|
789
|
-
|
|
790
|
-
onDragLeave: EventHandler = e => {
|
|
791
|
-
e.preventDefault(); // Prevent any browser native action
|
|
792
|
-
e.stopPropagation();
|
|
793
|
-
this.dragEnterCounter--;
|
|
794
|
-
|
|
795
|
-
// onDragLeave can be triggered on each layout's child.
|
|
796
|
-
// But we know that count of dragEnter and dragLeave events
|
|
797
|
-
// will be balanced after leaving the layout's container
|
|
798
|
-
// so we can increase and decrease count of dragEnter and
|
|
799
|
-
// when it'll be equal to 0 we'll remove the placeholder
|
|
800
|
-
if (this.dragEnterCounter === 0) {
|
|
801
|
-
this.removeDroppingPlaceholder();
|
|
802
|
-
}
|
|
803
|
-
};
|
|
804
|
-
|
|
805
|
-
onDragEnter: EventHandler = e => {
|
|
806
|
-
e.preventDefault(); // Prevent any browser native action
|
|
807
|
-
e.stopPropagation();
|
|
808
|
-
this.dragEnterCounter++;
|
|
809
|
-
};
|
|
810
|
-
|
|
811
|
-
onDrop: EventHandler = (e: Event) => {
|
|
812
|
-
e.preventDefault(); // Prevent any browser native action
|
|
813
|
-
e.stopPropagation();
|
|
814
|
-
const { droppingItem } = this.props;
|
|
815
|
-
const { layout } = this.state;
|
|
816
|
-
const item = layout.find(l => l.i === droppingItem.i);
|
|
817
|
-
|
|
818
|
-
// reset dragEnter counter on drop
|
|
819
|
-
this.dragEnterCounter = 0;
|
|
820
|
-
|
|
821
|
-
this.removeDroppingPlaceholder();
|
|
822
|
-
|
|
823
|
-
this.props.onDrop(layout, item, e);
|
|
824
|
-
};
|
|
825
|
-
|
|
826
|
-
render(): React.Element<"div"> {
|
|
827
|
-
const { className, style, isDroppable, innerRef } = this.props;
|
|
828
|
-
|
|
829
|
-
const mergedClassName = clsx(layoutClassName, className);
|
|
830
|
-
const mergedStyle = {
|
|
831
|
-
height: this.containerHeight(),
|
|
832
|
-
...style
|
|
833
|
-
};
|
|
834
|
-
|
|
835
|
-
return (
|
|
836
|
-
<div
|
|
837
|
-
ref={innerRef}
|
|
838
|
-
className={mergedClassName}
|
|
839
|
-
style={mergedStyle}
|
|
840
|
-
onDrop={isDroppable ? this.onDrop : noop}
|
|
841
|
-
onDragLeave={isDroppable ? this.onDragLeave : noop}
|
|
842
|
-
onDragEnter={isDroppable ? this.onDragEnter : noop}
|
|
843
|
-
onDragOver={isDroppable ? this.onDragOver : noop}
|
|
844
|
-
>
|
|
845
|
-
{React.Children.map(this.props.children, child =>
|
|
846
|
-
this.processGridItem(child)
|
|
847
|
-
)}
|
|
848
|
-
{isDroppable &&
|
|
849
|
-
this.state.droppingDOMNode &&
|
|
850
|
-
this.processGridItem(this.state.droppingDOMNode, true)}
|
|
851
|
-
{this.placeholder()}
|
|
852
|
-
</div>
|
|
853
|
-
);
|
|
854
|
-
}
|
|
855
|
-
}
|