UNPKG

@wix/design-system

Version:

@wix/design-system

614 lines (584 loc) 23.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports["default"] = exports.DropItemTarget = exports.DragItemSource = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); 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 _reactDnd = require("react-dnd"); var _itemTypes = _interopRequireDefault(require("./itemTypes")); var _utils = require("./utils"); var _NestableListBaseContext = require("./NestableListBaseContext"); var _DragUtils = require("../DragAndDrop/Draggable/DragUtils"); var _classnames = _interopRequireDefault(require("classnames")); var _constants = require("../DragAndDrop/Draggable/constants"); var _jsxFileName = "/home/builduser/work/57e038ea7326c1ec/packages/wix-design-system/dist/cjs/NestableListBase/Item.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; })(); } // keep track of horizontal mouse movement var mouse = { lastX: 0 }; function increaseHorizontalLevel(prevPosition, prevIndex) { var nextPosition = prevPosition.slice(0, -1); // append to prevSibling's children nextPosition.push(prevIndex - 1, -1); return nextPosition; } function decreaseHorizontalLevel(prevPosition) { var nextPosition = prevPosition.slice(0, -1); nextPosition[nextPosition.length - 1] += 1; return nextPosition; } function calculateHandleOffset(handleRect, containerRect) { return { x: handleRect.x - containerRect.x, y: handleRect.y - containerRect.y }; } var cardSource = { isDragging: function isDragging(props, monitor) { var ids = (0, _utils.getValuesByKey)(monitor.getItem().data, 'id', 'children'); return ids.indexOf(props.id) > -1; }, beginDrag: function beginDrag(props, monitor, component) { props.onDragStart && props.onDragStart(props); var node = component.rootRef.current; if (!node) { return null; } var clientRect = node.getBoundingClientRect(); var handleOffset = { x: 0, y: 0 }; // needed to fix dnd drag offset data if (component.handleNode) { handleOffset = calculateHandleOffset(component.handleNode.getBoundingClientRect(), clientRect); } return { id: props.id, dragged: false, // needed for workaround of immediately fired dragend event after dragstart index: props.index, position: props.position, data: props.item, groupName: props.groupName, depth: props.depth, // rect for entire component including children clientRect: clientRect, handleOffset: handleOffset }; }, endDrag: function endDrag(props, monitor) { mouse.lastX = 0; props.dropItem(monitor.getItem()); props.onDragEnd && props.onDragEnd(props); } }; var determineHorizontalPosition = function determineHorizontalPosition(_ref) { var monitor = _ref.monitor, props = _ref.props, hoverNode = _ref.hoverNode; var item = monitor.getItem(); // the item being dragged var prevPosition = item.position, dragDepth = item.depth, prevIndex = item.index; // props for component underneath drag var hoverPosition = props.position, hoverSiblings = props.siblings, maxDepth = props.maxDepth, threshold = props.threshold; // determine mouse position var clientOffset = monitor.getClientOffset() || { x: 0, y: 0 }; var initialClientOffset = monitor.getInitialClientOffset() || { x: 0, y: 0 }; // rect for entire component including children var hoverClientRect = hoverNode.getBoundingClientRect(); var isOverSelf = (0, _utils.hoverAboveItself)(prevPosition, hoverPosition); // set mouse.lastX if it isn't set yet (first hover event) mouse.lastX = mouse.lastX || initialClientOffset.x; var currMouseX = clientOffset.x; var mouseDistanceX = currMouseX - mouse.lastX; var nearLeftEdge = currMouseX < hoverClientRect.left + 10; var currentIndex = props.index; // nextPosition will be overwritten when moving horizontally var nextPosition = hoverPosition; // disable horizontal movement is previous sibling has lockDropArea=true prop if (isOverSelf && currentIndex !== 0 && !!hoverSiblings[currentIndex - 1].lockDropArea && mouseDistanceX > 0) { return nextPosition; } // disable horizontal movement is next sibling has lockDropArea=true prop if (isOverSelf && currentIndex < hoverSiblings.length - 2 && !!hoverSiblings[currentIndex + 1].lockDropArea && mouseDistanceX < 0) { return nextPosition; } // moving horizontally if (isOverSelf && (nearLeftEdge || Math.abs(mouseDistanceX) >= threshold)) { // reset lastX for new phase mouse.lastX = currMouseX; // increase horizontal level if (mouseDistanceX > 0 && // has previous sibling prevIndex - 1 >= 0 && // isn't at max depth prevPosition.length + dragDepth - 1 !== maxDepth) { nextPosition = increaseHorizontalLevel(prevPosition, prevIndex); } // decrease horizontal level if (mouseDistanceX < 0 && // is nested prevPosition.length > 1 && // is last item in array prevIndex === hoverSiblings.length - 1) { nextPosition = decreaseHorizontalLevel(prevPosition); } } if (props.preventChangeDepth && nextPosition.length - prevPosition.length === -1 // means that new parent is suitable for current dragged item ) { var isSameParent = nextPosition.every(function (position, depth) { return prevPosition[depth] === position; }); if (!isSameParent) { nextPosition = prevPosition.map(function (position, depth) { return nextPosition[depth] !== undefined ? nextPosition[depth] : 0; }); } } return nextPosition; }; var allowItemMove = function allowItemMove(_ref2) { var prevPosition = _ref2.prevPosition, nextPosition = _ref2.nextPosition, monitor = _ref2.monitor, hoverNode = _ref2.hoverNode, props = _ref2.props; // don't replace items with themselves if ((0, _utils.hoverAboveItself)(prevPosition, nextPosition)) { return; } // prevent drop if preventChangeDepth and depth is changed if (props.preventChangeDepth && nextPosition.length !== prevPosition.length) { return; } // Prevent drag drop, if parent has been changed if (props.preventChangeParent) { var prevParentPath = prevPosition.slice(0, -1); var nextParentPath = nextPosition.slice(0, -1); if (prevParentPath.length !== nextParentPath.length || !prevParentPath.every(function (val, i) { return Object.is(val, nextParentPath == null ? void 0 : nextParentPath[i]); })) { return; } } // Prevent drag drop, if element move outside pinned elements if (props.enforcePinnedOrder) { var prevIndex = prevPosition[prevPosition.length - 1]; var targetIndex = nextPosition[nextPosition.length - 1]; var prev = props.siblings[prevIndex]; var next = props.siblings[targetIndex]; if (!!prev.isPinned && !next.isPinned || !prev.isPinned && !!next.isPinned) { return; } } // Consumer-provided per-position validation if (props.canDrop) { var dragItem = monitor.getItem().data; var hoverItem = props.item; if (!props.canDrop(dragItem, hoverItem)) { return; } } var hoverPosition = props.position; var isOverSelf = (0, _utils.hoverAboveItself)(prevPosition, hoverPosition); var clientOffset = monitor.getClientOffset() || { x: 0, y: 0 }; // rect for entire component including children var hoverClientRect = hoverNode.getBoundingClientRect(); // rect for item without children var hoverItemClientRect = hoverNode.children[0].getBoundingClientRect(); // get vertical middle var hoverMiddleY = (hoverClientRect.bottom - hoverClientRect.top) / 2; // get pixels to the top var hoverClientY = clientOffset.y - hoverClientRect.top; // dragging child item to another position with same parent if (nextPosition.length === prevPosition.length) { var last = nextPosition.length - 1; var previousIndex = prevPosition[last]; var nextIndex = nextPosition[last]; // only perform the move when the mouse has crossed half of the items height // when dragging downwards, only move when the cursor is below 50% // when dragging upwards, only move when the cursor is above 50% // dragging downwards if (previousIndex < nextIndex && hoverClientY < hoverMiddleY) { return; } // dragging upwards if (previousIndex > nextIndex && hoverClientY > hoverMiddleY) { return; } } else if ( // dragging child item over parent item nextPosition.length < prevPosition.length && nextPosition[nextPosition.length - 1] === prevPosition[prevPosition.length - 2]) { var hoverItemMiddleY = (hoverItemClientRect.bottom - hoverItemClientRect.top) / 2; // cancel if hovering in lower half of parent item if (hoverClientY > hoverItemMiddleY) { return; } } else if (!isOverSelf && clientOffset.y > hoverItemClientRect.bottom) { // cancel if over a nested target that isn't its own child return; } return true; }; var cardTarget = { canDrop: function canDrop(props, monitor) { if (!props.canDrop) { return true; } var item = monitor.getItem(); if (!item) { return true; } return props.canDrop(item.data, props.item); }, hover: function hover(props, monitor, component) { // prevent drag and drop between different groups. // currently drag and drop between multiple nestable lists is not supported if (monitor.getItem().groupName !== props.groupName) { return; } var item = monitor.getItem(); // the item being dragged var prevPosition = item.position, dragItem = item.data, dragDepth = item.depth; // props for component underneath drag var hoverPosition = props.position, maxDepth = props.maxDepth; var hoverDepth = hoverPosition.length - 1; var totalDepth = hoverDepth + dragDepth; // don't exceed max depth if (totalDepth > maxDepth) { return; } var hoverNode = component.rootRef.current; if (!hoverNode) { return; } var nextPosition = determineHorizontalPosition({ monitor: monitor, props: props, hoverNode: hoverNode }); if (!allowItemMove({ prevPosition: prevPosition, nextPosition: nextPosition, monitor: monitor, hoverNode: hoverNode, props: props })) { return; } // this is where the actual move happens var nextPos = props.moveItem({ dragItem: dragItem, prevPosition: prevPosition, nextPosition: nextPosition }); item.prevPosition = prevPosition; item.prevIndex = item.index; item.dragged = true; // note: we're mutating the monitor item here! // generally it's better to avoid mutations, // but it's good here for the sake of performance // to avoid expensive index searches item.position = nextPos; item.index = nextPos[nextPos.length - 1]; } }; var Item = /*#__PURE__*/function (_React$PureComponent) { function Item() { var _this; (0, _classCallCheck2["default"])(this, Item); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, Item, [].concat(args)); _this.state = { shouldRenderChildren: true }; _this.unmounted = false; _this.rootRef = /*#__PURE__*/_react["default"].createRef(); _this.handleNode = null; return _this; } (0, _inherits2["default"])(Item, _React$PureComponent); return (0, _createClass2["default"])(Item, [{ key: "componentWillUnmount", value: function componentWillUnmount() { this.unmounted = true; } }, { key: "componentDidMount", value: function componentDidMount() { // use empty image as a drag preview so browsers don't draw it // and we can draw whatever we want on the custom drag layer instead. this.props.connectDragPreview((0, _DragUtils.getEmptyImage)(), { // IE fallback: specify that we'd rather screenshot the node // when it already knows it's being dragged so we can hide it with CSS. captureDraggingState: true }); this.updateShouldRenderChildren(); } }, { key: "componentDidUpdate", value: function componentDidUpdate() { this.updateShouldRenderChildren(); } }, { key: "updateShouldRenderChildren", value: function updateShouldRenderChildren() { var _this2 = this; var _this$props = this.props, isPlaceholder = _this$props.isPlaceholder, isRenderDraggingChildren = _this$props.isRenderDraggingChildren; var shouldRenderChildren = !isPlaceholder || isRenderDraggingChildren; // start workaround of immediately fired dragend event after dragstart // https://github.com/react-dnd/react-dnd/issues/766#issuecomment-748255082 if (shouldRenderChildren !== this.state.shouldRenderChildren) { if (!this.props.dragged && this.state.shouldRenderChildren !== shouldRenderChildren) { setTimeout(function () { if (!_this2.unmounted) { _this2.setState({ shouldRenderChildren: shouldRenderChildren }); } }, 0); } else { this.setState({ shouldRenderChildren: shouldRenderChildren }); } } // end workaround of immediately fired dragend event after dragstart } }, { key: "render", value: function render() { var _this3 = this; var _this$props2 = this.props, item = _this$props2.item, position = _this$props2.position, children = _this$props2.children, isPlaceholder = _this$props2.isPlaceholder, connectDragSource = _this$props2.connectDragSource, connectDropTarget = _this$props2.connectDropTarget, isOver = _this$props2.isOver, monitorCanDrop = _this$props2.monitorCanDrop, useDragHandle = _this$props2.useDragHandle, renderItem = _this$props2.renderItem, renderPrefix = _this$props2.renderPrefix, theme = _this$props2.theme, readOnly = _this$props2.readOnly, isVeryLastItem = _this$props2.isVeryLastItem, siblings = _this$props2.siblings; var dropTargetStyle = isOver && !monitorCanDrop ? { cursor: 'not-allowed' } : undefined; // params passed to renderItem callback var renderParams = { item: item, siblings: siblings, isVeryLastItem: isVeryLastItem, isPlaceholder: isPlaceholder, isPreview: false, connectDragSource: function connectDragSource() {}, depth: position.length }; var draggableTargetDataProps = (0, _defineProperty2["default"])((0, _defineProperty2["default"])({}, _constants.dataAttributes.draggableTarget, true), 'data-hook', 'nestable-item'); var renderItemWithDataAttributes = function renderItemWithDataAttributes(params) { return /*#__PURE__*/_react["default"].cloneElement(renderItem(params), (0, _defineProperty2["default"])((0, _defineProperty2["default"])((0, _defineProperty2["default"])({}, _constants.dataAttributes.draggableSource, true), _constants.dataAttributes.depth, position.length - 1), _constants.dataAttributes.id, item.id)); }; var classes = (0, _classnames["default"])('nestable-item', theme && theme.item); var _item$draggable = item.draggable, draggable = _item$draggable === void 0 ? true : _item$draggable, _item$lockDropArea = item.lockDropArea, lockDropArea = _item$lockDropArea === void 0 ? false : _item$lockDropArea, _item$isParentLocked = item.isParentLocked, isParentLocked = _item$isParentLocked === void 0 ? false : _item$isParentLocked, dragDisabled = item.dragDisabled; if (!draggable || readOnly || dragDisabled) { if (lockDropArea) { return /*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({ ref: this.rootRef, className: classes }, draggableTargetDataProps, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 475, columnNumber: 11 } }), renderPrefix(renderParams), renderItemWithDataAttributes(renderParams), this.state.shouldRenderChildren && children); } if (isParentLocked && draggable && !readOnly) { return connectDragSource(/*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({ ref: this.rootRef, className: classes }, draggableTargetDataProps, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 489, columnNumber: 11 } }), renderPrefix(renderParams), renderItemWithDataAttributes(renderParams), this.state.shouldRenderChildren && children)); } return /*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({ ref: this.rootRef, className: classes }, draggableTargetDataProps, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 502, columnNumber: 9 } }), renderPrefix(renderParams), renderItemWithDataAttributes(renderParams), this.state.shouldRenderChildren && children); } if (useDragHandle) { renderParams.connectDragSource = function (handle) { var handleWithRef = /*#__PURE__*/_react["default"].cloneElement(handle, { ref: function ref(node) { return _this3.handleNode = node; } }); return connectDragSource(handleWithRef); }; if (lockDropArea) { return connectDropTarget(/*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({ ref: this.rootRef, className: classes, style: dropTargetStyle }, draggableTargetDataProps, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 524, columnNumber: 11 } }), renderPrefix(renderParams), renderItemWithDataAttributes(renderParams), this.state.shouldRenderChildren && children)); } if (isParentLocked) { return connectDragSource(/*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({ ref: this.rootRef, className: classes }, draggableTargetDataProps, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 539, columnNumber: 11 } }), renderPrefix(renderParams), renderItemWithDataAttributes(renderParams), this.state.shouldRenderChildren && children)); } return connectDropTarget(/*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({ ref: this.rootRef, className: classes, style: dropTargetStyle }, draggableTargetDataProps, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 552, columnNumber: 9 } }), renderPrefix(renderParams), renderItemWithDataAttributes(renderParams), this.state.shouldRenderChildren && children)); } if (isParentLocked) { return connectDragSource(/*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({ ref: this.rootRef, className: classes }, draggableTargetDataProps, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 567, columnNumber: 9 } }), renderPrefix(renderParams), renderItemWithDataAttributes(renderParams), this.state.shouldRenderChildren && children)); } return connectDropTarget(connectDragSource(/*#__PURE__*/_react["default"].createElement("div", (0, _extends2["default"])({ ref: this.rootRef, className: classes, style: dropTargetStyle }, draggableTargetDataProps, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 581, columnNumber: 9 } }), renderPrefix(renderParams), renderItemWithDataAttributes(renderParams), this.state.shouldRenderChildren && children))); } }]); }(_react["default"].PureComponent); var DragItemSource = exports.DragItemSource = (0, _reactDnd.DragSource)(_itemTypes["default"].nestedItem, cardSource, function (connect, monitor) { return { connectDragSource: connect.dragSource(), connectDragPreview: connect.dragPreview(), isPlaceholder: monitor.isDragging(), dragged: monitor.getItem() && monitor.getItem().dragged }; })(Item); var DropItemTarget = exports.DropItemTarget = (0, _reactDnd.DropTarget)(_itemTypes["default"].nestedItem, cardTarget, function (connect, monitor) { return { connectDropTarget: connect.dropTarget(), isOver: monitor.isOver(), monitorCanDrop: monitor.canDrop() }; })(DragItemSource); var ItemWithContext = /*#__PURE__*/function (_React$PureComponent2) { function ItemWithContext() { (0, _classCallCheck2["default"])(this, ItemWithContext); return _callSuper(this, ItemWithContext, arguments); } (0, _inherits2["default"])(ItemWithContext, _React$PureComponent2); return (0, _createClass2["default"])(ItemWithContext, [{ key: "render", value: function render() { var _this4 = this; return /*#__PURE__*/_react["default"].createElement(_NestableListBaseContext.NestableListBaseContext.Consumer, { __self: this, __source: { fileName: _jsxFileName, lineNumber: 620, columnNumber: 7 } }, function (context) { return /*#__PURE__*/_react["default"].createElement(DropItemTarget, (0, _extends2["default"])({}, _this4.props, context, { __self: _this4, __source: { fileName: _jsxFileName, lineNumber: 621, columnNumber: 21 } })); }); } }]); }(_react["default"].PureComponent); var _default = exports["default"] = ItemWithContext;