index.mjs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { nextTick } from 'vue';
  2. import { obtainAllFocusableElements } from '../../utils/dom/aria.mjs';
  3. import { getEventCode } from '../../utils/dom/event.mjs';
  4. import { EVENT_CODE } from '../../constants/aria.mjs';
  5. const FOCUSABLE_CHILDREN = "_trap-focus-children";
  6. const TRAP_FOCUS_HANDLER = "_trap-focus-handler";
  7. const FOCUS_STACK = [];
  8. const FOCUS_HANDLER = (e) => {
  9. if (FOCUS_STACK.length === 0)
  10. return;
  11. const code = getEventCode(e);
  12. const focusableElement = FOCUS_STACK[FOCUS_STACK.length - 1][FOCUSABLE_CHILDREN];
  13. if (focusableElement.length > 0 && code === EVENT_CODE.tab) {
  14. if (focusableElement.length === 1) {
  15. e.preventDefault();
  16. if (document.activeElement !== focusableElement[0]) {
  17. focusableElement[0].focus();
  18. }
  19. return;
  20. }
  21. const goingBackward = e.shiftKey;
  22. const isFirst = e.target === focusableElement[0];
  23. const isLast = e.target === focusableElement[focusableElement.length - 1];
  24. if (isFirst && goingBackward) {
  25. e.preventDefault();
  26. focusableElement[focusableElement.length - 1].focus();
  27. }
  28. if (isLast && !goingBackward) {
  29. e.preventDefault();
  30. focusableElement[0].focus();
  31. }
  32. }
  33. };
  34. const TrapFocus = {
  35. beforeMount(el) {
  36. el[FOCUSABLE_CHILDREN] = obtainAllFocusableElements(el);
  37. FOCUS_STACK.push(el);
  38. if (FOCUS_STACK.length <= 1) {
  39. document.addEventListener("keydown", FOCUS_HANDLER);
  40. }
  41. },
  42. updated(el) {
  43. nextTick(() => {
  44. el[FOCUSABLE_CHILDREN] = obtainAllFocusableElements(el);
  45. });
  46. },
  47. unmounted() {
  48. FOCUS_STACK.shift();
  49. if (FOCUS_STACK.length === 0) {
  50. document.removeEventListener("keydown", FOCUS_HANDLER);
  51. }
  52. }
  53. };
  54. export { FOCUSABLE_CHILDREN, TRAP_FOCUS_HANDLER, TrapFocus as default };
  55. //# sourceMappingURL=index.mjs.map