云
13 小时以前 91bfcf61f44f353dfebc54a57b5b774721de3e9a
src/packages/@core/ui-kit/menu-ui/src/components/sub-menu.vue
@@ -3,7 +3,7 @@
import type { MenuItemRegistered, MenuProvider, SubMenuProps } from '../types';
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import { useNamespace } from '../../../../composables/src';
import { VbenHoverCard } from '../../../shadcn-ui/src';
@@ -41,6 +41,32 @@
const items = ref<MenuProvider['items']>({});
const subMenus = ref<MenuProvider['subMenus']>({});
const timer = ref<null | ReturnType<typeof setTimeout>>(null);
const popupRef = ref<HTMLElement>();
const popupTriggerRef = ref<InstanceType<typeof SubMenuContent>>();
function togglePopup() {
  if (props.disabled) return;
  if (timer.value) window.clearTimeout(timer.value);
  if (opened.value) rootMenu.closeMenu(props.path, parentPaths.value);
  else rootMenu.openMenu(props.path, parentPaths.value);
}
async function handlePopupKeydown(event: KeyboardEvent) {
  if (props.disabled) return;
  if (['Enter', ' ', 'ArrowDown'].includes(event.key)) {
    event.preventDefault();
    event.stopPropagation();
    rootMenu.openMenu(props.path, parentPaths.value);
    await nextTick();
    popupRef.value?.querySelector<HTMLElement>('[role="menuitem"]')?.focus();
  } else if (event.key === 'Escape') {
    event.preventDefault();
    event.stopPropagation();
    rootMenu.closeMenu(props.path, parentPaths.value);
    const trigger = popupTriggerRef.value?.$el;
    if (trigger instanceof HTMLElement) trigger.focus();
  }
}
createSubMenuContext({
  addSubMenu,
@@ -218,13 +244,19 @@
      >
        <template #trigger>
          <SubMenuContent
            ref="popupTriggerRef"
            :class="is('active', active)"
            :icon="menuIcon"
            :is-menu-more="isSubMenuMore"
            :is-top-level-menu-submenu="isTopLevelMenuSubmenu"
            :level="currentLevel"
            :path="path"
            @click.stop="handleClick"
            role="menuitem"
            :tabindex="disabled ? -1 : 0"
            aria-haspopup="menu"
            :aria-expanded="opened"
            @click.stop="togglePopup"
            @keydown="handlePopupKeydown"
          >
            <template #title>
              <slot name="title"></slot>
@@ -232,7 +264,9 @@
          </SubMenuContent>
        </template>
        <div
          ref="popupRef"
          :class="[nsMenu.is(mode, true), nsMenu.e('popup')]"
          @keydown.esc="handlePopupKeydown"
          @focus="(e) => handleMouseenter(e, 100)"
          @mouseenter="(e) => handleMouseenter(e, 100)"
          @mouseleave="() => handleMouseleave(true)"
@@ -240,6 +274,7 @@
          <ul
            :class="[nsMenu.b(), is('rounded', rounded)]"
            :style="subMenuStyle"
            role="menu"
          >
            <slot></slot>
          </ul>