focus-visible-7a0ce04f.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /*!
  2. * (C) Ionic http://ionicframework.com - MIT License
  3. */
  4. 'use strict';
  5. const ION_FOCUSED = 'ion-focused';
  6. const ION_FOCUSABLE = 'ion-focusable';
  7. const FOCUS_KEYS = [
  8. 'Tab',
  9. 'ArrowDown',
  10. 'Space',
  11. 'Escape',
  12. ' ',
  13. 'Shift',
  14. 'Enter',
  15. 'ArrowLeft',
  16. 'ArrowRight',
  17. 'ArrowUp',
  18. 'Home',
  19. 'End',
  20. ];
  21. const startFocusVisible = (rootEl) => {
  22. let currentFocus = [];
  23. let keyboardMode = true;
  24. const ref = rootEl ? rootEl.shadowRoot : document;
  25. const root = rootEl ? rootEl : document.body;
  26. const setFocus = (elements) => {
  27. currentFocus.forEach((el) => el.classList.remove(ION_FOCUSED));
  28. elements.forEach((el) => el.classList.add(ION_FOCUSED));
  29. currentFocus = elements;
  30. };
  31. const pointerDown = () => {
  32. keyboardMode = false;
  33. setFocus([]);
  34. };
  35. const onKeydown = (ev) => {
  36. keyboardMode = FOCUS_KEYS.includes(ev.key);
  37. if (!keyboardMode) {
  38. setFocus([]);
  39. }
  40. };
  41. const onFocusin = (ev) => {
  42. if (keyboardMode && ev.composedPath !== undefined) {
  43. const toFocus = ev.composedPath().filter((el) => {
  44. // TODO(FW-2832): type
  45. if (el.classList) {
  46. return el.classList.contains(ION_FOCUSABLE);
  47. }
  48. return false;
  49. });
  50. setFocus(toFocus);
  51. }
  52. };
  53. const onFocusout = () => {
  54. if (ref.activeElement === root) {
  55. setFocus([]);
  56. }
  57. };
  58. ref.addEventListener('keydown', onKeydown);
  59. ref.addEventListener('focusin', onFocusin);
  60. ref.addEventListener('focusout', onFocusout);
  61. ref.addEventListener('touchstart', pointerDown, { passive: true });
  62. ref.addEventListener('mousedown', pointerDown);
  63. const destroy = () => {
  64. ref.removeEventListener('keydown', onKeydown);
  65. ref.removeEventListener('focusin', onFocusin);
  66. ref.removeEventListener('focusout', onFocusout);
  67. ref.removeEventListener('touchstart', pointerDown);
  68. ref.removeEventListener('mousedown', pointerDown);
  69. };
  70. return {
  71. destroy,
  72. setFocus,
  73. };
  74. };
  75. exports.startFocusVisible = startFocusVisible;