"use strict";Object.defineProperty(exports, "__esModule", {value: true});

var _UI5KWBYVcjs = require('./UI5KWBYV.cjs');


var _VGI2PE2Bcjs = require('./VGI2PE2B.cjs');




var _743QABRAcjs = require('./743QABRA.cjs');




var _KGFTRA3Ccjs = require('./KGFTRA3C.cjs');


var _XMDZRF6Ycjs = require('./XMDZRF6Y.cjs');

// src/portal/portal.tsx
var _dom = require('@ariakit/core/utils/dom');
var _events = require('@ariakit/core/utils/events');





var _focus = require('@ariakit/core/utils/focus');
var _react = require('react');
var _reactdom = require('react-dom');
var _jsxruntime = require('react/jsx-runtime');
var TagName = "div";
function getRootElement(element) {
  return _dom.getDocument.call(void 0, element).body;
}
function getPortalElement(element, portalElement) {
  if (!portalElement) {
    return _dom.getDocument.call(void 0, 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 = _743QABRAcjs.createHook.call(void 0, function usePortal2({
  preserveTabOrder,
  preserveTabOrderAnchor,
  portalElement,
  portalRef,
  portal = true,
  ...props
}) {
  const ref = _react.useRef.call(void 0, null);
  const refProp = _KGFTRA3Ccjs.useMergeRefs.call(void 0, ref, props.ref);
  const context = _react.useContext.call(void 0, _UI5KWBYVcjs.PortalContext);
  const [portalNode, setPortalNode] = _react.useState.call(void 0, null);
  const [anchorPortalNode, setAnchorPortalNode] = _react.useState.call(void 0, 
    null
  );
  const outerBeforeRef = _react.useRef.call(void 0, null);
  const innerBeforeRef = _react.useRef.call(void 0, null);
  const innerAfterRef = _react.useRef.call(void 0, null);
  const outerAfterRef = _react.useRef.call(void 0, null);
  _KGFTRA3Ccjs.useSafeLayoutEffect.call(void 0, () => {
    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);
    _XMDZRF6Ycjs.setRef.call(void 0, portalRef, portalEl);
    if (isPortalInDocument) return;
    return () => {
      portalEl.remove();
      _XMDZRF6Ycjs.setRef.call(void 0, portalRef, null);
    };
  }, [portal, portalElement, context, portalRef]);
  _KGFTRA3Ccjs.useSafeLayoutEffect.call(void 0, () => {
    if (!portal) return;
    if (!preserveTabOrder) return;
    if (!preserveTabOrderAnchor) return;
    const doc = _dom.getDocument.call(void 0, preserveTabOrderAnchor);
    const element = doc.createElement("span");
    element.style.position = "fixed";
    preserveTabOrderAnchor.insertAdjacentElement("afterend", element);
    setAnchorPortalNode(element);
    return () => {
      element.remove();
      setAnchorPortalNode(null);
    };
  }, [portal, preserveTabOrder, preserveTabOrderAnchor]);
  _react.useEffect.call(void 0, () => {
    if (!portalNode) return;
    if (!preserveTabOrder) return;
    let raf = 0;
    const onFocus = (event) => {
      if (!_events.isFocusEventOutside.call(void 0, event)) return;
      const focusing = event.type === "focusin";
      cancelAnimationFrame(raf);
      if (focusing) {
        return _focus.restoreFocusIn.call(void 0, portalNode);
      }
      raf = requestAnimationFrame(() => {
        _focus.disableFocusIn.call(void 0, 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 = _KGFTRA3Ccjs.useWrapElement.call(void 0, 
    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__ */ _jsxruntime.jsx.call(void 0, _UI5KWBYVcjs.PortalContext.Provider, { value: portalNode || context, children: element });
      if (!portal) return element;
      if (!portalNode) {
        return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, 
          "span",
          {
            ref: refProp,
            id: props.id,
            style: { position: "fixed" },
            hidden: true
          }
        );
      }
      element = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
        preserveTabOrder && portalNode && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, 
          _VGI2PE2Bcjs.FocusTrap,
          {
            ref: innerBeforeRef,
            "data-focus-trap": props.id,
            className: "__focus-trap-inner-before",
            onFocus: (event) => {
              if (_events.isFocusEventOutside.call(void 0, event, portalNode)) {
                queueFocus(_focus.getNextTabbable.call(void 0, ));
              } else {
                queueFocus(outerBeforeRef.current);
              }
            }
          }
        ),
        element,
        preserveTabOrder && portalNode && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, 
          _VGI2PE2Bcjs.FocusTrap,
          {
            ref: innerAfterRef,
            "data-focus-trap": props.id,
            className: "__focus-trap-inner-after",
            onFocus: (event) => {
              if (_events.isFocusEventOutside.call(void 0, event, portalNode)) {
                queueFocus(_focus.getPreviousTabbable.call(void 0, ));
              } else {
                queueFocus(outerAfterRef.current);
              }
            }
          }
        )
      ] });
      if (portalNode) {
        element = _reactdom.createPortal.call(void 0, element, portalNode);
      }
      let preserveTabOrderElement = /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
        preserveTabOrder && portalNode && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, 
          _VGI2PE2Bcjs.FocusTrap,
          {
            ref: outerBeforeRef,
            "data-focus-trap": props.id,
            className: "__focus-trap-outer-before",
            onFocus: (event) => {
              const fromOuter = event.relatedTarget === outerAfterRef.current;
              if (!fromOuter && _events.isFocusEventOutside.call(void 0, event, portalNode)) {
                queueFocus(innerBeforeRef.current);
              } else {
                queueFocus(_focus.getPreviousTabbable.call(void 0, ));
              }
            }
          }
        ),
        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__ */ _jsxruntime.jsx.call(void 0, "span", { "aria-owns": portalNode == null ? void 0 : portalNode.id, style: { position: "fixed" } }),
        preserveTabOrder && portalNode && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, 
          _VGI2PE2Bcjs.FocusTrap,
          {
            ref: outerAfterRef,
            "data-focus-trap": props.id,
            className: "__focus-trap-outer-after",
            onFocus: (event) => {
              if (_events.isFocusEventOutside.call(void 0, event, portalNode)) {
                queueFocus(innerAfterRef.current);
              } else {
                const nextTabbable = _focus.getNextTabbable.call(void 0, );
                if (nextTabbable === innerBeforeRef.current) {
                  requestAnimationFrame(() => {
                    var _a;
                    return (_a = _focus.getNextTabbable.call(void 0, )) == null ? void 0 : _a.focus();
                  });
                  return;
                }
                queueFocus(nextTabbable);
              }
            }
          }
        )
      ] });
      if (anchorPortalNode && preserveTabOrder) {
        preserveTabOrderElement = _reactdom.createPortal.call(void 0, 
          preserveTabOrderElement,
          anchorPortalNode
        );
      }
      return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
        preserveTabOrderElement,
        element
      ] });
    },
    [portalNode, context, portal, props.id, preserveTabOrder, anchorPortalNode]
  );
  props = {
    ...props,
    ref: refProp
  };
  return props;
});
var Portal = _743QABRAcjs.forwardRef.call(void 0, function Portal2(props) {
  const htmlProps = usePortal(props);
  return _743QABRAcjs.createElement.call(void 0, TagName, htmlProps);
});




exports.usePortal = usePortal; exports.Portal = Portal;
