@wix/design-system
Version:
@wix/design-system
325 lines (322 loc) • 13.8 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports["default"] = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _react = _interopRequireDefault(require("react"));
var _utils = require("./utils");
var _DragLayer = _interopRequireDefault(require("./DragLayer"));
var _Container = _interopRequireDefault(require("./Container"));
var _VirtualContainer = _interopRequireDefault(require("./VirtualContainer"));
var _AutoScroller = _interopRequireDefault(require("./AutoScroller"));
var _NestableListBaseContext = require("./NestableListBaseContext");
var _withDNDContext = _interopRequireDefault(require("./withDNDContext"));
var _ZIndex = require("../common/ZIndex");
var _jsxFileName = "/home/builduser/work/57e038ea7326c1ec/packages/wix-design-system/dist/cjs/NestableListBase/NestableListBase.jsx";
function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2["default"])(o), (0, _possibleConstructorReturn2["default"])(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2["default"])(t).constructor) : o.apply(t, e)); }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
function replaceNegativeIndex(items, nextPosition, childrenProperty) {
var currItems = items;
return nextPosition.map(function (nextIndex) {
if (nextIndex !== -1) {
currItems = currItems[nextIndex][childrenProperty] || [];
return nextIndex;
}
return currItems.length;
});
}
// fixing a bug where the new path is increased in nesting
// and the first position jumps too far by 2, and that's why it decreased by 1
// need to check if the jump can become more severe
function getRealNextPosition(prev, next) {
// moving up a level
if (prev.length < next.length) {
return next.map(function (nextIndex, i) {
if (typeof prev[i] !== 'number') {
return nextIndex;
}
return nextIndex > prev[i] ? nextIndex - 1 : nextIndex;
});
}
return next;
}
var NestableListBase = /*#__PURE__*/function (_React$PureComponent) {
function NestableListBase() {
var _this;
(0, _classCallCheck2["default"])(this, NestableListBase);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _callSuper(this, NestableListBase, [].concat(args));
_this.state = {
items: _this.props.items,
dragging: false
};
_this.containerRef = /*#__PURE__*/_react["default"].createRef();
// drag and drop between multiple nestable lists is not supported
// according to prevent it for now was created groupName - unique value for every nestable list
// somethings similar exists in SortableListBase component.
_this.groupName = (0, _utils.generateUniqueGroupId)();
// FIXME: reference to latest `state.items`. This is a workaround for issue
// with `moveItem` where it updates `state.items` and if the update occurs
// multiple times before the component re-renders, the `state.items` will be
// be updated based on the previous state, not the latest one, which in some
// cases leads to item duplication or removal.
// This should be solved by not referring to current state by `this.state` and
// instead providing callback to `setState` that receives the latest state.
// However, due to architectural decisions this is not possible without
// rewriting the whole component as `moveItem` must return new position of the
// dragged item which is then used by the item itself to update its state.
_this._items = _this.props.items;
_this.moveItem = function (_ref) {
var dragItem = _ref.dragItem,
prevPosition = _ref.prevPosition,
nextPosition = _ref.nextPosition;
var _this$props = _this.props,
childrenProperty = _this$props.childrenProperty,
preventChangeDepth = _this$props.preventChangeDepth,
preventChangeParent = _this$props.preventChangeParent,
enforcePinnedOrder = _this$props.enforcePinnedOrder,
items = _this$props.items;
if (dragItem.preventItemChangeDepth && nextPosition.length !== prevPosition.length) {
return prevPosition;
}
if (preventChangeDepth && nextPosition.length > 1) {
var parent = (0, _utils.getDropParent)(items, nextPosition, childrenProperty);
if (!parent) {
return prevPosition;
}
}
if (preventChangeParent) {
var prevParentPath = prevPosition.slice(0, -1);
var nextParentPath = nextPosition.slice(0, -1);
var prevParent = (0, _utils.getDropParent)(items, prevParentPath, childrenProperty);
var nextParent = (0, _utils.getDropParent)(items, nextParentPath, childrenProperty);
if ((prevParent == null ? void 0 : prevParent.id) !== (nextParent == null ? void 0 : nextParent.id)) {
return prevPosition;
}
}
var newItems = _this._items;
// the remove action might affect the next position,
// so update next coordinates accordingly
var realNextPosition = getRealNextPosition(prevPosition, nextPosition);
if (enforcePinnedOrder) {
var shouldProhibitPinMoveDown = !!dragItem.isPinned && !realNextPosition.isPinned;
var shouldProhibitNonPinMoveUp = !dragItem.isPinned && !!realNextPosition.isPinned;
if (shouldProhibitPinMoveDown && shouldProhibitNonPinMoveUp) {
return prevPosition;
}
}
if (realNextPosition[realNextPosition.length - 1] === -1) {
realNextPosition = replaceNegativeIndex(newItems, realNextPosition, childrenProperty);
}
newItems = (0, _utils.removeFromTree)(newItems, prevPosition, childrenProperty);
newItems = (0, _utils.addToTree)(newItems, dragItem, realNextPosition, childrenProperty);
_this._items = newItems;
_this.setState({
items: newItems
});
return realNextPosition;
};
_this.dropItem = function (item) {
_this.props.onUpdate == null || _this.props.onUpdate({
items: _this.state.items,
item: item
});
};
_this.onDragStart = function (itemProps) {
_this.setState({
dragging: true
});
_this.props.onDragStart == null || _this.props.onDragStart(itemProps);
};
_this.onDragEnd = function (itemProps) {
_this.setState({
dragging: false
});
_this.props.onDragEnd == null || _this.props.onDragEnd(itemProps);
};
return _this;
}
(0, _inherits2["default"])(NestableListBase, _React$PureComponent);
return (0, _createClass2["default"])(NestableListBase, [{
key: "UNSAFE_componentWillReceiveProps",
value:
// tried to use getDerivedStateFromProps but encounter an issue where the state was
// updated internally but props items stayed the same and it caused the new state to be
// overridden with the old state
// can be done if component is controlled but requires refactor
function UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.items !== this.state.items && !this.state.dragging) {
this.setState({
items: newProps.items
});
this._items = newProps.items;
}
}
}, {
key: "render",
value: function render() {
var items = this.state.items;
var _this$props2 = this.props,
renderItem = _this$props2.renderItem,
readOnly = _this$props2.readOnly,
childrenProperty = _this$props2.childrenProperty,
childrenStyle = _this$props2.childrenStyle,
renderAction = _this$props2.renderAction,
isRenderDraggingChildren = _this$props2.isRenderDraggingChildren,
useDragHandle = _this$props2.useDragHandle,
maxDepth = _this$props2.maxDepth,
preventChangeDepth = _this$props2.preventChangeDepth,
preventChangeParent = _this$props2.preventChangeParent,
enforcePinnedOrder = _this$props2.enforcePinnedOrder,
canDrop = _this$props2.canDrop,
threshold = _this$props2.threshold,
theme = _this$props2.theme,
renderPrefix = _this$props2.renderPrefix,
dragLayerZIndex = _this$props2.dragLayerZIndex,
zIndex = _this$props2.zIndex,
virtualized = _this$props2.virtualized,
itemHeight = _this$props2.itemHeight,
viewportHeight = _this$props2.viewportHeight,
offscreenRowCount = _this$props2.offscreenRowCount,
pinnedItemId = _this$props2.pinnedItemId;
var useVirtualized = virtualized && Number(itemHeight) > 0 && Number(viewportHeight) > 0;
if (virtualized && !useVirtualized) {
console.warn('NestableListBase: `virtualized` requires both `itemHeight` and ' + '`viewportHeight` to be positive numbers. Falling back to ' + 'non-virtualized rendering.');
}
var dragOverlay = this.state.dragging && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, {
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 230,
columnNumber: 7
}
}, /*#__PURE__*/_react["default"].createElement(_DragLayer["default"], {
siblings: items,
isRenderDraggingChildren: isRenderDraggingChildren,
renderItem: renderItem,
childrenProperty: childrenProperty,
childrenStyle: childrenStyle,
theme: theme,
dragLayerZIndex: zIndex !== null && zIndex !== void 0 ? zIndex : dragLayerZIndex,
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 231,
columnNumber: 9
}
}), /*#__PURE__*/_react["default"].createElement(_AutoScroller["default"], {
containerRef: this.containerRef,
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 240,
columnNumber: 9
}
}));
return /*#__PURE__*/_react["default"].createElement(_NestableListBaseContext.NestableListBaseContext.Provider, {
value: {
groupName: this.groupName,
useDragHandle: useDragHandle,
maxDepth: maxDepth,
preventChangeDepth: preventChangeDepth,
preventChangeParent: preventChangeParent,
enforcePinnedOrder: enforcePinnedOrder,
canDrop: canDrop,
threshold: threshold,
readOnly: readOnly,
renderItem: renderItem,
renderPrefix: renderPrefix,
moveItem: this.moveItem,
dropItem: this.dropItem,
onDragStart: this.onDragStart,
onDragEnd: this.onDragEnd
},
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 245,
columnNumber: 7
}
}, useVirtualized ? /*#__PURE__*/_react["default"].createElement("div", {
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 265,
columnNumber: 11
}
}, /*#__PURE__*/_react["default"].createElement(_VirtualContainer["default"], {
ref: this.containerRef,
items: items,
renderAction: renderAction,
childrenProperty: childrenProperty,
childrenStyle: childrenStyle,
isRenderDraggingChildren: isRenderDraggingChildren,
theme: theme,
itemHeight: itemHeight,
viewportHeight: viewportHeight,
offscreenRowCount: offscreenRowCount,
pinnedItemId: pinnedItemId,
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 266,
columnNumber: 13
}
}), dragOverlay) : /*#__PURE__*/_react["default"].createElement("div", {
ref: this.containerRef,
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 282,
columnNumber: 11
}
}, /*#__PURE__*/_react["default"].createElement(_Container["default"], {
treeDepth: 1,
items: items,
renderAction: renderAction,
parentPosition: [],
childrenProperty: childrenProperty,
childrenStyle: childrenStyle,
isRenderDraggingChildren: isRenderDraggingChildren,
topLevel: true,
theme: theme,
__self: this,
__source: {
fileName: _jsxFileName,
lineNumber: 283,
columnNumber: 13
}
}), dragOverlay));
}
}]);
}(_react["default"].PureComponent);
NestableListBase.displayName = 'NestableListBase';
NestableListBase.defaultProps = {
items: [],
isRenderDraggingChildren: false,
childrenProperty: 'children',
childrenStyle: {},
renderPrefix: function renderPrefix() {
return null;
},
renderAction: function renderAction() {
return null;
},
onUpdate: function onUpdate() {},
useDragHandle: false,
preventChangeDepth: false,
preventChangeParent: false,
enforcePinnedOrder: false,
maxDepth: Infinity,
threshold: 30,
dragLayerZIndex: _ZIndex.ZIndex.nestableListDragLayer,
virtualized: false,
offscreenRowCount: 5
};
var _default = exports["default"] = (0, _withDNDContext["default"])(NestableListBase);