{"version":3,"file":"focus-trap.mjs","sources":["../../../../../../packages/components/focus-trap/src/focus-trap.vue"],"sourcesContent":["<template>\n  <slot />\n</template>\n<script lang=\"ts\">\nimport {\n  defineComponent,\n  nextTick,\n  onBeforeUnmount,\n  onMounted,\n  provide,\n  ref,\n  unref,\n  watch,\n} from 'vue'\nimport { EVENT_CODE } from '@element-plus/constants'\nimport {\n  focusFirstDescendant,\n  focusableStack,\n  getEdges,\n  obtainAllFocusableElements,\n  tryFocus,\n} from './utils'\nimport {\n  FOCUS_ON_MOUNT,\n  FOCUS_ON_MOUNT_OPTS,\n  FOCUS_ON_UNMOUNT,\n  FOCUS_TRAP_INJECTION_KEY,\n  ON_MOUNT_FOCUS_EVT,\n  ON_UNMOUNT_FOCUS_EVT,\n} from './tokens'\n\nimport type { FocusLayer } from './utils'\n\nexport default defineComponent({\n  name: 'ElFocusTrap',\n  inheritAttrs: false,\n  props: {\n    loop: Boolean,\n    trapped: Boolean,\n  },\n  emits: [ON_MOUNT_FOCUS_EVT, ON_UNMOUNT_FOCUS_EVT],\n  setup(props, { emit }) {\n    const focusTrapRef = ref<HTMLElement | null>()\n    const forwardRef = ref<HTMLElement | null>(null)\n    let lastFocusBeforeMounted: HTMLElement | null\n    let lastFocusAfterMounted: HTMLElement | null\n\n    const focusLayer: FocusLayer = {\n      paused: false,\n      pause() {\n        this.paused = true\n      },\n      resume() {\n        this.paused = false\n      },\n    }\n\n    const onKeydown = (e: KeyboardEvent) => {\n      if (!props.loop && !props.trapped) return\n      if (focusLayer.paused) return\n\n      const { key, altKey, ctrlKey, metaKey, currentTarget, shiftKey } = e\n      const { loop } = props\n      const isTabbing =\n        key === EVENT_CODE.tab && !altKey && !ctrlKey && !metaKey\n\n      const currentFocusingEl = document.activeElement\n      if (isTabbing && currentFocusingEl) {\n        const container = currentTarget as HTMLElement\n        const [first, last] = getEdges(container)\n        const isTabbable = first && last\n\n        if (!isTabbable) {\n          if (currentFocusingEl === container) e.preventDefault()\n        } else {\n          if (!shiftKey && currentFocusingEl === last) {\n            e.preventDefault()\n            if (loop) tryFocus(first, true)\n          } else if (shiftKey && currentFocusingEl === first) {\n            e.preventDefault()\n            if (loop) tryFocus(last, true)\n          }\n        }\n      }\n    }\n\n    provide(FOCUS_TRAP_INJECTION_KEY, {\n      focusTrapRef: forwardRef,\n      onKeydown,\n    })\n\n    const focusOnMount = (e: Event) => {\n      emit(ON_MOUNT_FOCUS_EVT, e)\n    }\n    const focusOnUnmount = (e: Event) => emit(ON_UNMOUNT_FOCUS_EVT, e)\n    const onFocusIn = (e: Event) => {\n      const trapContainer = unref(forwardRef)\n      if (focusLayer.paused || !trapContainer) return\n      const target = e.target as HTMLElement | null\n      if (target && trapContainer.contains(target)) {\n        lastFocusAfterMounted = target\n      } else {\n        tryFocus(lastFocusAfterMounted, true)\n      }\n    }\n\n    const onFocusOut = (e: Event) => {\n      const trapContainer = unref(forwardRef)\n      if (focusLayer.paused || !trapContainer) return\n\n      if (\n        !trapContainer.contains(\n          (e as FocusEvent).relatedTarget as HTMLElement | null\n        )\n      ) {\n        tryFocus(lastFocusAfterMounted, true)\n      }\n    }\n\n    const cleanupDocumentListeners = () => {\n      document.removeEventListener('focusin', onFocusIn)\n      document.removeEventListener('focusout', onFocusOut)\n    }\n\n    onMounted(() => {\n      const trapContainer = unref(forwardRef)\n      if (trapContainer) {\n        focusableStack.push(focusLayer)\n        const prevFocusedElement = document.activeElement\n        lastFocusBeforeMounted = prevFocusedElement as HTMLElement | null\n        const isPrevFocusContained = trapContainer.contains(prevFocusedElement)\n        if (!isPrevFocusContained) {\n          const mountEvent = new Event(FOCUS_ON_MOUNT, FOCUS_ON_MOUNT_OPTS)\n          trapContainer.addEventListener(FOCUS_ON_MOUNT, focusOnMount)\n          trapContainer.dispatchEvent(mountEvent)\n          if (!mountEvent.defaultPrevented) {\n            nextTick(() => {\n              focusFirstDescendant(\n                obtainAllFocusableElements(trapContainer),\n                true\n              )\n              if (document.activeElement === prevFocusedElement) {\n                tryFocus(trapContainer)\n              }\n            })\n          }\n        }\n      }\n\n      watch(\n        () => props.trapped,\n        (trapped) => {\n          if (trapped) {\n            document.addEventListener('focusin', onFocusIn)\n            document.addEventListener('focusout', onFocusOut)\n          } else {\n            cleanupDocumentListeners()\n          }\n        },\n        { immediate: true }\n      )\n    })\n\n    onBeforeUnmount(() => {\n      cleanupDocumentListeners()\n      const trapContainer = unref(forwardRef)\n\n      if (trapContainer) {\n        trapContainer.removeEventListener(FOCUS_ON_MOUNT, focusOnMount)\n        const unmountEvent = new Event(FOCUS_ON_UNMOUNT, FOCUS_ON_MOUNT_OPTS)\n\n        trapContainer.addEventListener(FOCUS_ON_UNMOUNT, focusOnUnmount)\n        trapContainer.dispatchEvent(unmountEvent)\n\n        if (!unmountEvent.defaultPrevented) {\n          tryFocus(lastFocusBeforeMounted ?? document.body, true)\n        }\n\n        trapContainer.removeEventListener(FOCUS_ON_UNMOUNT, focusOnMount)\n        focusableStack.remove(focusLayer)\n      }\n    })\n\n    return {\n      focusTrapRef,\n      forwardRef,\n      onKeydown,\n    }\n  },\n})\n</script>\n"],"names":["_renderSlot"],"mappings":"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"}