import { PortalContext } from './AOQQTIBO.js';
import { FocusTrap } from './W3VI7GFU.js';
import { createHook, forwardRef as forwardRef2, createElement } from './LMDWO4NN.js';
import { useMergeRefs, useSafeLayoutEffect, useWrapElement } from './ABQUS43J.js';
import { setRef } from './SK3NAZA3.js';
import { __objRest, __spreadProps, __spreadValues } from './3YLGPPWQ.js';
import { getDocument } from '../../../../../../@ariakit_core@0.4.15/node_modules/@ariakit/core/esm/__chunks/DTR5TSDJ.js';
import { isFocusEventOutside } from '../../../../../../@ariakit_core@0.4.15/node_modules/@ariakit/core/esm/utils/events.js';
import { getNextTabbable, getPreviousTabbable, restoreFocusIn, disableFocusIn } from '../../../../../../@ariakit_core@0.4.15/node_modules/@ariakit/core/esm/utils/focus.js';
import { useRef, useContext, useState, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { j as jsxRuntimeExports } from '../../../../../../react@18.2.0/node_modules/react/jsx-runtime.js';

var TagName = "div";
function getRootElement(element) {
  return getDocument(element).body;
}
function getPortalElement(element, portalElement) {
  if (!portalElement) {
    return getDocument(element).createElement("div");
  }
  if (typeof portalElement === "function") {
    return portalElement(element);
  }
  return portalElement;
}
function getRandomId(prefix = "id") {
  return `${prefix ? `${prefix}-` : ""}${Math.random().toString(36).slice(2, 8)}`;
}
function queueFocus(element) {
  queueMicrotask(() => {
    element == null ? void 0 : element.focus();
  });
}
var usePortal = createHook(function usePortal2(_a) {
  var _b = _a, {
    preserveTabOrder,
    preserveTabOrderAnchor,
    portalElement,
    portalRef,
    portal = true
  } = _b, props = __objRest(_b, [
    "preserveTabOrder",
    "preserveTabOrderAnchor",
    "portalElement",
    "portalRef",
    "portal"
  ]);
  const ref = useRef(null);
  const refProp = useMergeRefs(ref, props.ref);
  const context = useContext(PortalContext);
  const [portalNode, setPortalNode] = useState(null);
  const [anchorPortalNode, setAnchorPortalNode] = useState(
    null
  );
  const outerBeforeRef = useRef(null);
  const innerBeforeRef = useRef(null);
  const innerAfterRef = useRef(null);
  const outerAfterRef = useRef(null);
  useSafeLayoutEffect(() => {
    const element = ref.current;
    if (!element || !portal) {
      setPortalNode(null);
      return;
    }
    const portalEl = getPortalElement(element, portalElement);
    if (!portalEl) {
      setPortalNode(null);
      return;
    }
    const isPortalInDocument = portalEl.isConnected;
    if (!isPortalInDocument) {
      const rootElement = context || getRootElement(element);
      rootElement.appendChild(portalEl);
    }
    if (!portalEl.id) {
      portalEl.id = element.id ? `portal/${element.id}` : getRandomId();
    }
    setPortalNode(portalEl);
    setRef(portalRef, portalEl);
    if (isPortalInDocument) return;
    return () => {
      portalEl.remove();
      setRef(portalRef, null);
    };
  }, [portal, portalElement, context, portalRef]);
  useSafeLayoutEffect(() => {
    if (!portal) return;
    if (!preserveTabOrder) return;
    if (!preserveTabOrderAnchor) return;
    const doc = getDocument(preserveTabOrderAnchor);
    const element = doc.createElement("span");
    element.style.position = "fixed";
    preserveTabOrderAnchor.insertAdjacentElement("afterend", element);
    setAnchorPortalNode(element);
    return () => {
      element.remove();
      setAnchorPortalNode(null);
    };
  }, [portal, preserveTabOrder, preserveTabOrderAnchor]);
  useEffect(() => {
    if (!portalNode) return;
    if (!preserveTabOrder) return;
    let raf = 0;
    const onFocus = (event) => {
      if (!isFocusEventOutside(event)) return;
      const focusing = event.type === "focusin";
      cancelAnimationFrame(raf);
      if (focusing) {
        return restoreFocusIn(portalNode);
      }
      raf = requestAnimationFrame(() => {
        disableFocusIn(portalNode, true);
      });
    };
    portalNode.addEventListener("focusin", onFocus, true);
    portalNode.addEventListener("focusout", onFocus, true);
    return () => {
      cancelAnimationFrame(raf);
      portalNode.removeEventListener("focusin", onFocus, true);
      portalNode.removeEventListener("focusout", onFocus, true);
    };
  }, [portalNode, preserveTabOrder]);
  props = useWrapElement(
    props,
    (element) => {
      element = // While the portal node is not in the DOM, we need to pass the
      // current context to the portal context, otherwise it's going to
      // reset to the body element on nested portals.
      /* @__PURE__ */ jsxRuntimeExports.jsx(PortalContext.Provider, { value: portalNode || context, children: element });
      if (!portal) return element;
      if (!portalNode) {
        return /* @__PURE__ */ jsxRuntimeExports.jsx(
          "span",
          {
            ref: refProp,
            id: props.id,
            style: { position: "fixed" },
            hidden: true
          }
        );
      }
      element = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
        preserveTabOrder && portalNode && /* @__PURE__ */ jsxRuntimeExports.jsx(
          FocusTrap,
          {
            ref: innerBeforeRef,
            "data-focus-trap": props.id,
            className: "__focus-trap-inner-before",
            onFocus: (event) => {
              if (isFocusEventOutside(event, portalNode)) {
                queueFocus(getNextTabbable());
              } else {
                queueFocus(outerBeforeRef.current);
              }
            }
          }
        ),
        element,
        preserveTabOrder && portalNode && /* @__PURE__ */ jsxRuntimeExports.jsx(
          FocusTrap,
          {
            ref: innerAfterRef,
            "data-focus-trap": props.id,
            className: "__focus-trap-inner-after",
            onFocus: (event) => {
              if (isFocusEventOutside(event, portalNode)) {
                queueFocus(getPreviousTabbable());
              } else {
                queueFocus(outerAfterRef.current);
              }
            }
          }
        )
      ] });
      if (portalNode) {
        element = createPortal(element, portalNode);
      }
      let preserveTabOrderElement = /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
        preserveTabOrder && portalNode && /* @__PURE__ */ jsxRuntimeExports.jsx(
          FocusTrap,
          {
            ref: outerBeforeRef,
            "data-focus-trap": props.id,
            className: "__focus-trap-outer-before",
            onFocus: (event) => {
              const fromOuter = event.relatedTarget === outerAfterRef.current;
              if (!fromOuter && isFocusEventOutside(event, portalNode)) {
                queueFocus(innerBeforeRef.current);
              } else {
                queueFocus(getPreviousTabbable());
              }
            }
          }
        ),
        preserveTabOrder && // We're using position: fixed here so that the browser doesn't
        // add margin to the element when setting gap on a parent element.
        /* @__PURE__ */ jsxRuntimeExports.jsx("span", { "aria-owns": portalNode == null ? void 0 : portalNode.id, style: { position: "fixed" } }),
        preserveTabOrder && portalNode && /* @__PURE__ */ jsxRuntimeExports.jsx(
          FocusTrap,
          {
            ref: outerAfterRef,
            "data-focus-trap": props.id,
            className: "__focus-trap-outer-after",
            onFocus: (event) => {
              if (isFocusEventOutside(event, portalNode)) {
                queueFocus(innerAfterRef.current);
              } else {
                const nextTabbable = getNextTabbable();
                if (nextTabbable === innerBeforeRef.current) {
                  requestAnimationFrame(() => {
                    var _a2;
                    return (_a2 = getNextTabbable()) == null ? void 0 : _a2.focus();
                  });
                  return;
                }
                queueFocus(nextTabbable);
              }
            }
          }
        )
      ] });
      if (anchorPortalNode && preserveTabOrder) {
        preserveTabOrderElement = createPortal(
          preserveTabOrderElement,
          anchorPortalNode
        );
      }
      return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
        preserveTabOrderElement,
        element
      ] });
    },
    [portalNode, context, portal, props.id, preserveTabOrder, anchorPortalNode]
  );
  props = __spreadProps(__spreadValues({}, props), {
    ref: refProp
  });
  return props;
});
forwardRef2(function Portal2(props) {
  const htmlProps = usePortal(props);
  return createElement(TagName, htmlProps);
});

export { usePortal };
//# sourceMappingURL=WAGAC6PJ.js.map
