"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.DragNDropListItem = DragNDropListItem;
var _react = _interopRequireWildcard(require("react"));
var _reactDnd = require("react-dnd");
var _classnames = _interopRequireDefault(require("classnames"));
var _hooks = require("../hooks");
var _dragAndDropListItemContent = require("./drag-and-drop-list-item-content");
var _jsxRuntime = require("react/jsx-runtime");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
const DND_ITEM_TYPE = 'DND_ITEM_TYPE';
function DragNDropListItem({
  id,
  index,
  listItem,
  getIndexById,
  onItemMove,
  canDrag,
  canDrop,
  onDragEnd,
  ListItemComponent,
  isAnyItemDragging,
  setIsAnyItemDragging,
  listItemClassName,
  shouldUseSeparateDragRef,
  isActive,
  isError,
  ListItemContent = _dragAndDropListItemContent.DragNDropListItemContent,
  dragItemType = DND_ITEM_TYPE,
  additionalListItemProps = {}
}) {
  // this is needed as a workaround for WebKit bug with drag n drop and hovering:
  // https://bugs.webkit.org/show_bug.cgi?id=134555
  const [isHovered, setIsHovered] = (0, _react.useState)(false);
  const dropRef = (0, _react.useRef)(null);
  const dragRef = (0, _react.useRef)(null);
  const [, drop] = (0, _reactDnd.useDrop)({
    accept: dragItemType,
    hover(item, monitor) {
      if (!dropRef.current) {
        return;
      }
      // To avoid wrong ordering with too fast dragging and updates during dragging
      item.index = getIndexById(item.id);
      const dragIndex = item.index;
      const hoverIndex = index;
      if (!isAnyItemDragging) {
        setIsAnyItemDragging(true);
      }

      // Don't replace items with themselves
      if (dragIndex === hoverIndex) {
        return;
      }

      // Determine rectangle on screen
      const hoverBoundingRect = dropRef.current.getBoundingClientRect();
      // Get vertical middle
      const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
      // Determine mouse position
      const clientOffset = monitor.getClientOffset();
      // Get pixels to the top
      const hoverClientY = (clientOffset?.y || 0) - hoverBoundingRect.top;
      // 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 (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
        return;
      }
      // Dragging upwards
      if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
        return;
      }
      // Time to actually perform the action
      onItemMove(dragIndex, hoverIndex);
      item.index = hoverIndex;
    },
    canDrop: item => {
      return canDrop?.(listItem, item.index) ?? true;
    }
  });
  const [collected, drag] = (0, _reactDnd.useDrag)({
    type: dragItemType,
    item: {
      id,
      index
    },
    collect: monitor => {
      const isDragging = !!monitor.isDragging();
      return {
        isDragging
      };
    },
    canDrag() {
      return canDrag?.(listItem, index) ?? true;
    },
    end(item) {
      setIsAnyItemDragging(false);
      if (onDragEnd) {
        onDragEnd(listItem, item.index);
      }
    }
  });

  // if the whole list component is provided - render only it with appropriate props
  if (ListItemComponent) {
    const draggableRef = shouldUseSeparateDragRef ? dragRef : dropRef;
    drag(draggableRef);
    drop(dropRef);
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(ListItemComponent, {
      listItem: listItem,
      index: index,
      isDragging: collected.isDragging,
      dropRef: dropRef,
      dragRef: dragRef,
      isAnyItemDragging: isAnyItemDragging,
      ...additionalListItemProps
    });
  }
  drag(dropRef);
  drop(dropRef);
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
    ref: dropRef,
    className: (0, _classnames.default)('drag-n-drop-list-item', listItemClassName, {
      'drag-n-drop-list-item-active': isActive,
      'drag-n-drop-list-item-error': isError,
      'drag-n-drop-list-item-dragging': collected.isDragging,
      'drag-n-drop-list-item-hovered': isHovered && !isAnyItemDragging
    }),
    ...(0, _hooks.getNonNativeButtonAttrs)({
      onClick: () => setIsHovered(true),
      onKeyDown: () => setIsHovered(true)
    }),
    onMouseEnter: () => !isAnyItemDragging && setIsHovered(true),
    onMouseLeave: () => setIsHovered(false),
    children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
      className: "drag-n-drop-list-content-wrapper",
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ListItemContent, {
        listItem: listItem,
        index: index,
        isDragging: collected.isDragging,
        isAnyItemDragging: isAnyItemDragging,
        ...additionalListItemProps
      })
    })
  });
}