UNPKG

ivue-material-plus

Version:

A high quality UI components Library with Vue.js

1 lines 11.8 kB
{"version":3,"file":"submenu.mjs","sources":["../../../../../src/components/ivue-menu/submenu.vue"],"sourcesContent":["<template>\r\n <li\r\n :class=\"wrapperClasses\"\r\n @mouseenter=\"handleMouseenter\"\r\n @mouseleave=\"handleMouseleave\"\r\n >\r\n <div\r\n :class=\"`${prefixCls}--title`\"\r\n ref=\"reference\"\r\n @click.stop=\"handleTitleClick\"\r\n :style=\"titleStyle\"\r\n >\r\n <!-- title -->\r\n <slot name=\"title\"></slot>\r\n <!-- 箭头 -->\r\n <ivue-icon :class=\"iconClasses\">expand_more</ivue-icon>\r\n </div>\r\n <!-- 垂直打开 -->\r\n <collapse-transition v-if=\"Menu.mode === 'vertical'\">\r\n <ul class=\"ivue-menu\" v-show=\"data.opened\">\r\n <slot></slot>\r\n </ul>\r\n </collapse-transition>\r\n <!-- 水平打开 -->\r\n <drop-down\r\n :visible=\"data.opened\"\r\n placement=\"bottom\"\r\n transition-name=\"slide-up\"\r\n :styles=\"dropDownStyle\"\r\n ref=\"dropDown\"\r\n v-if=\"Menu.mode === 'horizontal'\"\r\n >\r\n <ul class=\"ivue-menu-dropdown--list\">\r\n <slot></slot>\r\n </ul>\r\n </drop-down>\r\n </li>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport {\r\n computed,\r\n getCurrentInstance,\r\n inject,\r\n onBeforeUnmount,\r\n onMounted,\r\n reactive,\r\n ref,\r\n watch,\r\n ComponentInternalInstance,\r\n provide,\r\n} from 'vue';\r\nimport CollapseTransition from '../../utils/collapse-transition';\r\nimport { getStyle } from '../../utils/assist';\r\nimport { findComponentUpward, findComponentsUpward } from '../../utils/helpers';\r\n\r\n// 下拉框\r\nimport DropDown from './drop-down.vue';\r\nimport IvueIcon from '../ivue-icon/index.vue';\r\n\r\n// ts\r\nimport { MenuContextKey, SubmenuProxy } from './types/menu';\r\nimport { SubmenuContextKey, Data, Props } from './types/submenu';\r\n\r\nconst prefixCls = 'ivue-menu-submenu';\r\n\r\nexport default {\r\n name: prefixCls,\r\n props: {\r\n /**\r\n * 菜单项的唯一标识,必填\r\n *\r\n * @type {String | NUmber}\r\n */\r\n name: {\r\n type: [String, Number],\r\n required: true,\r\n },\r\n /**\r\n * 禁用\r\n *\r\n * @type {Boolean}\r\n */\r\n disabled: {\r\n type: Boolean,\r\n default: false,\r\n },\r\n },\r\n setup(props: Props) {\r\n // vm\r\n const { proxy, uid } = getCurrentInstance() as ComponentInternalInstance;\r\n\r\n // dom\r\n const reference = ref<HTMLDivElement>();\r\n const dropDown = ref();\r\n\r\n // inject\r\n const Menu = inject(MenuContextKey, {\r\n default: null,\r\n });\r\n\r\n const Submenu = inject(SubmenuContextKey, {\r\n default: null,\r\n });\r\n\r\n // data\r\n const data = reactive<Data>({\r\n /**\r\n * 展开\r\n *\r\n * @type {Boolean}\r\n */\r\n opened: false,\r\n /**\r\n * 下拉框宽度\r\n *\r\n * @type {Number}\r\n */\r\n dropWidth: parseFloat(getStyle(proxy.$el, 'width')),\r\n /**\r\n * 延迟\r\n *\r\n * @type {Function}\r\n */\r\n timeout: null,\r\n /**\r\n * 子菜单列表\r\n *\r\n * @type {Array}\r\n */\r\n childSubmenuList: [],\r\n /**\r\n * 是否激活\r\n *\r\n * @type {Boolean}\r\n */\r\n active: false,\r\n });\r\n\r\n // computed\r\n\r\n // 外部样式\r\n const wrapperClasses = computed(() => {\r\n return [\r\n prefixCls,\r\n {\r\n // 激活\r\n [`${prefixCls}--active`]: data.active && !Submenu.default,\r\n // 子菜单激活\r\n [`${prefixCls}--child-active`]: data.active,\r\n // 打开下拉框\r\n [`${prefixCls}--opened`]: data.opened,\r\n },\r\n ];\r\n });\r\n\r\n // 标题样式\r\n const titleStyle = computed(() => {\r\n const styles: {\r\n paddingLeft?: string;\r\n } = {};\r\n\r\n const len = findComponentsUpward(proxy, 'ivue-menu-submenu').length;\r\n\r\n if (Submenu.default !== null && Menu.mode !== 'horizontal') {\r\n styles.paddingLeft = `${43 + (len - 1) * 24}px`;\r\n }\r\n\r\n return styles;\r\n });\r\n\r\n // 下拉框样式\r\n const dropDownStyle = computed(() => {\r\n const style = {\r\n minWidth: 'auto',\r\n };\r\n\r\n if (data.dropWidth) {\r\n style.minWidth = `${data.dropWidth}px`;\r\n }\r\n\r\n return style;\r\n });\r\n\r\n // icon样式\r\n const iconClasses = computed(() => {\r\n return [\r\n `${prefixCls}--icon`,\r\n {\r\n // 打开下拉框\r\n [`${prefixCls}--opened__icon`]: data.opened,\r\n },\r\n ];\r\n });\r\n\r\n // methods\r\n\r\n // 标题点击\r\n const handleTitleClick = () => {\r\n // 禁用\r\n if (props.disabled) {\r\n return;\r\n }\r\n\r\n // 水平\r\n if (Menu.mode === 'horizontal') {\r\n return;\r\n }\r\n\r\n const opened = data.opened;\r\n\r\n data.opened = !opened;\r\n\r\n // 更新打开的菜单名称\r\n Menu.updateOpenKeys(props.name);\r\n };\r\n\r\n // 鼠标进入\r\n const handleMouseenter = () => {\r\n // 禁用\r\n if (props.disabled) {\r\n return;\r\n }\r\n\r\n // 垂直\r\n if (Menu.mode === 'vertical') {\r\n return;\r\n }\r\n\r\n clearTimeout(data.timeout);\r\n\r\n data.timeout = setTimeout(() => {\r\n // 更新打开的菜单名称\r\n Menu.updateOpenKeys(props.name);\r\n\r\n data.opened = true;\r\n }, 250);\r\n };\r\n\r\n // 鼠标离开\r\n const handleMouseleave = () => {\r\n // 禁用\r\n if (props.disabled) {\r\n return;\r\n }\r\n\r\n // 垂直\r\n if (Menu.mode === 'vertical') {\r\n return;\r\n }\r\n\r\n clearTimeout(data.timeout);\r\n data.timeout = setTimeout(() => {\r\n // 更新打开的菜单名称\r\n Menu.updateOpenKeys(props.name);\r\n\r\n data.opened = false;\r\n }, 150);\r\n };\r\n\r\n // 添加子菜单\r\n const addSubmenu = () => {\r\n const { submenuList } = Menu.data;\r\n\r\n // 插入当前子菜单\r\n if (submenuList) {\r\n submenuList.push({\r\n uid: uid,\r\n submenu: proxy as unknown as SubmenuProxy,\r\n });\r\n }\r\n\r\n // 查找父子菜单\r\n const parentSubmenu = findComponentUpward(proxy, prefixCls);\r\n\r\n if (parentSubmenu) {\r\n if (!parentSubmenu.data.childSubmenuList) {\r\n parentSubmenu.data.childSubmenuList = [];\r\n }\r\n\r\n parentSubmenu.data.childSubmenuList.push({\r\n uid: uid,\r\n submenu: proxy as unknown as SubmenuProxy,\r\n });\r\n }\r\n };\r\n\r\n // 删除子菜单\r\n const removeSubmenu = () => {\r\n const { submenuList } = Menu.data;\r\n\r\n if (submenuList && submenuList.length) {\r\n const index = submenuList.findIndex((item) => item.uid === uid);\r\n\r\n submenuList.splice(index, 1);\r\n }\r\n };\r\n\r\n // 更新激活的名称\r\n const activeName = (status: boolean | string | number) => {\r\n if (findComponentUpward(proxy, 'ivue-menu-submenu')) {\r\n Submenu.activeName(status);\r\n }\r\n\r\n // 子菜单列表\r\n if (data.childSubmenuList && data.childSubmenuList.length) {\r\n data.childSubmenuList\r\n .map((item) => item.submenu)\r\n .forEach((item) => {\r\n item.data.active = false;\r\n });\r\n }\r\n\r\n // 激活\r\n data.active = status;\r\n };\r\n\r\n // 菜单选择\r\n const handleMenuItemSelect = (name) => {\r\n // 水平\r\n if (Menu.mode === 'horizontal') {\r\n data.opened = false;\r\n }\r\n\r\n Menu.handleMenuItemSelect(name);\r\n };\r\n\r\n // watch\r\n\r\n // 监听模式变化\r\n watch(\r\n () => Menu.mode,\r\n (value) => {\r\n // 水平\r\n if (value === 'horizontal') {\r\n dropDown.value.update();\r\n }\r\n }\r\n );\r\n\r\n // 监听打开\r\n watch(\r\n () => data.opened,\r\n (value) => {\r\n // 垂直打开\r\n if (Menu.mode === 'vertical') {\r\n return;\r\n }\r\n\r\n // 打开下拉框\r\n if (value) {\r\n // 下拉框宽度\r\n data.dropWidth = parseFloat(getStyle(proxy.$el, 'width'));\r\n\r\n dropDown.value.update();\r\n }\r\n // 销毁下拉框\r\n else {\r\n dropDown.value.destroy();\r\n }\r\n }\r\n );\r\n\r\n // provide\r\n\r\n provide(\r\n SubmenuContextKey,\r\n reactive({\r\n activeName,\r\n handleMenuItemSelect,\r\n })\r\n );\r\n\r\n // onMounted\r\n onMounted(() => {\r\n addSubmenu();\r\n });\r\n\r\n // onBeforeUnmount\r\n onBeforeUnmount(() => {\r\n removeSubmenu();\r\n });\r\n\r\n return {\r\n prefixCls,\r\n\r\n // dom\r\n reference,\r\n dropDown,\r\n\r\n // data\r\n data,\r\n\r\n // inject\r\n Menu,\r\n\r\n // computed\r\n wrapperClasses,\r\n titleStyle,\r\n dropDownStyle,\r\n iconClasses,\r\n\r\n // methods\r\n activeName,\r\n handleTitleClick,\r\n handleMouseenter,\r\n handleMouseleave,\r\n handleMenuItemSelect,\r\n };\r\n },\r\n components: {\r\n CollapseTransition,\r\n DropDown,\r\n IvueIcon,\r\n },\r\n};\r\n</script>\r\n"],"names":["_resolveComponent","_openBlock","_createElementBlock","_normalizeClass","_createElementVNode","_withModifiers","_normalizeStyle","_createCommentVNode","_renderSlot","_createVNode","_createBlock","_withCtx","_withDirectives"],"mappings":";;;;;;;;;+BACEA,iBAmCK,WAAA,CAAA,CAAA;EAjCF,OAAAC,SAAA,EAAU,EAAAC,kBAAA,CAAA,IAAA,EAAA;AAAA,IACV,KAAA,EAAUC,cAAA,CAAA,MAAA,CAAA,cAAA,CAAA;AAAA,IAAA,YAAA,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,MAAA,CAAA,gBAAA,IAAA,MAAA,CAAA,gBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,IAEX,YAUM,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,CAAA,GAAA,IAAA,KAAA,MAAA,CAAA,gBAAA,IAAA,MAAA,CAAA,gBAAA,CAAA,GAAA,IAAA,CAAA,CAAA;AAAA,GAAA,EAAA;AAAA,IARWC,mBAAA,KAAA,EAAA;AAAA,MACd,KAAK,EAAAD,cAAA,CAAA,CAAA,EAAA,MAAA,CAAA,SAAA,CAAA,OAAA,CAAA,CAAA;AAAA,MACL,GAAK,EAAA,WAAA;AAAA,MAAA,SAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAAE,cAAA,CAAA,GAAA,IAAA,KAAA,MAAA,CAAA,gBAAA,IAAA,OAAA,gBAAA,CAAA,GAAA,IAAA,CAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;AAAA,MAEN,KAAA,EAAcC,cAAA,CAAA,MAAA,CAAA,UAAA,CAAA;AAAA,KACd,EAAA;AAAA,MACAC,mBAAW,SAAA,CAAA;AAAA,MACXC,UAAA,CAAuD,IAAA,CAAA,MAAA,EAAA,OAAA,CAAA;AAAA,MAAAD,mBAAtC,gBAAE,CAAA;AAAA,MAAAE,YAAA,oBAAA,EAAA;AAAA,QAAwB,KAAA,EAAAN,cAAA,CAAA,MAAA,CAAA,WAAA,CAAA;AAAA,OAAA,EAAA;AAAA;;;;OAEhC,EAAA,CAAA,EAAA,CAAA,OAAA,CAAA,CAAA;AAAA,OACc,CAAS,CAAA;AAAA,IAApCI,mBAAA,4BAAA,CAAA;AAAA,IAAA,MAAA,CAAA,IAAA,CAAA,IAAA,KAAA,UAAA,IAAAN,SAAA,EAAA,EAAAS,WAAA,CACE,8BAEK,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA;AAAA,MAAA,OAAA,EADHC,QAAa,MAAA;AAAA,QAAAC,cAAA,CAAAR,kBAAA,CAAA,IAAA,EAAA,UAAA,EAAA;AAAA,UADeI,UAAA,CAAA,IAAA,CAAA,MAAA,EAAK,SAAM,CAAA;AAAA,SAAA,EAAA,GAAA,CAAA,EAAA;AAAA;;;;KAI3C,CAAA,IAOQD,kBAAS,CAAA,MAAA,EAAA,IAAA,CAAA;AAAA,IANjBA,mBAAA,4BAAA,CAAA;AAAA,IAAA,OAAA,IAAA,CAAA,IAAA,KAAA,gBAAAN,SACY,EAAA,cAAK,oBAAM,EAAA;AAAA,MACrB,GAAA,EAAA,CAAA;AAAA,MACA,OAAA,EAAgB,OAAA,IAAA,CAAA,MAAA;AAAA,MACf,SAAQ,EAAA,QAAA;AAAA,MACT,iBAAc,EAAA,UAAA;AAAA,MAAA,QAAA,MAAA,CAAA,aAAA;AAAA;;eAIZU,QAAa,MAAA;AAAA,QAAAP,kBAAA,CAAA,MAAA,UAAA,EAAA;AAAA;;;;;;;;;;;"}