import { some as h } from "../../../utils/collection/main.js";
import { isUndefined as R, isNullish as N, isNumber as m } from "../../../utils/value/is.js";
import { mod as x } from "../../../utils/value/number.js";
const k = `:scope ${`
    a[href],
    audio[controls],
    video[controls],
    button,
    input,
    select,
    textarea,
    [contenteditable],
    [tabindex]
`.replace(/\s+/g, "")}`, I = ["contenteditable", "controls", "disabled", "hidden", "href", "inert", "tabindex"], p = /* @__PURE__ */ new Map(), E = (t) => t.tagName === "INPUT", T = (t) => E(t) && t.type === "radio", A = (t) => {
  const e = t.name, n = t.form, r = p.get(n);
  let c = r?.get(e);
  return R(c) && n && (c = n.querySelector(`:scope input[type=radio][name='${e}']:checked`) || null, p.set(n, (r || /* @__PURE__ */ new Map()).set(e, c))), c === t;
}, g = (t = document) => {
  let e = t.activeElement;
  for (; e && e.shadowRoot && e.shadowRoot.activeElement; )
    e = e.shadowRoot.activeElement;
  return e;
}, w = (t = document.body, e) => {
  if (R(t))
    return !1;
  if (N(e)) {
    const r = g();
    return !!r && w(t, r);
  }
  let n = e.parentNode;
  for (; n; ) {
    if (n === t)
      return !0;
    n = n instanceof ShadowRoot ? n.host : n?.parentNode || null;
  }
  return !1;
}, C = (t) => !// [TODO]: Include all of these checks
// (1) matches focusable elements selector
// (2) is disabled element
// (3) is inert or inert subtree child
// (4) is hidden input
// (5) with visibility: hidden
// (6) is summary of open details element
// (7) is details with summary element
// (8) is disabled fieldset subtree child
/* (1) */
(!t.matches(k) || /* (2) */
t?.disabled || /* (3) */
/^(true)?$/.test(t.getAttribute("inert")) || /* (4) */
E(t) && t.hidden), b = (t) => !(T(t) && !A(t) || // (1) is not checked radio button
t?.tabIndex < 0 || // (2) has negative tabindex
!C(t)), L = () => {
  const t = new MutationObserver((o) => v(o) && l()), e = [];
  let n = -1, r = null;
  const c = (o) => {
    if (o < 0) return;
    const s = Math.min(o, e.length - 1);
    n !== s && (n = s), e[n]?.focus();
  }, l = () => {
    if (e.length = 0, !r) return;
    const o = {
      attributeFilter: I,
      attributes: !0,
      childList: !0,
      subtree: !0
    };
    t.observe(r, o);
    const s = (i) => {
      const a = document.createTreeWalker(i, NodeFilter.SHOW_ELEMENT, {
        acceptNode: () => NodeFilter.FILTER_ACCEPT
      });
      let u = a.nextNode();
      for (; u; ) {
        const d = u;
        b(d) && e.push(d), d.shadowRoot && (t.observe(d.shadowRoot, o), s(d.shadowRoot)), u = a.nextNode();
      }
    };
    s(r), w(r) && (f.current = g());
  }, v = (o) => {
    let s = !1;
    for (const i of o)
      if (i.type === "attributes" ? s ||= i.target instanceof Element && // Target is a tabbable element (possibly due to attribute changes)
      // For example, disabled set to false, tabindex set to a number, etc.
      (b(i.target) || // Target is already contained in the list of tabbables
      // Attribute changes could make it no longer tabbable (e.g. disabled set to true)
      e.includes(i.target)) : s ||= // At least one element was added or removed from the DOM tree of the root element
      h(i.addedNodes, (a) => a instanceof Element) || h(i.removedNodes, (a) => a instanceof Element), s) break;
    return s;
  }, f = Object.create(null, {
    current: {
      get: () => e[n] ?? null,
      set: (o) => {
        if (o) {
          if (!m(o))
            return c(e.indexOf(o));
          if (o === ~~o)
            return c(x(n + o, e.length));
        }
      }
    },
    root: {
      get: () => r,
      set: (o) => {
        o !== r && (r && t.disconnect(), r = o instanceof Element ? o : null, l());
      }
    },
    tabbables: { value: e }
  });
  return f;
};
export {
  k as SELECTORS,
  L as default,
  w as focusIsWithin,
  g as getDeepActiveElement,
  C as isFocusable,
  b as isTabbable,
  L as withTabbableRoot
};
