{"version":3,"file":"sub-menu.mjs","sources":["../../../../../../packages/components/menu/src/sub-menu.ts"],"sourcesContent":["import {\n  defineComponent,\n  computed,\n  ref,\n  provide,\n  inject,\n  getCurrentInstance,\n  watch,\n  onMounted,\n  onBeforeUnmount,\n  withDirectives,\n  Fragment,\n  vShow,\n  h,\n  reactive,\n} from 'vue'\nimport { useTimeoutFn } from '@vueuse/core'\nimport ElCollapseTransition from '@element-plus/components/collapse-transition'\nimport ElPopper from '@element-plus/components/popper'\nimport { buildProps } from '@element-plus/utils/props'\nimport { throwError } from '@element-plus/utils/error'\nimport { ArrowDown, ArrowRight } from '@element-plus/icons'\nimport { ElIcon } from '@element-plus/components/icon'\nimport useMenu from './use-menu'\nimport { useMenuCssVar } from './use-menu-css-var'\n\nimport type { Placement } from '@element-plus/components/popper'\nimport type { ExtractPropTypes, VNodeArrayChildren, CSSProperties } from 'vue'\nimport type { MenuProvider, SubMenuProvider } from './types'\n\nexport const subMenuProps = buildProps({\n  index: {\n    type: String,\n    required: true,\n  },\n  showTimeout: {\n    type: Number,\n    default: 300,\n  },\n  hideTimeout: {\n    type: Number,\n    default: 300,\n  },\n  popperClass: String,\n  disabled: Boolean,\n  popperAppendToBody: {\n    type: Boolean,\n    default: undefined,\n  },\n} as const)\nexport type SubMenuProps = ExtractPropTypes<typeof subMenuProps>\n\nconst COMPONENT_NAME = 'ElSubMenu'\nexport default defineComponent({\n  name: COMPONENT_NAME,\n  props: subMenuProps,\n\n  setup(props, { slots, expose }) {\n    const instance = getCurrentInstance()!\n    const { paddingStyle, indexPath, parentMenu } = useMenu(\n      instance,\n      computed(() => props.index)\n    )\n\n    // inject\n    const rootMenu = inject<MenuProvider>('rootMenu')\n    if (!rootMenu) throwError(COMPONENT_NAME, 'can not inject root menu')\n\n    const subMenu = inject<SubMenuProvider>(`subMenu:${parentMenu.value!.uid}`)\n    if (!subMenu) throwError(COMPONENT_NAME, 'can not inject sub menu')\n\n    const items = ref<MenuProvider['items']>({})\n    const subMenus = ref<MenuProvider['subMenus']>({})\n\n    let timeout: (() => void) | undefined\n    const currentPlacement = ref<Placement | ''>('')\n    const mouseInChild = ref(false)\n    const verticalTitleRef = ref<HTMLDivElement>()\n    const vPopper = ref()\n\n    // computed\n    const subMenuTitleIcon = computed(() => {\n      return (mode.value === 'horizontal' && isFirstLevel.value) ||\n        (mode.value === 'vertical' && !rootMenu.props.collapse)\n        ? ArrowDown\n        : ArrowRight\n    })\n    const isFirstLevel = computed(() => {\n      let isFirstLevel = true\n      let parent = instance.parent\n      while (parent && parent.type.name !== 'ElMenu') {\n        if (['ElSubMenu', 'ElMenuItemGroup'].includes(parent.type.name!)) {\n          isFirstLevel = false\n          break\n        } else {\n          parent = parent.parent\n        }\n      }\n      return isFirstLevel\n    })\n    const appendToBody = computed(() => {\n      return props.popperAppendToBody === undefined\n        ? isFirstLevel.value\n        : Boolean(props.popperAppendToBody)\n    })\n    const menuTransitionName = computed(() =>\n      rootMenu.props.collapse ? 'el-zoom-in-left' : 'el-zoom-in-top'\n    )\n    const fallbackPlacements = computed<Placement[]>(() =>\n      mode.value === 'horizontal' && isFirstLevel.value\n        ? [\n            'bottom-start',\n            'bottom-end',\n            'top-start',\n            'top-end',\n            'right-start',\n            'left-start',\n          ]\n        : [\n            'right-start',\n            'left-start',\n            'bottom-start',\n            'bottom-end',\n            'top-start',\n            'top-end',\n          ]\n    )\n    const opened = computed(() => rootMenu.openedMenus.includes(props.index))\n    const active = computed(() => {\n      let isActive = false\n\n      Object.values(items.value).forEach((item) => {\n        if (item.active) {\n          isActive = true\n        }\n      })\n\n      Object.values(subMenus.value).forEach((subItem) => {\n        if (subItem.active) {\n          isActive = true\n        }\n      })\n\n      return isActive\n    })\n\n    const backgroundColor = computed(() => rootMenu.props.backgroundColor || '')\n    const activeTextColor = computed(() => rootMenu.props.activeTextColor || '')\n    const textColor = computed(() => rootMenu.props.textColor || '')\n    const mode = computed(() => rootMenu.props.mode)\n    const item = reactive({\n      index: props.index,\n      indexPath,\n      active,\n    })\n\n    const titleStyle = computed<CSSProperties>(() => {\n      if (mode.value !== 'horizontal') {\n        return {\n          color: textColor.value,\n        }\n      }\n      return {\n        borderBottomColor: active.value\n          ? rootMenu.props.activeTextColor\n            ? activeTextColor.value\n            : ''\n          : 'transparent',\n        color: active.value ? activeTextColor.value : textColor.value,\n      }\n    })\n\n    // methods\n    const doDestroy = () => vPopper.value?.doDestroy()\n\n    const handleCollapseToggle = (value: boolean) => {\n      if (value) {\n        updatePlacement()\n      } else {\n        doDestroy()\n      }\n    }\n\n    const handleClick = () => {\n      if (\n        (rootMenu.props.menuTrigger === 'hover' &&\n          rootMenu.props.mode === 'horizontal') ||\n        (rootMenu.props.collapse && rootMenu.props.mode === 'vertical') ||\n        props.disabled\n      )\n        return\n\n      rootMenu.handleSubMenuClick({\n        index: props.index,\n        indexPath: indexPath.value,\n        active: active.value,\n      })\n    }\n\n    const handleMouseenter = (\n      event: MouseEvent | FocusEvent,\n      showTimeout = props.showTimeout\n    ) => {\n      if (event.type === 'focus' && !event.relatedTarget) {\n        return\n      }\n      if (\n        (rootMenu.props.menuTrigger === 'click' &&\n          rootMenu.props.mode === 'horizontal') ||\n        (!rootMenu.props.collapse && rootMenu.props.mode === 'vertical') ||\n        props.disabled\n      ) {\n        return\n      }\n      mouseInChild.value = true\n\n      timeout?.()\n      ;({ stop: timeout } = useTimeoutFn(\n        () => rootMenu.openMenu(props.index, indexPath.value),\n        showTimeout\n      ))\n\n      if (appendToBody.value) {\n        parentMenu.value.vnode.el?.dispatchEvent(new MouseEvent('mouseenter'))\n      }\n    }\n\n    const handleMouseleave = (deepDispatch = false) => {\n      if (\n        (rootMenu.props.menuTrigger === 'click' &&\n          rootMenu.props.mode === 'horizontal') ||\n        (!rootMenu.props.collapse && rootMenu.props.mode === 'vertical')\n      ) {\n        return\n      }\n      mouseInChild.value = false\n      timeout?.()\n      ;({ stop: timeout } = useTimeoutFn(\n        () =>\n          !mouseInChild.value &&\n          rootMenu.closeMenu(props.index, indexPath.value),\n        props.hideTimeout\n      ))\n\n      if (appendToBody.value && deepDispatch) {\n        if (instance.parent?.type.name === 'ElSubMenu') {\n          subMenu.handleMouseleave?.(true)\n        }\n      }\n    }\n\n    const updatePlacement = () => {\n      currentPlacement.value =\n        mode.value === 'horizontal' && isFirstLevel.value\n          ? 'bottom-start'\n          : 'right-start'\n    }\n\n    watch(\n      () => rootMenu.props.collapse,\n      (value) => handleCollapseToggle(Boolean(value))\n    )\n\n    // provide\n    {\n      const addSubMenu: SubMenuProvider['addSubMenu'] = (item) => {\n        subMenus.value[item.index] = item\n      }\n      const removeSubMenu: SubMenuProvider['removeSubMenu'] = (item) => {\n        delete subMenus.value[item.index]\n      }\n      provide<SubMenuProvider>(`subMenu:${instance.uid}`, {\n        addSubMenu,\n        removeSubMenu,\n        handleMouseleave,\n      })\n    }\n\n    // expose\n    expose({\n      opened,\n    })\n\n    // lifecycle\n    onMounted(() => {\n      rootMenu.addSubMenu(item)\n      subMenu.addSubMenu(item)\n      updatePlacement()\n    })\n\n    onBeforeUnmount(() => {\n      subMenu.removeSubMenu(item)\n      rootMenu.removeSubMenu(item)\n    })\n\n    return () => {\n      const titleTag: VNodeArrayChildren = [\n        slots.title?.(),\n        h(\n          ElIcon,\n          {\n            class: ['el-sub-menu__icon-arrow'],\n          },\n          { default: () => h(subMenuTitleIcon.value) }\n        ),\n      ]\n\n      const ulStyle = useMenuCssVar(rootMenu.props)\n\n      // this render function is only used for bypass `Vue`'s compiler caused patching issue.\n      // temporarily mark ElPopper as any due to type inconsistency.\n      const child = rootMenu.isMenuPopup\n        ? h(\n            // TODO: correct popper's type.\n            ElPopper as any,\n            {\n              ref: vPopper,\n              manualMode: true,\n              visible: opened.value,\n              effect: 'light',\n              pure: true,\n              offset: 6,\n              showArrow: false,\n              popperClass: props.popperClass,\n              placement: currentPlacement.value,\n              appendToBody: appendToBody.value,\n              fallbackPlacements: fallbackPlacements.value,\n              transition: menuTransitionName.value,\n              gpuAcceleration: false,\n            },\n            {\n              default: () =>\n                h(\n                  'div',\n                  {\n                    class: [`el-menu--${mode.value}`, props.popperClass],\n                    onMouseenter: (evt: MouseEvent) =>\n                      handleMouseenter(evt, 100),\n                    onMouseleave: () => handleMouseleave(true),\n                    onFocus: (evt: FocusEvent) => handleMouseenter(evt, 100),\n                  },\n                  [\n                    h(\n                      'ul',\n                      {\n                        class: [\n                          'el-menu el-menu--popup',\n                          `el-menu--popup-${currentPlacement.value}`,\n                        ],\n                        style: ulStyle.value,\n                      },\n                      [slots.default?.()]\n                    ),\n                  ]\n                ),\n              trigger: () =>\n                h(\n                  'div',\n                  {\n                    class: 'el-sub-menu__title',\n                    style: [\n                      paddingStyle.value,\n                      titleStyle.value,\n                      { backgroundColor: backgroundColor.value },\n                    ],\n                    onClick: handleClick,\n                  },\n                  titleTag\n                ),\n            }\n          )\n        : h(Fragment, {}, [\n            h(\n              'div',\n              {\n                class: 'el-sub-menu__title',\n                style: [\n                  paddingStyle.value,\n                  titleStyle.value,\n                  { backgroundColor: backgroundColor.value },\n                ],\n                ref: verticalTitleRef,\n                onClick: handleClick,\n              },\n              titleTag\n            ),\n            h(\n              ElCollapseTransition,\n              {},\n              {\n                default: () =>\n                  withDirectives(\n                    h(\n                      'ul',\n                      {\n                        role: 'menu',\n                        class: 'el-menu el-menu--inline',\n                        style: ulStyle.value,\n                      },\n                      [slots.default?.()]\n                    ),\n                    [[vShow, opened.value]]\n                  ),\n              }\n            ),\n          ])\n\n      return h(\n        'li',\n        {\n          class: [\n            'el-sub-menu',\n            {\n              'is-active': active.value,\n              'is-opened': opened.value,\n              'is-disabled': props.disabled,\n            },\n          ],\n          role: 'menuitem',\n          ariaHaspopup: true,\n          ariaExpanded: opened.value,\n          onMouseenter: handleMouseenter,\n          onMouseleave: () => handleMouseleave(true),\n          onFocus: handleMouseenter,\n        },\n        [child]\n      )\n    }\n  },\n})\n"],"names":["ElPopper","ElCollapseTransition"],"mappings":"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"}