You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

626 lines
20 KiB

"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.SubMenu = void 0;
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _createSuper2 = _interopRequireDefault(require("@babel/runtime/helpers/createSuper"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _objectSpread3 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
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 _rcMotion = _interopRequireDefault(require("rc-motion"));
var _classnames = _interopRequireDefault(require("classnames"));
var _miniStore = require("mini-store");
var _SubPopupMenu = _interopRequireDefault(require("./SubPopupMenu"));
var _placements = require("./placements");
var _util = require("./util");
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: (0, _objectSpread3.default)((0, _objectSpread3.default)({}, state.defaultActiveFirst), {}, (0, _defineProperty2.default)({}, menuId, defaultActiveFirst))
});
};
var SubMenu = /*#__PURE__*/function (_React$Component) {
(0, _inherits2.default)(SubMenu, _React$Component);
var _super = (0, _createSuper2.default)(SubMenu);
function SubMenu(props) {
var _this;
(0, _classCallCheck2.default)(this, SubMenu);
_this = _super.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 = (0, _assertThisInitialized2.default)(_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 = (0, _assertThisInitialized2.default)(_this);
onItemHover({
key: eventKey,
hover: false
});
onTitleMouseLeave({
key: eventKey,
domEvent: e
});
};
_this.onTitleClick = function (e) {
var _assertThisInitialize = (0, _assertThisInitialized2.default)(_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 (0, _objectSpread3.default)((0, _objectSpread3.default)({}, 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: (0, _assertThisInitialized2.default)(_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;
};
_this.getBaseProps = function () {
var _assertThisInitialize2 = (0, _assertThisInitialized2.default)(_this),
props = _assertThisInitialize2.props;
return {
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: (0, _assertThisInitialized2.default)(_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,
direction: props.direction
};
};
_this.getMotion = function (mode, visible) {
var _assertThisInitialize3 = (0, _assertThisInitialized2.default)(_this),
haveRendered = _assertThisInitialize3.haveRendered;
var _this$props6 = _this.props,
motion = _this$props6.motion,
rootPrefixCls = _this$props6.rootPrefixCls; // 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 = (0, _objectSpread3.default)((0, _objectSpread3.default)({}, motion), {}, {
leavedClassName: "".concat(rootPrefixCls, "-hidden"),
removeOnLeave: false,
motionAppear: haveRendered || !visible || mode !== 'inline'
});
return mergedMotion;
};
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;
}
(0, _createClass2.default)(SubMenu, [{
key: "componentDidMount",
value: function componentDidMount() {
this.componentDidUpdate();
}
}, {
key: "componentDidUpdate",
value: function componentDidUpdate() {
var _this2 = this;
var _this$props7 = this.props,
mode = _this$props7.mode,
parentMenu = _this$props7.parentMenu,
manualRef = _this$props7.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$props8 = this.props,
onDestroy = _this$props8.onDestroy,
eventKey = _this$props8.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 baseProps = this.getBaseProps(); // [Legacy] getMotion must be called before `haveRendered`
var mergedMotion = this.getMotion(baseProps.mode, baseProps.visible);
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);
}
var direction = baseProps.direction;
return React.createElement(_rcMotion.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, (0, _defineProperty2.default)({}, "".concat(baseProps.prefixCls, "-rtl"), direction === 'rtl'));
return React.createElement(_SubPopupMenu.default, Object.assign({}, baseProps, {
id: _this3.internalMenuId,
className: mergedClassName,
style: style
}), children);
});
}
}, {
key: "render",
value: function render() {
var _classNames2;
var props = (0, _objectSpread3.default)({}, 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), (_classNames2 = {}, (0, _defineProperty2.default)(_classNames2, props.className, !!props.className), (0, _defineProperty2.default)(_classNames2, this.getOpenClassName(), isOpen), (0, _defineProperty2.default)(_classNames2, this.getActiveClassName(), props.active || isOpen && !isInlineMode), (0, _defineProperty2.default)(_classNames2, this.getDisabledClassName(), props.disabled), (0, _defineProperty2.default)(_classNames2, this.getSelectedClassName(), this.isChildrenSelected()), _classNames2));
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 = {};
var direction = props.direction;
if (isInlineMode) {
if (direction === 'rtl') {
style.paddingRight = props.inlineIndent * props.level;
} else {
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, (0, _objectSpread3.default)({}, this.props));
}
}
var title = React.createElement("div", Object.assign({
ref: this.saveSubMenuTitle,
style: style,
className: "".concat(prefixCls, "-title"),
role: "button"
}, 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;
popupClassName += direction === 'rtl' ? " ".concat(prefixCls, "-rtl") : '';
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;
var placement = direction === 'rtl' ? Object.assign({}, _placements.placementsRtl, builtinPlacements) : Object.assign({}, _placements.placements, builtinPlacements);
delete props.direction;
return React.createElement("li", Object.assign({}, props, mouseEvents, {
className: className,
role: "menuitem"
}), isInlineMode && title, isInlineMode && children, !isInlineMode && React.createElement(_rcTrigger.default, {
prefixCls: prefixCls,
popupClassName: (0, _classnames.default)("".concat(prefixCls, "-popup"), popupClassName),
getPopupContainer: getPopupContainer,
builtinPlacements: placement,
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;