import * as o from "react";
import d from "./index-_virtual16.js";
import { jsxs as U, jsx as O } from "react/jsx-runtime";
import V from "./index-useForkRef.js";
import q from "./index-getReactElementRef.js";
import S from "./index-ownerDocument2.js";
import w from "./index-elementAcceptingRef.js";
import B from "./index-exactProp.js";
const M = ["input", "select", "textarea", "a[href]", "button", "[tabindex]", "audio[controls]", "video[controls]", '[contenteditable]:not([contenteditable="false"])'].join(",");
function G(e) {
  const c = parseInt(e.getAttribute("tabindex") || "", 10);
  return Number.isNaN(c) ? e.contentEditable === "true" || (e.nodeName === "AUDIO" || e.nodeName === "VIDEO" || e.nodeName === "DETAILS") && e.getAttribute("tabindex") === null ? 0 : e.tabIndex : c;
}
function H(e) {
  if (e.tagName !== "INPUT" || e.type !== "radio" || !e.name)
    return !1;
  const c = (r) => e.ownerDocument.querySelector(`input[type="radio"]${r}`);
  let u = c(`[name="${e.name}"]:checked`);
  return u || (u = c(`[name="${e.name}"]`)), u !== e;
}
function K(e) {
  return !(e.disabled || e.tagName === "INPUT" && e.type === "hidden" || H(e));
}
function Y(e) {
  const c = [], u = [];
  return Array.from(e.querySelectorAll(M)).forEach((r, s) => {
    const f = G(r);
    f === -1 || !K(r) || (f === 0 ? c.push(r) : u.push({
      documentOrder: s,
      tabIndex: f,
      node: r
    }));
  }), u.sort((r, s) => r.tabIndex === s.tabIndex ? r.documentOrder - s.documentOrder : r.tabIndex - s.tabIndex).map((r) => r.node).concat(c);
}
function _() {
  return !0;
}
function N(e) {
  const {
    children: c,
    disableAutoFocus: u = !1,
    disableEnforceFocus: r = !1,
    disableRestoreFocus: s = !1,
    getTabbable: f = Y,
    isEnabled: h = _,
    open: i
  } = e, v = o.useRef(!1), x = o.useRef(null), b = o.useRef(null), a = o.useRef(null), g = o.useRef(null), m = o.useRef(!1), n = o.useRef(null), k = V(q(c), n), T = o.useRef(null);
  o.useEffect(() => {
    !i || !n.current || (m.current = !u);
  }, [u, i]), o.useEffect(() => {
    if (!i || !n.current)
      return;
    const t = S(n.current);
    return n.current.contains(t.activeElement) || (n.current.hasAttribute("tabIndex") || (process.env.NODE_ENV, n.current.setAttribute("tabIndex", "-1")), m.current && n.current.focus()), () => {
      s || (a.current && a.current.focus && (v.current = !0, a.current.focus()), a.current = null);
    };
  }, [i]), o.useEffect(() => {
    if (!i || !n.current)
      return;
    const t = S(n.current), p = (l) => {
      T.current = l, !(r || !h() || l.key !== "Tab") && t.activeElement === n.current && l.shiftKey && (v.current = !0, b.current && b.current.focus());
    }, I = () => {
      const l = n.current;
      if (l === null)
        return;
      if (!t.hasFocus() || !h() || v.current) {
        v.current = !1;
        return;
      }
      if (l.contains(t.activeElement) || r && t.activeElement !== x.current && t.activeElement !== b.current)
        return;
      if (t.activeElement !== g.current)
        g.current = null;
      else if (g.current !== null)
        return;
      if (!m.current)
        return;
      let E = [];
      if ((t.activeElement === x.current || t.activeElement === b.current) && (E = f(n.current)), E.length > 0) {
        var F, y;
        const j = !!((F = T.current) != null && F.shiftKey && ((y = T.current) == null ? void 0 : y.key) === "Tab"), A = E[0], D = E[E.length - 1];
        typeof A != "string" && typeof D != "string" && (j ? D.focus() : A.focus());
      } else
        l.focus();
    };
    t.addEventListener("focusin", I), t.addEventListener("keydown", p, !0);
    const L = setInterval(() => {
      t.activeElement && t.activeElement.tagName === "BODY" && I();
    }, 50);
    return () => {
      clearInterval(L), t.removeEventListener("focusin", I), t.removeEventListener("keydown", p, !0);
    };
  }, [u, r, s, h, i, f]);
  const P = (t) => {
    a.current === null && (a.current = t.relatedTarget), m.current = !0, g.current = t.target;
    const p = c.props.onFocus;
    p && p(t);
  }, R = (t) => {
    a.current === null && (a.current = t.relatedTarget), m.current = !0;
  };
  return /* @__PURE__ */ U(o.Fragment, {
    children: [/* @__PURE__ */ O("div", {
      tabIndex: i ? 0 : -1,
      onFocus: R,
      ref: x,
      "data-testid": "sentinelStart"
    }), /* @__PURE__ */ o.cloneElement(c, {
      ref: k,
      onFocus: P
    }), /* @__PURE__ */ O("div", {
      tabIndex: i ? 0 : -1,
      onFocus: R,
      ref: b,
      "data-testid": "sentinelEnd"
    })]
  });
}
process.env.NODE_ENV !== "production" && (N.propTypes = {
  // ┌────────────────────────────── Warning ──────────────────────────────┐
  // │ These PropTypes are generated from the TypeScript type definitions. │
  // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │
  // └─────────────────────────────────────────────────────────────────────┘
  /**
   * A single child content element.
   */
  children: w,
  /**
   * If `true`, the focus trap will not automatically shift focus to itself when it opens, and
   * replace it to the last focused element when it closes.
   * This also works correctly with any focus trap children that have the `disableAutoFocus` prop.
   *
   * Generally this should never be set to `true` as it makes the focus trap less
   * accessible to assistive technologies, like screen readers.
   * @default false
   */
  disableAutoFocus: d.bool,
  /**
   * If `true`, the focus trap will not prevent focus from leaving the focus trap while open.
   *
   * Generally this should never be set to `true` as it makes the focus trap less
   * accessible to assistive technologies, like screen readers.
   * @default false
   */
  disableEnforceFocus: d.bool,
  /**
   * If `true`, the focus trap will not restore focus to previously focused element once
   * focus trap is hidden or unmounted.
   * @default false
   */
  disableRestoreFocus: d.bool,
  /**
   * Returns an array of ordered tabbable nodes (i.e. in tab order) within the root.
   * For instance, you can provide the "tabbable" npm dependency.
   * @param {HTMLElement} root
   */
  getTabbable: d.func,
  /**
   * This prop extends the `open` prop.
   * It allows to toggle the open state without having to wait for a rerender when changing the `open` prop.
   * This prop should be memoized.
   * It can be used to support multiple focus trap mounted at the same time.
   * @default function defaultIsEnabled(): boolean {
   *   return true;
   * }
   */
  isEnabled: d.func,
  /**
   * If `true`, focus is locked.
   */
  open: d.bool.isRequired
});
process.env.NODE_ENV !== "production" && (N.propTypes = B(N.propTypes));
export {
  N as default
};
