"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;
    }
  }
  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 = {
  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,
        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;

      // 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: 451,
              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: 465,
              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: 478,
            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
          }, draggableTargetDataProps, {
            __self: this,
            __source: {
              fileName: _jsxFileName,
              lineNumber: 500,
              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: 514,
              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
        }, draggableTargetDataProps, {
          __self: this,
          __source: {
            fileName: _jsxFileName,
            lineNumber: 527,
            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: 541,
            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
      }, draggableTargetDataProps, {
        __self: this,
        __source: {
          fileName: _jsxFileName,
          lineNumber: 555,
          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) {
  return {
    connectDropTarget: connect.dropTarget()
  };
})(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: 591,
          columnNumber: 7
        }
      }, function (context) {
        return /*#__PURE__*/_react["default"].createElement(DropItemTarget, (0, _extends2["default"])({}, _this4.props, context, {
          __self: _this4,
          __source: {
            fileName: _jsxFileName,
            lineNumber: 592,
            columnNumber: 21
          }
        }));
      });
    }
  }]);
}(_react["default"].PureComponent);
var _default = exports["default"] = ItemWithContext;