react-grid-layout
Advanced tools
Comparing version 0.17.1 to 0.18.0
@@ -1,9 +0,9 @@ | ||
'use strict'; | ||
"use strict"; | ||
module.exports = { | ||
"presets": [ | ||
presets: [ | ||
[ | ||
"@babel/preset-env", | ||
{ | ||
targets: "> 0.25%, not dead", | ||
targets: "> 0.25%, not dead" | ||
} | ||
@@ -14,13 +14,7 @@ ], | ||
], | ||
"plugins": [ | ||
plugins: [ | ||
"@babel/plugin-transform-flow-comments", | ||
"@babel/plugin-proposal-class-properties", | ||
], | ||
"env": { | ||
"test": { | ||
"plugins": [ | ||
"espower" | ||
] | ||
} | ||
} | ||
} | ||
"babel-plugin-preval" | ||
] | ||
}; |
@@ -20,2 +20,4 @@ "use strict"; | ||
var _calculateUtils = require("./calculateUtils"); | ||
var _classnames = _interopRequireDefault(require("classnames")); | ||
@@ -29,3 +31,3 @@ | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
@@ -106,5 +108,5 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var _this$calcXY = _this.calcXY(newPosition.top, newPosition.left), | ||
x = _this$calcXY.x, | ||
y = _this$calcXY.y; | ||
var _calcXY = (0, _calculateUtils.calcXY)(_this.getPositionParams(), newPosition.top, newPosition.left, _this.props.w, _this.props.h), | ||
x = _calcXY.x, | ||
y = _calcXY.y; | ||
@@ -124,3 +126,8 @@ return _this.props.onDragStart && _this.props.onDragStart.call(_assertThisInitialized(_this), _this.props.i, x, y, { | ||
deltaY = _ref2.deltaY; | ||
if (!_this.props.onDrag) return; | ||
var _this$props = _this.props, | ||
onDrag = _this$props.onDrag, | ||
transformScale = _this$props.transformScale; | ||
if (!onDrag) return; | ||
deltaX /= transformScale; | ||
deltaY /= transformScale; | ||
var newPosition | ||
@@ -140,7 +147,7 @@ /*: PartialPosition*/ | ||
var _this$calcXY2 = _this.calcXY(newPosition.top, newPosition.left), | ||
x = _this$calcXY2.x, | ||
y = _this$calcXY2.y; | ||
var _calcXY2 = (0, _calculateUtils.calcXY)(_this.getPositionParams(), newPosition.top, newPosition.left, _this.props.w, _this.props.h), | ||
x = _calcXY2.x, | ||
y = _calcXY2.y; | ||
return _this.props.onDrag && _this.props.onDrag.call(_assertThisInitialized(_this), _this.props.i, x, y, { | ||
return onDrag && onDrag.call(_assertThisInitialized(_this), _this.props.i, x, y, { | ||
e: e, | ||
@@ -171,5 +178,5 @@ node: node, | ||
var _this$calcXY3 = _this.calcXY(newPosition.top, newPosition.left), | ||
x = _this$calcXY3.x, | ||
y = _this$calcXY3.y; | ||
var _calcXY3 = (0, _calculateUtils.calcXY)(_this.getPositionParams(), newPosition.top, newPosition.left, _this.props.w, _this.props.h), | ||
x = _calcXY3.x, | ||
y = _calcXY3.y; | ||
@@ -211,2 +218,22 @@ return _this.props.onDragStop && _this.props.onDragStop.call(_assertThisInitialized(_this), _this.props.i, x, y, { | ||
_createClass(GridItem, [{ | ||
key: "shouldComponentUpdate", | ||
value: function shouldComponentUpdate(nextProps | ||
/*: Props*/ | ||
, nextState | ||
/*: State*/ | ||
) { | ||
var _this$props2 = this.props, | ||
x = _this$props2.x, | ||
y = _this$props2.y, | ||
w = _this$props2.w, | ||
h = _this$props2.h; | ||
var oldPosition = (0, _calculateUtils.calcGridItemPosition)(this.getPositionParams(this.props), x, y, w, h, this.state); | ||
x = nextProps.x; | ||
y = nextProps.y; | ||
w = nextProps.w; | ||
h = nextProps.h; | ||
var newPosition = (0, _calculateUtils.calcGridItemPosition)(this.getPositionParams(nextProps), x, y, w, h, nextState); | ||
return !(0, _utils.fastPositionEqual)(oldPosition, newPosition) || this.props.useCSSTransforms !== nextProps.useCSSTransforms; | ||
} | ||
}, { | ||
key: "componentDidUpdate", | ||
@@ -216,6 +243,6 @@ value: function componentDidUpdate(prevProps | ||
) { | ||
if (this.props.droppingPosition && prevProps.droppingPosition) { | ||
this.moveDroppingItem(prevProps); | ||
} | ||
} | ||
this.moveDroppingItem(prevProps); | ||
} // When a droppingPosition is present, this means we should fire a move event, as if we had moved | ||
// this element by `x, y` pixels. | ||
}, { | ||
@@ -227,5 +254,6 @@ key: "moveDroppingItem", | ||
var droppingPosition = this.props.droppingPosition; | ||
var prevDroppingPosition = prevProps.droppingPosition; | ||
var dragging = this.state.dragging; | ||
if (!droppingPosition || !prevProps.droppingPosition) { | ||
if (!droppingPosition || !prevDroppingPosition) { | ||
return; | ||
@@ -243,3 +271,3 @@ } | ||
var shouldDrag = dragging && droppingPosition.x !== prevProps.droppingPosition.x || droppingPosition.y !== prevProps.droppingPosition.y; | ||
var shouldDrag = dragging && droppingPosition.left !== prevDroppingPosition.left || droppingPosition.top !== prevDroppingPosition.top; | ||
@@ -249,8 +277,8 @@ if (!dragging) { | ||
node: this.currentNode, | ||
deltaX: droppingPosition.x, | ||
deltaY: droppingPosition.y | ||
deltaX: droppingPosition.left, | ||
deltaY: droppingPosition.top | ||
}); | ||
} else if (shouldDrag) { | ||
var deltaX = droppingPosition.x - dragging.left; | ||
var deltaY = droppingPosition.y - dragging.top; | ||
var deltaX = droppingPosition.left - dragging.left; | ||
var deltaY = droppingPosition.top - dragging.top; | ||
this.onDrag(droppingPosition.e, { | ||
@@ -262,149 +290,21 @@ node: this.currentNode, | ||
} | ||
} // Helper for generating column width | ||
}, { | ||
key: "calcColWidth", | ||
value: function calcColWidth() | ||
/*: number*/ | ||
{ | ||
var _this$props = this.props, | ||
margin = _this$props.margin, | ||
containerPadding = _this$props.containerPadding, | ||
containerWidth = _this$props.containerWidth, | ||
cols = _this$props.cols; | ||
return (containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / cols; | ||
} | ||
/** | ||
* Return position on the page given an x, y, w, h. | ||
* left, top, width, height are all in pixels. | ||
* @param {Number} x X coordinate in grid units. | ||
* @param {Number} y Y coordinate in grid units. | ||
* @param {Number} w W coordinate in grid units. | ||
* @param {Number} h H coordinate in grid units. | ||
* @return {Object} Object containing coords. | ||
*/ | ||
}, { | ||
key: "calcPosition", | ||
value: function calcPosition(x | ||
/*: number*/ | ||
, y | ||
/*: number*/ | ||
, w | ||
/*: number*/ | ||
, h | ||
/*: number*/ | ||
, state | ||
/*: ?Object*/ | ||
) | ||
/*: Position*/ | ||
key: "getPositionParams", | ||
value: function getPositionParams() | ||
/*: PositionParams*/ | ||
{ | ||
var _this$props2 = this.props, | ||
margin = _this$props2.margin, | ||
containerPadding = _this$props2.containerPadding, | ||
rowHeight = _this$props2.rowHeight; | ||
var colWidth = this.calcColWidth(); | ||
var out = {}; // If resizing, use the exact width and height as returned from resizing callbacks. | ||
if (state && state.resizing) { | ||
out.width = Math.round(state.resizing.width); | ||
out.height = Math.round(state.resizing.height); | ||
} // Otherwise, calculate from grid units. | ||
else { | ||
// 0 * Infinity === NaN, which causes problems with resize constraints; | ||
// Fix this if it occurs. | ||
// Note we do it here rather than later because Math.round(Infinity) causes deopt | ||
out.width = w === Infinity ? w : Math.round(colWidth * w + Math.max(0, w - 1) * margin[0]); | ||
out.height = h === Infinity ? h : Math.round(rowHeight * h + Math.max(0, h - 1) * margin[1]); | ||
} // If dragging, use the exact width and height as returned from dragging callbacks. | ||
if (state && state.dragging) { | ||
out.top = Math.round(state.dragging.top); | ||
out.left = Math.round(state.dragging.left); | ||
} // Otherwise, calculate from grid units. | ||
else { | ||
out.top = Math.round((rowHeight + margin[1]) * y + containerPadding[1]); | ||
out.left = Math.round((colWidth + margin[0]) * x + containerPadding[0]); | ||
} | ||
return out; | ||
} | ||
/** | ||
* Translate x and y coordinates from pixels to grid units. | ||
* @param {Number} top Top position (relative to parent) in pixels. | ||
* @param {Number} left Left position (relative to parent) in pixels. | ||
* @return {Object} x and y in grid units. | ||
*/ | ||
}, { | ||
key: "calcXY", | ||
value: function calcXY(top | ||
/*: number*/ | ||
, left | ||
/*: number*/ | ||
) | ||
/*: { x: number, y: number }*/ | ||
{ | ||
var _this$props3 = this.props, | ||
margin = _this$props3.margin, | ||
cols = _this$props3.cols, | ||
rowHeight = _this$props3.rowHeight, | ||
w = _this$props3.w, | ||
h = _this$props3.h, | ||
maxRows = _this$props3.maxRows; | ||
var colWidth = this.calcColWidth(); // left = colWidth * x + margin * (x + 1) | ||
// l = cx + m(x+1) | ||
// l = cx + mx + m | ||
// l - m = cx + mx | ||
// l - m = x(c + m) | ||
// (l - m) / (c + m) = x | ||
// x = (left - margin) / (coldWidth + margin) | ||
var x = Math.round((left - margin[0]) / (colWidth + margin[0])); | ||
var y = Math.round((top - margin[1]) / (rowHeight + margin[1])); // Capping | ||
x = Math.max(Math.min(x, cols - w), 0); | ||
y = Math.max(Math.min(y, maxRows - h), 0); | ||
var props | ||
/*: Props*/ | ||
= arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.props; | ||
return { | ||
x: x, | ||
y: y | ||
cols: props.cols, | ||
containerPadding: props.containerPadding, | ||
containerWidth: props.containerWidth, | ||
margin: props.margin, | ||
maxRows: props.maxRows, | ||
rowHeight: props.rowHeight | ||
}; | ||
} | ||
/** | ||
* Given a height and width in pixel values, calculate grid units. | ||
* @param {Number} height Height in pixels. | ||
* @param {Number} width Width in pixels. | ||
* @return {Object} w, h as grid units. | ||
*/ | ||
}, { | ||
key: "calcWH", | ||
value: function calcWH(_ref4) | ||
/*: { w: number, h: number }*/ | ||
{ | ||
var height = _ref4.height, | ||
width = _ref4.width; | ||
var _this$props4 = this.props, | ||
margin = _this$props4.margin, | ||
maxRows = _this$props4.maxRows, | ||
cols = _this$props4.cols, | ||
rowHeight = _this$props4.rowHeight, | ||
x = _this$props4.x, | ||
y = _this$props4.y; | ||
var colWidth = this.calcColWidth(); // width = colWidth * w - (margin * (w - 1)) | ||
// ... | ||
// w = (width + margin) / (colWidth + margin) | ||
var w = Math.round((width + margin[0]) / (colWidth + margin[0])); | ||
var h = Math.round((height + margin[1]) / (rowHeight + margin[1])); // Capping | ||
w = Math.max(Math.min(w, cols - x), 0); | ||
h = Math.max(Math.min(h, maxRows - y), 0); | ||
return { | ||
w: w, | ||
h: h | ||
}; | ||
} | ||
/** | ||
* This is where we set the grid item's absolute placement. It gets a little tricky because we want to do it | ||
@@ -427,6 +327,6 @@ * well when server rendering, and the only way to do that properly is to use percentage width/left because | ||
{ | ||
var _this$props5 = this.props, | ||
usePercentages = _this$props5.usePercentages, | ||
containerWidth = _this$props5.containerWidth, | ||
useCSSTransforms = _this$props5.useCSSTransforms; | ||
var _this$props3 = this.props, | ||
usePercentages = _this$props3.usePercentages, | ||
containerWidth = _this$props3.containerWidth, | ||
useCSSTransforms = _this$props3.useCSSTransforms; | ||
var style; // CSS Transforms support (default) | ||
@@ -458,2 +358,4 @@ | ||
/*: ReactElement<any>*/ | ||
, isDraggable | ||
/*: boolean*/ | ||
) | ||
@@ -463,2 +365,3 @@ /*: ReactElement<any>*/ | ||
return _react.default.createElement(_reactDraggable.DraggableCore, { | ||
disabled: !isDraggable, | ||
onStart: this.onDragStart, | ||
@@ -485,20 +388,28 @@ onDrag: this.onDrag, | ||
/*: Position*/ | ||
, isResizable | ||
/*: boolean*/ | ||
) | ||
/*: ReactElement<any>*/ | ||
{ | ||
var _this$props6 = this.props, | ||
cols = _this$props6.cols, | ||
x = _this$props6.x, | ||
minW = _this$props6.minW, | ||
minH = _this$props6.minH, | ||
maxW = _this$props6.maxW, | ||
maxH = _this$props6.maxH; // This is the max possible width - doesn't go to infinity because of the width of the window | ||
var _this$props4 = this.props, | ||
cols = _this$props4.cols, | ||
x = _this$props4.x, | ||
minW = _this$props4.minW, | ||
minH = _this$props4.minH, | ||
maxW = _this$props4.maxW, | ||
maxH = _this$props4.maxH, | ||
transformScale = _this$props4.transformScale; | ||
var positionParams = this.getPositionParams(); // This is the max possible width - doesn't go to infinity because of the width of the window | ||
var maxWidth = this.calcPosition(0, 0, cols - x, 0).width; // Calculate min/max constraints using our min & maxes | ||
var maxWidth = (0, _calculateUtils.calcGridItemPosition)(positionParams, 0, 0, cols - x, 0).width; // Calculate min/max constraints using our min & maxes | ||
var mins = this.calcPosition(0, 0, minW, minH); | ||
var maxes = this.calcPosition(0, 0, maxW, maxH); | ||
var mins = (0, _calculateUtils.calcGridItemPosition)(positionParams, 0, 0, minW, minH); | ||
var maxes = (0, _calculateUtils.calcGridItemPosition)(positionParams, 0, 0, maxW, maxH); | ||
var minConstraints = [mins.width, mins.height]; | ||
var maxConstraints = [Math.min(maxes.width, maxWidth), Math.min(maxes.height, Infinity)]; | ||
return _react.default.createElement(_reactResizable.Resizable, { | ||
draggableOpts: { | ||
disabled: !isResizable | ||
}, | ||
className: isResizable ? undefined : "react-resizable-hide", | ||
width: position.width, | ||
@@ -510,3 +421,4 @@ height: position.height, | ||
onResizeStart: this.onResizeStart, | ||
onResize: this.onResize | ||
onResize: this.onResize, | ||
transformScale: transformScale | ||
}, child); | ||
@@ -533,21 +445,22 @@ } | ||
/*: Event*/ | ||
, _ref5, handlerName | ||
, _ref4, handlerName | ||
/*: string*/ | ||
) { | ||
var node = _ref5.node, | ||
size = _ref5.size; | ||
var node = _ref4.node, | ||
size = _ref4.size; | ||
var handler = this.props[handlerName]; | ||
if (!handler) return; | ||
var _this$props7 = this.props, | ||
cols = _this$props7.cols, | ||
x = _this$props7.x, | ||
i = _this$props7.i, | ||
maxW = _this$props7.maxW, | ||
minW = _this$props7.minW, | ||
maxH = _this$props7.maxH, | ||
minH = _this$props7.minH; // Get new XY | ||
var _this$props5 = this.props, | ||
cols = _this$props5.cols, | ||
x = _this$props5.x, | ||
y = _this$props5.y, | ||
i = _this$props5.i, | ||
maxW = _this$props5.maxW, | ||
minW = _this$props5.minW, | ||
maxH = _this$props5.maxH, | ||
minH = _this$props5.minH; // Get new XY | ||
var _this$calcWH = this.calcWH(size), | ||
w = _this$calcWH.w, | ||
h = _this$calcWH.h; // Cap w at numCols | ||
var _calcWH = (0, _calculateUtils.calcWH)(this.getPositionParams(), size.width, size.height, x, y), | ||
w = _calcWH.w, | ||
h = _calcWH.h; // Cap w at numCols | ||
@@ -575,12 +488,12 @@ | ||
{ | ||
var _this$props8 = this.props, | ||
x = _this$props8.x, | ||
y = _this$props8.y, | ||
w = _this$props8.w, | ||
h = _this$props8.h, | ||
isDraggable = _this$props8.isDraggable, | ||
isResizable = _this$props8.isResizable, | ||
droppingPosition = _this$props8.droppingPosition, | ||
useCSSTransforms = _this$props8.useCSSTransforms; | ||
var pos = this.calcPosition(x, y, w, h, this.state); | ||
var _this$props6 = this.props, | ||
x = _this$props6.x, | ||
y = _this$props6.y, | ||
w = _this$props6.w, | ||
h = _this$props6.h, | ||
isDraggable = _this$props6.isDraggable, | ||
isResizable = _this$props6.isResizable, | ||
droppingPosition = _this$props6.droppingPosition, | ||
useCSSTransforms = _this$props6.useCSSTransforms; | ||
var pos = (0, _calculateUtils.calcGridItemPosition)(this.getPositionParams(), x, y, w, h, this.state); | ||
@@ -604,5 +517,5 @@ var child = _react.default.Children.only(this.props.children); // Create the child element. We clone the existing element but modify its className and style. | ||
if (isResizable) newChild = this.mixinResizable(newChild, pos); // Draggable support. This is always on, except for with placeholders. | ||
newChild = this.mixinResizable(newChild, pos, isResizable); // Draggable support. This is always on, except for with placeholders. | ||
if (isDraggable) newChild = this.mixinDraggable(newChild); | ||
newChild = this.mixinDraggable(newChild, isDraggable); | ||
return newChild; | ||
@@ -694,4 +607,4 @@ } | ||
e: _propTypes.default.object.isRequired, | ||
x: _propTypes.default.number.isRequired, | ||
y: _propTypes.default.number.isRequired | ||
left: _propTypes.default.number.isRequired, | ||
top: _propTypes.default.number.isRequired | ||
}) | ||
@@ -698,0 +611,0 @@ }); |
@@ -10,4 +10,2 @@ "use strict"; | ||
var _propTypes = _interopRequireDefault(require("prop-types")); | ||
var _lodash = _interopRequireDefault(require("lodash.isequal")); | ||
@@ -19,4 +17,8 @@ | ||
var _calculateUtils = require("./calculateUtils"); | ||
var _GridItem = _interopRequireDefault(require("./GridItem")); | ||
var _ReactGridLayoutPropTypes = _interopRequireDefault(require("./ReactGridLayoutPropTypes")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -28,3 +30,3 @@ | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
@@ -58,14 +60,2 @@ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } | ||
// End Types | ||
var compactType = function compactType(props | ||
/*: Props*/ | ||
) | ||
/*: CompactType*/ | ||
{ | ||
var _ref = props || {}, | ||
verticalCompact = _ref.verticalCompact, | ||
compactType = _ref.compactType; | ||
return verticalCompact === false ? null : compactType; | ||
}; | ||
var layoutClassName = "react-grid-layout"; | ||
@@ -75,3 +65,3 @@ var isFirefox = false; // Try...catch will protect from navigator not existing (e.g. node) or a bad implementation of navigator | ||
try { | ||
isFirefox = navigator.userAgent.toLowerCase().includes("firefox"); | ||
isFirefox = /firefox/i.test(navigator.userAgent); | ||
} catch (e) {} | ||
@@ -91,2 +81,3 @@ /* Ignore */ | ||
// TODO publish internal ReactClass displayName transform | ||
// Refactored to another module to make way for preval | ||
function ReactGridLayout(props | ||
@@ -108,3 +99,3 @@ /*: Props*/ | ||
layout: (0, _utils.synchronizeLayoutWithChildren)(_this.props.layout, _this.props.children, _this.props.cols, // Legacy support for verticalCompact: false | ||
compactType(_this.props)), | ||
(0, _utils.compactType)(_this.props)), | ||
mounted: false, | ||
@@ -125,8 +116,17 @@ oldDragItem: null, | ||
// to avoid unpredictable jumping of a dropping placeholder | ||
if (isFirefox && !e.nativeEvent.target.className.includes(layoutClassName)) { | ||
// FIXME remove this hack | ||
if (isFirefox && e.nativeEvent.target.className.indexOf(layoutClassName) === -1) { | ||
return false; | ||
} | ||
var droppingItem = _this.props.droppingItem; | ||
var layout = _this.state.layout; | ||
var _this$props = _this.props, | ||
droppingItem = _this$props.droppingItem, | ||
margin = _this$props.margin, | ||
cols = _this$props.cols, | ||
rowHeight = _this$props.rowHeight, | ||
maxRows = _this$props.maxRows, | ||
width = _this$props.width, | ||
containerPadding = _this$props.containerPadding; | ||
var layout = _this.state.layout; // This is relative to the DOM element that this event fired for. | ||
var _e$nativeEvent = e.nativeEvent, | ||
@@ -136,4 +136,4 @@ layerX = _e$nativeEvent.layerX, | ||
var droppingPosition = { | ||
x: layerX, | ||
y: layerY, | ||
left: layerX, | ||
top: layerY, | ||
e: e | ||
@@ -143,2 +143,14 @@ }; | ||
if (!_this.state.droppingDOMNode) { | ||
var positionParams | ||
/*: PositionParams*/ | ||
= { | ||
cols: cols, | ||
margin: margin, | ||
maxRows: maxRows, | ||
rowHeight: rowHeight, | ||
containerWidth: width, | ||
containerPadding: containerPadding || margin | ||
}; | ||
var calculatedPosition = (0, _calculateUtils.calcXY)(positionParams, layerY, layerX, droppingItem.w, droppingItem.h); | ||
_this.setState({ | ||
@@ -150,4 +162,4 @@ droppingDOMNode: _react.default.createElement("div", { | ||
layout: [].concat(_toConsumableArray(layout), [_objectSpread({}, droppingItem, { | ||
x: 0, | ||
y: 0, | ||
x: calculatedPosition.x, | ||
y: calculatedPosition.y, | ||
static: false, | ||
@@ -158,6 +170,12 @@ isDraggable: true | ||
} else if (_this.state.droppingPosition) { | ||
var shouldUpdatePosition = _this.state.droppingPosition.x != layerX || _this.state.droppingPosition.y != layerY; | ||
shouldUpdatePosition && _this.setState({ | ||
droppingPosition: droppingPosition | ||
}); | ||
var _this$state$droppingP = _this.state.droppingPosition, | ||
left = _this$state$droppingP.left, | ||
top = _this$state$droppingP.top; | ||
var shouldUpdatePosition = left != layerX || top != layerY; | ||
if (shouldUpdatePosition) { | ||
_this.setState({ | ||
droppingPosition: droppingPosition | ||
}); | ||
} | ||
} | ||
@@ -170,9 +188,9 @@ | ||
_defineProperty(_assertThisInitialized(_this), "removeDroppingPlaceholder", function () { | ||
var _this$props = _this.props, | ||
droppingItem = _this$props.droppingItem, | ||
cols = _this$props.cols; | ||
var _this$props2 = _this.props, | ||
droppingItem = _this$props2.droppingItem, | ||
cols = _this$props2.cols; | ||
var layout = _this.state.layout; | ||
var newLayout = (0, _utils.compact)(layout.filter(function (l) { | ||
return l.i !== droppingItem.i; | ||
}), compactType(_this.props), cols); | ||
}), (0, _utils.compactType)(_this.props), cols); | ||
@@ -203,13 +221,15 @@ _this.setState({ | ||
_defineProperty(_assertThisInitialized(_this), "onDrop", function () { | ||
_defineProperty(_assertThisInitialized(_this), "onDrop", function (e | ||
/*: Event*/ | ||
) { | ||
var droppingItem = _this.props.droppingItem; | ||
var layout = _this.state.layout; | ||
var _ref2 = layout.find(function (l) { | ||
var _ref = layout.find(function (l) { | ||
return l.i === droppingItem.i; | ||
}) || {}, | ||
x = _ref2.x, | ||
y = _ref2.y, | ||
w = _ref2.w, | ||
h = _ref2.h; // reset gragEnter counter on drop | ||
x = _ref.x, | ||
y = _ref.y, | ||
w = _ref.w, | ||
h = _ref.h; // reset gragEnter counter on drop | ||
@@ -225,3 +245,4 @@ | ||
w: w, | ||
h: h | ||
h: h, | ||
e: e | ||
}); | ||
@@ -245,2 +266,11 @@ }); | ||
}, { | ||
key: "shouldComponentUpdate", | ||
value: function shouldComponentUpdate(nextProps | ||
/*: Props*/ | ||
, nextState | ||
/*: State*/ | ||
) { | ||
return !(0, _utils.fastRGLPropsEqual)(this.props, nextProps, _lodash.default) || !(0, _lodash.default)(this.state.activeDrag, nextState.activeDrag); | ||
} | ||
}, { | ||
key: "componentDidUpdate", | ||
@@ -288,5 +318,5 @@ value: function componentDidUpdate(prevProps | ||
/*: number*/ | ||
, _ref3) { | ||
var e = _ref3.e, | ||
node = _ref3.node; | ||
, _ref2) { | ||
var e = _ref2.e, | ||
node = _ref2.node; | ||
var layout = this.state.layout; | ||
@@ -318,5 +348,5 @@ var l = (0, _utils.getLayoutItem)(layout, i); | ||
/*: number*/ | ||
, _ref4) { | ||
var e = _ref4.e, | ||
node = _ref4.node; | ||
, _ref3) { | ||
var e = _ref3.e, | ||
node = _ref3.node; | ||
var oldDragItem = this.state.oldDragItem; | ||
@@ -338,6 +368,6 @@ var layout = this.state.layout; | ||
var isUserAction = true; | ||
layout = (0, _utils.moveElement)(layout, l, x, y, isUserAction, this.props.preventCollision, compactType(this.props), cols); | ||
layout = (0, _utils.moveElement)(layout, l, x, y, isUserAction, this.props.preventCollision, (0, _utils.compactType)(this.props), cols); | ||
this.props.onDrag(layout, oldDragItem, l, placeholder, e, node); | ||
this.setState({ | ||
layout: (0, _utils.compact)(layout, compactType(this.props), cols), | ||
layout: (0, _utils.compact)(layout, (0, _utils.compactType)(this.props), cols), | ||
activeDrag: placeholder | ||
@@ -363,10 +393,11 @@ }); | ||
/*: number*/ | ||
, _ref5) { | ||
var e = _ref5.e, | ||
node = _ref5.node; | ||
, _ref4) { | ||
var e = _ref4.e, | ||
node = _ref4.node; | ||
if (!this.state.activeDrag) return; | ||
var oldDragItem = this.state.oldDragItem; | ||
var layout = this.state.layout; | ||
var _this$props2 = this.props, | ||
cols = _this$props2.cols, | ||
preventCollision = _this$props2.preventCollision; | ||
var _this$props3 = this.props, | ||
cols = _this$props3.cols, | ||
preventCollision = _this$props3.preventCollision; | ||
var l = (0, _utils.getLayoutItem)(layout, i); | ||
@@ -376,10 +407,6 @@ if (!l) return; // Move the element here | ||
var isUserAction = true; | ||
layout = (0, _utils.moveElement)(layout, l, x, y, isUserAction, preventCollision, compactType(this.props), cols); | ||
layout = (0, _utils.moveElement)(layout, l, x, y, isUserAction, preventCollision, (0, _utils.compactType)(this.props), cols); | ||
this.props.onDragStop(layout, oldDragItem, l, null, e, node); // Set state | ||
if (this.state.activeDrag) { | ||
this.props.onDragStop(layout, oldDragItem, l, null, e, node); | ||
} // Set state | ||
var newLayout = (0, _utils.compact)(layout, compactType(this.props), cols); | ||
var newLayout = (0, _utils.compact)(layout, (0, _utils.compactType)(this.props), cols); | ||
var oldLayout = this.state.oldLayout; | ||
@@ -415,5 +442,5 @@ this.setState({ | ||
/*: number*/ | ||
, _ref6) { | ||
var e = _ref6.e, | ||
node = _ref6.node; | ||
, _ref5) { | ||
var e = _ref5.e, | ||
node = _ref5.node; | ||
var layout = this.state.layout; | ||
@@ -436,11 +463,11 @@ var l = (0, _utils.getLayoutItem)(layout, i); | ||
/*: number*/ | ||
, _ref7) { | ||
var e = _ref7.e, | ||
node = _ref7.node; | ||
, _ref6) { | ||
var e = _ref6.e, | ||
node = _ref6.node; | ||
var _this$state = this.state, | ||
layout = _this$state.layout, | ||
oldResizeItem = _this$state.oldResizeItem; | ||
var _this$props3 = this.props, | ||
cols = _this$props3.cols, | ||
preventCollision = _this$props3.preventCollision; | ||
var _this$props4 = this.props, | ||
cols = _this$props4.cols, | ||
preventCollision = _this$props4.preventCollision; | ||
var l | ||
@@ -494,3 +521,3 @@ /*: ?LayoutItem*/ | ||
this.setState({ | ||
layout: (0, _utils.compact)(layout, compactType(this.props), cols), | ||
layout: (0, _utils.compact)(layout, (0, _utils.compactType)(this.props), cols), | ||
activeDrag: placeholder | ||
@@ -507,5 +534,5 @@ }); | ||
/*: number*/ | ||
, _ref8) { | ||
var e = _ref8.e, | ||
node = _ref8.node; | ||
, _ref7) { | ||
var e = _ref7.e, | ||
node = _ref7.node; | ||
var _this$state2 = this.state, | ||
@@ -518,3 +545,3 @@ layout = _this$state2.layout, | ||
var newLayout = (0, _utils.compact)(layout, compactType(this.props), cols); | ||
var newLayout = (0, _utils.compact)(layout, (0, _utils.compactType)(this.props), cols); | ||
var oldLayout = this.state.oldLayout; | ||
@@ -541,11 +568,11 @@ this.setState({ | ||
if (!activeDrag) return null; | ||
var _this$props4 = this.props, | ||
width = _this$props4.width, | ||
cols = _this$props4.cols, | ||
margin = _this$props4.margin, | ||
containerPadding = _this$props4.containerPadding, | ||
rowHeight = _this$props4.rowHeight, | ||
maxRows = _this$props4.maxRows, | ||
useCSSTransforms = _this$props4.useCSSTransforms, | ||
transformScale = _this$props4.transformScale; // {...this.state.activeDrag} is pretty slow, actually | ||
var _this$props5 = this.props, | ||
width = _this$props5.width, | ||
cols = _this$props5.cols, | ||
margin = _this$props5.margin, | ||
containerPadding = _this$props5.containerPadding, | ||
rowHeight = _this$props5.rowHeight, | ||
maxRows = _this$props5.maxRows, | ||
useCSSTransforms = _this$props5.useCSSTransforms, | ||
transformScale = _this$props5.transformScale; // {...this.state.activeDrag} is pretty slow, actually | ||
@@ -589,21 +616,23 @@ return _react.default.createElement(_GridItem.default, { | ||
if (!l) return null; | ||
var _this$props5 = this.props, | ||
width = _this$props5.width, | ||
cols = _this$props5.cols, | ||
margin = _this$props5.margin, | ||
containerPadding = _this$props5.containerPadding, | ||
rowHeight = _this$props5.rowHeight, | ||
maxRows = _this$props5.maxRows, | ||
isDraggable = _this$props5.isDraggable, | ||
isResizable = _this$props5.isResizable, | ||
useCSSTransforms = _this$props5.useCSSTransforms, | ||
transformScale = _this$props5.transformScale, | ||
draggableCancel = _this$props5.draggableCancel, | ||
draggableHandle = _this$props5.draggableHandle; | ||
var _this$props6 = this.props, | ||
width = _this$props6.width, | ||
cols = _this$props6.cols, | ||
margin = _this$props6.margin, | ||
containerPadding = _this$props6.containerPadding, | ||
rowHeight = _this$props6.rowHeight, | ||
maxRows = _this$props6.maxRows, | ||
isDraggable = _this$props6.isDraggable, | ||
isResizable = _this$props6.isResizable, | ||
useCSSTransforms = _this$props6.useCSSTransforms, | ||
transformScale = _this$props6.transformScale, | ||
draggableCancel = _this$props6.draggableCancel, | ||
draggableHandle = _this$props6.draggableHandle; | ||
var _this$state3 = this.state, | ||
mounted = _this$state3.mounted, | ||
droppingPosition = _this$state3.droppingPosition; // Parse 'static'. Any properties defined directly on the grid item will take precedence. | ||
droppingPosition = _this$state3.droppingPosition; // Determine user manipulations possible. | ||
// If an item is static, it can't be manipulated by default. | ||
// Any properties defined directly on the grid item will take precedence. | ||
var draggable = Boolean(!l.static && isDraggable && (l.isDraggable || l.isDraggable == null)); | ||
var resizable = Boolean(!l.static && isResizable && (l.isResizable || l.isResizable == null)); | ||
var draggable = typeof l.isDraggable === "boolean" ? l.isDraggable : !l.static && isDraggable; | ||
var resizable = typeof l.isResizable === "boolean" ? l.isResizable : !l.static && isResizable; | ||
return _react.default.createElement(_GridItem.default, { | ||
@@ -641,3 +670,5 @@ containerWidth: width, | ||
}, child); | ||
} | ||
} // Called while dragging an element. Part of browser native drag/drop API. | ||
// Native event target might be the layout itself, or an element within the layout. | ||
}, { | ||
@@ -648,6 +679,6 @@ key: "render", | ||
var _this$props6 = this.props, | ||
className = _this$props6.className, | ||
style = _this$props6.style, | ||
isDroppable = _this$props6.isDroppable; | ||
var _this$props7 = this.props, | ||
className = _this$props7.className, | ||
style = _this$props7.style, | ||
isDroppable = _this$props7.isDroppable; | ||
var mergedClassName = (0, _classnames.default)(layoutClassName, className); | ||
@@ -696,3 +727,3 @@ | ||
if (newLayoutBase) { | ||
var newLayout = (0, _utils.synchronizeLayoutWithChildren)(newLayoutBase, nextProps.children, nextProps.cols, compactType(nextProps)); | ||
var newLayout = (0, _utils.synchronizeLayoutWithChildren)(newLayoutBase, nextProps.children, nextProps.cols, (0, _utils.compactType)(nextProps)); | ||
return { | ||
@@ -719,117 +750,4 @@ layout: newLayout, | ||
_defineProperty(ReactGridLayout, "propTypes", { | ||
// | ||
// Basic props | ||
// | ||
className: _propTypes.default.string, | ||
style: _propTypes.default.object, | ||
// This can be set explicitly. If it is not set, it will automatically | ||
// be set to the container width. Note that resizes will *not* cause this to adjust. | ||
// If you need that behavior, use WidthProvider. | ||
width: _propTypes.default.number, | ||
// If true, the container height swells and contracts to fit contents | ||
autoSize: _propTypes.default.bool, | ||
// # of cols. | ||
cols: _propTypes.default.number, | ||
// A selector that will not be draggable. | ||
draggableCancel: _propTypes.default.string, | ||
// A selector for the draggable handler | ||
draggableHandle: _propTypes.default.string, | ||
// Deprecated | ||
verticalCompact: function verticalCompact(props | ||
/*: Props*/ | ||
) { | ||
if (props.verticalCompact === false && process.env.NODE_ENV !== "production") { | ||
console.warn( // eslint-disable-line no-console | ||
"`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. " + 'Use `compactType`: "horizontal" | "vertical" | null.'); | ||
} | ||
}, | ||
// Choose vertical or hotizontal compaction | ||
compactType: _propTypes.default.oneOf(["vertical", "horizontal"]), | ||
// layout is an array of object with the format: | ||
// {x: Number, y: Number, w: Number, h: Number, i: String} | ||
layout: function layout(props | ||
/*: Props*/ | ||
) { | ||
var layout = props.layout; // I hope you're setting the data-grid property on the grid items | ||
_defineProperty(ReactGridLayout, "propTypes", _ReactGridLayoutPropTypes.default); | ||
if (layout === undefined) return; | ||
(0, _utils.validateLayout)(layout, "layout"); | ||
}, | ||
// | ||
// Grid Dimensions | ||
// | ||
// Margin between items [x, y] in px | ||
margin: _propTypes.default.arrayOf(_propTypes.default.number), | ||
// Padding inside the container [x, y] in px | ||
containerPadding: _propTypes.default.arrayOf(_propTypes.default.number), | ||
// Rows have a static height, but you can change this based on breakpoints if you like | ||
rowHeight: _propTypes.default.number, | ||
// Default Infinity, but you can specify a max here if you like. | ||
// Note that this isn't fully fleshed out and won't error if you specify a layout that | ||
// extends beyond the row capacity. It will, however, not allow users to drag/resize | ||
// an item past the barrier. They can push items beyond the barrier, though. | ||
// Intentionally not documented for this reason. | ||
maxRows: _propTypes.default.number, | ||
// | ||
// Flags | ||
// | ||
isDraggable: _propTypes.default.bool, | ||
isResizable: _propTypes.default.bool, | ||
// If true, grid items won't change position when being dragged over. | ||
preventCollision: _propTypes.default.bool, | ||
// Use CSS transforms instead of top/left | ||
useCSSTransforms: _propTypes.default.bool, | ||
// parent layout transform scale | ||
transformScale: _propTypes.default.number, | ||
// If true, an external element can trigger onDrop callback with a specific grid position as a parameter | ||
isDroppable: _propTypes.default.bool, | ||
// | ||
// Callbacks | ||
// | ||
// Callback so you can save the layout. Calls after each drag & resize stops. | ||
onLayoutChange: _propTypes.default.func, | ||
// Calls when drag starts. Callback is of the signature (layout, oldItem, newItem, placeholder, e, ?node). | ||
// All callbacks below have the same signature. 'start' and 'stop' callbacks omit the 'placeholder'. | ||
onDragStart: _propTypes.default.func, | ||
// Calls on each drag movement. | ||
onDrag: _propTypes.default.func, | ||
// Calls when drag is complete. | ||
onDragStop: _propTypes.default.func, | ||
//Calls when resize starts. | ||
onResizeStart: _propTypes.default.func, | ||
// Calls when resize movement happens. | ||
onResize: _propTypes.default.func, | ||
// Calls when resize is complete. | ||
onResizeStop: _propTypes.default.func, | ||
// Calls when some element is dropped. | ||
onDrop: _propTypes.default.func, | ||
// | ||
// Other validations | ||
// | ||
droppingItem: _propTypes.default.shape({ | ||
i: _propTypes.default.string.isRequired, | ||
w: _propTypes.default.number.isRequired, | ||
h: _propTypes.default.number.isRequired | ||
}), | ||
// Children must not have duplicate keys. | ||
children: function children(props | ||
/*: Props*/ | ||
, propName | ||
/*: string*/ | ||
) { | ||
var children = props[propName]; // Check children keys for duplicates. Throw if found. | ||
var keys = {}; | ||
_react.default.Children.forEach(children, function (child) { | ||
if (keys[child.key]) { | ||
throw new Error('Duplicate child key "' + child.key + '" found! This will cause problems in ReactGridLayout.'); | ||
} | ||
keys[child.key] = true; | ||
}); | ||
} | ||
}); | ||
_defineProperty(ReactGridLayout, "defaultProps", { | ||
@@ -836,0 +754,0 @@ autoSize: true, |
@@ -32,3 +32,3 @@ "use strict"; | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
@@ -162,3 +162,3 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
if (this.props.width != prevProps.width || this.props.breakpoint !== prevProps.breakpoint || !(0, _lodash.default)(this.props.breakpoints, prevProps.breakpoints) || !(0, _lodash.default)(this.props.cols, prevProps.cols)) { | ||
this.onWidthChange(this.props); | ||
this.onWidthChange(prevProps); | ||
} | ||
@@ -174,26 +174,30 @@ } // wrap layouts so we do not need to pass layouts to child | ||
*/ | ||
value: function onWidthChange(nextProps | ||
value: function onWidthChange(prevProps | ||
/*: Props<*>*/ | ||
) { | ||
var breakpoints = nextProps.breakpoints, | ||
cols = nextProps.cols, | ||
layouts = nextProps.layouts, | ||
compactType = nextProps.compactType; | ||
var newBreakpoint = nextProps.breakpoint || (0, _responsiveUtils.getBreakpointFromWidth)(nextProps.breakpoints, nextProps.width); | ||
var _this$props2 = this.props, | ||
breakpoints = _this$props2.breakpoints, | ||
cols = _this$props2.cols, | ||
layouts = _this$props2.layouts, | ||
compactType = _this$props2.compactType; | ||
var newBreakpoint = this.props.breakpoint || (0, _responsiveUtils.getBreakpointFromWidth)(this.props.breakpoints, this.props.width); | ||
var lastBreakpoint = this.state.breakpoint; | ||
var newCols | ||
/*: number*/ | ||
= (0, _responsiveUtils.getColsFromBreakpoint)(newBreakpoint, cols); // Breakpoint change | ||
= (0, _responsiveUtils.getColsFromBreakpoint)(newBreakpoint, cols); | ||
if (lastBreakpoint !== newBreakpoint || this.props.breakpoints !== breakpoints || this.props.cols !== cols) { | ||
var newLayouts = _objectSpread({}, layouts); // Breakpoint change | ||
if (lastBreakpoint !== newBreakpoint || prevProps.breakpoints !== breakpoints || prevProps.cols !== cols) { | ||
// Preserve the current layout if the current breakpoint is not present in the next layouts. | ||
if (!(lastBreakpoint in layouts)) layouts[lastBreakpoint] = (0, _utils.cloneLayout)(this.state.layout); // Find or generate a new layout. | ||
if (!(lastBreakpoint in newLayouts)) newLayouts[lastBreakpoint] = (0, _utils.cloneLayout)(this.state.layout); // Find or generate a new layout. | ||
var layout = (0, _responsiveUtils.findOrGenerateResponsiveLayout)(layouts, breakpoints, newBreakpoint, lastBreakpoint, newCols, compactType); // This adds missing items. | ||
var layout = (0, _responsiveUtils.findOrGenerateResponsiveLayout)(newLayouts, breakpoints, newBreakpoint, lastBreakpoint, newCols, compactType); // This adds missing items. | ||
layout = (0, _utils.synchronizeLayoutWithChildren)(layout, nextProps.children, newCols, compactType); // Store the new layout. | ||
layout = (0, _utils.synchronizeLayoutWithChildren)(layout, this.props.children, newCols, compactType); // Store the new layout. | ||
layouts[newBreakpoint] = layout; // callbacks | ||
newLayouts[newBreakpoint] = layout; // callbacks | ||
this.props.onLayoutChange(layout, layouts); | ||
this.props.onLayoutChange(layout, newLayouts); | ||
this.props.onBreakpointChange(newBreakpoint, newCols); | ||
@@ -207,6 +211,6 @@ this.setState({ | ||
var margin = getIndentationValue(nextProps.margin, newBreakpoint); | ||
var containerPadding = getIndentationValue(nextProps.containerPadding, newBreakpoint); //call onWidthChange on every change of width, not only on breakpoint changes | ||
var margin = getIndentationValue(this.props.margin, newBreakpoint); | ||
var containerPadding = getIndentationValue(this.props.containerPadding, newBreakpoint); //call onWidthChange on every change of width, not only on breakpoint changes | ||
this.props.onWidthChange(nextProps.width, margin, newCols, containerPadding); | ||
this.props.onWidthChange(this.props.width, margin, newCols, containerPadding); | ||
} | ||
@@ -217,13 +221,13 @@ }, { | ||
/* eslint-disable no-unused-vars */ | ||
var _this$props2 = this.props, | ||
breakpoint = _this$props2.breakpoint, | ||
breakpoints = _this$props2.breakpoints, | ||
cols = _this$props2.cols, | ||
layouts = _this$props2.layouts, | ||
margin = _this$props2.margin, | ||
containerPadding = _this$props2.containerPadding, | ||
onBreakpointChange = _this$props2.onBreakpointChange, | ||
onLayoutChange = _this$props2.onLayoutChange, | ||
onWidthChange = _this$props2.onWidthChange, | ||
other = _objectWithoutProperties(_this$props2, ["breakpoint", "breakpoints", "cols", "layouts", "margin", "containerPadding", "onBreakpointChange", "onLayoutChange", "onWidthChange"]); | ||
var _this$props3 = this.props, | ||
breakpoint = _this$props3.breakpoint, | ||
breakpoints = _this$props3.breakpoints, | ||
cols = _this$props3.cols, | ||
layouts = _this$props3.layouts, | ||
margin = _this$props3.margin, | ||
containerPadding = _this$props3.containerPadding, | ||
onBreakpointChange = _this$props3.onBreakpointChange, | ||
onLayoutChange = _this$props3.onLayoutChange, | ||
onWidthChange = _this$props3.onWidthChange, | ||
other = _objectWithoutProperties(_this$props3, ["breakpoint", "breakpoints", "cols", "layouts", "margin", "containerPadding", "onBreakpointChange", "onLayoutChange", "onWidthChange"]); | ||
/* eslint-enable no-unused-vars */ | ||
@@ -230,0 +234,0 @@ |
@@ -10,2 +10,3 @@ "use strict"; | ||
exports.childrenEqual = childrenEqual; | ||
exports.fastPositionEqual = fastPositionEqual; | ||
exports.collides = collides; | ||
@@ -29,4 +30,5 @@ exports.compact = compact; | ||
exports.validateLayout = validateLayout; | ||
exports.compactType = compactType; | ||
exports.autoBindHandlers = autoBindHandlers; | ||
exports.noop = void 0; | ||
exports.noop = exports.fastRGLPropsEqual = void 0; | ||
@@ -41,3 +43,3 @@ var _lodash = _interopRequireDefault(require("lodash.isequal")); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
@@ -128,2 +130,28 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
/** | ||
* See `fastRGLPropsEqual.js`. | ||
* We want this to run as fast as possible - it is called often - and to be | ||
* resilient to new props that we add. So rather than call lodash.isEqual, | ||
* which isn't suited to comparing props very well, we use this specialized | ||
* function in conjunction with preval to generate the fastest possible comparison | ||
* function, tuned for exactly our props. | ||
*/ | ||
/*:: type FastRGLPropsEqual = (Object, Object, Function) => boolean;*/ | ||
var fastRGLPropsEqual | ||
/*: FastRGLPropsEqual*/ | ||
= require("./fastRGLPropsEqual"); // Like the above, but a lot simpler. | ||
exports.fastRGLPropsEqual = fastRGLPropsEqual; | ||
function fastPositionEqual(a | ||
/*: Position*/ | ||
, b | ||
/*: Position*/ | ||
) { | ||
return a.left === b.left && a.top === b.top && a.width === b.width && a.height === b.height; | ||
} | ||
/** | ||
* Given two layoutitems, check if they collide. | ||
@@ -429,3 +457,5 @@ */ | ||
{ | ||
if (l.static) return layout; // Short-circuit if nothing to do. | ||
// If this is static and not explicitly enabled as draggable, | ||
// no move is possible, so we can short-circuit this immediately. | ||
if (l.static && l.isDraggable !== true) return layout; // Short-circuit if nothing to do. | ||
@@ -739,2 +769,15 @@ if (l.y === y && l.x === x) return layout; | ||
} | ||
} // Legacy support for verticalCompact: false | ||
function compactType(props | ||
/*: ?{ verticalCompact: boolean, compactType: CompactType }*/ | ||
) | ||
/*: CompactType*/ | ||
{ | ||
var _ref3 = props || {}, | ||
verticalCompact = _ref3.verticalCompact, | ||
compactType = _ref3.compactType; | ||
return verticalCompact === false ? null : compactType; | ||
} // Flow can't really figure this out, so we just use Object | ||
@@ -741,0 +784,0 @@ |
# Changelog | ||
0.18.0 (Feb 25, 2020) | ||
---- | ||
Thanks to all of our maintainers for this big release. 0.18.0 contains a large number of bugfixes that users have been asking for. Please read the full list so you know what to expect. Some of the biggest improvements include fixing changes of `isResizable`/`isDraggable` without a remount ([#892](https://github.com/STRML/react-grid-layout/pull/892)), fixes to prop changes on `ResponsiveReactGridLayout` ([#1090](https://github.com/STRML/react-grid-layout/pull/1090)), `shouldComponentUpdate` improvements for speed ([#1123](https://github.com/STRML/react-grid-layout/pull/1123)), improvements to droppability ([#1127](https://github.com/STRML/react-grid-layout/pull/1127)), and much more. | ||
### (Potentially) Breaking Changes | ||
- You can now locally set `isDraggable`/`isResizable` on a `static` item and it will have that property. This could be useful, but be sure to check your layouts if you use `static`. Relates to [#1060](https://github.com/STRML/react-grid-layout/pull/1060). | ||
- `shouldComponentUpdate` is now implemented on major components to improve render speed while you manipulate the layout. In our testing there are no issues. If you encounter one, please open an issue asap and we'll get it fixed. See [#1123](https://github.com/STRML/react-grid-layout/pull/1123). | ||
### New Features | ||
- You can now manipulate `isDraggable`/`isResizable` without the child component remounting. We do this by always rendering the child `<Resizable>` and `<Draggable>` wrappers, optionally in a `disabled` state. This feature has been heavily requested. [#892](https://github.com/STRML/react-grid-layout/pull/892) | ||
- The event is now passed as `e` on the `onDrop` callback. [#1065](https://github.com/STRML/react-grid-layout/pull/1065) | ||
- Pass `transformScale` to `Resizable`. [#1075](https://github.com/STRML/react-grid-layout/pull/1075) | ||
### Bugfixes | ||
- Fix handling of width changes in `ResponsiveReactGridLayout`. [#1090](https://github.com/STRML/react-grid-layout/pull/1090) | ||
- Fixes ignored changes of breakpoints and columns. See also [issue #1083](https://github.com/STRML/react-grid-layout/issues/1083). | ||
- Forbid layout change on click without drag. [#1044](https://github.com/STRML/react-grid-layout/pull/1044) | ||
- Do not mutate `layouts` prop. [#1064](https://github.com/STRML/react-grid-layout/pull/1064) | ||
- Ensure locally set `isDraggable`/`isResizable` on a `GridItem` overrides the global setting on the layout. [#1060](https://github.com/STRML/react-grid-layout/pull/1060) | ||
- Avoid additional element jumping when an item is dropped. [#1127](https://github.com/STRML/react-grid-layout/issues/1127) | ||
- Don't use `String#includes` for Firefox test. [#1096](https://github.com/STRML/react-grid-layout/pull/1096) | ||
### Internal Refactors | ||
- Added `shouldComponentUpdate` to major elements for speed. Significant [performance improvements](https://github.com/STRML/react-grid-layout/pull/1032#issuecomment-541604763) while dragging. Started in [#1032](https://github.com/STRML/react-grid-layout/pull/1032) and finished in [#1123](https://github.com/STRML/react-grid-layout/pull/1123). | ||
- A [fun trick for the curious](https://github.com/STRML/react-grid-layout/blob/44e200067b3640c3230f5511e8624a7c629d2f9a/lib/fastRGLPropsEqual.js). | ||
- Internal refactor of dropping capability. It is now more predictable and uses similar unit labels (`left`, `top`) to other features. [#1128](https://github.com/STRML/react-grid-layout/issues/1128) | ||
- Upgrade devDependencies. | ||
- Remove ESPower from test suite (not useful with Jest). | ||
0.17.1 (Oct 29, 2019) | ||
@@ -4,0 +39,0 @@ ---- |
@@ -13,5 +13,5 @@ // @flow | ||
type WPState = { | ||
type WPState = {| | ||
width: number | ||
}; | ||
|}; | ||
@@ -18,0 +18,0 @@ /* |
@@ -7,3 +7,4 @@ // @flow | ||
import { Resizable } from "react-resizable"; | ||
import { perc, setTopLeft, setTransform } from "./utils"; | ||
import { fastPositionEqual, perc, setTopLeft, setTransform } from "./utils"; | ||
import { calcGridItemPosition, calcXY, calcWH } from "./calculateUtils"; | ||
import classNames from "classnames"; | ||
@@ -20,2 +21,4 @@ import type { Element as ReactElement, Node as ReactNode } from "react"; | ||
import type { PositionParams } from "./calculateUtils"; | ||
type PartialPosition = { top: number, left: number }; | ||
@@ -156,4 +159,4 @@ type GridItemCallback<Data: GridDragEvent | GridResizeEvent> = ( | ||
e: PropTypes.object.isRequired, | ||
x: PropTypes.number.isRequired, | ||
y: PropTypes.number.isRequired | ||
left: PropTypes.number.isRequired, | ||
top: PropTypes.number.isRequired | ||
}) | ||
@@ -181,13 +184,39 @@ }; | ||
shouldComponentUpdate(nextProps: Props, nextState: State) { | ||
let { x, y, w, h } = this.props; | ||
const oldPosition = calcGridItemPosition( | ||
this.getPositionParams(this.props), | ||
x, | ||
y, | ||
w, | ||
h, | ||
this.state | ||
); | ||
({ x, y, w, h } = nextProps); | ||
const newPosition = calcGridItemPosition( | ||
this.getPositionParams(nextProps), | ||
x, | ||
y, | ||
w, | ||
h, | ||
nextState | ||
); | ||
return ( | ||
!fastPositionEqual(oldPosition, newPosition) || | ||
this.props.useCSSTransforms !== nextProps.useCSSTransforms | ||
); | ||
} | ||
componentDidUpdate(prevProps: Props) { | ||
if (this.props.droppingPosition && prevProps.droppingPosition) { | ||
this.moveDroppingItem(prevProps); | ||
} | ||
this.moveDroppingItem(prevProps); | ||
} | ||
// When a droppingPosition is present, this means we should fire a move event, as if we had moved | ||
// this element by `x, y` pixels. | ||
moveDroppingItem(prevProps: Props) { | ||
const { droppingPosition } = this.props; | ||
const prevDroppingPosition = prevProps.droppingPosition; | ||
const { dragging } = this.state; | ||
if (!droppingPosition || !prevProps.droppingPosition) { | ||
if (!droppingPosition || !prevDroppingPosition) { | ||
return; | ||
@@ -202,4 +231,4 @@ } | ||
const shouldDrag = | ||
(dragging && droppingPosition.x !== prevProps.droppingPosition.x) || | ||
droppingPosition.y !== prevProps.droppingPosition.y; | ||
(dragging && droppingPosition.left !== prevDroppingPosition.left) || | ||
droppingPosition.top !== prevDroppingPosition.top; | ||
@@ -209,8 +238,8 @@ if (!dragging) { | ||
node: this.currentNode, | ||
deltaX: droppingPosition.x, | ||
deltaY: droppingPosition.y | ||
deltaX: droppingPosition.left, | ||
deltaY: droppingPosition.top | ||
}); | ||
} else if (shouldDrag) { | ||
const deltaX = droppingPosition.x - dragging.left; | ||
const deltaY = droppingPosition.y - dragging.top; | ||
const deltaX = droppingPosition.left - dragging.left; | ||
const deltaY = droppingPosition.top - dragging.top; | ||
@@ -225,120 +254,14 @@ this.onDrag(droppingPosition.e, { | ||
// Helper for generating column width | ||
calcColWidth(): number { | ||
const { margin, containerPadding, containerWidth, cols } = this.props; | ||
return ( | ||
(containerWidth - margin[0] * (cols - 1) - containerPadding[0] * 2) / cols | ||
); | ||
getPositionParams(props: Props = this.props): PositionParams { | ||
return { | ||
cols: props.cols, | ||
containerPadding: props.containerPadding, | ||
containerWidth: props.containerWidth, | ||
margin: props.margin, | ||
maxRows: props.maxRows, | ||
rowHeight: props.rowHeight | ||
}; | ||
} | ||
/** | ||
* Return position on the page given an x, y, w, h. | ||
* left, top, width, height are all in pixels. | ||
* @param {Number} x X coordinate in grid units. | ||
* @param {Number} y Y coordinate in grid units. | ||
* @param {Number} w W coordinate in grid units. | ||
* @param {Number} h H coordinate in grid units. | ||
* @return {Object} Object containing coords. | ||
*/ | ||
calcPosition( | ||
x: number, | ||
y: number, | ||
w: number, | ||
h: number, | ||
state: ?Object | ||
): Position { | ||
const { margin, containerPadding, rowHeight } = this.props; | ||
const colWidth = this.calcColWidth(); | ||
const out = {}; | ||
// If resizing, use the exact width and height as returned from resizing callbacks. | ||
if (state && state.resizing) { | ||
out.width = Math.round(state.resizing.width); | ||
out.height = Math.round(state.resizing.height); | ||
} | ||
// Otherwise, calculate from grid units. | ||
else { | ||
// 0 * Infinity === NaN, which causes problems with resize constraints; | ||
// Fix this if it occurs. | ||
// Note we do it here rather than later because Math.round(Infinity) causes deopt | ||
out.width = | ||
w === Infinity | ||
? w | ||
: Math.round(colWidth * w + Math.max(0, w - 1) * margin[0]); | ||
out.height = | ||
h === Infinity | ||
? h | ||
: Math.round(rowHeight * h + Math.max(0, h - 1) * margin[1]); | ||
} | ||
// If dragging, use the exact width and height as returned from dragging callbacks. | ||
if (state && state.dragging) { | ||
out.top = Math.round(state.dragging.top); | ||
out.left = Math.round(state.dragging.left); | ||
} | ||
// Otherwise, calculate from grid units. | ||
else { | ||
out.top = Math.round((rowHeight + margin[1]) * y + containerPadding[1]); | ||
out.left = Math.round((colWidth + margin[0]) * x + containerPadding[0]); | ||
} | ||
return out; | ||
} | ||
/** | ||
* Translate x and y coordinates from pixels to grid units. | ||
* @param {Number} top Top position (relative to parent) in pixels. | ||
* @param {Number} left Left position (relative to parent) in pixels. | ||
* @return {Object} x and y in grid units. | ||
*/ | ||
calcXY(top: number, left: number): { x: number, y: number } { | ||
const { margin, cols, rowHeight, w, h, maxRows } = this.props; | ||
const colWidth = this.calcColWidth(); | ||
// left = colWidth * x + margin * (x + 1) | ||
// l = cx + m(x+1) | ||
// l = cx + mx + m | ||
// l - m = cx + mx | ||
// l - m = x(c + m) | ||
// (l - m) / (c + m) = x | ||
// x = (left - margin) / (coldWidth + margin) | ||
let x = Math.round((left - margin[0]) / (colWidth + margin[0])); | ||
let y = Math.round((top - margin[1]) / (rowHeight + margin[1])); | ||
// Capping | ||
x = Math.max(Math.min(x, cols - w), 0); | ||
y = Math.max(Math.min(y, maxRows - h), 0); | ||
return { x, y }; | ||
} | ||
/** | ||
* Given a height and width in pixel values, calculate grid units. | ||
* @param {Number} height Height in pixels. | ||
* @param {Number} width Width in pixels. | ||
* @return {Object} w, h as grid units. | ||
*/ | ||
calcWH({ | ||
height, | ||
width | ||
}: { | ||
height: number, | ||
width: number | ||
}): { w: number, h: number } { | ||
const { margin, maxRows, cols, rowHeight, x, y } = this.props; | ||
const colWidth = this.calcColWidth(); | ||
// width = colWidth * w - (margin * (w - 1)) | ||
// ... | ||
// w = (width + margin) / (colWidth + margin) | ||
let w = Math.round((width + margin[0]) / (colWidth + margin[0])); | ||
let h = Math.round((height + margin[1]) / (rowHeight + margin[1])); | ||
// Capping | ||
w = Math.max(Math.min(w, cols - x), 0); | ||
h = Math.max(Math.min(h, maxRows - y), 0); | ||
return { w, h }; | ||
} | ||
/** | ||
* This is where we set the grid item's absolute placement. It gets a little tricky because we want to do it | ||
@@ -379,5 +302,9 @@ * well when server rendering, and the only way to do that properly is to use percentage width/left because | ||
*/ | ||
mixinDraggable(child: ReactElement<any>): ReactElement<any> { | ||
mixinDraggable( | ||
child: ReactElement<any>, | ||
isDraggable: boolean | ||
): ReactElement<any> { | ||
return ( | ||
<DraggableCore | ||
disabled={!isDraggable} | ||
onStart={this.onDragStart} | ||
@@ -406,12 +333,15 @@ onDrag={this.onDrag} | ||
child: ReactElement<any>, | ||
position: Position | ||
position: Position, | ||
isResizable: boolean | ||
): ReactElement<any> { | ||
const { cols, x, minW, minH, maxW, maxH } = this.props; | ||
const { cols, x, minW, minH, maxW, maxH, transformScale } = this.props; | ||
const positionParams = this.getPositionParams(); | ||
// This is the max possible width - doesn't go to infinity because of the width of the window | ||
const maxWidth = this.calcPosition(0, 0, cols - x, 0).width; | ||
const maxWidth = calcGridItemPosition(positionParams, 0, 0, cols - x, 0) | ||
.width; | ||
// Calculate min/max constraints using our min & maxes | ||
const mins = this.calcPosition(0, 0, minW, minH); | ||
const maxes = this.calcPosition(0, 0, maxW, maxH); | ||
const mins = calcGridItemPosition(positionParams, 0, 0, minW, minH); | ||
const maxes = calcGridItemPosition(positionParams, 0, 0, maxW, maxH); | ||
const minConstraints = [mins.width, mins.height]; | ||
@@ -424,2 +354,6 @@ const maxConstraints = [ | ||
<Resizable | ||
draggableOpts={{ | ||
disabled: !isResizable | ||
}} | ||
className={isResizable ? undefined : "react-resizable-hide"} | ||
width={position.width} | ||
@@ -432,2 +366,3 @@ height={position.height} | ||
onResize={this.onResize} | ||
transformScale={transformScale} | ||
> | ||
@@ -462,3 +397,9 @@ {child} | ||
const { x, y } = this.calcXY(newPosition.top, newPosition.left); | ||
const { x, y } = calcXY( | ||
this.getPositionParams(), | ||
newPosition.top, | ||
newPosition.left, | ||
this.props.w, | ||
this.props.h | ||
); | ||
@@ -481,3 +422,6 @@ return ( | ||
onDrag = (e: Event, { node, deltaX, deltaY }: ReactDraggableCallbackData) => { | ||
if (!this.props.onDrag) return; | ||
const { onDrag, transformScale } = this.props; | ||
if (!onDrag) return; | ||
deltaX /= transformScale; | ||
deltaY /= transformScale; | ||
@@ -492,7 +436,13 @@ const newPosition: PartialPosition = { top: 0, left: 0 }; | ||
const { x, y } = this.calcXY(newPosition.top, newPosition.left); | ||
const { x, y } = calcXY( | ||
this.getPositionParams(), | ||
newPosition.top, | ||
newPosition.left, | ||
this.props.w, | ||
this.props.h | ||
); | ||
return ( | ||
this.props.onDrag && | ||
this.props.onDrag.call(this, this.props.i, x, y, { | ||
onDrag && | ||
onDrag.call(this, this.props.i, x, y, { | ||
e, | ||
@@ -521,3 +471,9 @@ node, | ||
const { x, y } = this.calcXY(newPosition.top, newPosition.left); | ||
const { x, y } = calcXY( | ||
this.getPositionParams(), | ||
newPosition.top, | ||
newPosition.left, | ||
this.props.w, | ||
this.props.h | ||
); | ||
@@ -585,6 +541,12 @@ return ( | ||
if (!handler) return; | ||
const { cols, x, i, maxW, minW, maxH, minH } = this.props; | ||
const { cols, x, y, i, maxW, minW, maxH, minH } = this.props; | ||
// Get new XY | ||
let { w, h } = this.calcWH(size); | ||
let { w, h } = calcWH( | ||
this.getPositionParams(), | ||
size.width, | ||
size.height, | ||
x, | ||
y | ||
); | ||
@@ -617,3 +579,10 @@ // Cap w at numCols | ||
const pos = this.calcPosition(x, y, w, h, this.state); | ||
const pos = calcGridItemPosition( | ||
this.getPositionParams(), | ||
x, | ||
y, | ||
w, | ||
h, | ||
this.state | ||
); | ||
const child = React.Children.only(this.props.children); | ||
@@ -645,6 +614,6 @@ | ||
// Resizable support. This is usually on but the user can toggle it off. | ||
if (isResizable) newChild = this.mixinResizable(newChild, pos); | ||
newChild = this.mixinResizable(newChild, pos, isResizable); | ||
// Draggable support. This is always on, except for with placeholders. | ||
if (isDraggable) newChild = this.mixinDraggable(newChild); | ||
newChild = this.mixinDraggable(newChild, isDraggable); | ||
@@ -651,0 +620,0 @@ return newChild; |
// @flow | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import isEqual from "lodash.isequal"; | ||
@@ -15,7 +15,12 @@ import classNames from "classnames"; | ||
synchronizeLayoutWithChildren, | ||
validateLayout, | ||
getAllCollisions, | ||
noop | ||
compactType, | ||
noop, | ||
fastRGLPropsEqual | ||
} from "./utils"; | ||
import { calcXY } from "./calculateUtils"; | ||
import GridItem from "./GridItem"; | ||
import ReactGridLayoutPropTypes from "./ReactGridLayoutPropTypes"; | ||
import type { | ||
@@ -28,3 +33,2 @@ ChildrenArray as ReactChildrenArray, | ||
import type { | ||
EventCallback, | ||
CompactType, | ||
@@ -39,2 +43,4 @@ GridResizeEvent, | ||
import type { PositionParams } from "./calculateUtils"; | ||
type State = { | ||
@@ -55,49 +61,6 @@ activeDrag: ?LayoutItem, | ||
export type Props = { | ||
className: string, | ||
style: Object, | ||
width: number, | ||
autoSize: boolean, | ||
cols: number, | ||
draggableCancel: string, | ||
draggableHandle: string, | ||
verticalCompact: boolean, | ||
compactType: CompactType, | ||
layout: Layout, | ||
margin: [number, number], | ||
containerPadding: [number, number] | null, | ||
rowHeight: number, | ||
maxRows: number, | ||
isDraggable: boolean, | ||
isResizable: boolean, | ||
isDroppable: boolean, | ||
preventCollision: boolean, | ||
useCSSTransforms: boolean, | ||
transformScale: number, | ||
droppingItem: $Shape<LayoutItem>, | ||
import type { Props } from "./ReactGridLayoutPropTypes"; | ||
// Callbacks | ||
onLayoutChange: Layout => void, | ||
onDrag: EventCallback, | ||
onDragStart: EventCallback, | ||
onDragStop: EventCallback, | ||
onResize: EventCallback, | ||
onResizeStart: EventCallback, | ||
onResizeStop: EventCallback, | ||
onDrop: (itemPosition: { | ||
x: number, | ||
y: number, | ||
w: number, | ||
h: number | ||
}) => void, | ||
children: ReactChildrenArray<ReactElement<any>> | ||
}; | ||
// End Types | ||
const compactType = (props: Props): CompactType => { | ||
const { verticalCompact, compactType } = props || {}; | ||
return verticalCompact === false ? null : compactType; | ||
}; | ||
const layoutClassName = "react-grid-layout"; | ||
@@ -107,3 +70,3 @@ let isFirefox = false; | ||
try { | ||
isFirefox = navigator.userAgent.toLowerCase().includes("firefox"); | ||
isFirefox = /firefox/i.test(navigator.userAgent); | ||
} catch (e) { | ||
@@ -121,132 +84,5 @@ /* Ignore */ | ||
static propTypes = { | ||
// | ||
// Basic props | ||
// | ||
className: PropTypes.string, | ||
style: PropTypes.object, | ||
// Refactored to another module to make way for preval | ||
static propTypes = ReactGridLayoutPropTypes; | ||
// This can be set explicitly. If it is not set, it will automatically | ||
// be set to the container width. Note that resizes will *not* cause this to adjust. | ||
// If you need that behavior, use WidthProvider. | ||
width: PropTypes.number, | ||
// If true, the container height swells and contracts to fit contents | ||
autoSize: PropTypes.bool, | ||
// # of cols. | ||
cols: PropTypes.number, | ||
// A selector that will not be draggable. | ||
draggableCancel: PropTypes.string, | ||
// A selector for the draggable handler | ||
draggableHandle: PropTypes.string, | ||
// Deprecated | ||
verticalCompact: function(props: Props) { | ||
if ( | ||
props.verticalCompact === false && | ||
process.env.NODE_ENV !== "production" | ||
) { | ||
console.warn( | ||
// eslint-disable-line no-console | ||
"`verticalCompact` on <ReactGridLayout> is deprecated and will be removed soon. " + | ||
'Use `compactType`: "horizontal" | "vertical" | null.' | ||
); | ||
} | ||
}, | ||
// Choose vertical or hotizontal compaction | ||
compactType: PropTypes.oneOf(["vertical", "horizontal"]), | ||
// layout is an array of object with the format: | ||
// {x: Number, y: Number, w: Number, h: Number, i: String} | ||
layout: function(props: Props) { | ||
var layout = props.layout; | ||
// I hope you're setting the data-grid property on the grid items | ||
if (layout === undefined) return; | ||
validateLayout(layout, "layout"); | ||
}, | ||
// | ||
// Grid Dimensions | ||
// | ||
// Margin between items [x, y] in px | ||
margin: PropTypes.arrayOf(PropTypes.number), | ||
// Padding inside the container [x, y] in px | ||
containerPadding: PropTypes.arrayOf(PropTypes.number), | ||
// Rows have a static height, but you can change this based on breakpoints if you like | ||
rowHeight: PropTypes.number, | ||
// Default Infinity, but you can specify a max here if you like. | ||
// Note that this isn't fully fleshed out and won't error if you specify a layout that | ||
// extends beyond the row capacity. It will, however, not allow users to drag/resize | ||
// an item past the barrier. They can push items beyond the barrier, though. | ||
// Intentionally not documented for this reason. | ||
maxRows: PropTypes.number, | ||
// | ||
// Flags | ||
// | ||
isDraggable: PropTypes.bool, | ||
isResizable: PropTypes.bool, | ||
// If true, grid items won't change position when being dragged over. | ||
preventCollision: PropTypes.bool, | ||
// Use CSS transforms instead of top/left | ||
useCSSTransforms: PropTypes.bool, | ||
// parent layout transform scale | ||
transformScale: PropTypes.number, | ||
// If true, an external element can trigger onDrop callback with a specific grid position as a parameter | ||
isDroppable: PropTypes.bool, | ||
// | ||
// Callbacks | ||
// | ||
// Callback so you can save the layout. Calls after each drag & resize stops. | ||
onLayoutChange: PropTypes.func, | ||
// Calls when drag starts. Callback is of the signature (layout, oldItem, newItem, placeholder, e, ?node). | ||
// All callbacks below have the same signature. 'start' and 'stop' callbacks omit the 'placeholder'. | ||
onDragStart: PropTypes.func, | ||
// Calls on each drag movement. | ||
onDrag: PropTypes.func, | ||
// Calls when drag is complete. | ||
onDragStop: PropTypes.func, | ||
//Calls when resize starts. | ||
onResizeStart: PropTypes.func, | ||
// Calls when resize movement happens. | ||
onResize: PropTypes.func, | ||
// Calls when resize is complete. | ||
onResizeStop: PropTypes.func, | ||
// Calls when some element is dropped. | ||
onDrop: PropTypes.func, | ||
// | ||
// Other validations | ||
// | ||
droppingItem: PropTypes.shape({ | ||
i: PropTypes.string.isRequired, | ||
w: PropTypes.number.isRequired, | ||
h: PropTypes.number.isRequired | ||
}), | ||
// Children must not have duplicate keys. | ||
children: function(props: Props, propName: string) { | ||
var children = props[propName]; | ||
// Check children keys for duplicates. Throw if found. | ||
var keys = {}; | ||
React.Children.forEach(children, function(child) { | ||
if (keys[child.key]) { | ||
throw new Error( | ||
'Duplicate child key "' + | ||
child.key + | ||
'" found! This will cause problems in ReactGridLayout.' | ||
); | ||
} | ||
keys[child.key] = true; | ||
}); | ||
} | ||
}; | ||
static defaultProps = { | ||
@@ -368,2 +204,9 @@ autoSize: true, | ||
shouldComponentUpdate(nextProps: Props, nextState: State) { | ||
return ( | ||
!fastRGLPropsEqual(this.props, nextProps, isEqual) || | ||
!isEqual(this.state.activeDrag, nextState.activeDrag) | ||
); | ||
} | ||
componentDidUpdate(prevProps: Props, prevState: State) { | ||
@@ -472,2 +315,4 @@ if (!this.state.activeDrag) { | ||
onDragStop(i: string, x: number, y: number, { e, node }: GridDragEvent) { | ||
if (!this.state.activeDrag) return; | ||
const { oldDragItem } = this.state; | ||
@@ -491,6 +336,5 @@ let { layout } = this.state; | ||
); | ||
if (this.state.activeDrag) { | ||
this.props.onDragStop(layout, oldDragItem, l, null, e, node); | ||
} | ||
this.props.onDragStop(layout, oldDragItem, l, null, e, node); | ||
// Set state | ||
@@ -676,9 +520,13 @@ const newLayout = compact(layout, compactType(this.props), cols); | ||
// Parse 'static'. Any properties defined directly on the grid item will take precedence. | ||
const draggable = Boolean( | ||
!l.static && isDraggable && (l.isDraggable || l.isDraggable == null) | ||
); | ||
const resizable = Boolean( | ||
!l.static && isResizable && (l.isResizable || l.isResizable == null) | ||
); | ||
// Determine user manipulations possible. | ||
// If an item is static, it can't be manipulated by default. | ||
// Any properties defined directly on the grid item will take precedence. | ||
const draggable = | ||
typeof l.isDraggable === "boolean" | ||
? l.isDraggable | ||
: !l.static && isDraggable; | ||
const resizable = | ||
typeof l.isResizable === "boolean" | ||
? l.isResizable | ||
: !l.static && isResizable; | ||
@@ -723,8 +571,11 @@ return ( | ||
// Called while dragging an element. Part of browser native drag/drop API. | ||
// Native event target might be the layout itself, or an element within the layout. | ||
onDragOver = (e: DragOverEvent) => { | ||
// we should ignore events from layout's children in Firefox | ||
// to avoid unpredictable jumping of a dropping placeholder | ||
// FIXME remove this hack | ||
if ( | ||
isFirefox && | ||
!e.nativeEvent.target.className.includes(layoutClassName) | ||
e.nativeEvent.target.className.indexOf(layoutClassName) === -1 | ||
) { | ||
@@ -734,8 +585,34 @@ return false; | ||
const { droppingItem } = this.props; | ||
const { | ||
droppingItem, | ||
margin, | ||
cols, | ||
rowHeight, | ||
maxRows, | ||
width, | ||
containerPadding | ||
} = this.props; | ||
const { layout } = this.state; | ||
// This is relative to the DOM element that this event fired for. | ||
const { layerX, layerY } = e.nativeEvent; | ||
const droppingPosition = { x: layerX, y: layerY, e }; | ||
const droppingPosition = { left: layerX, top: layerY, e }; | ||
if (!this.state.droppingDOMNode) { | ||
const positionParams: PositionParams = { | ||
cols, | ||
margin, | ||
maxRows, | ||
rowHeight, | ||
containerWidth: width, | ||
containerPadding: containerPadding || margin | ||
}; | ||
const calculatedPosition = calcXY( | ||
positionParams, | ||
layerY, | ||
layerX, | ||
droppingItem.w, | ||
droppingItem.h | ||
); | ||
this.setState({ | ||
@@ -748,4 +625,4 @@ droppingDOMNode: <div key={droppingItem.i} />, | ||
...droppingItem, | ||
x: 0, | ||
y: 0, | ||
x: calculatedPosition.x, | ||
y: calculatedPosition.y, | ||
static: false, | ||
@@ -757,6 +634,7 @@ isDraggable: true | ||
} else if (this.state.droppingPosition) { | ||
const shouldUpdatePosition = | ||
this.state.droppingPosition.x != layerX || | ||
this.state.droppingPosition.y != layerY; | ||
shouldUpdatePosition && this.setState({ droppingPosition }); | ||
const { left, top } = this.state.droppingPosition; | ||
const shouldUpdatePosition = left != layerX || top != layerY; | ||
if (shouldUpdatePosition) { | ||
this.setState({ droppingPosition }); | ||
} | ||
} | ||
@@ -803,3 +681,3 @@ | ||
onDrop = () => { | ||
onDrop = (e: Event) => { | ||
const { droppingItem } = this.props; | ||
@@ -814,3 +692,3 @@ const { layout } = this.state; | ||
this.props.onDrop({ x, y, w, h }); | ||
this.props.onDrop({ x, y, w, h, e }); | ||
}; | ||
@@ -817,0 +695,0 @@ |
@@ -18,3 +18,3 @@ // @flow | ||
import ReactGridLayout from "./ReactGridLayout"; | ||
import type { Props as RGLProps } from "./ReactGridLayout"; | ||
import type { Props as RGLProps } from "./ReactGridLayoutPropTypes"; | ||
import type { Layout } from "./utils"; | ||
@@ -207,3 +207,3 @@ | ||
) { | ||
this.onWidthChange(this.props); | ||
this.onWidthChange(prevProps); | ||
} | ||
@@ -224,10 +224,11 @@ } | ||
*/ | ||
onWidthChange(nextProps: Props<*>) { | ||
const { breakpoints, cols, layouts, compactType } = nextProps; | ||
onWidthChange(prevProps: Props<*>) { | ||
const { breakpoints, cols, layouts, compactType } = this.props; | ||
const newBreakpoint = | ||
nextProps.breakpoint || | ||
getBreakpointFromWidth(nextProps.breakpoints, nextProps.width); | ||
this.props.breakpoint || | ||
getBreakpointFromWidth(this.props.breakpoints, this.props.width); | ||
const lastBreakpoint = this.state.breakpoint; | ||
const newCols: number = getColsFromBreakpoint(newBreakpoint, cols); | ||
const newLayouts = { ...layouts }; | ||
@@ -237,12 +238,12 @@ // Breakpoint change | ||
lastBreakpoint !== newBreakpoint || | ||
this.props.breakpoints !== breakpoints || | ||
this.props.cols !== cols | ||
prevProps.breakpoints !== breakpoints || | ||
prevProps.cols !== cols | ||
) { | ||
// Preserve the current layout if the current breakpoint is not present in the next layouts. | ||
if (!(lastBreakpoint in layouts)) | ||
layouts[lastBreakpoint] = cloneLayout(this.state.layout); | ||
if (!(lastBreakpoint in newLayouts)) | ||
newLayouts[lastBreakpoint] = cloneLayout(this.state.layout); | ||
// Find or generate a new layout. | ||
let layout = findOrGenerateResponsiveLayout( | ||
layouts, | ||
newLayouts, | ||
breakpoints, | ||
@@ -258,3 +259,3 @@ newBreakpoint, | ||
layout, | ||
nextProps.children, | ||
this.props.children, | ||
newCols, | ||
@@ -265,6 +266,6 @@ compactType | ||
// Store the new layout. | ||
layouts[newBreakpoint] = layout; | ||
newLayouts[newBreakpoint] = layout; | ||
// callbacks | ||
this.props.onLayoutChange(layout, layouts); | ||
this.props.onLayoutChange(layout, newLayouts); | ||
this.props.onBreakpointChange(newBreakpoint, newCols); | ||
@@ -279,5 +280,5 @@ | ||
const margin = getIndentationValue(nextProps.margin, newBreakpoint); | ||
const margin = getIndentationValue(this.props.margin, newBreakpoint); | ||
const containerPadding = getIndentationValue( | ||
nextProps.containerPadding, | ||
this.props.containerPadding, | ||
newBreakpoint | ||
@@ -288,3 +289,3 @@ ); | ||
this.props.onWidthChange( | ||
nextProps.width, | ||
this.props.width, | ||
margin, | ||
@@ -291,0 +292,0 @@ newCols, |
@@ -41,3 +41,3 @@ // @flow | ||
export type PartialPosition = { left: number, top: number }; | ||
export type DroppingPosition = { x: number, y: number, e: Event }; | ||
export type DroppingPosition = { left: number, top: number, e: Event }; | ||
export type Size = { width: number, height: number }; | ||
@@ -133,2 +133,23 @@ export type GridDragEvent = { | ||
/** | ||
* See `fastRGLPropsEqual.js`. | ||
* We want this to run as fast as possible - it is called often - and to be | ||
* resilient to new props that we add. So rather than call lodash.isEqual, | ||
* which isn't suited to comparing props very well, we use this specialized | ||
* function in conjunction with preval to generate the fastest possible comparison | ||
* function, tuned for exactly our props. | ||
*/ | ||
type FastRGLPropsEqual = (Object, Object, Function) => boolean; | ||
export const fastRGLPropsEqual: FastRGLPropsEqual = require("./fastRGLPropsEqual"); | ||
// Like the above, but a lot simpler. | ||
export function fastPositionEqual(a: Position, b: Position) { | ||
return ( | ||
a.left === b.left && | ||
a.top === b.top && | ||
a.width === b.width && | ||
a.height === b.height | ||
); | ||
} | ||
/** | ||
* Given two layoutitems, check if they collide. | ||
@@ -371,3 +392,5 @@ */ | ||
): Layout { | ||
if (l.static) return layout; | ||
// If this is static and not explicitly enabled as draggable, | ||
// no move is possible, so we can short-circuit this immediately. | ||
if (l.static && l.isDraggable !== true) return layout; | ||
@@ -688,2 +711,10 @@ // Short-circuit if nothing to do. | ||
// Legacy support for verticalCompact: false | ||
export function compactType( | ||
props: ?{ verticalCompact: boolean, compactType: CompactType } | ||
): CompactType { | ||
const { verticalCompact, compactType } = props || {}; | ||
return verticalCompact === false ? null : compactType; | ||
} | ||
// Flow can't really figure this out, so we just use Object | ||
@@ -690,0 +721,0 @@ export function autoBindHandlers(el: Object, fns: Array<string>): void { |
{ | ||
"name": "react-grid-layout", | ||
"version": "0.17.1", | ||
"version": "0.18.0", | ||
"description": "A draggable and resizable grid layout with responsive breakpoints, for React.", | ||
@@ -15,4 +15,3 @@ "main": "index.js", | ||
"validate": "npm ls", | ||
"flow": "flow", | ||
"precommit": "lint-staged && make lint" | ||
"flow": "flow" | ||
}, | ||
@@ -47,36 +46,37 @@ "repository": { | ||
"devDependencies": { | ||
"@babel/cli": "^7.6.4", | ||
"@babel/core": "^7.6.4", | ||
"@babel/plugin-proposal-class-properties": "^7.5.5", | ||
"@babel/plugin-transform-flow-comments": "^7.6.0", | ||
"@babel/preset-env": "^7.6.0", | ||
"@babel/preset-flow": "^7.0.0", | ||
"@babel/preset-react": "^7.0.0", | ||
"@babel/cli": "^7.8.0", | ||
"@babel/core": "^7.8.0", | ||
"@babel/plugin-proposal-class-properties": "^7.8.0", | ||
"@babel/plugin-transform-flow-comments": "^7.8.0", | ||
"@babel/preset-env": "^7.8.2", | ||
"@babel/preset-flow": "^7.8.0", | ||
"@babel/preset-react": "^7.8.0", | ||
"@babel/register": "^7.8.0", | ||
"babel-eslint": "^10.0.3", | ||
"babel-jest": "^24.9.0", | ||
"babel-loader": "^8.0.6", | ||
"babel-plugin-espower": "^3.0.1", | ||
"css-loader": "^3.2.0", | ||
"ejs": "^2.7.1", | ||
"eslint": "^6.4.0", | ||
"eslint-plugin-flowtype": "^4.3.0", | ||
"eslint-plugin-mocha": "^6.2.0", | ||
"eslint-plugin-react": "^7.14.3", | ||
"babel-plugin-preval": "^4.0.0", | ||
"css-loader": "^3.4.2", | ||
"ejs": "^3.0.1", | ||
"eslint": "^6.8.0", | ||
"eslint-plugin-flowtype": "^4.6.0", | ||
"eslint-plugin-mocha": "^6.2.2", | ||
"eslint-plugin-react": "^7.17.0", | ||
"exports-loader": "^0.7.0", | ||
"flow-bin": "^0.110.1", | ||
"flow-bin": "^0.115.0", | ||
"husky": "^3.0.9", | ||
"imports-loader": "^0.8.0", | ||
"jest-cli": "^24.9.0", | ||
"lint-staged": "^9.2.5", | ||
"lint-staged": "^9.5.0", | ||
"lodash": "^4.17.5", | ||
"opener": "^1.4.3", | ||
"prettier": "^1.18.2", | ||
"react": "^16.11.0", | ||
"react-dom": "^16.11.0", | ||
"react-hot-loader": "^4.12.13", | ||
"prettier": "^1.19.1", | ||
"react": "^16.12.0", | ||
"react-dom": "^16.12.0", | ||
"react-hot-loader": "^4.12.18", | ||
"react-transform-hmr": "^1.0.2", | ||
"style-loader": "^1.0.0", | ||
"webpack": "^4.41.2", | ||
"webpack-cli": "^3.3.9", | ||
"webpack-dev-server": "^3.9.0" | ||
"style-loader": "^1.1.2", | ||
"webpack": "^4.41.5", | ||
"webpack-cli": "^3.3.10", | ||
"webpack-dev-server": "^3.10.1" | ||
}, | ||
@@ -97,3 +97,8 @@ "publishConfig": { | ||
] | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged && make lint && make test" | ||
} | ||
} | ||
} |
@@ -32,2 +32,3 @@ # React-Grid-Layout | ||
- [Grid Item Props](#grid-item-props) | ||
- [Users recipes](../../wiki/Users-recipes) | ||
- [Contribute](#contribute) | ||
@@ -70,2 +71,3 @@ - [TODO List](#todo-list) | ||
- [Quadency](https://quadency.com/) | ||
- [Hakkiri](https://www.hakkiri.io) | ||
@@ -92,2 +94,3 @@ *Know of others? Create a PR to let me know!* | ||
|----------------|------------------| | ||
| >= 0.17.0 | React 0.16 | | ||
| >= 0.11.3 | React 0.14 & v15 | | ||
@@ -128,3 +131,3 @@ | >= 0.10.0 | React 0.14 | | ||
// layout is an array of objects, see the demo for more complete usage | ||
var layout = [ | ||
const layout = [ | ||
{i: 'a', x: 0, y: 0, w: 1, h: 2, static: true}, | ||
@@ -178,3 +181,3 @@ {i: 'b', x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4}, | ||
// {lg: layout1, md: layout2, ...} | ||
var layouts = getLayoutsFromSomewhere(); | ||
const layouts = getLayoutsFromSomewhere(); | ||
return ( | ||
@@ -295,3 +298,3 @@ <ResponsiveGridLayout className="layout" layouts={layouts} | ||
// Configuration of a dropping element. Dropping element is a "virtual" element | ||
// Configuration of a dropping element. Dropping element is a "virtual" element | ||
// which appears when you drag over some element from outside. | ||
@@ -320,5 +323,5 @@ // It can be changed by passing specific parameters: | ||
// If true, droppable elements (with `draggable={true}` attribute) | ||
// If true, droppable elements (with `draggable={true}` attribute) | ||
// can be dropped on the grid. It triggers "onDrop" callback | ||
// with position and event object as parameters. | ||
// with position and event object as parameters. | ||
// It can be useful for dropping an element in a specific position | ||
@@ -361,3 +364,3 @@ // | ||
// Calls when some element has been dropped | ||
onDrop: (elemParams: { x: number, y: number, e: Event }) => void | ||
onDrop: (elemParams: { x: number, y: number, w: number, h: number, e: Event }) => void | ||
``` | ||
@@ -424,3 +427,3 @@ | ||
example, if the layout has the property `isDraggable: false`, but the grid item has the prop `isDraggable: true`, the item | ||
will be draggable. | ||
will be draggable, even if the item is marked `static: true`. | ||
@@ -427,0 +430,0 @@ ```js |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
239205
33
5364
468
35
1
4
1