"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// packages/block-editor/src/components/writing-flow/use-arrow-nav.js
var use_arrow_nav_exports = {};
__export(use_arrow_nav_exports, {
  default: () => useArrowNav,
  getClosestTabbable: () => getClosestTabbable,
  isNavigationCandidate: () => isNavigationCandidate
});
module.exports = __toCommonJS(use_arrow_nav_exports);
var import_dom = require("@wordpress/dom");
var import_keycodes = require("@wordpress/keycodes");
var import_data = require("@wordpress/data");
var import_compose = require("@wordpress/compose");
var import_dom2 = require("../../utils/dom.cjs");
var import_store = require("../../store/index.cjs");
function isNavigationCandidate(element, keyCode, hasModifier) {
  const isVertical = keyCode === import_keycodes.UP || keyCode === import_keycodes.DOWN;
  const { tagName } = element;
  const elementType = element.getAttribute("type");
  if (isVertical && !hasModifier) {
    if (tagName === "INPUT") {
      const verticalInputTypes = [
        "date",
        "datetime-local",
        "month",
        "number",
        "range",
        "time",
        "week"
      ];
      return !verticalInputTypes.includes(elementType);
    }
    return true;
  }
  if (tagName === "INPUT") {
    const simpleInputTypes = [
      "button",
      "checkbox",
      "number",
      "color",
      "file",
      "image",
      "radio",
      "reset",
      "submit"
    ];
    return simpleInputTypes.includes(elementType);
  }
  return tagName !== "TEXTAREA";
}
function getClosestTabbable(target, isReverse, containerElement, onlyVertical) {
  let focusableNodes = import_dom.focus.focusable.find(containerElement);
  if (isReverse) {
    focusableNodes.reverse();
  }
  focusableNodes = focusableNodes.slice(
    focusableNodes.indexOf(target) + 1
  );
  let targetRect;
  if (onlyVertical) {
    targetRect = target.getBoundingClientRect();
  }
  function isTabCandidate(node) {
    if (node.children.length === 1 && (0, import_dom2.isInSameBlock)(node, node.firstElementChild) && node.firstElementChild.getAttribute("contenteditable") === "true") {
      return;
    }
    if (!import_dom.focus.tabbable.isTabbableIndex(node)) {
      return false;
    }
    if (node.isContentEditable && node.contentEditable !== "true") {
      return false;
    }
    if (onlyVertical) {
      const nodeRect = node.getBoundingClientRect();
      if (nodeRect.left >= targetRect.right || nodeRect.right <= targetRect.left) {
        return false;
      }
    }
    return true;
  }
  return focusableNodes.find(isTabCandidate);
}
function useArrowNav() {
  const {
    getMultiSelectedBlocksStartClientId,
    getMultiSelectedBlocksEndClientId,
    getSettings,
    hasMultiSelection,
    __unstableIsFullySelected
  } = (0, import_data.useSelect)(import_store.store);
  const { selectBlock } = (0, import_data.useDispatch)(import_store.store);
  return (0, import_compose.useRefEffect)((node) => {
    let verticalRect;
    function onMouseDown() {
      verticalRect = null;
    }
    function isClosestTabbableABlock(target, isReverse) {
      const closestTabbable = getClosestTabbable(
        target,
        isReverse,
        node
      );
      return closestTabbable && (0, import_dom2.getBlockClientId)(closestTabbable);
    }
    function onKeyDown(event) {
      if (event.defaultPrevented) {
        return;
      }
      const { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } = event;
      const isUp = keyCode === import_keycodes.UP;
      const isDown = keyCode === import_keycodes.DOWN;
      const isLeft = keyCode === import_keycodes.LEFT;
      const isRight = keyCode === import_keycodes.RIGHT;
      const isReverse = isUp || isLeft;
      const isHorizontal = isLeft || isRight;
      const isVertical = isUp || isDown;
      const isNav = isHorizontal || isVertical;
      const hasModifier = shiftKey || ctrlKey || altKey || metaKey;
      const isNavEdge = isVertical ? import_dom.isVerticalEdge : import_dom.isHorizontalEdge;
      const { ownerDocument } = node;
      const { defaultView } = ownerDocument;
      if (!isNav) {
        return;
      }
      if (getSettings().isPreviewMode) {
        return;
      }
      if (hasMultiSelection()) {
        if (shiftKey) {
          return;
        }
        if (!__unstableIsFullySelected()) {
          return;
        }
        event.preventDefault();
        if (isReverse) {
          selectBlock(getMultiSelectedBlocksStartClientId());
        } else {
          selectBlock(getMultiSelectedBlocksEndClientId(), -1);
        }
        return;
      }
      if (!isNavigationCandidate(target, keyCode, hasModifier)) {
        return;
      }
      if (!isVertical) {
        verticalRect = null;
      } else if (!verticalRect) {
        verticalRect = (0, import_dom.computeCaretRect)(defaultView);
      }
      const isReverseDir = (0, import_dom.isRTL)(target) ? !isReverse : isReverse;
      const { keepCaretInsideBlock } = getSettings();
      if (shiftKey) {
        if (isClosestTabbableABlock(target, isReverse) && isNavEdge(target, isReverse)) {
          node.contentEditable = true;
          node.focus();
        }
      } else if (isVertical && (0, import_dom.isVerticalEdge)(target, isReverse) && // When Alt is pressed, only intercept if the caret is also at
      // the horizontal edge.
      (altKey ? (0, import_dom.isHorizontalEdge)(target, isReverseDir) : true) && !keepCaretInsideBlock) {
        const closestTabbable = getClosestTabbable(
          target,
          isReverse,
          node,
          true
        );
        if (closestTabbable) {
          (0, import_dom.placeCaretAtVerticalEdge)(
            closestTabbable,
            // When Alt is pressed, place the caret at the furthest
            // horizontal edge and the furthest vertical edge.
            altKey ? !isReverse : isReverse,
            altKey ? void 0 : verticalRect
          );
          event.preventDefault();
        }
      } else if (isHorizontal && defaultView.getSelection().isCollapsed && (0, import_dom.isHorizontalEdge)(target, isReverseDir) && !keepCaretInsideBlock) {
        const closestTabbable = getClosestTabbable(
          target,
          isReverseDir,
          node
        );
        (0, import_dom.placeCaretAtHorizontalEdge)(closestTabbable, isReverse);
        event.preventDefault();
      }
    }
    node.addEventListener("mousedown", onMouseDown);
    node.addEventListener("keydown", onKeyDown);
    return () => {
      node.removeEventListener("mousedown", onMouseDown);
      node.removeEventListener("keydown", onKeyDown);
    };
  }, []);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  getClosestTabbable,
  isNavigationCandidate
});
//# sourceMappingURL=use-arrow-nav.cjs.map
