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