// packages/rich-text/src/component/use-anchor.js
import { usePrevious } from "@wordpress/compose";
import { useState, useLayoutEffect } from "@wordpress/element";
import { getRectangleFromRange } from "@wordpress/dom";
function getFormatElement(range, editableContentElement, tagName, className) {
  let element = range.startContainer;
  if (element.nodeType === element.TEXT_NODE && range.startOffset === element.length && element.nextSibling) {
    element = element.nextSibling;
    while (element.firstChild) {
      element = element.firstChild;
    }
  }
  if (element.nodeType !== element.ELEMENT_NODE) {
    element = element.parentElement;
  }
  if (!element) {
    return;
  }
  if (element === editableContentElement) {
    return;
  }
  if (!editableContentElement.contains(element)) {
    return;
  }
  const selector = tagName + (className ? "." + className : "");
  while (element !== editableContentElement) {
    if (element.matches(selector)) {
      return element;
    }
    element = element.parentElement;
  }
}
function createVirtualAnchorElement(range, editableContentElement) {
  return {
    contextElement: editableContentElement,
    getBoundingClientRect() {
      return editableContentElement.contains(range.startContainer) ? getRectangleFromRange(range) : editableContentElement.getBoundingClientRect();
    }
  };
}
function getAnchor(editableContentElement, tagName, className) {
  if (!editableContentElement) {
    return;
  }
  const { ownerDocument } = editableContentElement;
  const { defaultView } = ownerDocument;
  const selection = defaultView.getSelection();
  if (!selection) {
    return;
  }
  if (!selection.rangeCount) {
    return;
  }
  const range = selection.getRangeAt(0);
  if (!range || !range.startContainer) {
    return;
  }
  const formatElement = getFormatElement(
    range,
    editableContentElement,
    tagName,
    className
  );
  if (formatElement) {
    return formatElement;
  }
  return createVirtualAnchorElement(range, editableContentElement);
}
function useAnchor({ editableContentElement, settings = {} }) {
  const { tagName, className, isActive } = settings;
  const [anchor, setAnchor] = useState(
    () => getAnchor(editableContentElement, tagName, className)
  );
  const wasActive = usePrevious(isActive);
  useLayoutEffect(() => {
    if (!editableContentElement) {
      return;
    }
    function callback() {
      setAnchor(
        getAnchor(editableContentElement, tagName, className)
      );
    }
    function attach() {
      ownerDocument.addEventListener("selectionchange", callback);
    }
    function detach() {
      ownerDocument.removeEventListener("selectionchange", callback);
    }
    const { ownerDocument } = editableContentElement;
    if (editableContentElement === ownerDocument.activeElement || // When a link is created, we need to attach the popover to the newly created anchor.
    !wasActive && isActive || // Sometimes we're _removing_ an active anchor, such as the inline color popover.
    // When we add the color, it switches from a virtual anchor to a `<mark>` element.
    // When we _remove_ the color, it switches from a `<mark>` element to a virtual anchor.
    wasActive && !isActive) {
      setAnchor(
        getAnchor(editableContentElement, tagName, className)
      );
      attach();
    }
    editableContentElement.addEventListener("focusin", attach);
    editableContentElement.addEventListener("focusout", detach);
    return () => {
      detach();
      editableContentElement.removeEventListener("focusin", attach);
      editableContentElement.removeEventListener("focusout", detach);
    };
  }, [editableContentElement, tagName, className, isActive, wasActive]);
  return anchor;
}
export {
  useAnchor
};
//# sourceMappingURL=use-anchor.mjs.map
