import { defineComponent, getCurrentInstance, computed, inject, ref, reactive, watch, provide, onMounted, onBeforeUnmount, h, Fragment, withDirectives, vShow } from 'vue'; import { useTimeoutFn } from '@vueuse/core'; import { ElCollapseTransition } from '../../collapse-transition/index.mjs'; import { ElTooltip } from '../../tooltip/index.mjs'; import '../../../utils/index.mjs'; import '../../../hooks/index.mjs'; import { ArrowDown, ArrowRight } from '@element-plus/icons-vue'; import { ElIcon } from '../../icon/index.mjs'; import useMenu from './use-menu.mjs'; import { useMenuCssVar } from './use-menu-css-var.mjs'; import { buildProps } from '../../../utils/vue/props/runtime.mjs'; import { iconPropType } from '../../../utils/vue/icon.mjs'; import { useNamespace } from '../../../hooks/use-namespace/index.mjs'; import { throwError } from '../../../utils/error.mjs'; import { isString } from '@vue/shared'; const subMenuProps = buildProps({ index: { type: String, required: true }, showTimeout: Number, hideTimeout: Number, popperClass: String, disabled: Boolean, teleported: { type: Boolean, default: void 0 }, popperOffset: Number, expandCloseIcon: { type: iconPropType }, expandOpenIcon: { type: iconPropType }, collapseCloseIcon: { type: iconPropType }, collapseOpenIcon: { type: iconPropType } }); const COMPONENT_NAME = "ElSubMenu"; var SubMenu = defineComponent({ name: COMPONENT_NAME, props: subMenuProps, setup(props, { slots, expose }) { const instance = getCurrentInstance(); const { indexPath, parentMenu } = useMenu(instance, computed(() => props.index)); const nsMenu = useNamespace("menu"); const nsSubMenu = useNamespace("sub-menu"); const rootMenu = inject("rootMenu"); if (!rootMenu) throwError(COMPONENT_NAME, "can not inject root menu"); const subMenu = inject(`subMenu:${parentMenu.value.uid}`); if (!subMenu) throwError(COMPONENT_NAME, "can not inject sub menu"); const items = ref({}); const subMenus = ref({}); let timeout; const mouseInChild = ref(false); const verticalTitleRef = ref(); const vPopper = ref(null); const currentPlacement = computed(() => mode.value === "horizontal" && isFirstLevel.value ? "bottom-start" : "right-start"); const subMenuTitleIcon = computed(() => { return mode.value === "horizontal" && isFirstLevel.value || mode.value === "vertical" && !rootMenu.props.collapse ? props.expandCloseIcon && props.expandOpenIcon ? opened.value ? props.expandOpenIcon : props.expandCloseIcon : ArrowDown : props.collapseCloseIcon && props.collapseOpenIcon ? opened.value ? props.collapseOpenIcon : props.collapseCloseIcon : ArrowRight; }); const isFirstLevel = computed(() => { return subMenu.level === 0; }); const appendToBody = computed(() => { const value = props.teleported; return value === void 0 ? isFirstLevel.value : value; }); const menuTransitionName = computed(() => rootMenu.props.collapse ? `${nsMenu.namespace.value}-zoom-in-left` : `${nsMenu.namespace.value}-zoom-in-top`); const fallbackPlacements = computed(() => mode.value === "horizontal" && isFirstLevel.value ? [ "bottom-start", "bottom-end", "top-start", "top-end", "right-start", "left-start" ] : [ "right-start", "right", "right-end", "left-start", "bottom-start", "bottom-end", "top-start", "top-end" ]); const opened = computed(() => rootMenu.openedMenus.includes(props.index)); const active = computed(() => { let isActive = false; Object.values(items.value).forEach((item2) => { if (item2.active) { isActive = true; } }); Object.values(subMenus.value).forEach((subItem) => { if (subItem.active) { isActive = true; } }); return isActive; }); const mode = computed(() => rootMenu.props.mode); const item = reactive({ index: props.index, indexPath, active }); const ulStyle = useMenuCssVar(rootMenu.props, subMenu.level + 1); const subMenuPopperOffset = computed(() => { var _a; return (_a = props.popperOffset) != null ? _a : rootMenu.props.popperOffset; }); const subMenuPopperClass = computed(() => { var _a; return (_a = props.popperClass) != null ? _a : rootMenu.props.popperClass; }); const subMenuShowTimeout = computed(() => { var _a; return (_a = props.showTimeout) != null ? _a : rootMenu.props.showTimeout; }); const subMenuHideTimeout = computed(() => { var _a; return (_a = props.hideTimeout) != null ? _a : rootMenu.props.hideTimeout; }); const doDestroy = () => { var _a, _b, _c; return (_c = (_b = (_a = vPopper.value) == null ? void 0 : _a.popperRef) == null ? void 0 : _b.popperInstanceRef) == null ? void 0 : _c.destroy(); }; const handleCollapseToggle = (value) => { if (!value) { doDestroy(); } }; const handleClick = () => { if (rootMenu.props.menuTrigger === "hover" && rootMenu.props.mode === "horizontal" || rootMenu.props.collapse && rootMenu.props.mode === "vertical" || props.disabled) return; rootMenu.handleSubMenuClick({ index: props.index, indexPath: indexPath.value, active: active.value }); }; const handleMouseenter = (event, showTimeout = subMenuShowTimeout.value) => { var _a; if (event.type === "focus") { return; } if (rootMenu.props.menuTrigger === "click" && rootMenu.props.mode === "horizontal" || !rootMenu.props.collapse && rootMenu.props.mode === "vertical" || props.disabled) { subMenu.mouseInChild.value = true; return; } subMenu.mouseInChild.value = true; timeout == null ? void 0 : timeout(); ({ stop: timeout } = useTimeoutFn(() => { rootMenu.openMenu(props.index, indexPath.value); }, showTimeout)); if (appendToBody.value) { (_a = parentMenu.value.vnode.el) == null ? void 0 : _a.dispatchEvent(new MouseEvent("mouseenter")); } }; const handleMouseleave = (deepDispatch = false) => { var _a; if (rootMenu.props.menuTrigger === "click" && rootMenu.props.mode === "horizontal" || !rootMenu.props.collapse && rootMenu.props.mode === "vertical") { subMenu.mouseInChild.value = false; return; } timeout == null ? void 0 : timeout(); subMenu.mouseInChild.value = false; ({ stop: timeout } = useTimeoutFn(() => !mouseInChild.value && rootMenu.closeMenu(props.index, indexPath.value), subMenuHideTimeout.value)); if (appendToBody.value && deepDispatch) { (_a = subMenu.handleMouseleave) == null ? void 0 : _a.call(subMenu, true); } }; watch(() => rootMenu.props.collapse, (value) => handleCollapseToggle(Boolean(value))); { const addSubMenu = (item2) => { subMenus.value[item2.index] = item2; }; const removeSubMenu = (item2) => { delete subMenus.value[item2.index]; }; provide(`subMenu:${instance.uid}`, { addSubMenu, removeSubMenu, handleMouseleave, mouseInChild, level: subMenu.level + 1 }); } expose({ opened }); onMounted(() => { rootMenu.addSubMenu(item); subMenu.addSubMenu(item); }); onBeforeUnmount(() => { subMenu.removeSubMenu(item); rootMenu.removeSubMenu(item); }); return () => { var _a; const titleTag = [ (_a = slots.title) == null ? void 0 : _a.call(slots), h(ElIcon, { class: nsSubMenu.e("icon-arrow"), style: { transform: opened.value ? props.expandCloseIcon && props.expandOpenIcon || props.collapseCloseIcon && props.collapseOpenIcon && rootMenu.props.collapse ? "none" : "rotateZ(180deg)" : "none" } }, { default: () => isString(subMenuTitleIcon.value) ? h(instance.appContext.components[subMenuTitleIcon.value]) : h(subMenuTitleIcon.value) }) ]; const child = rootMenu.isMenuPopup ? h(ElTooltip, { ref: vPopper, visible: opened.value, effect: "light", pure: true, offset: subMenuPopperOffset.value, showArrow: false, persistent: true, popperClass: subMenuPopperClass.value, placement: currentPlacement.value, teleported: appendToBody.value, fallbackPlacements: fallbackPlacements.value, transition: menuTransitionName.value, gpuAcceleration: false }, { content: () => { var _a2; return h("div", { class: [ nsMenu.m(mode.value), nsMenu.m("popup-container"), subMenuPopperClass.value ], onMouseenter: (evt) => handleMouseenter(evt, 100), onMouseleave: () => handleMouseleave(true), onFocus: (evt) => handleMouseenter(evt, 100) }, [ h("ul", { class: [ nsMenu.b(), nsMenu.m("popup"), nsMenu.m(`popup-${currentPlacement.value}`) ], style: ulStyle.value }, [(_a2 = slots.default) == null ? void 0 : _a2.call(slots)]) ]); }, default: () => h("div", { class: nsSubMenu.e("title"), onClick: handleClick }, titleTag) }) : h(Fragment, {}, [ h("div", { class: nsSubMenu.e("title"), ref: verticalTitleRef, onClick: handleClick }, titleTag), h(ElCollapseTransition, {}, { default: () => { var _a2; return withDirectives(h("ul", { role: "menu", class: [nsMenu.b(), nsMenu.m("inline")], style: ulStyle.value }, [(_a2 = slots.default) == null ? void 0 : _a2.call(slots)]), [[vShow, opened.value]]); } }) ]); return h("li", { class: [ nsSubMenu.b(), nsSubMenu.is("active", active.value), nsSubMenu.is("opened", opened.value), nsSubMenu.is("disabled", props.disabled) ], role: "menuitem", ariaHaspopup: true, ariaExpanded: opened.value, onMouseenter: handleMouseenter, onMouseleave: () => handleMouseleave(), onFocus: handleMouseenter }, [child]); }; } }); export { SubMenu as default, subMenuProps }; //# sourceMappingURL=sub-menu.mjs.map