@wix/design-system
Version:
@wix/design-system
252 lines (249 loc) • 9.03 kB
JavaScript
"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