UNPKG

@fesjs/fes-design

Version:
192 lines (189 loc) 6.33 kB
import { defineComponent, getCurrentInstance, ref, computed, onMounted, onBeforeUnmount, provide, watch, createVNode, mergeProps, Fragment, withDirectives, vShow } from 'vue'; import { pick } from 'lodash-es'; import getPrefixCls from '../_util/getPrefixCls'; import FadeInExpandTransition from '../_util/components/fadeInExpandTransition'; import Popper from '../popper/popper'; import DownOutlined from '../icon/DownOutlined'; import RightOutlined from '../icon/RightOutlined'; import Ellipsis from '../ellipsis/ellipsis'; import { COMPONENT_NAME, SUB_MENU_KEY } from './const'; import useChildren from './useChildren'; import useParent from './useParent'; import useMenu from './useMenu'; const prefixCls = getPrefixCls('sub-menu'); const subMenuProps = { value: { type: [String, Number] }, label: String }; var subMenu = defineComponent({ name: COMPONENT_NAME.SUB_MENU, components: { Ellipsis, FadeInExpandTransition }, props: { value: { type: [String, Number], default: null }, label: String }, setup(props, _ref) { let { slots } = _ref; const instance = getCurrentInstance(); const { indexPath } = useMenu(instance); const subMenuRef = ref(null); const { rootMenu, parentMenu, paddingStyle, isFirstLevel, onlyIcon } = useChildren(indexPath); // 根节点 menu if (!rootMenu) { console.warn(`[${COMPONENT_NAME.SUB_MENU}] must be a child of ${COMPONENT_NAME.MENU}`); } // 父级组件,可能为 menu 或者 sub-menu if (!parentMenu) { console.warn(`[${COMPONENT_NAME.SUB_MENU}] must be a child of ${COMPONENT_NAME.MENU} or ${COMPONENT_NAME.SUB_MENU}`); } const { children } = useParent(); const isOpened = ref(false); const isActive = computed(() => children.some(child => child === null || child === void 0 ? void 0 : child.isActive)); const subMenu = { uid: instance.uid, value: props.value, type: 'subMenu', children, isOpened, isActive }; onMounted(() => { parentMenu.addChild(subMenu); }); onBeforeUnmount(() => { parentMenu.removeChild(subMenu); }); provide(SUB_MENU_KEY, { handleItemClick: () => { if (rootMenu.renderWithPopper.value) { isOpened.value = false; rootMenu.updateExpandedKeys([]); } } }); const placement = computed(() => { if (rootMenu.props.mode === 'horizontal') { return isFirstLevel.value ? 'bottom-start' : 'right-start'; } return 'right-start'; }); const classList = computed(() => [prefixCls, isActive.value && 'is-active'].filter(Boolean).join(' ')); const handleTriggerClick = () => { isOpened.value = !isOpened.value; rootMenu.handleSubMenuExpand(subMenu, indexPath); }; watch([rootMenu.currentExpandedKeys], () => { // 要通过监听 currentExpandedKeys,自动打开或者关闭子菜单 const currentIsExpanded = rootMenu.currentExpandedKeys.value.includes(props.value || instance.uid); if (isOpened.value && !currentIsExpanded) { isOpened.value = false; } else if (!isOpened.value && currentIsExpanded) { isOpened.value = true; } }, { immediate: true }); const renderTitle = () => { var _slots$label; return createVNode(Ellipsis, { "class": `${prefixCls}-label` }, { default: () => [((_slots$label = slots.label) === null || _slots$label === void 0 ? void 0 : _slots$label.call(slots)) || props.label] }); }; const renderIcon = () => { if (slots.icon) { return createVNode("div", { "class": `${prefixCls}-icon` }, [slots.icon()]); } if (onlyIcon.value) { return renderTitle(); } return null; }; const renderArrow = () => { if (rootMenu.renderWithPopper.value && !isFirstLevel.value) { return createVNode("span", { "class": `${prefixCls}-arrow` }, [createVNode(RightOutlined, null, null)]); } return createVNode("span", { "class": [`${prefixCls}-arrow`, isOpened.value && 'is-opened'] }, [createVNode(DownOutlined, null, null)]); }; const wrapperContent = () => { return createVNode(Fragment, null, [renderIcon(), !onlyIcon.value ? renderTitle() : null, !onlyIcon.value ? renderArrow() : null]); }; const renderWrapperClick = () => { return createVNode("div", { "class": `${prefixCls}-wrapper`, "style": paddingStyle.value, "onClick": handleTriggerClick }, [wrapperContent()]); }; const renderWrapperPopper = () => { return createVNode("div", { "class": `${prefixCls}-wrapper`, "style": paddingStyle.value }, [wrapperContent()]); }; const renderDefault = () => { var _slots$default; return (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots); }; const popperProps = computed(() => { if (!rootMenu.renderWithPopper.value) { return {}; } return pick(rootMenu.props, ['getContainer', 'appendToContainer']); }); const renderContent = () => { if (rootMenu.renderWithPopper.value) { return createVNode(Popper, mergeProps({ "modelValue": isOpened.value, "onUpdate:modelValue": $event => isOpened.value = $event }, popperProps.value, { "trigger": `hover`, "placement": placement.value, "popperClass": `${prefixCls}-popper`, "appendToContainer": !(indexPath.value.length > 2), "offset": 1 }), { default: renderDefault, trigger: () => renderWrapperPopper() }); } return createVNode(Fragment, null, [renderWrapperClick(), createVNode(FadeInExpandTransition, null, { default: () => [withDirectives(createVNode("div", { "class": `${prefixCls}-children` }, [renderDefault()]), [[vShow, isOpened.value]])] })]); }; return () => createVNode("div", { "class": classList.value, "ref": subMenuRef }, [renderContent()]); } }); export { subMenu as default, subMenuProps };