SubMenu.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _typeof3 = require("@babel/runtime/helpers/typeof");
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.subMenuProps = exports.default = void 0;
  8. var _vue = require("vue");
  9. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  10. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  11. var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
  12. var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
  13. var _vueTypes = _interopRequireDefault(require("../../_util/vue-types"));
  14. var _useKeyPath = _interopRequireWildcard(require("./hooks/useKeyPath"));
  15. var _useMenuContext = require("./hooks/useMenuContext");
  16. var _propsUtil = require("../../_util/props-util");
  17. var _classNames2 = _interopRequireDefault(require("../../_util/classNames"));
  18. var _useDirectionStyle = _interopRequireDefault(require("./hooks/useDirectionStyle"));
  19. var _PopupTrigger = _interopRequireDefault(require("./PopupTrigger"));
  20. var _SubMenuList = _interopRequireDefault(require("./SubMenuList"));
  21. var _InlineSubMenuList = _interopRequireDefault(require("./InlineSubMenuList"));
  22. var _vnode = require("../../_util/vnode");
  23. var _vcOverflow = _interopRequireDefault(require("../../vc-overflow"));
  24. var _devWarning = _interopRequireDefault(require("../../vc-util/devWarning"));
  25. var _isValid = _interopRequireDefault(require("../../_util/isValid"));
  26. function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
  27. function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof3(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  28. var indexGuid = 0;
  29. var subMenuProps = function subMenuProps() {
  30. return {
  31. icon: _vueTypes.default.any,
  32. title: _vueTypes.default.any,
  33. disabled: Boolean,
  34. level: Number,
  35. popupClassName: String,
  36. popupOffset: Array,
  37. internalPopupClose: Boolean,
  38. eventKey: String,
  39. expandIcon: Function,
  40. onMouseenter: Function,
  41. onMouseleave: Function,
  42. onTitleClick: Function
  43. };
  44. };
  45. exports.subMenuProps = subMenuProps;
  46. var _default2 = (0, _vue.defineComponent)({
  47. compatConfig: {
  48. MODE: 3
  49. },
  50. name: 'ASubMenu',
  51. inheritAttrs: false,
  52. props: subMenuProps(),
  53. slots: ['icon', 'title', 'expandIcon'],
  54. // emits: ['titleClick', 'mouseenter', 'mouseleave'],
  55. setup: function setup(props, _ref) {
  56. var _props$eventKey, _parentInfo$childrenE;
  57. var slots = _ref.slots,
  58. attrs = _ref.attrs,
  59. emit = _ref.emit;
  60. (0, _useMenuContext.useProvideFirstLevel)(false);
  61. var isMeasure = (0, _useKeyPath.useMeasure)();
  62. var instance = (0, _vue.getCurrentInstance)();
  63. var vnodeKey = (0, _typeof2.default)(instance.vnode.key) === 'symbol' ? String(instance.vnode.key) : instance.vnode.key;
  64. (0, _devWarning.default)((0, _typeof2.default)(instance.vnode.key) !== 'symbol', 'SubMenu', "SubMenu `:key=\"".concat(String(vnodeKey), "\"` not support Symbol type"));
  65. var key = (0, _isValid.default)(vnodeKey) ? vnodeKey : "sub_menu_".concat(++indexGuid, "_$$_not_set_key");
  66. var eventKey = (_props$eventKey = props.eventKey) !== null && _props$eventKey !== void 0 ? _props$eventKey : (0, _isValid.default)(vnodeKey) ? "sub_menu_".concat(++indexGuid, "_$$_").concat(vnodeKey) : key;
  67. var _useInjectKeyPath = (0, _useKeyPath.useInjectKeyPath)(),
  68. parentEventKeys = _useInjectKeyPath.parentEventKeys,
  69. parentInfo = _useInjectKeyPath.parentInfo,
  70. parentKeys = _useInjectKeyPath.parentKeys;
  71. var keysPath = (0, _vue.computed)(function () {
  72. return [].concat((0, _toConsumableArray2.default)(parentKeys.value), [key]);
  73. });
  74. var childrenEventKeys = (0, _vue.ref)([]);
  75. var menuInfo = {
  76. eventKey: eventKey,
  77. key: key,
  78. parentEventKeys: parentEventKeys,
  79. childrenEventKeys: childrenEventKeys,
  80. parentKeys: parentKeys
  81. };
  82. (_parentInfo$childrenE = parentInfo.childrenEventKeys) === null || _parentInfo$childrenE === void 0 ? void 0 : _parentInfo$childrenE.value.push(eventKey);
  83. (0, _vue.onBeforeUnmount)(function () {
  84. if (parentInfo.childrenEventKeys) {
  85. var _parentInfo$childrenE2;
  86. parentInfo.childrenEventKeys.value = (_parentInfo$childrenE2 = parentInfo.childrenEventKeys) === null || _parentInfo$childrenE2 === void 0 ? void 0 : _parentInfo$childrenE2.value.filter(function (k) {
  87. return k != eventKey;
  88. });
  89. }
  90. });
  91. (0, _useKeyPath.default)(eventKey, key, menuInfo);
  92. var _useInjectMenu = (0, _useMenuContext.useInjectMenu)(),
  93. prefixCls = _useInjectMenu.prefixCls,
  94. activeKeys = _useInjectMenu.activeKeys,
  95. contextDisabled = _useInjectMenu.disabled,
  96. changeActiveKeys = _useInjectMenu.changeActiveKeys,
  97. mode = _useInjectMenu.mode,
  98. inlineCollapsed = _useInjectMenu.inlineCollapsed,
  99. antdMenuTheme = _useInjectMenu.antdMenuTheme,
  100. openKeys = _useInjectMenu.openKeys,
  101. overflowDisabled = _useInjectMenu.overflowDisabled,
  102. onOpenChange = _useInjectMenu.onOpenChange,
  103. registerMenuInfo = _useInjectMenu.registerMenuInfo,
  104. unRegisterMenuInfo = _useInjectMenu.unRegisterMenuInfo,
  105. selectedSubMenuKeys = _useInjectMenu.selectedSubMenuKeys,
  106. menuExpandIcon = _useInjectMenu.expandIcon;
  107. var hasKey = vnodeKey !== undefined && vnodeKey !== null;
  108. // If not set key, use forceRender = true for children
  109. // 如果没有 key,强制 render 子元素
  110. var forceRender = !isMeasure && ((0, _useMenuContext.useInjectForceRender)() || !hasKey);
  111. (0, _useMenuContext.useProvideForceRender)(forceRender);
  112. if (isMeasure && hasKey || !isMeasure && !hasKey || forceRender) {
  113. registerMenuInfo(eventKey, menuInfo);
  114. (0, _vue.onBeforeUnmount)(function () {
  115. unRegisterMenuInfo(eventKey);
  116. });
  117. }
  118. var subMenuPrefixCls = (0, _vue.computed)(function () {
  119. return "".concat(prefixCls.value, "-submenu");
  120. });
  121. var mergedDisabled = (0, _vue.computed)(function () {
  122. return contextDisabled.value || props.disabled;
  123. });
  124. var elementRef = (0, _vue.ref)();
  125. var popupRef = (0, _vue.ref)();
  126. // // ================================ Icon ================================
  127. // const mergedItemIcon = itemIcon || contextItemIcon;
  128. // const mergedExpandIcon = expandIcon || contextExpandIcon;
  129. // ================================ Open ================================
  130. var originOpen = (0, _vue.computed)(function () {
  131. return openKeys.value.includes(key);
  132. });
  133. var open = (0, _vue.computed)(function () {
  134. return !overflowDisabled.value && originOpen.value;
  135. });
  136. // =============================== Select ===============================
  137. var childrenSelected = (0, _vue.computed)(function () {
  138. return selectedSubMenuKeys.value.includes(key);
  139. });
  140. var isActive = (0, _vue.ref)(false);
  141. (0, _vue.watch)(activeKeys, function () {
  142. isActive.value = !!activeKeys.value.find(function (val) {
  143. return val === key;
  144. });
  145. }, {
  146. immediate: true
  147. });
  148. // =============================== Events ===============================
  149. // >>>> Title click
  150. var onInternalTitleClick = function onInternalTitleClick(e) {
  151. // Skip if disabled
  152. if (mergedDisabled.value) {
  153. return;
  154. }
  155. emit('titleClick', e, key);
  156. // Trigger open by click when mode is `inline`
  157. if (mode.value === 'inline') {
  158. onOpenChange(key, !originOpen.value);
  159. }
  160. };
  161. var onMouseEnter = function onMouseEnter(event) {
  162. if (!mergedDisabled.value) {
  163. changeActiveKeys(keysPath.value);
  164. emit('mouseenter', event);
  165. }
  166. };
  167. var onMouseLeave = function onMouseLeave(event) {
  168. if (!mergedDisabled.value) {
  169. changeActiveKeys([]);
  170. emit('mouseleave', event);
  171. }
  172. };
  173. // ========================== DirectionStyle ==========================
  174. var directionStyle = (0, _useDirectionStyle.default)((0, _vue.computed)(function () {
  175. return keysPath.value.length;
  176. }));
  177. // >>>>> Visible change
  178. var onPopupVisibleChange = function onPopupVisibleChange(newVisible) {
  179. if (mode.value !== 'inline') {
  180. onOpenChange(key, newVisible);
  181. }
  182. };
  183. /**
  184. * Used for accessibility. Helper will focus element without key board.
  185. * We should manually trigger an active
  186. */
  187. var onInternalFocus = function onInternalFocus() {
  188. changeActiveKeys(keysPath.value);
  189. };
  190. // =============================== Render ===============================
  191. var popupId = eventKey && "".concat(eventKey, "-popup");
  192. var popupClassName = (0, _vue.computed)(function () {
  193. return (0, _classNames2.default)(prefixCls.value, "".concat(prefixCls.value, "-").concat(antdMenuTheme.value), props.popupClassName);
  194. });
  195. var renderTitle = function renderTitle(title, icon) {
  196. if (!icon) {
  197. return inlineCollapsed.value && !parentKeys.value.length && title && typeof title === 'string' ? (0, _vue.createVNode)("div", {
  198. "class": "".concat(prefixCls.value, "-inline-collapsed-noicon")
  199. }, [title.charAt(0)]) : (0, _vue.createVNode)("span", {
  200. "class": "".concat(prefixCls.value, "-title-content")
  201. }, [title]);
  202. }
  203. // inline-collapsed.md demo 依赖 span 来隐藏文字,有 icon 属性,则内部包裹一个 span
  204. // ref: https://github.com/ant-design/ant-design/pull/23456
  205. var titleIsSpan = (0, _propsUtil.isValidElement)(title) && title.type === 'span';
  206. return (0, _vue.createVNode)(_vue.Fragment, null, [(0, _vnode.cloneElement)(icon, {
  207. class: "".concat(prefixCls.value, "-item-icon")
  208. }, false), titleIsSpan ? title : (0, _vue.createVNode)("span", {
  209. "class": "".concat(prefixCls.value, "-title-content")
  210. }, [title])]);
  211. };
  212. // Cache mode if it change to `inline` which do not have popup motion
  213. var triggerModeRef = (0, _vue.computed)(function () {
  214. return mode.value !== 'inline' && keysPath.value.length > 1 ? 'vertical' : mode.value;
  215. });
  216. var renderMode = (0, _vue.computed)(function () {
  217. return mode.value === 'horizontal' ? 'vertical' : mode.value;
  218. });
  219. var subMenuTriggerModeRef = (0, _vue.computed)(function () {
  220. return triggerModeRef.value === 'horizontal' ? 'vertical' : triggerModeRef.value;
  221. });
  222. var baseTitleNode = function baseTitleNode() {
  223. var subMenuPrefixClsValue = subMenuPrefixCls.value;
  224. var icon = (0, _propsUtil.getPropsSlot)(slots, props, 'icon');
  225. var expandIcon = props.expandIcon || slots.expandIcon || menuExpandIcon.value;
  226. var title = renderTitle((0, _propsUtil.getPropsSlot)(slots, props, 'title'), icon);
  227. return (0, _vue.createVNode)("div", {
  228. "style": directionStyle.value,
  229. "class": "".concat(subMenuPrefixClsValue, "-title"),
  230. "tabindex": mergedDisabled.value ? null : -1,
  231. "ref": elementRef,
  232. "title": typeof title === 'string' ? title : null,
  233. "data-menu-id": key,
  234. "aria-expanded": open.value,
  235. "aria-haspopup": true,
  236. "aria-controls": popupId,
  237. "aria-disabled": mergedDisabled.value,
  238. "onClick": onInternalTitleClick,
  239. "onFocus": onInternalFocus
  240. }, [title, mode.value !== 'horizontal' && expandIcon ? expandIcon((0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
  241. isOpen: open.value
  242. })) : (0, _vue.createVNode)("i", {
  243. "class": "".concat(subMenuPrefixClsValue, "-arrow")
  244. }, null)]);
  245. };
  246. return function () {
  247. var _classNames;
  248. if (isMeasure) {
  249. var _slots$default;
  250. if (!hasKey) {
  251. return null;
  252. }
  253. return (_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots);
  254. }
  255. var subMenuPrefixClsValue = subMenuPrefixCls.value;
  256. var titleNode = function titleNode() {
  257. return null;
  258. };
  259. if (!overflowDisabled.value && mode.value !== 'inline') {
  260. titleNode = function titleNode() {
  261. return (0, _vue.createVNode)(_PopupTrigger.default, {
  262. "mode": triggerModeRef.value,
  263. "prefixCls": subMenuPrefixClsValue,
  264. "visible": !props.internalPopupClose && open.value,
  265. "popupClassName": popupClassName.value,
  266. "popupOffset": props.popupOffset,
  267. "disabled": mergedDisabled.value,
  268. "onVisibleChange": onPopupVisibleChange
  269. }, {
  270. default: function _default() {
  271. return [baseTitleNode()];
  272. },
  273. popup: function popup() {
  274. return (0, _vue.createVNode)(_useMenuContext.MenuContextProvider, {
  275. "mode": subMenuTriggerModeRef.value,
  276. "isRootMenu": false
  277. }, {
  278. default: function _default() {
  279. return [(0, _vue.createVNode)(_SubMenuList.default, {
  280. "id": popupId,
  281. "ref": popupRef
  282. }, {
  283. default: slots.default
  284. })];
  285. }
  286. });
  287. }
  288. });
  289. };
  290. } else {
  291. // 包裹一层,保持结构一致,防止动画丢失
  292. // https://github.com/vueComponent/ant-design-vue/issues/4325
  293. titleNode = function titleNode() {
  294. return (0, _vue.createVNode)(_PopupTrigger.default, null, {
  295. default: baseTitleNode
  296. });
  297. };
  298. }
  299. return (0, _vue.createVNode)(_useMenuContext.MenuContextProvider, {
  300. "mode": renderMode.value
  301. }, {
  302. default: function _default() {
  303. return [(0, _vue.createVNode)(_vcOverflow.default.Item, (0, _objectSpread2.default)((0, _objectSpread2.default)({
  304. "component": "li"
  305. }, attrs), {}, {
  306. "role": "none",
  307. "class": (0, _classNames2.default)(subMenuPrefixClsValue, "".concat(subMenuPrefixClsValue, "-").concat(mode.value), attrs.class, (_classNames = {}, (0, _defineProperty2.default)(_classNames, "".concat(subMenuPrefixClsValue, "-open"), open.value), (0, _defineProperty2.default)(_classNames, "".concat(subMenuPrefixClsValue, "-active"), isActive.value), (0, _defineProperty2.default)(_classNames, "".concat(subMenuPrefixClsValue, "-selected"), childrenSelected.value), (0, _defineProperty2.default)(_classNames, "".concat(subMenuPrefixClsValue, "-disabled"), mergedDisabled.value), _classNames)),
  308. "onMouseenter": onMouseEnter,
  309. "onMouseleave": onMouseLeave,
  310. "data-submenu-id": key
  311. }), {
  312. default: function _default() {
  313. return (0, _vue.createVNode)(_vue.Fragment, null, [titleNode(), !overflowDisabled.value && (0, _vue.createVNode)(_InlineSubMenuList.default, {
  314. "id": popupId,
  315. "open": open.value,
  316. "keyPath": keysPath.value
  317. }, {
  318. default: slots.default
  319. })]);
  320. }
  321. })];
  322. }
  323. });
  324. };
  325. }
  326. });
  327. exports.default = _default2;