"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// packages/block-editor/src/components/list-view/use-list-view-drop-zone.js
var use_list_view_drop_zone_exports = {};
__export(use_list_view_drop_zone_exports, {
  NESTING_LEVEL_INDENTATION: () => NESTING_LEVEL_INDENTATION,
  default: () => useListViewDropZone,
  getListViewDropTarget: () => getListViewDropTarget
});
module.exports = __toCommonJS(use_list_view_drop_zone_exports);
var import_data = require("@wordpress/data");
var import_element = require("@wordpress/element");
var import_compose = require("@wordpress/compose");
var import_i18n = require("@wordpress/i18n");
var import_math = require("../../utils/math");
var import_use_on_block_drop = __toESM(require("../use-on-block-drop"));
var import_store = require("../../store");
var NESTING_LEVEL_INDENTATION = 24;
function isUpGesture(point, rect, nestingLevel = 1, rtl = false) {
  const blockIndentPosition = rtl ? rect.right - nestingLevel * NESTING_LEVEL_INDENTATION : rect.left + nestingLevel * NESTING_LEVEL_INDENTATION;
  return rtl ? point.x > blockIndentPosition : point.x < blockIndentPosition;
}
function getDesiredRelativeParentLevel(point, rect, nestingLevel = 1, rtl = false) {
  const blockIndentPosition = rtl ? rect.right - nestingLevel * NESTING_LEVEL_INDENTATION : rect.left + nestingLevel * NESTING_LEVEL_INDENTATION;
  const distanceBetweenPointAndBlockIndentPosition = rtl ? blockIndentPosition - point.x : point.x - blockIndentPosition;
  const desiredParentLevel = Math.round(
    distanceBetweenPointAndBlockIndentPosition / NESTING_LEVEL_INDENTATION
  );
  return Math.abs(desiredParentLevel);
}
function getCandidateBlockParents(candidateBlockData, blocksData) {
  const candidateBlockParents = [];
  let currentBlockData = candidateBlockData;
  while (currentBlockData) {
    candidateBlockParents.push({ ...currentBlockData });
    currentBlockData = blocksData.find(
      (blockData) => blockData.clientId === currentBlockData.rootClientId
    );
  }
  return candidateBlockParents;
}
function getNextNonDraggedBlock(blocksData, index) {
  const nextBlockData = blocksData[index + 1];
  if (nextBlockData && nextBlockData.isDraggedBlock) {
    return getNextNonDraggedBlock(blocksData, index + 1);
  }
  return nextBlockData;
}
function isNestingGesture(point, rect, nestingLevel = 1, rtl = false) {
  const blockIndentPosition = rtl ? rect.right - nestingLevel * NESTING_LEVEL_INDENTATION : rect.left + nestingLevel * NESTING_LEVEL_INDENTATION;
  const isNestingHorizontalGesture = rtl ? point.x < blockIndentPosition - NESTING_LEVEL_INDENTATION : point.x > blockIndentPosition + NESTING_LEVEL_INDENTATION;
  return isNestingHorizontalGesture && point.y < rect.bottom;
}
var ALLOWED_DROP_EDGES = ["top", "bottom"];
function getListViewDropTarget(blocksData, position, rtl = false) {
  let candidateEdge;
  let candidateBlockData;
  let candidateDistance;
  let candidateRect;
  let candidateBlockIndex;
  for (let i = 0; i < blocksData.length; i++) {
    const blockData = blocksData[i];
    if (blockData.isDraggedBlock) {
      continue;
    }
    const rect = blockData.element.getBoundingClientRect();
    const [distance, edge] = (0, import_math.getDistanceToNearestEdge)(
      position,
      rect,
      ALLOWED_DROP_EDGES
    );
    const isCursorWithinBlock = (0, import_math.isPointContainedByRect)(position, rect);
    if (candidateDistance === void 0 || distance < candidateDistance || isCursorWithinBlock) {
      candidateDistance = distance;
      const index = blocksData.indexOf(blockData);
      const previousBlockData = blocksData[index - 1];
      if (edge === "top" && previousBlockData && previousBlockData.rootClientId === blockData.rootClientId && !previousBlockData.isDraggedBlock) {
        candidateBlockData = previousBlockData;
        candidateEdge = "bottom";
        candidateRect = previousBlockData.element.getBoundingClientRect();
        candidateBlockIndex = index - 1;
      } else {
        candidateBlockData = blockData;
        candidateEdge = edge;
        candidateRect = rect;
        candidateBlockIndex = index;
      }
      if (isCursorWithinBlock) {
        break;
      }
    }
  }
  if (!candidateBlockData) {
    return;
  }
  const candidateBlockParents = getCandidateBlockParents(
    candidateBlockData,
    blocksData
  );
  const isDraggingBelow = candidateEdge === "bottom";
  if (isDraggingBelow && candidateBlockData.canInsertDraggedBlocksAsChild && (candidateBlockData.innerBlockCount > 0 && candidateBlockData.isExpanded || isNestingGesture(
    position,
    candidateRect,
    candidateBlockParents.length,
    rtl
  ))) {
    const newBlockIndex = candidateBlockData.isExpanded ? 0 : candidateBlockData.innerBlockCount || 0;
    return {
      rootClientId: candidateBlockData.clientId,
      clientId: candidateBlockData.clientId,
      blockIndex: newBlockIndex,
      dropPosition: "inside"
    };
  }
  if (isDraggingBelow && candidateBlockData.rootClientId && isUpGesture(
    position,
    candidateRect,
    candidateBlockParents.length,
    rtl
  )) {
    const nextBlock = getNextNonDraggedBlock(
      blocksData,
      candidateBlockIndex
    );
    const currentLevel = candidateBlockData.nestingLevel;
    const nextLevel = nextBlock ? nextBlock.nestingLevel : 1;
    if (currentLevel && nextLevel) {
      const desiredRelativeLevel = getDesiredRelativeParentLevel(
        position,
        candidateRect,
        candidateBlockParents.length,
        rtl
      );
      const targetParentIndex = Math.max(
        Math.min(desiredRelativeLevel, currentLevel - nextLevel),
        0
      );
      if (candidateBlockParents[targetParentIndex]) {
        let newBlockIndex = candidateBlockData.blockIndex;
        if (candidateBlockParents[targetParentIndex].nestingLevel === nextBlock?.nestingLevel) {
          newBlockIndex = nextBlock?.blockIndex;
        } else {
          for (let i = candidateBlockIndex; i >= 0; i--) {
            const blockData = blocksData[i];
            if (blockData.rootClientId === candidateBlockParents[targetParentIndex].rootClientId) {
              newBlockIndex = blockData.blockIndex + 1;
              break;
            }
          }
        }
        return {
          rootClientId: candidateBlockParents[targetParentIndex].rootClientId,
          clientId: candidateBlockData.clientId,
          blockIndex: newBlockIndex,
          dropPosition: candidateEdge
        };
      }
    }
  }
  if (!candidateBlockData.canInsertDraggedBlocksAsSibling) {
    return;
  }
  const offset = isDraggingBelow ? 1 : 0;
  return {
    rootClientId: candidateBlockData.rootClientId,
    clientId: candidateBlockData.clientId,
    blockIndex: candidateBlockData.blockIndex + offset,
    dropPosition: candidateEdge
  };
}
var EXPAND_THROTTLE_OPTIONS = {
  leading: false,
  // Don't call the function immediately on the first call.
  trailing: true
  // Do call the function on the last call.
};
function useListViewDropZone({
  dropZoneElement,
  expandedState,
  setExpandedState
}) {
  const {
    getBlockRootClientId,
    getBlockIndex,
    getBlockCount,
    getDraggedBlockClientIds,
    canInsertBlocks
  } = (0, import_data.useSelect)(import_store.store);
  const [target, setTarget] = (0, import_element.useState)();
  const { rootClientId: targetRootClientId, blockIndex: targetBlockIndex } = target || {};
  const onBlockDrop = (0, import_use_on_block_drop.default)(targetRootClientId, targetBlockIndex);
  const rtl = (0, import_i18n.isRTL)();
  const previousRootClientId = (0, import_compose.usePrevious)(targetRootClientId);
  const maybeExpandBlock = (0, import_element.useCallback)(
    (_expandedState, _target) => {
      const { rootClientId } = _target || {};
      if (!rootClientId) {
        return;
      }
      if (_target?.dropPosition === "inside" && !_expandedState[rootClientId]) {
        setExpandedState({
          type: "expand",
          clientIds: [rootClientId]
        });
      }
    },
    [setExpandedState]
  );
  const throttledMaybeExpandBlock = (0, import_compose.useThrottle)(
    maybeExpandBlock,
    500,
    EXPAND_THROTTLE_OPTIONS
  );
  (0, import_element.useEffect)(() => {
    if (target?.dropPosition !== "inside" || previousRootClientId !== target?.rootClientId) {
      throttledMaybeExpandBlock.cancel();
      return;
    }
    throttledMaybeExpandBlock(expandedState, target);
  }, [
    expandedState,
    previousRootClientId,
    target,
    throttledMaybeExpandBlock
  ]);
  const draggedBlockClientIds = getDraggedBlockClientIds();
  const throttled = (0, import_compose.useThrottle)(
    (0, import_element.useCallback)(
      (event, currentTarget) => {
        const position = { x: event.clientX, y: event.clientY };
        const isBlockDrag = !!draggedBlockClientIds?.length;
        const blockElements = Array.from(
          currentTarget.querySelectorAll("[data-block]")
        );
        const blocksData = blockElements.map((blockElement) => {
          const clientId = blockElement.dataset.block;
          const isExpanded = blockElement.dataset.expanded === "true";
          const isDraggedBlock = blockElement.classList.contains("is-dragging");
          const nestingLevel = parseInt(
            blockElement.getAttribute("aria-level"),
            10
          );
          const rootClientId = getBlockRootClientId(clientId);
          return {
            clientId,
            isExpanded,
            rootClientId,
            blockIndex: getBlockIndex(clientId),
            element: blockElement,
            nestingLevel: nestingLevel || void 0,
            isDraggedBlock: isBlockDrag ? isDraggedBlock : false,
            innerBlockCount: getBlockCount(clientId),
            canInsertDraggedBlocksAsSibling: isBlockDrag ? canInsertBlocks(
              draggedBlockClientIds,
              rootClientId
            ) : true,
            canInsertDraggedBlocksAsChild: isBlockDrag ? canInsertBlocks(draggedBlockClientIds, clientId) : true
          };
        });
        const newTarget = getListViewDropTarget(
          blocksData,
          position,
          rtl
        );
        if (newTarget) {
          setTarget(newTarget);
        }
      },
      [
        canInsertBlocks,
        draggedBlockClientIds,
        getBlockCount,
        getBlockIndex,
        getBlockRootClientId,
        rtl
      ]
    ),
    50
  );
  const ref = (0, import_compose.__experimentalUseDropZone)({
    dropZoneElement,
    onDrop(event) {
      throttled.cancel();
      if (target) {
        onBlockDrop(event);
      }
      setTarget(void 0);
    },
    onDragLeave() {
      throttled.cancel();
      setTarget(null);
    },
    onDragOver(event) {
      throttled(event, event.currentTarget);
    },
    onDragEnd() {
      throttled.cancel();
      setTarget(void 0);
    }
  });
  return { ref, target };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  NESTING_LEVEL_INDENTATION,
  getListViewDropTarget
});
//# sourceMappingURL=use-list-view-drop-zone.js.map
