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.
Files changed (94) hide show
  1. package/README.md +1075 -432
  2. package/css/styles.css +6 -4
  3. package/dist/ResponsiveGridLayout-CH4s0tKj.d.ts +124 -0
  4. package/dist/ResponsiveGridLayout-D6lFRE3f.d.mts +124 -0
  5. package/dist/calculate-CwYDW8na.d.mts +168 -0
  6. package/dist/calculate-mgLpNJ5O.d.ts +168 -0
  7. package/dist/chunk-2KUHNJXF.mjs +90 -0
  8. package/dist/chunk-2KUHNJXF.mjs.map +1 -0
  9. package/dist/chunk-3WO4SAYB.js +868 -0
  10. package/dist/chunk-3WO4SAYB.js.map +1 -0
  11. package/dist/chunk-4HNUMWQK.mjs +822 -0
  12. package/dist/chunk-4HNUMWQK.mjs.map +1 -0
  13. package/dist/chunk-BFTKGAP3.js +1309 -0
  14. package/dist/chunk-BFTKGAP3.js.map +1 -0
  15. package/dist/chunk-F6NQPYKT.js +98 -0
  16. package/dist/chunk-F6NQPYKT.js.map +1 -0
  17. package/dist/chunk-H5KMDLY3.js +434 -0
  18. package/dist/chunk-H5KMDLY3.js.map +1 -0
  19. package/dist/chunk-PBQSHIID.js +4 -0
  20. package/dist/chunk-PBQSHIID.js.map +1 -0
  21. package/dist/chunk-R35HZZTA.mjs +1300 -0
  22. package/dist/chunk-R35HZZTA.mjs.map +1 -0
  23. package/dist/chunk-ZCXE6SR5.mjs +428 -0
  24. package/dist/chunk-ZCXE6SR5.mjs.map +1 -0
  25. package/dist/chunk-ZWN22PS2.mjs +3 -0
  26. package/dist/chunk-ZWN22PS2.mjs.map +1 -0
  27. package/dist/core.d.mts +33 -0
  28. package/dist/core.d.ts +33 -0
  29. package/dist/core.js +218 -0
  30. package/dist/core.js.map +1 -0
  31. package/dist/core.mjs +5 -0
  32. package/dist/core.mjs.map +1 -0
  33. package/dist/extras.d.mts +78 -0
  34. package/dist/extras.d.ts +78 -0
  35. package/dist/extras.js +91 -0
  36. package/dist/extras.js.map +1 -0
  37. package/dist/extras.mjs +89 -0
  38. package/dist/extras.mjs.map +1 -0
  39. package/dist/index.d.mts +7 -0
  40. package/dist/index.d.ts +7 -0
  41. package/dist/index.js +154 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/index.mjs +7 -0
  44. package/dist/index.mjs.map +1 -0
  45. package/dist/legacy.d.mts +163 -0
  46. package/dist/legacy.d.ts +163 -0
  47. package/dist/legacy.js +319 -0
  48. package/dist/legacy.js.map +1 -0
  49. package/dist/legacy.mjs +307 -0
  50. package/dist/legacy.mjs.map +1 -0
  51. package/dist/position-BmN1z36J.d.mts +319 -0
  52. package/dist/position-Dk2b4ZMS.d.ts +319 -0
  53. package/dist/react.d.mts +351 -0
  54. package/dist/react.d.ts +351 -0
  55. package/dist/react.js +96 -0
  56. package/dist/react.js.map +1 -0
  57. package/dist/react.mjs +7 -0
  58. package/dist/react.mjs.map +1 -0
  59. package/dist/responsive-C4L1ESlm.d.ts +145 -0
  60. package/dist/responsive-CJxefsYw.d.mts +145 -0
  61. package/dist/types-Cxf4nHNr.d.mts +375 -0
  62. package/dist/types-Cxf4nHNr.d.ts +375 -0
  63. package/index-dev.js +8 -0
  64. package/package.json +132 -39
  65. package/.babelrc.js +0 -22
  66. package/.browserslistrc +0 -3
  67. package/.eslintignore +0 -4
  68. package/.flowconfig +0 -20
  69. package/.prettierignore +0 -4
  70. package/.prettierrc +0 -17
  71. package/CHANGELOG.md +0 -985
  72. package/build/GridItem.js +0 -640
  73. package/build/ReactGridLayout.js +0 -744
  74. package/build/ReactGridLayoutPropTypes.js +0 -210
  75. package/build/ResponsiveReactGridLayout.js +0 -294
  76. package/build/calculateUtils.js +0 -165
  77. package/build/components/WidthProvider.js +0 -111
  78. package/build/fastRGLPropsEqual.js +0 -5
  79. package/build/responsiveUtils.js +0 -101
  80. package/build/utils.js +0 -834
  81. package/dist/react-grid-layout.min.js +0 -2
  82. package/dist/react-grid-layout.min.js.map +0 -1
  83. package/index.js.flow +0 -8
  84. package/ip_fetcher +0 -0
  85. package/ip_fetcher.c +0 -47
  86. package/lib/GridItem.jsx +0 -689
  87. package/lib/ReactGridLayout.jsx +0 -855
  88. package/lib/ReactGridLayoutPropTypes.js +0 -241
  89. package/lib/ResponsiveReactGridLayout.jsx +0 -349
  90. package/lib/calculateUtils.js +0 -169
  91. package/lib/components/WidthProvider.jsx +0 -110
  92. package/lib/fastRGLPropsEqual.js +0 -46
  93. package/lib/responsiveUtils.js +0 -118
  94. package/lib/utils.js +0 -979
@@ -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
- }