react-grid-layout 0.16.4 → 0.17.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/css/styles.css CHANGED
@@ -20,6 +20,10 @@
20
20
  will-change: transform;
21
21
  }
22
22
 
23
+ .react-grid-item.dropping {
24
+ visibility: hidden;
25
+ }
26
+
23
27
  .react-grid-item.react-grid-placeholder {
24
28
  background: red;
25
29
  opacity: 0.2;
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
- module.exports = require('./build/ReactGridLayout').default;
2
- module.exports.utils = require('./build/utils');
3
- module.exports.Responsive = require('./build/ResponsiveReactGridLayout').default;
4
- module.exports.Responsive.utils = require('./build/responsiveUtils');
5
- module.exports.WidthProvider = require('./build/components/WidthProvider').default;
1
+ module.exports = require("./build/ReactGridLayout").default;
2
+ module.exports.utils = require("./build/utils");
3
+ module.exports.Responsive = require("./build/ResponsiveReactGridLayout").default;
4
+ module.exports.Responsive.utils = require("./build/responsiveUtils");
5
+ module.exports.WidthProvider = require("./build/components/WidthProvider").default;
package/index.js.flow CHANGED
@@ -1,10 +1,8 @@
1
1
  // @flow
2
2
 
3
- import * as utils from './build/utils';
4
- export { default } from './build/ReactGridLayout';
5
- export { default as Responsive } from './build/ResponsiveReactGridLayout';
6
- export { default as WidthProvider } from './build/components/WidthProvider';
3
+ import * as utils from "./lib/utils";
4
+ export { default } from "./lib/ReactGridLayout";
5
+ export { default as Responsive } from "./lib/ResponsiveReactGridLayout";
6
+ export { default as WidthProvider } from "./lib/components/WidthProvider";
7
7
 
8
- export {
9
- utils
10
- };
8
+ export { utils };
@@ -1,3 +1,4 @@
1
+ // @flow
1
2
  // flow-typed signature: 3fba12a77525f37b0492c8dab3e04f0e
2
3
  // flow-typed version: 94e9f7e0a4/classnames_v2.x.x/flow_>=v0.28.x
3
4
 
@@ -1,5 +1,6 @@
1
1
  // @flow
2
2
  import React from "react";
3
+ import ReactDOM from "react-dom";
3
4
  import PropTypes from "prop-types";
4
5
  import { DraggableCore } from "react-draggable";
5
6
  import { Resizable } from "react-resizable";
@@ -11,6 +12,7 @@ import type {
11
12
  ReactDraggableCallbackData,
12
13
  GridDragEvent,
13
14
  GridResizeEvent,
15
+ DroppingPosition,
14
16
  Position
15
17
  } from "./utils";
16
18
 
@@ -41,6 +43,8 @@ type Props = {
41
43
  static?: boolean,
42
44
  useCSSTransforms?: boolean,
43
45
  usePercentages?: boolean,
46
+ transformScale: number,
47
+ droppingPosition?: DroppingPosition,
44
48
 
45
49
  className: string,
46
50
  style?: Object,
@@ -136,13 +140,20 @@ export default class GridItem extends React.Component<Props, State> {
136
140
 
137
141
  // Use CSS transforms instead of top/left
138
142
  useCSSTransforms: PropTypes.bool.isRequired,
143
+ transformScale: PropTypes.number,
139
144
 
140
145
  // Others
141
146
  className: PropTypes.string,
142
147
  // Selector for draggable handle
143
148
  handle: PropTypes.string,
144
149
  // Selector for draggable cancel (see react-draggable)
145
- cancel: PropTypes.string
150
+ cancel: PropTypes.string,
151
+ // Current position of a dropping element
152
+ droppingPosition: PropTypes.shape({
153
+ e: PropTypes.object.isRequired,
154
+ x: PropTypes.number.isRequired,
155
+ y: PropTypes.number.isRequired
156
+ })
146
157
  };
147
158
 
148
159
  static defaultProps = {
@@ -152,7 +163,8 @@ export default class GridItem extends React.Component<Props, State> {
152
163
  minH: 1,
153
164
  minW: 1,
154
165
  maxH: Infinity,
155
- maxW: Infinity
166
+ maxW: Infinity,
167
+ transformScale: 1
156
168
  };
157
169
 
158
170
  state: State = {
@@ -161,6 +173,49 @@ export default class GridItem extends React.Component<Props, State> {
161
173
  className: ""
162
174
  };
163
175
 
176
+ currentNode: HTMLElement;
177
+
178
+ componentDidUpdate(prevProps: Props) {
179
+ if (this.props.droppingPosition && prevProps.droppingPosition) {
180
+ this.moveDroppingItem(prevProps);
181
+ }
182
+ }
183
+
184
+ moveDroppingItem(prevProps: Props) {
185
+ const { droppingPosition } = this.props;
186
+ const { dragging } = this.state;
187
+
188
+ if (!droppingPosition || !prevProps.droppingPosition) {
189
+ return;
190
+ }
191
+
192
+ if (!this.currentNode) {
193
+ // eslint-disable-next-line react/no-find-dom-node
194
+ this.currentNode = ((ReactDOM.findDOMNode(this): any): HTMLElement);
195
+ }
196
+
197
+ const shouldDrag =
198
+ (dragging && droppingPosition.x !== prevProps.droppingPosition.x) ||
199
+ droppingPosition.y !== prevProps.droppingPosition.y;
200
+
201
+ if (!dragging) {
202
+ this.onDragStart(droppingPosition.e, {
203
+ node: this.currentNode,
204
+ deltaX: droppingPosition.x,
205
+ deltaY: droppingPosition.y
206
+ });
207
+ } else if (shouldDrag) {
208
+ const deltaX = droppingPosition.x - dragging.left;
209
+ const deltaY = droppingPosition.y - dragging.top;
210
+
211
+ this.onDrag(droppingPosition.e, {
212
+ node: this.currentNode,
213
+ deltaX,
214
+ deltaY
215
+ });
216
+ }
217
+ }
218
+
164
219
  // Helper for generating column width
165
220
  calcColWidth(): number {
166
221
  const { margin, containerPadding, containerWidth, cols } = this.props;
@@ -187,32 +242,38 @@ export default class GridItem extends React.Component<Props, State> {
187
242
  ): Position {
188
243
  const { margin, containerPadding, rowHeight } = this.props;
189
244
  const colWidth = this.calcColWidth();
245
+ const out = {};
190
246
 
191
- const out = {
192
- left: Math.round((colWidth + margin[0]) * x + containerPadding[0]),
193
- top: Math.round((rowHeight + margin[1]) * y + containerPadding[1]),
247
+ // If resizing, use the exact width and height as returned from resizing callbacks.
248
+ if (state && state.resizing) {
249
+ out.width = Math.round(state.resizing.width);
250
+ out.height = Math.round(state.resizing.height);
251
+ }
252
+ // Otherwise, calculate from grid units.
253
+ else {
194
254
  // 0 * Infinity === NaN, which causes problems with resize constraints;
195
255
  // Fix this if it occurs.
196
256
  // Note we do it here rather than later because Math.round(Infinity) causes deopt
197
- width:
257
+ out.width =
198
258
  w === Infinity
199
259
  ? w
200
- : Math.round(colWidth * w + Math.max(0, w - 1) * margin[0]),
201
- height:
260
+ : Math.round(colWidth * w + Math.max(0, w - 1) * margin[0]);
261
+ out.height =
202
262
  h === Infinity
203
263
  ? h
204
- : Math.round(rowHeight * h + Math.max(0, h - 1) * margin[1])
205
- };
206
-
207
- if (state && state.resizing) {
208
- out.width = Math.round(state.resizing.width);
209
- out.height = Math.round(state.resizing.height);
264
+ : Math.round(rowHeight * h + Math.max(0, h - 1) * margin[1]);
210
265
  }
211
266
 
267
+ // If dragging, use the exact width and height as returned from dragging callbacks.
212
268
  if (state && state.dragging) {
213
269
  out.top = Math.round(state.dragging.top);
214
270
  out.left = Math.round(state.dragging.left);
215
271
  }
272
+ // Otherwise, calculate from grid units.
273
+ else {
274
+ out.top = Math.round((rowHeight + margin[1]) * y + containerPadding[1]);
275
+ out.left = Math.round((colWidth + margin[0]) * x + containerPadding[0]);
276
+ }
216
277
 
217
278
  return out;
218
279
  }
@@ -311,14 +372,15 @@ export default class GridItem extends React.Component<Props, State> {
311
372
  mixinDraggable(child: ReactElement<any>): ReactElement<any> {
312
373
  return (
313
374
  <DraggableCore
314
- onStart={this.onDragHandler("onDragStart")}
315
- onDrag={this.onDragHandler("onDrag")}
316
- onStop={this.onDragHandler("onDragStop")}
375
+ onStart={this.onDragStart}
376
+ onDrag={this.onDrag}
377
+ onStop={this.onDragStop}
317
378
  handle={this.props.handle}
318
379
  cancel={
319
380
  ".react-resizable-handle" +
320
381
  (this.props.cancel ? "," + this.props.cancel : "")
321
382
  }
383
+ scale={this.props.transformScale}
322
384
  >
323
385
  {child}
324
386
  </DraggableCore>
@@ -354,9 +416,9 @@ export default class GridItem extends React.Component<Props, State> {
354
416
  height={position.height}
355
417
  minConstraints={minConstraints}
356
418
  maxConstraints={maxConstraints}
357
- onResizeStop={this.onResizeHandler("onResizeStop")}
358
- onResizeStart={this.onResizeHandler("onResizeStart")}
359
- onResize={this.onResizeHandler("onResize")}
419
+ onResizeStop={this.onResizeStop}
420
+ onResizeStart={this.onResizeStart}
421
+ onResize={this.onResize}
360
422
  >
361
423
  {child}
362
424
  </Resizable>
@@ -364,60 +426,131 @@ export default class GridItem extends React.Component<Props, State> {
364
426
  }
365
427
 
366
428
  /**
367
- * Wrapper around drag events to provide more useful data.
368
- * All drag events call the function with the given handler name,
369
- * with the signature (index, x, y).
370
- *
371
- * @param {String} handlerName Handler name to wrap.
372
- * @return {Function} Handler function.
429
+ * onDragStart event handler
430
+ * @param {Event} e event data
431
+ * @param {Object} callbackData an object with node, delta and position information
373
432
  */
374
- onDragHandler(handlerName: string) {
375
- return (e: Event, { node, deltaX, deltaY }: ReactDraggableCallbackData) => {
376
- const handler = this.props[handlerName];
377
- if (!handler) return;
378
-
379
- const newPosition: PartialPosition = { top: 0, left: 0 };
380
-
381
- // Get new XY
382
- switch (handlerName) {
383
- case "onDragStart": {
384
- // TODO: this wont work on nested parents
385
- const { offsetParent } = node;
386
- if (!offsetParent) return;
387
- const parentRect = offsetParent.getBoundingClientRect();
388
- const clientRect = node.getBoundingClientRect();
389
- newPosition.left =
390
- clientRect.left - parentRect.left + offsetParent.scrollLeft;
391
- newPosition.top =
392
- clientRect.top - parentRect.top + offsetParent.scrollTop;
393
- this.setState({ dragging: newPosition });
394
- break;
395
- }
396
- case "onDrag":
397
- if (!this.state.dragging)
398
- throw new Error("onDrag called before onDragStart.");
399
- newPosition.left = this.state.dragging.left + deltaX;
400
- newPosition.top = this.state.dragging.top + deltaY;
401
- this.setState({ dragging: newPosition });
402
- break;
403
- case "onDragStop":
404
- if (!this.state.dragging)
405
- throw new Error("onDragEnd called before onDragStart.");
406
- newPosition.left = this.state.dragging.left;
407
- newPosition.top = this.state.dragging.top;
408
- this.setState({ dragging: null });
409
- break;
410
- default:
411
- throw new Error(
412
- "onDragHandler called with unrecognized handlerName: " + handlerName
413
- );
414
- }
433
+ onDragStart = (e: Event, { node }: ReactDraggableCallbackData) => {
434
+ if (!this.props.onDragStart) return;
435
+
436
+ const newPosition: PartialPosition = { top: 0, left: 0 };
437
+
438
+ // TODO: this wont work on nested parents
439
+ const { offsetParent } = node;
440
+ if (!offsetParent) return;
441
+ const parentRect = offsetParent.getBoundingClientRect();
442
+ const clientRect = node.getBoundingClientRect();
443
+ const cLeft = clientRect.left / this.props.transformScale;
444
+ const pLeft = parentRect.left / this.props.transformScale;
445
+ const cTop = clientRect.top / this.props.transformScale;
446
+ const pTop = parentRect.top / this.props.transformScale;
447
+ newPosition.left = cLeft - pLeft + offsetParent.scrollLeft;
448
+ newPosition.top = cTop - pTop + offsetParent.scrollTop;
449
+ this.setState({ dragging: newPosition });
450
+
451
+ const { x, y } = this.calcXY(newPosition.top, newPosition.left);
415
452
 
416
- const { x, y } = this.calcXY(newPosition.top, newPosition.left);
453
+ return (
454
+ this.props.onDragStart &&
455
+ this.props.onDragStart.call(this, this.props.i, x, y, {
456
+ e,
457
+ node,
458
+ newPosition
459
+ })
460
+ );
461
+ };
417
462
 
418
- return handler.call(this, this.props.i, x, y, { e, node, newPosition });
419
- };
420
- }
463
+ /**
464
+ * onDrag event handler
465
+ * @param {Event} e event data
466
+ * @param {Object} callbackData an object with node, delta and position information
467
+ */
468
+ onDrag = (e: Event, { node, deltaX, deltaY }: ReactDraggableCallbackData) => {
469
+ if (!this.props.onDrag) return;
470
+
471
+ const newPosition: PartialPosition = { top: 0, left: 0 };
472
+
473
+ if (!this.state.dragging)
474
+ throw new Error("onDrag called before onDragStart.");
475
+ newPosition.left = this.state.dragging.left + deltaX;
476
+ newPosition.top = this.state.dragging.top + deltaY;
477
+ this.setState({ dragging: newPosition });
478
+
479
+ const { x, y } = this.calcXY(newPosition.top, newPosition.left);
480
+
481
+ return (
482
+ this.props.onDrag &&
483
+ this.props.onDrag.call(this, this.props.i, x, y, {
484
+ e,
485
+ node,
486
+ newPosition
487
+ })
488
+ );
489
+ };
490
+
491
+ /**
492
+ * onDragStop event handler
493
+ * @param {Event} e event data
494
+ * @param {Object} callbackData an object with node, delta and position information
495
+ */
496
+ onDragStop = (e: Event, { node }: ReactDraggableCallbackData) => {
497
+ if (!this.props.onDragStop) return;
498
+
499
+ const newPosition: PartialPosition = { top: 0, left: 0 };
500
+
501
+ if (!this.state.dragging)
502
+ throw new Error("onDragEnd called before onDragStart.");
503
+ newPosition.left = this.state.dragging.left;
504
+ newPosition.top = this.state.dragging.top;
505
+ this.setState({ dragging: null });
506
+
507
+ const { x, y } = this.calcXY(newPosition.top, newPosition.left);
508
+
509
+ return (
510
+ this.props.onDragStop &&
511
+ this.props.onDragStop.call(this, this.props.i, x, y, {
512
+ e,
513
+ node,
514
+ newPosition
515
+ })
516
+ );
517
+ };
518
+
519
+ /**
520
+ * onResizeStop event handler
521
+ * @param {Event} e event data
522
+ * @param {Object} callbackData an object with node and size information
523
+ */
524
+ onResizeStop = (
525
+ e: Event,
526
+ callbackData: { node: HTMLElement, size: Position }
527
+ ) => {
528
+ this.onResizeHandler(e, callbackData, "onResizeStop");
529
+ };
530
+
531
+ /**
532
+ * onResizeStart event handler
533
+ * @param {Event} e event data
534
+ * @param {Object} callbackData an object with node and size information
535
+ */
536
+ onResizeStart = (
537
+ e: Event,
538
+ callbackData: { node: HTMLElement, size: Position }
539
+ ) => {
540
+ this.onResizeHandler(e, callbackData, "onResizeStart");
541
+ };
542
+
543
+ /**
544
+ * onResize event handler
545
+ * @param {Event} e event data
546
+ * @param {Object} callbackData an object with node and size information
547
+ */
548
+ onResize = (
549
+ e: Event,
550
+ callbackData: { node: HTMLElement, size: Position }
551
+ ) => {
552
+ this.onResizeHandler(e, callbackData, "onResize");
553
+ };
421
554
 
422
555
  /**
423
556
  * Wrapper around drag events to provide more useful data.
@@ -427,31 +560,30 @@ export default class GridItem extends React.Component<Props, State> {
427
560
  * @param {String} handlerName Handler name to wrap.
428
561
  * @return {Function} Handler function.
429
562
  */
430
- onResizeHandler(handlerName: string) {
431
- return (
432
- e: Event,
433
- { node, size }: { node: HTMLElement, size: Position }
434
- ) => {
435
- const handler = this.props[handlerName];
436
- if (!handler) return;
437
- const { cols, x, i, maxW, minW, maxH, minH } = this.props;
438
-
439
- // Get new XY
440
- let { w, h } = this.calcWH(size);
441
-
442
- // Cap w at numCols
443
- w = Math.min(w, cols - x);
444
- // Ensure w is at least 1
445
- w = Math.max(w, 1);
446
-
447
- // Min/max capping
448
- w = Math.max(Math.min(w, maxW), minW);
449
- h = Math.max(Math.min(h, maxH), minH);
450
-
451
- this.setState({ resizing: handlerName === "onResizeStop" ? null : size });
452
-
453
- handler.call(this, i, w, h, { e, node, size });
454
- };
563
+ onResizeHandler(
564
+ e: Event,
565
+ { node, size }: { node: HTMLElement, size: Position },
566
+ handlerName: string
567
+ ) {
568
+ const handler = this.props[handlerName];
569
+ if (!handler) return;
570
+ const { cols, x, i, maxW, minW, maxH, minH } = this.props;
571
+
572
+ // Get new XY
573
+ let { w, h } = this.calcWH(size);
574
+
575
+ // Cap w at numCols
576
+ w = Math.min(w, cols - x);
577
+ // Ensure w is at least 1
578
+ w = Math.max(w, 1);
579
+
580
+ // Min/max capping
581
+ w = Math.max(Math.min(w, maxW), minW);
582
+ h = Math.max(Math.min(h, maxH), minH);
583
+
584
+ this.setState({ resizing: handlerName === "onResizeStop" ? null : size });
585
+
586
+ handler.call(this, i, w, h, { e, node, size });
455
587
  }
456
588
 
457
589
  render(): ReactNode {
@@ -462,6 +594,7 @@ export default class GridItem extends React.Component<Props, State> {
462
594
  h,
463
595
  isDraggable,
464
596
  isResizable,
597
+ droppingPosition,
465
598
  useCSSTransforms
466
599
  } = this.props;
467
600
 
@@ -479,6 +612,7 @@ export default class GridItem extends React.Component<Props, State> {
479
612
  resizing: Boolean(this.state.resizing),
480
613
  "react-draggable": isDraggable,
481
614
  "react-draggable-dragging": Boolean(this.state.dragging),
615
+ dropping: Boolean(droppingPosition),
482
616
  cssTransforms: useCSSTransforms
483
617
  }
484
618
  ),