"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.SubMenu = void 0; var React = _interopRequireWildcard(require("react")); var ReactDOM = _interopRequireWildcard(require("react-dom")); var _rcTrigger = _interopRequireDefault(require("rc-trigger")); var _KeyCode = _interopRequireDefault(require("rc-util/lib/KeyCode")); var _CSSMotion = _interopRequireDefault(require("rc-animate/lib/CSSMotion")); var _classnames = _interopRequireDefault(require("classnames")); var _miniStore = require("mini-store"); var _SubPopupMenu = _interopRequireDefault(require("./SubPopupMenu")); var _placements = _interopRequireDefault(require("./placements")); var _util = require("./util"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (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; } function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } var guid = 0; var popupPlacementMap = { horizontal: 'bottomLeft', vertical: 'rightTop', 'vertical-left': 'rightTop', 'vertical-right': 'leftTop' }; var updateDefaultActiveFirst = function updateDefaultActiveFirst(store, eventKey, defaultActiveFirst) { var menuId = (0, _util.getMenuIdFromSubMenuEventKey)(eventKey); var state = store.getState(); store.setState({ defaultActiveFirst: _objectSpread({}, state.defaultActiveFirst, _defineProperty({}, menuId, defaultActiveFirst)) }); }; var SubMenu = /*#__PURE__*/ function (_React$Component) { _inherits(SubMenu, _React$Component); function SubMenu(props) { var _this; _classCallCheck(this, SubMenu); _this = _possibleConstructorReturn(this, _getPrototypeOf(SubMenu).call(this, props)); _this.onDestroy = function (key) { _this.props.onDestroy(key); }; /** * note: * This legacy code that `onKeyDown` is called by parent instead of dom self. * which need return code to check if this event is handled */ _this.onKeyDown = function (e) { var keyCode = e.keyCode; var menu = _this.menuInstance; var _this$props = _this.props, isOpen = _this$props.isOpen, store = _this$props.store; if (keyCode === _KeyCode.default.ENTER) { _this.onTitleClick(e); updateDefaultActiveFirst(store, _this.props.eventKey, true); return true; } if (keyCode === _KeyCode.default.RIGHT) { if (isOpen) { menu.onKeyDown(e); } else { _this.triggerOpenChange(true); // need to update current menu's defaultActiveFirst value updateDefaultActiveFirst(store, _this.props.eventKey, true); } return true; } if (keyCode === _KeyCode.default.LEFT) { var handled; if (isOpen) { handled = menu.onKeyDown(e); } else { return undefined; } if (!handled) { _this.triggerOpenChange(false); handled = true; } return handled; } if (isOpen && (keyCode === _KeyCode.default.UP || keyCode === _KeyCode.default.DOWN)) { return menu.onKeyDown(e); } return undefined; }; _this.onOpenChange = function (e) { _this.props.onOpenChange(e); }; _this.onPopupVisibleChange = function (visible) { _this.triggerOpenChange(visible, visible ? 'mouseenter' : 'mouseleave'); }; _this.onMouseEnter = function (e) { var _this$props2 = _this.props, key = _this$props2.eventKey, onMouseEnter = _this$props2.onMouseEnter, store = _this$props2.store; updateDefaultActiveFirst(store, _this.props.eventKey, false); onMouseEnter({ key: key, domEvent: e }); }; _this.onMouseLeave = function (e) { var _this$props3 = _this.props, parentMenu = _this$props3.parentMenu, eventKey = _this$props3.eventKey, onMouseLeave = _this$props3.onMouseLeave; parentMenu.subMenuInstance = _assertThisInitialized(_this); onMouseLeave({ key: eventKey, domEvent: e }); }; _this.onTitleMouseEnter = function (domEvent) { var _this$props4 = _this.props, key = _this$props4.eventKey, onItemHover = _this$props4.onItemHover, onTitleMouseEnter = _this$props4.onTitleMouseEnter; onItemHover({ key: key, hover: true }); onTitleMouseEnter({ key: key, domEvent: domEvent }); }; _this.onTitleMouseLeave = function (e) { var _this$props5 = _this.props, parentMenu = _this$props5.parentMenu, eventKey = _this$props5.eventKey, onItemHover = _this$props5.onItemHover, onTitleMouseLeave = _this$props5.onTitleMouseLeave; parentMenu.subMenuInstance = _assertThisInitialized(_this); onItemHover({ key: eventKey, hover: false }); onTitleMouseLeave({ key: eventKey, domEvent: e }); }; _this.onTitleClick = function (e) { var _assertThisInitialize = _assertThisInitialized(_this), props = _assertThisInitialize.props; props.onTitleClick({ key: props.eventKey, domEvent: e }); if (props.triggerSubMenuAction === 'hover') { return; } _this.triggerOpenChange(!props.isOpen, 'click'); updateDefaultActiveFirst(props.store, _this.props.eventKey, false); }; _this.onSubMenuClick = function (info) { // in the case of overflowed submenu // onClick is not copied over if (typeof _this.props.onClick === 'function') { _this.props.onClick(_this.addKeyPath(info)); } }; _this.onSelect = function (info) { _this.props.onSelect(info); }; _this.onDeselect = function (info) { _this.props.onDeselect(info); }; _this.getPrefixCls = function () { return "".concat(_this.props.rootPrefixCls, "-submenu"); }; _this.getActiveClassName = function () { return "".concat(_this.getPrefixCls(), "-active"); }; _this.getDisabledClassName = function () { return "".concat(_this.getPrefixCls(), "-disabled"); }; _this.getSelectedClassName = function () { return "".concat(_this.getPrefixCls(), "-selected"); }; _this.getOpenClassName = function () { return "".concat(_this.props.rootPrefixCls, "-submenu-open"); }; _this.saveMenuInstance = function (c) { // children menu instance _this.menuInstance = c; }; _this.addKeyPath = function (info) { return _objectSpread({}, info, { keyPath: (info.keyPath || []).concat(_this.props.eventKey) }); }; _this.triggerOpenChange = function (open, type) { var key = _this.props.eventKey; var openChange = function openChange() { _this.onOpenChange({ key: key, item: _assertThisInitialized(_this), trigger: type, open: open }); }; if (type === 'mouseenter') { // make sure mouseenter happen after other menu item's mouseleave _this.mouseenterTimeout = setTimeout(function () { openChange(); }, 0); } else { openChange(); } }; _this.isChildrenSelected = function () { var ret = { find: false }; (0, _util.loopMenuItemRecursively)(_this.props.children, _this.props.selectedKeys, ret); return ret.find; }; _this.isOpen = function () { return _this.props.openKeys.indexOf(_this.props.eventKey) !== -1; }; _this.adjustWidth = function () { /* istanbul ignore if */ if (!_this.subMenuTitle || !_this.menuInstance) { return; } var popupMenu = ReactDOM.findDOMNode(_this.menuInstance); if (popupMenu.offsetWidth >= _this.subMenuTitle.offsetWidth) { return; } /* istanbul ignore next */ popupMenu.style.minWidth = "".concat(_this.subMenuTitle.offsetWidth, "px"); }; _this.saveSubMenuTitle = function (subMenuTitle) { _this.subMenuTitle = subMenuTitle; }; var store = props.store, eventKey = props.eventKey; var _store$getState = store.getState(), defaultActiveFirst = _store$getState.defaultActiveFirst; _this.isRootMenu = false; var value = false; if (defaultActiveFirst) { value = defaultActiveFirst[eventKey]; } updateDefaultActiveFirst(store, eventKey, value); return _this; } _createClass(SubMenu, [{ key: "componentDidMount", value: function componentDidMount() { this.componentDidUpdate(); } }, { key: "componentDidUpdate", value: function componentDidUpdate() { var _this2 = this; var _this$props6 = this.props, mode = _this$props6.mode, parentMenu = _this$props6.parentMenu, manualRef = _this$props6.manualRef; // invoke customized ref to expose component to mixin if (manualRef) { manualRef(this); } if (mode !== 'horizontal' || !parentMenu.isRootMenu || !this.props.isOpen) { return; } this.minWidthTimeout = setTimeout(function () { return _this2.adjustWidth(); }, 0); } }, { key: "componentWillUnmount", value: function componentWillUnmount() { var _this$props7 = this.props, onDestroy = _this$props7.onDestroy, eventKey = _this$props7.eventKey; if (onDestroy) { onDestroy(eventKey); } /* istanbul ignore if */ if (this.minWidthTimeout) { clearTimeout(this.minWidthTimeout); } /* istanbul ignore if */ if (this.mouseenterTimeout) { clearTimeout(this.mouseenterTimeout); } } }, { key: "renderChildren", value: function renderChildren(children) { var _this3 = this; var props = this.props; var baseProps = { mode: props.mode === 'horizontal' ? 'vertical' : props.mode, visible: this.props.isOpen, level: props.level + 1, inlineIndent: props.inlineIndent, focusable: false, onClick: this.onSubMenuClick, onSelect: this.onSelect, onDeselect: this.onDeselect, onDestroy: this.onDestroy, selectedKeys: props.selectedKeys, eventKey: "".concat(props.eventKey, "-menu-"), openKeys: props.openKeys, motion: props.motion, onOpenChange: this.onOpenChange, subMenuOpenDelay: props.subMenuOpenDelay, parentMenu: this, subMenuCloseDelay: props.subMenuCloseDelay, forceSubMenuRender: props.forceSubMenuRender, triggerSubMenuAction: props.triggerSubMenuAction, builtinPlacements: props.builtinPlacements, defaultActiveFirst: props.store.getState().defaultActiveFirst[(0, _util.getMenuIdFromSubMenuEventKey)(props.eventKey)], multiple: props.multiple, prefixCls: props.rootPrefixCls, id: this.internalMenuId, manualRef: this.saveMenuInstance, itemIcon: props.itemIcon, expandIcon: props.expandIcon }; var haveRendered = this.haveRendered; this.haveRendered = true; this.haveOpened = this.haveOpened || baseProps.visible || baseProps.forceSubMenuRender; // never rendered not planning to, don't render if (!this.haveOpened) { return React.createElement("div", null); } // ================== Motion ================== // don't show transition on first rendering (no animation for opened menu) // show appear transition if it's not visible (not sure why) // show appear transition if it's not inline mode var mergedMotion = _objectSpread({}, props.motion, { leavedClassName: "".concat(props.rootPrefixCls, "-hidden"), removeOnLeave: false, motionAppear: haveRendered || !baseProps.visible || baseProps.mode !== 'inline' }); return React.createElement(_CSSMotion.default, Object.assign({ visible: baseProps.visible }, mergedMotion), function (_ref) { var className = _ref.className, style = _ref.style; var mergedClassName = (0, _classnames.default)("".concat(baseProps.prefixCls, "-sub"), className); return React.createElement(_SubPopupMenu.default, Object.assign({}, baseProps, { id: _this3.internalMenuId, className: mergedClassName, style: style }), children); }); } }, { key: "render", value: function render() { var _classNames; var props = _objectSpread({}, this.props); var isOpen = props.isOpen; var prefixCls = this.getPrefixCls(); var isInlineMode = props.mode === 'inline'; var className = (0, _classnames.default)(prefixCls, "".concat(prefixCls, "-").concat(props.mode), (_classNames = {}, _defineProperty(_classNames, props.className, !!props.className), _defineProperty(_classNames, this.getOpenClassName(), isOpen), _defineProperty(_classNames, this.getActiveClassName(), props.active || isOpen && !isInlineMode), _defineProperty(_classNames, this.getDisabledClassName(), props.disabled), _defineProperty(_classNames, this.getSelectedClassName(), this.isChildrenSelected()), _classNames)); if (!this.internalMenuId) { if (props.eventKey) { this.internalMenuId = "".concat(props.eventKey, "$Menu"); } else { guid += 1; this.internalMenuId = "$__$".concat(guid, "$Menu"); } } var mouseEvents = {}; var titleClickEvents = {}; var titleMouseEvents = {}; if (!props.disabled) { mouseEvents = { onMouseLeave: this.onMouseLeave, onMouseEnter: this.onMouseEnter }; // only works in title, not outer li titleClickEvents = { onClick: this.onTitleClick }; titleMouseEvents = { onMouseEnter: this.onTitleMouseEnter, onMouseLeave: this.onTitleMouseLeave }; } var style = {}; if (isInlineMode) { style.paddingLeft = props.inlineIndent * props.level; } var ariaOwns = {}; // only set aria-owns when menu is open // otherwise it would be an invalid aria-owns value // since corresponding node cannot be found if (this.props.isOpen) { ariaOwns = { 'aria-owns': this.internalMenuId }; } // expand custom icon should NOT be displayed in menu with horizontal mode. var icon = null; if (props.mode !== 'horizontal') { icon = this.props.expandIcon; // ReactNode if (typeof this.props.expandIcon === 'function') { icon = React.createElement(this.props.expandIcon, _objectSpread({}, this.props)); } } var title = React.createElement("div", Object.assign({ ref: this.saveSubMenuTitle, style: style, className: "".concat(prefixCls, "-title") }, titleMouseEvents, titleClickEvents, { "aria-expanded": isOpen }, ariaOwns, { "aria-haspopup": "true", title: typeof props.title === 'string' ? props.title : undefined }), props.title, icon || React.createElement("i", { className: "".concat(prefixCls, "-arrow") })); var children = this.renderChildren(props.children); var getPopupContainer = props.parentMenu.isRootMenu ? props.parentMenu.props.getPopupContainer : function (triggerNode) { return triggerNode.parentNode; }; var popupPlacement = popupPlacementMap[props.mode]; var popupAlign = props.popupOffset ? { offset: props.popupOffset } : {}; var popupClassName = props.mode === 'inline' ? '' : props.popupClassName; var disabled = props.disabled, triggerSubMenuAction = props.triggerSubMenuAction, subMenuOpenDelay = props.subMenuOpenDelay, forceSubMenuRender = props.forceSubMenuRender, subMenuCloseDelay = props.subMenuCloseDelay, builtinPlacements = props.builtinPlacements; _util.menuAllProps.forEach(function (key) { return delete props[key]; }); // Set onClick to null, to ignore propagated onClick event delete props.onClick; return React.createElement("li", Object.assign({}, props, mouseEvents, { className: className, role: "menuitem" }), isInlineMode && title, isInlineMode && children, !isInlineMode && React.createElement(_rcTrigger.default, { prefixCls: prefixCls, popupClassName: "".concat(prefixCls, "-popup ").concat(popupClassName), getPopupContainer: getPopupContainer, builtinPlacements: Object.assign({}, _placements.default, builtinPlacements), popupPlacement: popupPlacement, popupVisible: isOpen, popupAlign: popupAlign, popup: children, action: disabled ? [] : [triggerSubMenuAction], mouseEnterDelay: subMenuOpenDelay, mouseLeaveDelay: subMenuCloseDelay, onPopupVisibleChange: this.onPopupVisibleChange, forceRender: forceSubMenuRender }, title)); } }]); return SubMenu; }(React.Component); exports.SubMenu = SubMenu; SubMenu.defaultProps = { onMouseEnter: _util.noop, onMouseLeave: _util.noop, onTitleMouseEnter: _util.noop, onTitleMouseLeave: _util.noop, onTitleClick: _util.noop, manualRef: _util.noop, mode: 'vertical', title: '' }; var connected = (0, _miniStore.connect)(function (_ref2, _ref3) { var openKeys = _ref2.openKeys, activeKey = _ref2.activeKey, selectedKeys = _ref2.selectedKeys; var eventKey = _ref3.eventKey, subMenuKey = _ref3.subMenuKey; return { isOpen: openKeys.indexOf(eventKey) > -1, active: activeKey[subMenuKey] === eventKey, selectedKeys: selectedKeys }; })(SubMenu); connected.isSubMenu = true; var _default = connected; exports.default = _default;