import { defineComponent, ref, provide, watch, unref, onMounted, onBeforeUnmount, nextTick, renderSlot } from "vue";
import { useFocusReason as I, tryFocus as S, createFocusOutPreventedEvent as O, getEdges as R, focusableStack as k, focusFirstDescendant as _$1, obtainAllFocusableElements as T$1, isFocusCausedByUserEvent as C } from "./utils.mjs";
import { ON_TRAP_FOCUS_EVT as o, ON_RELEASE_FOCUS_EVT as _, FOCUS_TRAP_INJECTION_KEY as T, FOCUS_AFTER_TRAPPED as e, FOCUS_AFTER_TRAPPED_OPTS as t, FOCUS_AFTER_RELEASED as s } from "./tokens.mjs";
import c from "../../../_virtual/plugin-vue_export-helper.mjs";
import { useEscapeKeydown as p } from "../../../hooks/use-escape-keydown/index.mjs";
import { EVENT_CODE as e$1 } from "../../../constants/aria.mjs";
import { isString as p$1 } from "../../../../../@vue/shared/dist/shared.esm-bundler.mjs";
import n from "../../../../../lodash-es/isNil.mjs";
const ne = defineComponent({
  name: "ElFocusTrap",
  inheritAttrs: false,
  props: {
    loop: Boolean,
    trapped: Boolean,
    focusTrapEl: Object,
    focusStartEl: {
      type: [Object, String],
      default: "first"
    }
  },
  emits: [
    o,
    _,
    "focusin",
    "focusout",
    "focusout-prevented",
    "release-requested"
  ],
  setup(n$1, { emit: a }) {
    const u = ref();
    let l, v;
    const { focusReason: i } = I();
    p((e2) => {
      n$1.trapped && !f.paused && a("release-requested", e2);
    });
    const f = {
      paused: false,
      pause() {
        this.paused = true;
      },
      resume() {
        this.paused = false;
      }
    }, p$2 = (e2) => {
      if (!n$1.loop && !n$1.trapped || f.paused)
        return;
      const { key: t2, altKey: o2, ctrlKey: s2, metaKey: r, currentTarget: h, shiftKey: K } = e2, { loop: D } = n$1, B = t2 === e$1.tab && !o2 && !s2 && !r, E = document.activeElement;
      if (B && E) {
        const F = h, [_2, P] = R(F);
        if (_2 && P) {
          if (!K && E === P) {
            const c2 = O({
              focusReason: i.value
            });
            a("focusout-prevented", c2), c2.defaultPrevented || (e2.preventDefault(), D && S(_2, true));
          } else if (K && [_2, F].includes(E)) {
            const c2 = O({
              focusReason: i.value
            });
            a("focusout-prevented", c2), c2.defaultPrevented || (e2.preventDefault(), D && S(P, true));
          }
        } else if (E === F) {
          const c2 = O({
            focusReason: i.value
          });
          a("focusout-prevented", c2), c2.defaultPrevented || e2.preventDefault();
        }
      }
    };
    provide(T, {
      focusTrapRef: u,
      onKeydown: p$2
    }), watch(() => n$1.focusTrapEl, (e2) => {
      e2 && (u.value = e2);
    }, { immediate: true }), watch([u], ([e2], [t2]) => {
      e2 && (e2.addEventListener("keydown", p$2), e2.addEventListener("focusin", g), e2.addEventListener("focusout", L)), t2 && (t2.removeEventListener("keydown", p$2), t2.removeEventListener("focusin", g), t2.removeEventListener("focusout", L));
    });
    const b = (e2) => {
      a(o, e2);
    }, S$1 = (e2) => a(_, e2), g = (e2) => {
      const t2 = unref(u);
      if (!t2)
        return;
      const o2 = e2.target, s2 = e2.relatedTarget, r = o2 && t2.contains(o2);
      n$1.trapped || s2 && t2.contains(s2) || (l = s2), r && a("focusin", e2), !f.paused && n$1.trapped && (r ? v = o2 : S(v, true));
    }, L = (e2) => {
      const t2 = unref(u);
      if (!(f.paused || !t2))
        if (n$1.trapped) {
          const o2 = e2.relatedTarget;
          !n(o2) && !t2.contains(o2) && setTimeout(() => {
            if (!f.paused && n$1.trapped) {
              const s2 = O({
                focusReason: i.value
              });
              a("focusout-prevented", s2), s2.defaultPrevented || S(v, true);
            }
          }, 0);
        } else {
          const o2 = e2.target;
          o2 && t2.contains(o2) || a("focusout", e2);
        }
    };
    async function A() {
      await nextTick();
      const e$12 = unref(u);
      if (e$12) {
        k.push(f);
        const t$1 = e$12.contains(document.activeElement) ? l : document.activeElement;
        if (l = t$1, !e$12.contains(t$1)) {
          const s2 = new Event(e, t);
          e$12.addEventListener(e, b), e$12.dispatchEvent(s2), s2.defaultPrevented || nextTick(() => {
            let r = n$1.focusStartEl;
            p$1(r) || (S(r), document.activeElement !== r && (r = "first")), r === "first" && _$1(T$1(e$12), true), (document.activeElement === t$1 || r === "container") && S(e$12);
          });
        }
      }
    }
    function R$1() {
      const e$12 = unref(u);
      if (e$12) {
        e$12.removeEventListener(e, b);
        const t$1 = new CustomEvent(s, {
          ...t,
          detail: {
            focusReason: i.value
          }
        });
        e$12.addEventListener(s, S$1), e$12.dispatchEvent(t$1), !t$1.defaultPrevented && (i.value == "keyboard" || !C() || e$12.contains(document.activeElement)) && S(l ?? document.body), e$12.removeEventListener(s, S$1), k.remove(f);
      }
    }
    return onMounted(() => {
      n$1.trapped && A(), watch(() => n$1.trapped, (e2) => {
        e2 ? A() : R$1();
      });
    }), onBeforeUnmount(() => {
      n$1.trapped && R$1();
    }), {
      onKeydown: p$2
    };
  }
});
function oe(n2, a, u, l, v, i) {
  return renderSlot(n2.$slots, "default", { handleKeydown: n2.onKeydown });
}
var ve = /* @__PURE__ */ c(ne, [["render", oe], ["__file", "focus-trap.vue"]]);
export {
  ve as default
};
