index.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. var _typeof = require("@babel/runtime/helpers/typeof");
  4. Object.defineProperty(exports, "__esModule", {
  5. value: true
  6. });
  7. exports.default = void 0;
  8. var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  9. var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
  10. var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
  11. var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  12. var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
  13. var React = _interopRequireWildcard(require("react"));
  14. var _classnames = _interopRequireDefault(require("classnames"));
  15. var _rcOverflow = _interopRequireDefault(require("rc-overflow"));
  16. var _warning = _interopRequireDefault(require("rc-util/lib/warning"));
  17. var _SubMenuList = _interopRequireDefault(require("./SubMenuList"));
  18. var _commonUtil = require("../utils/commonUtil");
  19. var _MenuContext = _interopRequireWildcard(require("../context/MenuContext"));
  20. var _useMemoCallback = _interopRequireDefault(require("../hooks/useMemoCallback"));
  21. var _PopupTrigger = _interopRequireDefault(require("./PopupTrigger"));
  22. var _Icon = _interopRequireDefault(require("../Icon"));
  23. var _useActive2 = _interopRequireDefault(require("../hooks/useActive"));
  24. var _warnUtil = require("../utils/warnUtil");
  25. var _useDirectionStyle = _interopRequireDefault(require("../hooks/useDirectionStyle"));
  26. var _InlineSubMenuList = _interopRequireDefault(require("./InlineSubMenuList"));
  27. var _PathContext = require("../context/PathContext");
  28. var _IdContext = require("../context/IdContext");
  29. var _PrivateContext = _interopRequireDefault(require("../context/PrivateContext"));
  30. var _excluded = ["style", "className", "title", "eventKey", "warnKey", "disabled", "internalPopupClose", "children", "itemIcon", "expandIcon", "popupClassName", "popupOffset", "popupStyle", "onClick", "onMouseEnter", "onMouseLeave", "onTitleClick", "onTitleMouseEnter", "onTitleMouseLeave"],
  31. _excluded2 = ["active"];
  32. function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
  33. function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
  34. var InternalSubMenu = /*#__PURE__*/React.forwardRef(function (props, ref) {
  35. var style = props.style,
  36. className = props.className,
  37. title = props.title,
  38. eventKey = props.eventKey,
  39. warnKey = props.warnKey,
  40. disabled = props.disabled,
  41. internalPopupClose = props.internalPopupClose,
  42. children = props.children,
  43. itemIcon = props.itemIcon,
  44. expandIcon = props.expandIcon,
  45. popupClassName = props.popupClassName,
  46. popupOffset = props.popupOffset,
  47. popupStyle = props.popupStyle,
  48. onClick = props.onClick,
  49. onMouseEnter = props.onMouseEnter,
  50. onMouseLeave = props.onMouseLeave,
  51. onTitleClick = props.onTitleClick,
  52. onTitleMouseEnter = props.onTitleMouseEnter,
  53. onTitleMouseLeave = props.onTitleMouseLeave,
  54. restProps = (0, _objectWithoutProperties2.default)(props, _excluded);
  55. var domDataId = (0, _IdContext.useMenuId)(eventKey);
  56. var _React$useContext = React.useContext(_MenuContext.MenuContext),
  57. prefixCls = _React$useContext.prefixCls,
  58. mode = _React$useContext.mode,
  59. openKeys = _React$useContext.openKeys,
  60. contextDisabled = _React$useContext.disabled,
  61. overflowDisabled = _React$useContext.overflowDisabled,
  62. activeKey = _React$useContext.activeKey,
  63. selectedKeys = _React$useContext.selectedKeys,
  64. contextItemIcon = _React$useContext.itemIcon,
  65. contextExpandIcon = _React$useContext.expandIcon,
  66. onItemClick = _React$useContext.onItemClick,
  67. onOpenChange = _React$useContext.onOpenChange,
  68. onActive = _React$useContext.onActive;
  69. var _React$useContext2 = React.useContext(_PrivateContext.default),
  70. _internalRenderSubMenuItem = _React$useContext2._internalRenderSubMenuItem;
  71. var _React$useContext3 = React.useContext(_PathContext.PathUserContext),
  72. isSubPathKey = _React$useContext3.isSubPathKey;
  73. var connectedPath = (0, _PathContext.useFullPath)();
  74. var subMenuPrefixCls = "".concat(prefixCls, "-submenu");
  75. var mergedDisabled = contextDisabled || disabled;
  76. var elementRef = React.useRef();
  77. var popupRef = React.useRef();
  78. // ================================ Warn ================================
  79. if (process.env.NODE_ENV !== 'production' && warnKey) {
  80. (0, _warning.default)(false, 'SubMenu should not leave undefined `key`.');
  81. }
  82. // ================================ Icon ================================
  83. var mergedItemIcon = itemIcon !== null && itemIcon !== void 0 ? itemIcon : contextItemIcon;
  84. var mergedExpandIcon = expandIcon !== null && expandIcon !== void 0 ? expandIcon : contextExpandIcon;
  85. // ================================ Open ================================
  86. var originOpen = openKeys.includes(eventKey);
  87. var open = !overflowDisabled && originOpen;
  88. // =============================== Select ===============================
  89. var childrenSelected = isSubPathKey(selectedKeys, eventKey);
  90. // =============================== Active ===============================
  91. var _useActive = (0, _useActive2.default)(eventKey, mergedDisabled, onTitleMouseEnter, onTitleMouseLeave),
  92. active = _useActive.active,
  93. activeProps = (0, _objectWithoutProperties2.default)(_useActive, _excluded2);
  94. // Fallback of active check to avoid hover on menu title or disabled item
  95. var _React$useState = React.useState(false),
  96. _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2),
  97. childrenActive = _React$useState2[0],
  98. setChildrenActive = _React$useState2[1];
  99. var triggerChildrenActive = function triggerChildrenActive(newActive) {
  100. if (!mergedDisabled) {
  101. setChildrenActive(newActive);
  102. }
  103. };
  104. var onInternalMouseEnter = function onInternalMouseEnter(domEvent) {
  105. triggerChildrenActive(true);
  106. onMouseEnter === null || onMouseEnter === void 0 || onMouseEnter({
  107. key: eventKey,
  108. domEvent: domEvent
  109. });
  110. };
  111. var onInternalMouseLeave = function onInternalMouseLeave(domEvent) {
  112. triggerChildrenActive(false);
  113. onMouseLeave === null || onMouseLeave === void 0 || onMouseLeave({
  114. key: eventKey,
  115. domEvent: domEvent
  116. });
  117. };
  118. var mergedActive = React.useMemo(function () {
  119. if (active) {
  120. return active;
  121. }
  122. if (mode !== 'inline') {
  123. return childrenActive || isSubPathKey([activeKey], eventKey);
  124. }
  125. return false;
  126. }, [mode, active, activeKey, childrenActive, eventKey, isSubPathKey]);
  127. // ========================== DirectionStyle ==========================
  128. var directionStyle = (0, _useDirectionStyle.default)(connectedPath.length);
  129. // =============================== Events ===============================
  130. // >>>> Title click
  131. var onInternalTitleClick = function onInternalTitleClick(e) {
  132. // Skip if disabled
  133. if (mergedDisabled) {
  134. return;
  135. }
  136. onTitleClick === null || onTitleClick === void 0 || onTitleClick({
  137. key: eventKey,
  138. domEvent: e
  139. });
  140. // Trigger open by click when mode is `inline`
  141. if (mode === 'inline') {
  142. onOpenChange(eventKey, !originOpen);
  143. }
  144. };
  145. // >>>> Context for children click
  146. var onMergedItemClick = (0, _useMemoCallback.default)(function (info) {
  147. onClick === null || onClick === void 0 || onClick((0, _warnUtil.warnItemProp)(info));
  148. onItemClick(info);
  149. });
  150. // >>>>> Visible change
  151. var onPopupVisibleChange = function onPopupVisibleChange(newVisible) {
  152. if (mode !== 'inline') {
  153. onOpenChange(eventKey, newVisible);
  154. }
  155. };
  156. /**
  157. * Used for accessibility. Helper will focus element without key board.
  158. * We should manually trigger an active
  159. */
  160. var onInternalFocus = function onInternalFocus() {
  161. onActive(eventKey);
  162. };
  163. // =============================== Render ===============================
  164. var popupId = domDataId && "".concat(domDataId, "-popup");
  165. var expandIconNode = React.useMemo(function () {
  166. return /*#__PURE__*/React.createElement(_Icon.default, {
  167. icon: mode !== 'horizontal' ? mergedExpandIcon : undefined,
  168. props: (0, _objectSpread2.default)((0, _objectSpread2.default)({}, props), {}, {
  169. isOpen: open,
  170. // [Legacy] Not sure why need this mark
  171. isSubMenu: true
  172. })
  173. }, /*#__PURE__*/React.createElement("i", {
  174. className: "".concat(subMenuPrefixCls, "-arrow")
  175. }));
  176. }, [mode, mergedExpandIcon, props, open, subMenuPrefixCls]);
  177. // >>>>> Title
  178. var titleNode = /*#__PURE__*/React.createElement("div", (0, _extends2.default)({
  179. role: "menuitem",
  180. style: directionStyle,
  181. className: "".concat(subMenuPrefixCls, "-title"),
  182. tabIndex: mergedDisabled ? null : -1,
  183. ref: elementRef,
  184. title: typeof title === 'string' ? title : null,
  185. "data-menu-id": overflowDisabled && domDataId ? null : domDataId,
  186. "aria-expanded": open,
  187. "aria-haspopup": true,
  188. "aria-controls": popupId,
  189. "aria-disabled": mergedDisabled,
  190. onClick: onInternalTitleClick,
  191. onFocus: onInternalFocus
  192. }, activeProps), title, expandIconNode);
  193. // Cache mode if it change to `inline` which do not have popup motion
  194. var triggerModeRef = React.useRef(mode);
  195. if (mode !== 'inline' && connectedPath.length > 1) {
  196. triggerModeRef.current = 'vertical';
  197. } else {
  198. triggerModeRef.current = mode;
  199. }
  200. if (!overflowDisabled) {
  201. var triggerMode = triggerModeRef.current;
  202. // Still wrap with Trigger here since we need avoid react re-mount dom node
  203. // Which makes motion failed
  204. titleNode = /*#__PURE__*/React.createElement(_PopupTrigger.default, {
  205. mode: triggerMode,
  206. prefixCls: subMenuPrefixCls,
  207. visible: !internalPopupClose && open && mode !== 'inline',
  208. popupClassName: popupClassName,
  209. popupOffset: popupOffset,
  210. popupStyle: popupStyle,
  211. popup: /*#__PURE__*/React.createElement(_MenuContext.default
  212. // Special handle of horizontal mode
  213. , {
  214. mode: triggerMode === 'horizontal' ? 'vertical' : triggerMode
  215. }, /*#__PURE__*/React.createElement(_SubMenuList.default, {
  216. id: popupId,
  217. ref: popupRef
  218. }, children)),
  219. disabled: mergedDisabled,
  220. onVisibleChange: onPopupVisibleChange
  221. }, titleNode);
  222. }
  223. // >>>>> List node
  224. var listNode = /*#__PURE__*/React.createElement(_rcOverflow.default.Item, (0, _extends2.default)({
  225. ref: ref,
  226. role: "none"
  227. }, restProps, {
  228. component: "li",
  229. style: style,
  230. className: (0, _classnames.default)(subMenuPrefixCls, "".concat(subMenuPrefixCls, "-").concat(mode), className, (0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)((0, _defineProperty2.default)({}, "".concat(subMenuPrefixCls, "-open"), open), "".concat(subMenuPrefixCls, "-active"), mergedActive), "".concat(subMenuPrefixCls, "-selected"), childrenSelected), "".concat(subMenuPrefixCls, "-disabled"), mergedDisabled)),
  231. onMouseEnter: onInternalMouseEnter,
  232. onMouseLeave: onInternalMouseLeave
  233. }), titleNode, !overflowDisabled && /*#__PURE__*/React.createElement(_InlineSubMenuList.default, {
  234. id: popupId,
  235. open: open,
  236. keyPath: connectedPath
  237. }, children));
  238. if (_internalRenderSubMenuItem) {
  239. listNode = _internalRenderSubMenuItem(listNode, props, {
  240. selected: childrenSelected,
  241. active: mergedActive,
  242. open: open,
  243. disabled: mergedDisabled
  244. });
  245. }
  246. // >>>>> Render
  247. return /*#__PURE__*/React.createElement(_MenuContext.default, {
  248. onItemClick: onMergedItemClick,
  249. mode: mode === 'horizontal' ? 'vertical' : mode,
  250. itemIcon: mergedItemIcon,
  251. expandIcon: mergedExpandIcon
  252. }, listNode);
  253. });
  254. var SubMenu = /*#__PURE__*/React.forwardRef(function (props, ref) {
  255. var eventKey = props.eventKey,
  256. children = props.children;
  257. var connectedKeyPath = (0, _PathContext.useFullPath)(eventKey);
  258. var childList = (0, _commonUtil.parseChildren)(children, connectedKeyPath);
  259. // ==================== Record KeyPath ====================
  260. var measure = (0, _PathContext.useMeasure)();
  261. // eslint-disable-next-line consistent-return
  262. React.useEffect(function () {
  263. if (measure) {
  264. measure.registerPath(eventKey, connectedKeyPath);
  265. return function () {
  266. measure.unregisterPath(eventKey, connectedKeyPath);
  267. };
  268. }
  269. }, [connectedKeyPath]);
  270. var renderNode;
  271. // ======================== Render ========================
  272. if (measure) {
  273. renderNode = childList;
  274. } else {
  275. renderNode = /*#__PURE__*/React.createElement(InternalSubMenu, (0, _extends2.default)({
  276. ref: ref
  277. }, props), childList);
  278. }
  279. return /*#__PURE__*/React.createElement(_PathContext.PathTrackerContext.Provider, {
  280. value: connectedKeyPath
  281. }, renderNode);
  282. });
  283. if (process.env.NODE_ENV !== 'production') {
  284. SubMenu.displayName = 'SubMenu';
  285. }
  286. var _default = exports.default = SubMenu;