// packages/block-editor/src/components/typewriter/index.js
import { useRefEffect } from "@wordpress/compose";
import { computeCaretRect, getScrollContainer } from "@wordpress/dom";
import { useSelect } from "@wordpress/data";
import { UP, DOWN, LEFT, RIGHT } from "@wordpress/keycodes";
import { store as blockEditorStore } from "../../store";
import { jsx } from "react/jsx-runtime";
var isIE = window.navigator.userAgent.indexOf("Trident") !== -1;
var arrowKeyCodes = /* @__PURE__ */ new Set([UP, DOWN, LEFT, RIGHT]);
var initialTriggerPercentage = 0.75;
function useTypewriter() {
  const hasSelectedBlock = useSelect(
    (select) => select(blockEditorStore).hasSelectedBlock(),
    []
  );
  return useRefEffect(
    (node) => {
      if (!hasSelectedBlock) {
        return;
      }
      const { ownerDocument } = node;
      const { defaultView } = ownerDocument;
      let scrollResizeRafId;
      let onKeyDownRafId;
      let caretRect;
      function onScrollResize() {
        if (scrollResizeRafId) {
          return;
        }
        scrollResizeRafId = defaultView.requestAnimationFrame(() => {
          computeCaretRectangle();
          scrollResizeRafId = null;
        });
      }
      function onKeyDown(event) {
        if (onKeyDownRafId) {
          defaultView.cancelAnimationFrame(onKeyDownRafId);
        }
        onKeyDownRafId = defaultView.requestAnimationFrame(() => {
          maintainCaretPosition(event);
          onKeyDownRafId = null;
        });
      }
      function maintainCaretPosition({ keyCode }) {
        if (!isSelectionEligibleForScroll()) {
          return;
        }
        const currentCaretRect = computeCaretRect(defaultView);
        if (!currentCaretRect) {
          return;
        }
        if (!caretRect) {
          caretRect = currentCaretRect;
          return;
        }
        if (arrowKeyCodes.has(keyCode)) {
          caretRect = currentCaretRect;
          return;
        }
        const diff = currentCaretRect.top - caretRect.top;
        if (diff === 0) {
          return;
        }
        const scrollContainer = getScrollContainer(node);
        if (!scrollContainer) {
          return;
        }
        const windowScroll = scrollContainer === ownerDocument.body || scrollContainer === ownerDocument.documentElement;
        const scrollY = windowScroll ? defaultView.scrollY : scrollContainer.scrollTop;
        const scrollContainerY = windowScroll ? 0 : scrollContainer.getBoundingClientRect().top;
        const relativeScrollPosition = windowScroll ? caretRect.top / defaultView.innerHeight : (caretRect.top - scrollContainerY) / (defaultView.innerHeight - scrollContainerY);
        if (scrollY === 0 && relativeScrollPosition < initialTriggerPercentage && isLastEditableNode()) {
          caretRect = currentCaretRect;
          return;
        }
        const scrollContainerHeight = windowScroll ? defaultView.innerHeight : scrollContainer.clientHeight;
        if (
          // The caret is under the lower fold.
          caretRect.top + caretRect.height > scrollContainerY + scrollContainerHeight || // The caret is above the upper fold.
          caretRect.top < scrollContainerY
        ) {
          caretRect = currentCaretRect;
          return;
        }
        if (windowScroll) {
          defaultView.scrollBy(0, diff);
        } else {
          scrollContainer.scrollTop += diff;
        }
      }
      function addSelectionChangeListener() {
        ownerDocument.addEventListener(
          "selectionchange",
          computeCaretRectOnSelectionChange
        );
      }
      function computeCaretRectOnSelectionChange() {
        ownerDocument.removeEventListener(
          "selectionchange",
          computeCaretRectOnSelectionChange
        );
        computeCaretRectangle();
      }
      function computeCaretRectangle() {
        if (isSelectionEligibleForScroll()) {
          caretRect = computeCaretRect(defaultView);
        }
      }
      function isSelectionEligibleForScroll() {
        return node.contains(ownerDocument.activeElement) && ownerDocument.activeElement.isContentEditable;
      }
      function isLastEditableNode() {
        const editableNodes = node.querySelectorAll(
          '[contenteditable="true"]'
        );
        const lastEditableNode = editableNodes[editableNodes.length - 1];
        return lastEditableNode === ownerDocument.activeElement;
      }
      defaultView.addEventListener("scroll", onScrollResize, true);
      defaultView.addEventListener("resize", onScrollResize, true);
      node.addEventListener("keydown", onKeyDown);
      node.addEventListener("keyup", maintainCaretPosition);
      node.addEventListener("mousedown", addSelectionChangeListener);
      node.addEventListener("touchstart", addSelectionChangeListener);
      return () => {
        defaultView.removeEventListener(
          "scroll",
          onScrollResize,
          true
        );
        defaultView.removeEventListener(
          "resize",
          onScrollResize,
          true
        );
        node.removeEventListener("keydown", onKeyDown);
        node.removeEventListener("keyup", maintainCaretPosition);
        node.removeEventListener(
          "mousedown",
          addSelectionChangeListener
        );
        node.removeEventListener(
          "touchstart",
          addSelectionChangeListener
        );
        ownerDocument.removeEventListener(
          "selectionchange",
          computeCaretRectOnSelectionChange
        );
        defaultView.cancelAnimationFrame(scrollResizeRafId);
        defaultView.cancelAnimationFrame(onKeyDownRafId);
      };
    },
    [hasSelectedBlock]
  );
}
function Typewriter({ children }) {
  return /* @__PURE__ */ jsx("div", { ref: useTypewriter(), className: "block-editor__typewriter", children });
}
var TypewriterOrIEBypass = isIE ? (props) => props.children : Typewriter;
var typewriter_default = TypewriterOrIEBypass;
export {
  typewriter_default as default,
  useTypewriter
};
//# sourceMappingURL=index.js.map
