UNPKG

@wix/design-system

Version:

@wix/design-system

252 lines (249 loc) 9.03 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _utils = require("./utils"); var _DragLayer = _interopRequireDefault(require("./DragLayer")); var _Container = _interopRequireDefault(require("./Container")); 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.js"; function replaceNegativeIndex(items, nextPosition, childrenProperty) { var currItems = items; return nextPosition.map(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((nextIndex, i) => { if (typeof prev[i] !== 'number') { return nextIndex; } return nextIndex > prev[i] ? nextIndex - 1 : nextIndex; }); } return next; } class NestableListBase extends _react.default.PureComponent { constructor() { super(...arguments); this.state = { items: this.props.items, dragging: false }; // 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 = _ref => { var { dragItem, prevPosition, nextPosition } = _ref; var { childrenProperty, preventChangeDepth, preventChangeParent, enforcePinnedOrder, items } = this.props; 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 = item => { var _this$props$onUpdate, _this$props; (_this$props$onUpdate = (_this$props = this.props).onUpdate) == null || _this$props$onUpdate.call(_this$props, { items: this.state.items, item }); }; this.onDragStart = itemProps => { var _this$props$onDragSta, _this$props2; this.setState({ dragging: true }); (_this$props$onDragSta = (_this$props2 = this.props).onDragStart) == null || _this$props$onDragSta.call(_this$props2, itemProps); }; this.onDragEnd = itemProps => { var _this$props$onDragEnd, _this$props3; this.setState({ dragging: false }); (_this$props$onDragEnd = (_this$props3 = this.props).onDragEnd) == null || _this$props$onDragEnd.call(_this$props3, itemProps); }; } // 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 UNSAFE_componentWillReceiveProps(newProps) { if (newProps.items !== this.state.items) { this.setState({ items: newProps.items }); this._items = newProps.items; } } render() { var { items } = this.state; var { renderItem, readOnly, childrenProperty, childrenStyle, renderAction, isRenderDraggingChildren, useDragHandle, maxDepth, preventChangeDepth, preventChangeParent, enforcePinnedOrder, threshold, theme, renderPrefix, dragLayerZIndex, zIndex } = this.props; return /*#__PURE__*/_react.default.createElement(_NestableListBaseContext.NestableListBaseContext.Provider, { value: { groupName: this.groupName, useDragHandle, maxDepth, preventChangeDepth, preventChangeParent, enforcePinnedOrder, threshold, readOnly, renderItem, renderPrefix, moveItem: this.moveItem, dropItem: this.dropItem, onDragStart: this.onDragStart, onDragEnd: this.onDragEnd }, __self: this, __source: { fileName: _jsxFileName, lineNumber: 205, columnNumber: 7 } }, /*#__PURE__*/_react.default.createElement("div", { __self: this, __source: { fileName: _jsxFileName, lineNumber: 223, columnNumber: 9 } }, /*#__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: 224, columnNumber: 11 } }), this.state.dragging && /*#__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: 236, columnNumber: 13 } }))); } } NestableListBase.defaultProps = { items: [], isRenderDraggingChildren: false, childrenProperty: 'children', childrenStyle: {}, renderPrefix: () => null, renderAction: () => null, onUpdate: () => {}, useDragHandle: false, preventChangeDepth: false, preventChangeParent: false, enforcePinnedOrder: false, maxDepth: Infinity, threshold: 30, dragLayerZIndex: _ZIndex.ZIndex.nestableListDragLayer }; var _default = exports.default = (0, _withDNDContext.default)(NestableListBase); //# sourceMappingURL=NestableListBase.js.map