roving-focus-group-impl.mjs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { defineComponent, ref, inject, computed, provide, readonly, toRef, unref, watch, renderSlot } from 'vue';
  2. import { useEventListener } from '@vueuse/core';
  3. import { rovingFocusGroupProps, ROVING_FOCUS_COLLECTION_INJECTION_KEY as COLLECTION_INJECTION_KEY } from './roving-focus-group2.mjs';
  4. import { ROVING_FOCUS_GROUP_INJECTION_KEY } from './tokens.mjs';
  5. import { focusFirst } from './utils.mjs';
  6. import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
  7. import { composeEventHandlers } from '../../../utils/dom/event.mjs';
  8. const CURRENT_TAB_ID_CHANGE_EVT = "currentTabIdChange";
  9. const ENTRY_FOCUS_EVT = "rovingFocusGroup.entryFocus";
  10. const EVT_OPTS = { bubbles: false, cancelable: true };
  11. const _sfc_main = defineComponent({
  12. name: "ElRovingFocusGroupImpl",
  13. inheritAttrs: false,
  14. props: rovingFocusGroupProps,
  15. emits: [CURRENT_TAB_ID_CHANGE_EVT, "entryFocus"],
  16. setup(props, { emit }) {
  17. var _a;
  18. const currentTabbedId = ref((_a = props.currentTabId || props.defaultCurrentTabId) != null ? _a : null);
  19. const isBackingOut = ref(false);
  20. const isClickFocus = ref(false);
  21. const rovingFocusGroupRef = ref();
  22. const { getItems } = inject(COLLECTION_INJECTION_KEY, void 0);
  23. const rovingFocusGroupRootStyle = computed(() => {
  24. return [
  25. {
  26. outline: "none"
  27. },
  28. props.style
  29. ];
  30. });
  31. const onItemFocus = (tabbedId) => {
  32. emit(CURRENT_TAB_ID_CHANGE_EVT, tabbedId);
  33. };
  34. const onItemShiftTab = () => {
  35. isBackingOut.value = true;
  36. };
  37. const onMousedown = composeEventHandlers((e) => {
  38. var _a2;
  39. (_a2 = props.onMousedown) == null ? void 0 : _a2.call(props, e);
  40. }, () => {
  41. isClickFocus.value = true;
  42. });
  43. const onFocus = composeEventHandlers((e) => {
  44. var _a2;
  45. (_a2 = props.onFocus) == null ? void 0 : _a2.call(props, e);
  46. }, (e) => {
  47. const isKeyboardFocus = !unref(isClickFocus);
  48. const { target, currentTarget } = e;
  49. if (target === currentTarget && isKeyboardFocus && !unref(isBackingOut)) {
  50. const entryFocusEvt = new Event(ENTRY_FOCUS_EVT, EVT_OPTS);
  51. currentTarget == null ? void 0 : currentTarget.dispatchEvent(entryFocusEvt);
  52. if (!entryFocusEvt.defaultPrevented) {
  53. const items = getItems().filter((item) => item.focusable);
  54. const activeItem = items.find((item) => item.active);
  55. const currentItem = items.find((item) => item.id === unref(currentTabbedId));
  56. const candidates = [activeItem, currentItem, ...items].filter(Boolean);
  57. const candidateNodes = candidates.map((item) => item.ref);
  58. focusFirst(candidateNodes);
  59. }
  60. }
  61. isClickFocus.value = false;
  62. });
  63. const onBlur = composeEventHandlers((e) => {
  64. var _a2;
  65. (_a2 = props.onBlur) == null ? void 0 : _a2.call(props, e);
  66. }, () => {
  67. isBackingOut.value = false;
  68. });
  69. const handleEntryFocus = (...args) => {
  70. emit("entryFocus", ...args);
  71. };
  72. provide(ROVING_FOCUS_GROUP_INJECTION_KEY, {
  73. currentTabbedId: readonly(currentTabbedId),
  74. loop: toRef(props, "loop"),
  75. tabIndex: computed(() => {
  76. return unref(isBackingOut) ? -1 : 0;
  77. }),
  78. rovingFocusGroupRef,
  79. rovingFocusGroupRootStyle,
  80. orientation: toRef(props, "orientation"),
  81. dir: toRef(props, "dir"),
  82. onItemFocus,
  83. onItemShiftTab,
  84. onBlur,
  85. onFocus,
  86. onMousedown
  87. });
  88. watch(() => props.currentTabId, (val) => {
  89. currentTabbedId.value = val != null ? val : null;
  90. });
  91. useEventListener(rovingFocusGroupRef, ENTRY_FOCUS_EVT, handleEntryFocus);
  92. }
  93. });
  94. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  95. return renderSlot(_ctx.$slots, "default");
  96. }
  97. var ElRovingFocusGroupImpl = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "roving-focus-group-impl.vue"]]);
  98. export { ElRovingFocusGroupImpl as default };
  99. //# sourceMappingURL=roving-focus-group-impl.mjs.map