{"version":3,"file":"menu.mjs","sources":["../../../../../../packages/components/menu/src/menu.ts"],"sourcesContent":["import {\n  defineComponent,\n  getCurrentInstance,\n  watch,\n  computed,\n  ref,\n  provide,\n  onMounted,\n  h,\n  withDirectives,\n  reactive,\n  nextTick,\n} from 'vue'\nimport { Resize } from '@element-plus/directives'\nimport ElIcon from '@element-plus/components/icon'\nimport { More } from '@element-plus/icons'\nimport Menubar from '@element-plus/utils/menu/menu-bar'\nimport { buildProps, definePropType, mutable } from '@element-plus/utils/props'\nimport { isString, isObject } from '@element-plus/utils/util'\nimport ElMenuCollapseTransition from './menu-collapse-transition.vue'\nimport ElSubMenu from './sub-menu'\nimport { useMenuCssVar } from './use-menu-css-var'\n\nimport type { MenuItemClicked, MenuProvider, SubMenuProvider } from './types'\nimport type { NavigationFailure, Router } from 'vue-router'\nimport type { VNode, ExtractPropTypes, VNodeNormalizedChildren } from 'vue'\n\nexport const menuProps = buildProps({\n  mode: {\n    type: String,\n    values: ['horizontal', 'vertical'],\n    default: 'vertical',\n  },\n  defaultActive: {\n    type: String,\n    default: '',\n  },\n  defaultOpeneds: {\n    type: definePropType<string[]>(Array),\n    default: () => mutable([] as const),\n  },\n  uniqueOpened: Boolean,\n  router: Boolean,\n  menuTrigger: {\n    type: String,\n    values: ['hover', 'click'],\n    default: 'hover',\n  },\n  collapse: Boolean,\n  backgroundColor: String,\n  textColor: String,\n  activeTextColor: String,\n  collapseTransition: {\n    type: Boolean,\n    default: true,\n  },\n  ellipsis: {\n    type: Boolean,\n    default: true,\n  },\n} as const)\nexport type MenuProps = ExtractPropTypes<typeof menuProps>\n\nconst checkIndexPath = (indexPath: unknown): indexPath is string[] =>\n  Array.isArray(indexPath) && indexPath.every((path) => isString(path))\n\nexport const menuEmits = {\n  close: (index: string, indexPath: string[]) =>\n    isString(index) && checkIndexPath(indexPath),\n\n  open: (index: string, indexPath: string[]) =>\n    isString(index) && checkIndexPath(indexPath),\n\n  select: (\n    index: string,\n    indexPath: string[],\n    item: MenuItemClicked,\n    routerResult?: Promise<void | NavigationFailure>\n  ) =>\n    isString(index) &&\n    checkIndexPath(indexPath) &&\n    isObject(item) &&\n    (routerResult === undefined || routerResult instanceof Promise),\n}\nexport type MenuEmits = typeof menuEmits\n\nexport default defineComponent({\n  name: 'ElMenu',\n\n  props: menuProps,\n  emits: menuEmits,\n\n  setup(props, { emit, slots, expose }) {\n    const instance = getCurrentInstance()!\n    const router = instance.appContext.config.globalProperties.$router as Router\n    const menu = ref<HTMLUListElement>()\n\n    // data\n    const openedMenus = ref<MenuProvider['openedMenus']>(\n      props.defaultOpeneds && !props.collapse\n        ? props.defaultOpeneds.slice(0)\n        : []\n    )\n    const activeIndex = ref<MenuProvider['activeIndex']>(props.defaultActive)\n    const items = ref<MenuProvider['items']>({})\n    const subMenus = ref<MenuProvider['subMenus']>({})\n\n    const alteredCollapse = ref(false)\n\n    // computed\n    const isMenuPopup = computed<MenuProvider['isMenuPopup']>(() => {\n      return (\n        props.mode === 'horizontal' ||\n        (props.mode === 'vertical' && props.collapse)\n      )\n    })\n\n    // methods\n    const initMenu = () => {\n      const activeItem = activeIndex.value && items.value[activeIndex.value]\n      if (!activeItem || props.mode === 'horizontal' || props.collapse) return\n\n      const indexPath = activeItem.indexPath\n\n      // 展开该菜单项的路径上所有子菜单\n      // expand all subMenus of the menu item\n      indexPath.forEach((index) => {\n        const subMenu = subMenus.value[index]\n        subMenu && openMenu(index, subMenu.indexPath)\n      })\n    }\n\n    const openMenu: MenuProvider['openMenu'] = (index, indexPath) => {\n      if (openedMenus.value.includes(index)) return\n      // 将不在该菜单路径下的其余菜单收起\n      // collapse all menu that are not under current menu item\n      if (props.uniqueOpened) {\n        openedMenus.value = openedMenus.value.filter((index: string) =>\n          indexPath.includes(index)\n        )\n      }\n      openedMenus.value.push(index)\n      emit('open', index, indexPath)\n    }\n\n    const closeMenu: MenuProvider['closeMenu'] = (index, indexPath) => {\n      const i = openedMenus.value.indexOf(index)\n      if (i !== -1) {\n        openedMenus.value.splice(i, 1)\n      }\n      emit('close', index, indexPath)\n    }\n\n    const handleSubMenuClick: MenuProvider['handleSubMenuClick'] = ({\n      index,\n      indexPath,\n    }) => {\n      const isOpened = openedMenus.value.includes(index)\n\n      if (isOpened) {\n        closeMenu(index, indexPath)\n      } else {\n        openMenu(index, indexPath)\n      }\n    }\n\n    const handleMenuItemClick: MenuProvider['handleMenuItemClick'] = (\n      menuItem\n    ) => {\n      if (props.mode === 'horizontal' || props.collapse) {\n        openedMenus.value = []\n      }\n\n      const { index, indexPath } = menuItem\n      if (index === undefined || indexPath === undefined) return\n\n      if (props.router && router) {\n        const route = menuItem.route || index\n        const routerResult = router.push(route).then((res) => {\n          if (!res) activeIndex.value = index\n          return res\n        })\n        emit(\n          'select',\n          index,\n          indexPath,\n          { index, indexPath, route },\n          routerResult\n        )\n      } else {\n        activeIndex.value = index\n        emit('select', index, indexPath, { index, indexPath })\n      }\n    }\n\n    const updateActiveIndex = (val: string) => {\n      const itemsInData = items.value\n      const item =\n        itemsInData[val] ||\n        (activeIndex.value && itemsInData[activeIndex.value]) ||\n        itemsInData[props.defaultActive]\n\n      if (item) {\n        activeIndex.value = item.index\n        initMenu()\n      } else {\n        // Can't find item when collapsing\n        // and activeIndex shouldn't be changed when 'collapse' was changed.\n        // Then reset 'alteredCollapse' immediately.\n        if (!alteredCollapse.value) {\n          activeIndex.value = undefined\n        } else {\n          alteredCollapse.value = false\n        }\n      }\n    }\n    const handleResize = () => {\n      nextTick(() => instance.proxy!.$forceUpdate())\n    }\n\n    watch(\n      () => props.defaultActive,\n      (currentActive) => {\n        if (!items.value[currentActive]) {\n          activeIndex.value = ''\n        }\n        updateActiveIndex(currentActive)\n      }\n    )\n\n    watch(items.value, () => initMenu())\n\n    watch(\n      () => props.collapse,\n      (value, prev) => {\n        if (value !== prev) {\n          alteredCollapse.value = true\n        }\n        if (value) openedMenus.value = []\n      }\n    )\n\n    // provide\n    {\n      const addSubMenu: MenuProvider['addSubMenu'] = (item) => {\n        subMenus.value[item.index] = item\n      }\n\n      const removeSubMenu: MenuProvider['removeSubMenu'] = (item) => {\n        delete subMenus.value[item.index]\n      }\n\n      const addMenuItem: MenuProvider['addMenuItem'] = (item) => {\n        items.value[item.index] = item\n      }\n\n      const removeMenuItem: MenuProvider['removeMenuItem'] = (item) => {\n        delete items.value[item.index]\n      }\n      provide<MenuProvider>(\n        'rootMenu',\n        reactive({\n          props,\n          openedMenus,\n          items,\n          subMenus,\n          activeIndex,\n          isMenuPopup,\n\n          addMenuItem,\n          removeMenuItem,\n          addSubMenu,\n          removeSubMenu,\n          openMenu,\n          closeMenu,\n          handleMenuItemClick,\n          handleSubMenuClick,\n        })\n      )\n      provide<SubMenuProvider>(`subMenu:${instance.uid}`, {\n        addSubMenu,\n        removeSubMenu,\n      })\n    }\n\n    // lifecycle\n    onMounted(() => {\n      initMenu()\n      if (props.mode === 'horizontal') {\n        new Menubar(instance.vnode.el!)\n      }\n    })\n\n    {\n      const open = (index: string) => {\n        const { indexPath } = subMenus.value[index]\n        indexPath.forEach((i) => openMenu(i, indexPath))\n      }\n      expose({\n        open,\n        close: closeMenu,\n        handleResize,\n      })\n    }\n\n    const flattedChildren = (children: VNodeNormalizedChildren) => {\n      const vnodes = Array.isArray(children) ? children : [children]\n      const result: any[] = []\n      vnodes.forEach((child: any) => {\n        if (Array.isArray(child.children)) {\n          result.push(...flattedChildren(child.children))\n        } else {\n          result.push(child)\n        }\n      })\n      return result\n    }\n\n    const useVNodeResize = (vnode: VNode) =>\n      props.mode === 'horizontal'\n        ? withDirectives(vnode, [[Resize, handleResize]])\n        : vnode\n    return () => {\n      let slot = slots.default?.() ?? []\n      const vShowMore: VNode[] = []\n\n      if (props.mode === 'horizontal' && menu.value) {\n        const items = Array.from(menu.value?.childNodes ?? []).filter(\n          (item) => item.nodeName !== '#text' || item.nodeValue\n        ) as HTMLElement[]\n        const originalSlot = flattedChildren(slot)\n        const moreItemWidth = 64\n        const paddingLeft = parseInt(\n          getComputedStyle(menu.value).paddingLeft,\n          10\n        )\n        const paddingRight = parseInt(\n          getComputedStyle(menu.value).paddingRight,\n          10\n        )\n        const menuWidth = menu.value.clientWidth - paddingLeft - paddingRight\n        let calcWidth = 0\n        let sliceIndex = 0\n        items.forEach((item, index) => {\n          calcWidth += item.offsetWidth || 0\n          if (calcWidth <= menuWidth - moreItemWidth) {\n            sliceIndex = index + 1\n          }\n        })\n        const slotDefault = originalSlot.slice(0, sliceIndex)\n        const slotMore = originalSlot.slice(sliceIndex)\n        if (slotMore?.length && props.ellipsis) {\n          slot = slotDefault\n          vShowMore.push(\n            h(\n              ElSubMenu,\n              {\n                index: 'sub-menu-more',\n                class: 'el-sub-menu__hide-arrow',\n              },\n              {\n                title: () =>\n                  h(\n                    ElIcon,\n                    {\n                      class: ['el-sub-menu__icon-more'],\n                    },\n                    { default: () => h(More) }\n                  ),\n                default: () => slotMore,\n              }\n            )\n          )\n        }\n      }\n\n      const ulStyle = useMenuCssVar(props)\n\n      const resizeMenu = (vNode: VNode) =>\n        props.ellipsis ? useVNodeResize(vNode) : vNode\n\n      const vMenu = resizeMenu(\n        h(\n          'ul',\n          {\n            key: String(props.collapse),\n            role: 'menubar',\n            ref: menu,\n            style: ulStyle.value,\n            class: {\n              'el-menu': true,\n              'el-menu--horizontal': props.mode === 'horizontal',\n              'el-menu--collapse': props.collapse,\n            },\n          },\n          [...slot.map((vnode) => resizeMenu(vnode)), ...vShowMore]\n        )\n      )\n\n      if (props.collapseTransition && props.mode === 'vertical') {\n        return h(ElMenuCollapseTransition, () => vMenu)\n      }\n\n      return vMenu\n    }\n  },\n})\n"],"names":["Menubar","ElSubMenu","ElMenuCollapseTransition"],"mappings":"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"}