791a853fa9f579fa629fa34f3404a6d80f025cfa7d380fb79eb19cd4450ea7395b7d4387970187a3c646d0a350c856bf44f0d13339390fc59d042bc39a40b2 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var core = require('@vueuse/core');
  5. var index$3 = require('../../collapse-transition/index.js');
  6. var index$2 = require('../../tooltip/index.js');
  7. var iconsVue = require('@element-plus/icons-vue');
  8. var index$1 = require('../../icon/index.js');
  9. var useMenu = require('./use-menu.js');
  10. var useMenuCssVar = require('./use-menu-css-var.js');
  11. var tokens = require('./tokens.js');
  12. var runtime = require('../../../utils/vue/props/runtime.js');
  13. var icon = require('../../../utils/vue/icon.js');
  14. var index = require('../../../hooks/use-namespace/index.js');
  15. var error = require('../../../utils/error.js');
  16. var types = require('../../../utils/types.js');
  17. var shared = require('@vue/shared');
  18. var aria = require('../../../utils/dom/aria.js');
  19. const subMenuProps = runtime.buildProps({
  20. index: {
  21. type: String,
  22. required: true
  23. },
  24. showTimeout: Number,
  25. hideTimeout: Number,
  26. popperClass: String,
  27. disabled: Boolean,
  28. teleported: {
  29. type: Boolean,
  30. default: void 0
  31. },
  32. popperOffset: Number,
  33. expandCloseIcon: {
  34. type: icon.iconPropType
  35. },
  36. expandOpenIcon: {
  37. type: icon.iconPropType
  38. },
  39. collapseCloseIcon: {
  40. type: icon.iconPropType
  41. },
  42. collapseOpenIcon: {
  43. type: icon.iconPropType
  44. }
  45. });
  46. const COMPONENT_NAME = "ElSubMenu";
  47. var SubMenu = vue.defineComponent({
  48. name: COMPONENT_NAME,
  49. props: subMenuProps,
  50. setup(props, { slots, expose }) {
  51. const instance = vue.getCurrentInstance();
  52. const { indexPath, parentMenu } = useMenu["default"](instance, vue.computed(() => props.index));
  53. const nsMenu = index.useNamespace("menu");
  54. const nsSubMenu = index.useNamespace("sub-menu");
  55. const rootMenu = vue.inject(tokens.MENU_INJECTION_KEY);
  56. if (!rootMenu)
  57. error.throwError(COMPONENT_NAME, "can not inject root menu");
  58. const subMenu = vue.inject(`${tokens.SUB_MENU_INJECTION_KEY}${parentMenu.value.uid}`);
  59. if (!subMenu)
  60. error.throwError(COMPONENT_NAME, "can not inject sub menu");
  61. const items = vue.ref({});
  62. const subMenus = vue.ref({});
  63. let timeout;
  64. const mouseInChild = vue.ref(false);
  65. const verticalTitleRef = vue.ref();
  66. const vPopper = vue.ref();
  67. const isFirstLevel = vue.computed(() => subMenu.level === 0);
  68. const currentPlacement = vue.computed(() => mode.value === "horizontal" && isFirstLevel.value ? "bottom-start" : "right-start");
  69. const subMenuTitleIcon = vue.computed(() => {
  70. const isExpandedMode = mode.value === "horizontal" && isFirstLevel.value || mode.value === "vertical" && !rootMenu.props.collapse;
  71. if (isExpandedMode) {
  72. if (props.expandCloseIcon && props.expandOpenIcon) {
  73. return opened.value ? props.expandOpenIcon : props.expandCloseIcon;
  74. }
  75. return iconsVue.ArrowDown;
  76. } else {
  77. if (props.collapseCloseIcon && props.collapseOpenIcon) {
  78. return opened.value ? props.collapseOpenIcon : props.collapseCloseIcon;
  79. }
  80. return iconsVue.ArrowRight;
  81. }
  82. });
  83. const appendToBody = vue.computed(() => {
  84. const value = props.teleported;
  85. return types.isUndefined(value) ? isFirstLevel.value : value;
  86. });
  87. const menuTransitionName = vue.computed(() => rootMenu.props.collapse ? `${nsMenu.namespace.value}-zoom-in-left` : `${nsMenu.namespace.value}-zoom-in-top`);
  88. const fallbackPlacements = vue.computed(() => mode.value === "horizontal" && isFirstLevel.value ? [
  89. "bottom-start",
  90. "bottom-end",
  91. "top-start",
  92. "top-end",
  93. "right-start",
  94. "left-start"
  95. ] : [
  96. "right-start",
  97. "right",
  98. "right-end",
  99. "left-start",
  100. "bottom-start",
  101. "bottom-end",
  102. "top-start",
  103. "top-end"
  104. ]);
  105. const opened = vue.computed(() => rootMenu.openedMenus.includes(props.index));
  106. const active = vue.computed(() => [...Object.values(items.value), ...Object.values(subMenus.value)].some(({ active: active2 }) => active2));
  107. const mode = vue.computed(() => rootMenu.props.mode);
  108. const persistent = vue.computed(() => rootMenu.props.persistent);
  109. const item = vue.reactive({
  110. index: props.index,
  111. indexPath,
  112. active
  113. });
  114. const ulStyle = useMenuCssVar.useMenuCssVar(rootMenu.props, subMenu.level + 1);
  115. const subMenuPopperOffset = vue.computed(() => {
  116. var _a;
  117. return (_a = props.popperOffset) != null ? _a : rootMenu.props.popperOffset;
  118. });
  119. const subMenuPopperClass = vue.computed(() => {
  120. var _a;
  121. return (_a = props.popperClass) != null ? _a : rootMenu.props.popperClass;
  122. });
  123. const subMenuShowTimeout = vue.computed(() => {
  124. var _a;
  125. return (_a = props.showTimeout) != null ? _a : rootMenu.props.showTimeout;
  126. });
  127. const subMenuHideTimeout = vue.computed(() => {
  128. var _a;
  129. return (_a = props.hideTimeout) != null ? _a : rootMenu.props.hideTimeout;
  130. });
  131. const doDestroy = () => {
  132. var _a, _b, _c;
  133. return (_c = (_b = (_a = vPopper.value) == null ? void 0 : _a.popperRef) == null ? void 0 : _b.popperInstanceRef) == null ? void 0 : _c.destroy();
  134. };
  135. const handleCollapseToggle = (value) => {
  136. if (!value) {
  137. doDestroy();
  138. }
  139. };
  140. const handleClick = () => {
  141. if (rootMenu.props.menuTrigger === "hover" && rootMenu.props.mode === "horizontal" || rootMenu.props.collapse && rootMenu.props.mode === "vertical" || props.disabled)
  142. return;
  143. rootMenu.handleSubMenuClick({
  144. index: props.index,
  145. indexPath: indexPath.value,
  146. active: active.value
  147. });
  148. };
  149. const handleMouseenter = (event, showTimeout = subMenuShowTimeout.value) => {
  150. var _a;
  151. if (event.type === "focus")
  152. return;
  153. if (rootMenu.props.menuTrigger === "click" && rootMenu.props.mode === "horizontal" || !rootMenu.props.collapse && rootMenu.props.mode === "vertical" || props.disabled) {
  154. subMenu.mouseInChild.value = true;
  155. return;
  156. }
  157. subMenu.mouseInChild.value = true;
  158. timeout == null ? void 0 : timeout();
  159. ({ stop: timeout } = core.useTimeoutFn(() => {
  160. rootMenu.openMenu(props.index, indexPath.value);
  161. }, showTimeout));
  162. if (appendToBody.value) {
  163. (_a = parentMenu.value.vnode.el) == null ? void 0 : _a.dispatchEvent(new MouseEvent("mouseenter"));
  164. }
  165. if (event.type === "mouseenter" && event.target) {
  166. vue.nextTick(() => {
  167. aria.focusElement(event.target, { preventScroll: true });
  168. });
  169. }
  170. };
  171. const handleMouseleave = (deepDispatch = false) => {
  172. var _a;
  173. if (rootMenu.props.menuTrigger === "click" && rootMenu.props.mode === "horizontal" || !rootMenu.props.collapse && rootMenu.props.mode === "vertical") {
  174. subMenu.mouseInChild.value = false;
  175. return;
  176. }
  177. timeout == null ? void 0 : timeout();
  178. subMenu.mouseInChild.value = false;
  179. ({ stop: timeout } = core.useTimeoutFn(() => !mouseInChild.value && rootMenu.closeMenu(props.index, indexPath.value), subMenuHideTimeout.value));
  180. if (appendToBody.value && deepDispatch) {
  181. (_a = subMenu.handleMouseleave) == null ? void 0 : _a.call(subMenu, true);
  182. }
  183. };
  184. vue.watch(() => rootMenu.props.collapse, (value) => handleCollapseToggle(Boolean(value)));
  185. {
  186. const addSubMenu = (item2) => {
  187. subMenus.value[item2.index] = item2;
  188. };
  189. const removeSubMenu = (item2) => {
  190. delete subMenus.value[item2.index];
  191. };
  192. vue.provide(`${tokens.SUB_MENU_INJECTION_KEY}${instance.uid}`, {
  193. addSubMenu,
  194. removeSubMenu,
  195. handleMouseleave,
  196. mouseInChild,
  197. level: subMenu.level + 1
  198. });
  199. }
  200. expose({
  201. opened
  202. });
  203. vue.onMounted(() => {
  204. rootMenu.addSubMenu(item);
  205. subMenu.addSubMenu(item);
  206. });
  207. vue.onBeforeUnmount(() => {
  208. subMenu.removeSubMenu(item);
  209. rootMenu.removeSubMenu(item);
  210. });
  211. return () => {
  212. var _a;
  213. const titleTag = [
  214. (_a = slots.title) == null ? void 0 : _a.call(slots),
  215. vue.h(index$1.ElIcon, {
  216. class: nsSubMenu.e("icon-arrow"),
  217. style: {
  218. transform: opened.value ? props.expandCloseIcon && props.expandOpenIcon || props.collapseCloseIcon && props.collapseOpenIcon && rootMenu.props.collapse ? "none" : "rotateZ(180deg)" : "none"
  219. }
  220. }, {
  221. default: () => shared.isString(subMenuTitleIcon.value) ? vue.h(instance.appContext.components[subMenuTitleIcon.value]) : vue.h(subMenuTitleIcon.value)
  222. })
  223. ];
  224. const child = rootMenu.isMenuPopup ? vue.h(index$2.ElTooltip, {
  225. ref: vPopper,
  226. visible: opened.value,
  227. effect: "light",
  228. pure: true,
  229. offset: subMenuPopperOffset.value,
  230. showArrow: false,
  231. persistent: persistent.value,
  232. popperClass: subMenuPopperClass.value,
  233. placement: currentPlacement.value,
  234. teleported: appendToBody.value,
  235. fallbackPlacements: fallbackPlacements.value,
  236. transition: menuTransitionName.value,
  237. gpuAcceleration: false
  238. }, {
  239. content: () => {
  240. var _a2;
  241. return vue.h("div", {
  242. class: [
  243. nsMenu.m(mode.value),
  244. nsMenu.m("popup-container"),
  245. subMenuPopperClass.value
  246. ],
  247. onMouseenter: (evt) => handleMouseenter(evt, 100),
  248. onMouseleave: () => handleMouseleave(true),
  249. onFocus: (evt) => handleMouseenter(evt, 100)
  250. }, [
  251. vue.h("ul", {
  252. class: [
  253. nsMenu.b(),
  254. nsMenu.m("popup"),
  255. nsMenu.m(`popup-${currentPlacement.value}`)
  256. ],
  257. style: ulStyle.value
  258. }, [(_a2 = slots.default) == null ? void 0 : _a2.call(slots)])
  259. ]);
  260. },
  261. default: () => vue.h("div", {
  262. class: nsSubMenu.e("title"),
  263. onClick: handleClick
  264. }, titleTag)
  265. }) : vue.h(vue.Fragment, {}, [
  266. vue.h("div", {
  267. class: nsSubMenu.e("title"),
  268. ref: verticalTitleRef,
  269. onClick: handleClick
  270. }, titleTag),
  271. vue.h(index$3.ElCollapseTransition, {}, {
  272. default: () => {
  273. var _a2;
  274. return vue.withDirectives(vue.h("ul", {
  275. role: "menu",
  276. class: [nsMenu.b(), nsMenu.m("inline")],
  277. style: ulStyle.value
  278. }, [(_a2 = slots.default) == null ? void 0 : _a2.call(slots)]), [[vue.vShow, opened.value]]);
  279. }
  280. })
  281. ]);
  282. return vue.h("li", {
  283. class: [
  284. nsSubMenu.b(),
  285. nsSubMenu.is("active", active.value),
  286. nsSubMenu.is("opened", opened.value),
  287. nsSubMenu.is("disabled", props.disabled)
  288. ],
  289. role: "menuitem",
  290. ariaHaspopup: true,
  291. ariaExpanded: opened.value,
  292. onMouseenter: handleMouseenter,
  293. onMouseleave: () => handleMouseleave(),
  294. onFocus: handleMouseenter
  295. }, [child]);
  296. };
  297. }
  298. });
  299. exports["default"] = SubMenu;
  300. exports.subMenuProps = subMenuProps;
  301. //# sourceMappingURL=sub-menu.js.map