b645bb58fec9e348244ac0fef58aa8547589e2c97ed3bad811de877ab0491149b2153d293cabd0809c9e64a399cd64425511e9c8d3a07a4c045786a17f10f3 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { onMounted, onUpdated } from 'vue';
  2. import { useEventListener } from '@vueuse/core';
  3. import { useNamespace } from '../../../../hooks/use-namespace/index.mjs';
  4. import { EVENT_CODE } from '../../../../constants/aria.mjs';
  5. function useKeydown({ el$ }, store) {
  6. const ns = useNamespace("tree");
  7. onMounted(() => {
  8. initTabIndex();
  9. });
  10. onUpdated(() => {
  11. const checkboxItems = Array.from(el$.value.querySelectorAll("input[type=checkbox]"));
  12. checkboxItems.forEach((checkbox) => {
  13. checkbox.setAttribute("tabindex", "-1");
  14. });
  15. });
  16. function canNodeFocus(treeItems, nextIndex) {
  17. var _a, _b;
  18. const currentNode = store.value.getNode(treeItems[nextIndex].dataset.key);
  19. return currentNode.canFocus && currentNode.visible && (((_a = currentNode.parent) == null ? void 0 : _a.expanded) || ((_b = currentNode.parent) == null ? void 0 : _b.level) === 0);
  20. }
  21. const handleKeydown = (ev) => {
  22. const currentItem = ev.target;
  23. if (!currentItem.className.includes(ns.b("node")))
  24. return;
  25. const code = ev.code;
  26. const treeItems = Array.from(el$.value.querySelectorAll(`.${ns.is("focusable")}[role=treeitem]`));
  27. const currentIndex = treeItems.indexOf(currentItem);
  28. let nextIndex;
  29. if ([EVENT_CODE.up, EVENT_CODE.down].includes(code)) {
  30. ev.preventDefault();
  31. if (code === EVENT_CODE.up) {
  32. nextIndex = currentIndex === -1 ? 0 : currentIndex !== 0 ? currentIndex - 1 : treeItems.length - 1;
  33. const startIndex = nextIndex;
  34. while (true) {
  35. if (canNodeFocus(treeItems, nextIndex)) {
  36. break;
  37. }
  38. nextIndex--;
  39. if (nextIndex === startIndex) {
  40. nextIndex = -1;
  41. break;
  42. }
  43. if (nextIndex < 0) {
  44. nextIndex = treeItems.length - 1;
  45. }
  46. }
  47. } else {
  48. nextIndex = currentIndex === -1 ? 0 : currentIndex < treeItems.length - 1 ? currentIndex + 1 : 0;
  49. const startIndex = nextIndex;
  50. while (true) {
  51. if (canNodeFocus(treeItems, nextIndex)) {
  52. break;
  53. }
  54. nextIndex++;
  55. if (nextIndex === startIndex) {
  56. nextIndex = -1;
  57. break;
  58. }
  59. if (nextIndex >= treeItems.length) {
  60. nextIndex = 0;
  61. }
  62. }
  63. }
  64. nextIndex !== -1 && treeItems[nextIndex].focus();
  65. }
  66. if ([EVENT_CODE.left, EVENT_CODE.right].includes(code)) {
  67. ev.preventDefault();
  68. currentItem.click();
  69. }
  70. const hasInput = currentItem.querySelector('[type="checkbox"]');
  71. if ([EVENT_CODE.enter, EVENT_CODE.numpadEnter, EVENT_CODE.space].includes(code) && hasInput) {
  72. ev.preventDefault();
  73. hasInput.click();
  74. }
  75. };
  76. useEventListener(el$, "keydown", handleKeydown);
  77. const initTabIndex = () => {
  78. var _a;
  79. if (!el$.value)
  80. return;
  81. const treeItems = Array.from(el$.value.querySelectorAll(`.${ns.is("focusable")}[role=treeitem]`));
  82. const checkboxItems = Array.from(el$.value.querySelectorAll("input[type=checkbox]"));
  83. checkboxItems.forEach((checkbox) => {
  84. checkbox.setAttribute("tabindex", "-1");
  85. });
  86. const checkedItem = el$.value.querySelectorAll(`.${ns.is("checked")}[role=treeitem]`);
  87. if (checkedItem.length) {
  88. checkedItem[0].setAttribute("tabindex", "0");
  89. return;
  90. }
  91. (_a = treeItems[0]) == null ? void 0 : _a.setAttribute("tabindex", "0");
  92. };
  93. }
  94. export { useKeydown };
  95. //# sourceMappingURL=useKeydown.mjs.map