You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1 line
4.5 KiB

{"version":3,"file":"index.mjs","sources":["../../../../../packages/directives/trap-focus/index.ts"],"sourcesContent":["import { nextTick } from 'vue'\nimport { obtainAllFocusableElements } from '@element-plus/utils'\nimport { EVENT_CODE } from '@element-plus/constants'\nimport type { ObjectDirective } from 'vue'\n\nexport const FOCUSABLE_CHILDREN = '_trap-focus-children'\nexport const TRAP_FOCUS_HANDLER = '_trap-focus-handler'\n\nexport interface TrapFocusElement extends HTMLElement {\n [FOCUSABLE_CHILDREN]: HTMLElement[]\n [TRAP_FOCUS_HANDLER]: (e: KeyboardEvent) => void\n}\n\nconst FOCUS_STACK: TrapFocusElement[] = []\n\nconst FOCUS_HANDLER = (e: KeyboardEvent) => {\n // Getting the top layer.\n if (FOCUS_STACK.length === 0) return\n const focusableElement =\n FOCUS_STACK[FOCUS_STACK.length - 1][FOCUSABLE_CHILDREN]\n if (focusableElement.length > 0 && e.code === EVENT_CODE.tab) {\n if (focusableElement.length === 1) {\n e.preventDefault()\n if (document.activeElement !== focusableElement[0]) {\n focusableElement[0].focus()\n }\n return\n }\n const goingBackward = e.shiftKey\n const isFirst = e.target === focusableElement[0]\n const isLast = e.target === focusableElement[focusableElement.length - 1]\n if (isFirst && goingBackward) {\n e.preventDefault()\n focusableElement[focusableElement.length - 1].focus()\n }\n if (isLast && !goingBackward) {\n e.preventDefault()\n focusableElement[0].focus()\n }\n\n // the is critical since jsdom did not implement user actions, you can only mock it\n // DELETE ME: when testing env switches to puppeteer\n if (process.env.NODE_ENV === 'test') {\n const index = focusableElement.indexOf(e.target as HTMLElement)\n if (index !== -1) {\n focusableElement[goingBackward ? index - 1 : index + 1]?.focus()\n }\n }\n }\n}\n\nconst TrapFocus: ObjectDirective = {\n beforeMount(el: TrapFocusElement) {\n el[FOCUSABLE_CHILDREN] = obtainAllFocusableElements(el)\n FOCUS_STACK.push(el)\n if (FOCUS_STACK.length <= 1) {\n document.addEventListener('keydown', FOCUS_HANDLER)\n }\n },\n updated(el: TrapFocusElement) {\n nextTick(() => {\n el[FOCUSABLE_CHILDREN] = obtainAllFocusableElements(el)\n })\n },\n unmounted() {\n FOCUS_STACK.shift()\n if (FOCUS_STACK.length === 0) {\n document.removeEventListener('keydown', FOCUS_HANDLER)\n }\n },\n}\n\nexport default TrapFocus\n"],"names":[],"mappings":";;;;;;AAGY,MAAC,kBAAkB,GAAG,uBAAuB;AAC7C,MAAC,kBAAkB,GAAG,sBAAsB;AACxD,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK;AAC7B,EAAE,IAAI,EAAE,CAAC;AACT,EAAE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;AAC9B,IAAI,OAAO;AACX,EAAE,MAAM,gBAAgB,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;AACnF,EAAE,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,GAAG,EAAE;AAChE,IAAI,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE;AACvC,MAAM,CAAC,CAAC,cAAc,EAAE,CAAC;AACzB,MAAM,IAAI,QAAQ,CAAC,aAAa,KAAK,gBAAgB,CAAC,CAAC,CAAC,EAAE;AAC1D,QAAQ,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AACpC,OAAO;AACP,MAAM,OAAO;AACb,KAAK;AACL,IAAI,MAAM,aAAa,GAAG,CAAC,CAAC,QAAQ,CAAC;AACrC,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,KAAK,gBAAgB,CAAC,CAAC,CAAC,CAAC;AACrD,IAAI,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,KAAK,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC9E,IAAI,IAAI,OAAO,IAAI,aAAa,EAAE;AAClC,MAAM,CAAC,CAAC,cAAc,EAAE,CAAC;AACzB,MAAM,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AAC5D,KAAK;AACL,IAAI,IAAI,MAAM,IAAI,CAAC,aAAa,EAAE;AAClC,MAAM,CAAC,CAAC,cAAc,EAAE,CAAC;AACzB,MAAM,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;AAClC,KAAK;AACL,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM,EAAE;AACzC,MAAM,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACvD,MAAM,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;AACxB,QAAQ,CAAC,EAAE,GAAG,gBAAgB,CAAC,aAAa,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;AACrG,OAAO;AACP,KAAK;AACL,GAAG;AACH,CAAC,CAAC;AACG,MAAC,SAAS,GAAG;AAClB,EAAE,WAAW,CAAC,EAAE,EAAE;AAClB,IAAI,EAAE,CAAC,kBAAkB,CAA