acud
Version:
acg react 组件库
545 lines • 23.2 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
import _isNativeReflectConstruct from "@babel/runtime/helpers/esm/isNativeReflectConstruct";
import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/esm/inherits";
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
import some from 'lodash/some';
import isEqual from 'lodash/isEqual';
import isEmpty from 'lodash/isEmpty';
import map from 'lodash/map';
import every from 'lodash/every';
import differenceBy from 'lodash/differenceBy';
import forEach from 'lodash/forEach';
import findIndex from 'lodash/findIndex';
import React from 'react';
import arrayTreeFilter from 'array-tree-filter';
import classnames from 'classnames';
import CSSMotion from 'rc-motion';
import Checkbox from '../checkbox';
import List from '../virtual-list';
import MenuItem from './MenuItem';
import { getElementStyle, isIncludeArray } from './utils';
var DEFAULT_MENU_GAP = 4; // 菜单之间默认4px的间距
var Menus = /*#__PURE__*/function (_React$Component) {
function Menus(props) {
var _this;
_classCallCheck(this, Menus);
_this = _callSuper(this, Menus, [props]);
_this.menus = {};
_this.vMenus = {};
_this.menuItems = {};
_this.saveMenuWrap = function (menuWrap) {
_this.menuWrap = menuWrap;
};
_this.saveMenus = function (menuIndex) {
return function (menus) {
_this.menus[menuIndex] = menus;
};
};
_this.saveVMenus = function (menuIndex) {
return function (menus) {
_this.vMenus[menuIndex] = menus;
};
};
_this.saveMenuItems = function (index) {
return function (node) {
_this.menuItems[index] = node;
};
};
_this.handleMenuScroll = function (menuIndex) {
return function (e) {
var _a, _b, _c, _d;
var menuScrollOpen = _this.state.menuScrollOpen;
if (menuScrollOpen) {
// 当前menu滚动时,取消当前选中项高亮,隐藏子级
var activeValue = _this.props.activeValue.slice(0, menuIndex);
if (!isEqual(activeValue, _this.props.activeValue)) {
(_b = (_a = _this.props).onActiveValueSet) === null || _b === void 0 ? void 0 : _b.call(_a, activeValue);
}
(_d = (_c = _this.props).onDropdownMenuScroll) === null || _d === void 0 ? void 0 : _d.call(_c, e, menuIndex);
}
};
};
_this.onShowActive = function () {
_this.scrollActiveItemToView();
window.setTimeout(function () {
_this.setMenuPosition();
window.setTimeout(function () {
_this.handleMenuScrollChange(true);
}, 0);
}, 0);
};
_this.onShowEnd = function () {
_this.handleMenuScrollChange(false);
};
_this.state = {
// 默认关闭对menu scroll事件的监听,待scrollActiveItemToView完成后开启
menuScrollOpen: false
};
return _this;
}
_inherits(Menus, _React$Component);
return _createClass(Menus, [{
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps) {
if (!isEqual(prevProps.activeValue, this.props.activeValue) || prevProps.options !== this.props.options) {
this.setMenuPosition();
}
}
}, {
key: "isStatusOption",
value: function isStatusOption() {
var statusValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var option = arguments.length > 1 ? arguments[1] : undefined;
var menuIndex = arguments.length > 2 ? arguments[2] : undefined;
return statusValue[menuIndex] === option[this.getFieldName('value')];
}
}, {
key: "isActiveOption",
value: function isActiveOption(value, optionValue) {
var active = true;
forEach(optionValue, function (val, index) {
if (val !== value[index]) {
active = false;
return false;
}
});
return active;
}
}, {
key: "getFieldName",
value: function getFieldName(name) {
var _this$props = this.props,
fieldNames = _this$props.fieldNames,
defaultFieldNames = _this$props.defaultFieldNames;
// 防止只设置单个属性的名字
return fieldNames[name] || defaultFieldNames[name];
}
}, {
key: "getOption",
value: function getOption(option, menuIndex) {
var _this2 = this;
var _this$props2 = this.props,
prefixCls = _this$props2.prefixCls,
mode = _this$props2.mode,
keyword = _this$props2.keyword,
value = _this$props2.value,
activeValue = _this$props2.activeValue,
hoveredValue = _this$props2.hoveredValue,
expandTrigger = _this$props2.expandTrigger,
expandIcon = _this$props2.expandIcon,
loadingIcon = _this$props2.loadingIcon,
titlePlacement = _this$props2.titlePlacement;
var isMulti = mode === 'multiple';
var optionValue = function () {
var value = option[_this2.getFieldName('value')];
return /*#__PURE__*/React.isValidElement(value) ? menuIndex : value;
}();
var optionKey = [].concat(_toConsumableArray(activeValue.slice(0, menuIndex)), [optionValue]);
var hasChildren = option[this.getFieldName('children')] && option[this.getFieldName('children')].length > 0;
var hasLeaf = hasChildren || option.isLeaf === false;
var onSelect = this.props.onSelect.bind(this, option, menuIndex);
var onMultiSelect = this.props.onMultiSelect.bind(this, option, menuIndex, optionKey);
var onItemDoubleClick = this.props.onItemDoubleClick.bind(this, option, menuIndex);
var handleClick = function handleClick(e) {
isMulti && !hasLeaf ? undefined : onSelect(e);
};
var handleMultiClick = function handleMultiClick(e) {
if (activeValue[menuIndex] === optionValue) {
e.stopPropagation();
}
};
var expandProps = {
onClick: handleClick,
onDoubleClick: onItemDoubleClick
};
var menuItemCls = "".concat(prefixCls, "-menu-item");
if (isMulti) {
menuItemCls += " ".concat(prefixCls, "-menu-item-multi");
}
var expandIconNode = null;
if (hasLeaf) {
menuItemCls += " ".concat(prefixCls, "-menu-item-expand");
if (!option.loading) {
expandIconNode = /*#__PURE__*/React.createElement("span", {
className: "".concat(prefixCls, "-menu-item-expand-icon")
}, expandIcon);
}
}
if (expandTrigger === 'hover') {
expandProps = {
onMouseEnter: this.delayOnEvent.bind(this, onSelect),
onMouseLeave: this.delayOnEvent.bind(this),
onClick: handleClick
};
}
if (this.isStatusOption(hoveredValue, option, menuIndex) && hasLeaf) {
menuItemCls += " ".concat(prefixCls, "-menu-item-hovered");
}
if (this.isStatusOption(activeValue, option, menuIndex)) {
expandProps.ref = this.saveMenuItems(menuIndex);
}
if (!isMulti && this.isActiveOption(value, optionKey)) {
menuItemCls += " ".concat(prefixCls, "-menu-item-active");
}
if (option.disabled) {
menuItemCls += " ".concat(prefixCls, "-menu-item-disabled");
}
var loadingIconNode = null;
if (option.loading) {
menuItemCls += " ".concat(prefixCls, "-menu-item-loading");
loadingIconNode = loadingIcon || null;
}
var _ref = function () {
if (!isMulti) {
return {};
}
var checked;
var indeterminate;
if (keyword) {
checked = isIncludeArray(value, optionValue);
} else if (hasLeaf) {
var children = option[_this2.getFieldName('children')];
var getEnableValues = _this2.props.getEnableValues.bind(_this2);
var getTotalValues = _this2.props.getTotalValues.bind(_this2);
var enableValues = getEnableValues(children);
var totalValues = getTotalValues(children);
var disabledValues = differenceBy(totalValues, enableValues, JSON.stringify);
var selectedValue = map(value, function (valueItem) {
return valueItem.slice(menuIndex + 1);
});
var disabledSelectedValues = [];
forEach(disabledValues, function (valueItem) {
if (isIncludeArray(selectedValue, valueItem)) {
disabledSelectedValues.push(valueItem);
}
});
var childrenValue = [].concat(_toConsumableArray(getEnableValues(children)), disabledSelectedValues);
var includeCallback = function includeCallback(valueItem) {
return isIncludeArray(value, [].concat(_toConsumableArray(optionKey), _toConsumableArray(valueItem)));
};
checked = !isEmpty(childrenValue) && every(childrenValue, includeCallback);
indeterminate = !checked && some(childrenValue, includeCallback);
} else {
checked = isIncludeArray(value, optionKey);
}
return {
checked: checked,
indeterminate: indeterminate
};
}(),
checked = _ref.checked,
indeterminate = _ref.indeterminate;
var label = option[this.getFieldName('label')];
var labelContent = /*#__PURE__*/React.createElement("span", {
className: "".concat(prefixCls, "-menu-item-label")
}, label);
var menuItemProps = {
key: optionKey,
option: option,
label: label,
menuItemCls: menuItemCls,
expandProps: expandProps,
prefixCls: prefixCls,
isMulti: isMulti,
checked: checked,
indeterminate: indeterminate,
labelContent: labelContent,
expandIconNode: expandIconNode,
loadingIconNode: loadingIconNode,
handleMultiClick: handleMultiClick,
onMultiSelect: onMultiSelect,
onMouseEnter: expandProps === null || expandProps === void 0 ? void 0 : expandProps.onMouseEnter,
titlePlacement: titlePlacement
};
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(MenuItem, menuItemProps));
}
}, {
key: "getCheckAllOption",
value: function getCheckAllOption(menuIndex) {
var _this$props3 = this.props,
mode = _this$props3.mode,
prefixCls = _this$props3.prefixCls,
value = _this$props3.value,
enableValues = _this$props3.enableValues,
totalValues = _this$props3.totalValues,
_this$props3$withChec = _this$props3.withCheckAll,
withCheckAll = _this$props3$withChec === void 0 ? true : _this$props3$withChec,
locale = _this$props3.locale;
var isMulti = mode === 'multiple';
if (!(isMulti && menuIndex === 0) || !withCheckAll) {
return null;
}
var disabledValues = differenceBy(totalValues, enableValues, JSON.stringify);
var disabledSelectedValues = [];
forEach(disabledValues, function (valueItem) {
if (isIncludeArray(value, valueItem)) {
disabledSelectedValues.push(valueItem);
}
});
var childrenValue = [].concat(_toConsumableArray(enableValues), disabledSelectedValues);
var checked = value.length > 0 && value.length >= childrenValue.length && childrenValue.every(function (valueItem) {
return isIncludeArray(value, valueItem);
});
var indeterminate = !checked && value.length > 0;
var onMultiSelectAll = this.props.onMultiSelectAll.bind(this);
return /*#__PURE__*/React.createElement("li", {
className: "".concat(prefixCls, "-menu-item ").concat(prefixCls, "-menu-item-multi ").concat(prefixCls, "-menu-item-multi-check-all"),
role: "menuitem",
onMouseDown: function onMouseDown(e) {
return e.preventDefault();
}
}, /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-menu-item-content")
}, /*#__PURE__*/React.createElement(Checkbox, {
className: "".concat(prefixCls, "-menu-item-checkbox"),
checked: checked,
indeterminate: indeterminate,
onChange: onMultiSelectAll
}, /*#__PURE__*/React.createElement("span", {
className: "".concat(prefixCls, "-menu-item-label")
}, locale === null || locale === void 0 ? void 0 : locale.checkAll))));
}
}, {
key: "getActiveOptions",
value: function getActiveOptions(values) {
var _this3 = this;
var options = this.props.options;
var activeValue = values || this.props.activeValue;
return arrayTreeFilter(options, function (o, level) {
return o[_this3.getFieldName('value')] === activeValue[level];
}, {
childrenKeyName: this.getFieldName('children')
});
}
}, {
key: "getShowOptions",
value: function getShowOptions() {
var _this4 = this;
var options = this.props.options;
var result = this.getActiveOptions().map(function (activeOption) {
return activeOption[_this4.getFieldName('children')];
}).filter(function (activeOption) {
return !isEmpty(activeOption);
});
result.unshift(options);
return result;
}
}, {
key: "delayOnEvent",
value: function delayOnEvent(onEvent) {
var _this5 = this;
for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
if (this.delayTimer) {
clearTimeout(this.delayTimer);
this.delayTimer = null;
}
if (typeof onEvent === 'function') {
this.delayTimer = window.setTimeout(function () {
onEvent.apply(void 0, args);
_this5.delayTimer = null;
}, 150);
}
}
}, {
key: "scrollActiveItemToView",
value: function scrollActiveItemToView() {
var _this6 = this;
var _a;
// scroll into view
var showOptions = this.getShowOptions();
var optionsLength = showOptions.length;
var activeValue = this.props.activeValue;
// eslint-disable-next-line no-plusplus
var _loop = function _loop(i) {
var menuItemParent = _this6.vMenus[i];
var options = showOptions[i];
var index = findIndex(options, function (option) {
var value = option[_this6.getFieldName('value')];
return value === activeValue[i];
});
(_a = menuItemParent === null || menuItemParent === void 0 ? void 0 : menuItemParent.scrollTo) === null || _a === void 0 ? void 0 : _a.call(menuItemParent, {
index: index
});
};
for (var i = 0; i < optionsLength; i++) {
_loop(i);
}
}
}, {
key: "setMenuPosition",
value: function setMenuPosition() {
var _this7 = this;
var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
var _a, _b, _c, _d, _e, _f;
var _this$props4 = this.props,
menusEdgeBuffer = _this$props4.menusEdgeBuffer,
popupPlacement = _this$props4.popupPlacement;
var menuDirections = [];
var optionsLength = this.getShowOptions().length;
if (Number(optionsLength) <= 0) {
return;
}
var isPlaceTop = ['topLeft', 'topRight'].includes(popupPlacement);
var clientHeight = window.innerHeight;
var clientWidth = window.innerWidth;
var _loop2 = function _loop2() {
var currentMenu = _this7.menus[i];
var prevMenu = _this7.menus[i - 1];
var prevVMenu = _this7.vMenus[i - 1].componentRef.current;
// 1、计算left并设置
var prevMenusWidthSum = 0;
var prevMenuDir = menuDirections[i - 1] || 'right';
if (prevMenuDir === 'right') {
// 往右展开时到达边界
// eslint-disable-next-line max-len
if (clientWidth - prevMenu.getBoundingClientRect().left - prevMenu.offsetWidth - DEFAULT_MENU_GAP < currentMenu.offsetWidth) {
prevMenusWidthSum = prevMenu.offsetLeft - currentMenu.offsetWidth - DEFAULT_MENU_GAP;
menuDirections[i] = 'left';
} else {
prevMenusWidthSum = prevMenu.offsetLeft + prevMenu.offsetWidth + DEFAULT_MENU_GAP;
menuDirections[i] = 'right';
}
} else if (prevMenuDir === 'left') {
// 往左展开时到达边界
if (prevMenu.getBoundingClientRect().left - DEFAULT_MENU_GAP < currentMenu.offsetWidth) {
prevMenusWidthSum = prevMenu.offsetLeft + prevMenu.offsetWidth + DEFAULT_MENU_GAP;
menuDirections[i] = 'right';
} else {
prevMenusWidthSum = prevMenu.offsetLeft - currentMenu.offsetWidth - DEFAULT_MENU_GAP;
menuDirections[i] = 'left';
}
}
// 设置left
currentMenu.style.left = prevMenusWidthSum + 'px';
// 2、计算top/bottom并设置
if (isPlaceTop) {
var prevMenuBottom = Number(getElementStyle(prevMenu).bottom.replace('px', ''));
var prevMenuTransform = (_b = getElementStyle((_a = _this7.menuItems[i - 1]) === null || _a === void 0 ? void 0 : _a.parentElement)) === null || _b === void 0 ? void 0 : _b.transform;
var prevMenuTranslateY = prevMenuTransform && prevMenuTransform !== 'none' ? parseFloat(prevMenuTransform.substring(6).split(',')[5]) : 0;
var bottom = prevMenu.offsetHeight + prevMenuBottom + (prevVMenu.scrollTop - prevMenuTranslateY) - (((_c = _this7.menuItems[i - 1]) === null || _c === void 0 ? void 0 : _c.offsetTop) || 0) - currentMenu.offsetHeight;
currentMenu.style.bottom = (bottom < 0 ? 0 : bottom) + 'px';
} else {
var prevMenuTop = Number(getElementStyle(prevMenu).top.replace('px', ''));
var _prevMenuTransform = (_e = getElementStyle((_d = _this7.menuItems[i - 1]) === null || _d === void 0 ? void 0 : _d.parentElement)) === null || _e === void 0 ? void 0 : _e.transform;
var _prevMenuTranslateY = _prevMenuTransform && _prevMenuTransform !== 'none' ? parseFloat(_prevMenuTransform.substring(6).split(',')[5]) : 0;
var prevMenuItemsTopSum = prevMenuTop + (((_f = _this7.menuItems[i - 1]) === null || _f === void 0 ? void 0 : _f.offsetTop) || 0) - (prevVMenu.scrollTop - _prevMenuTranslateY);
var menuWrapTop = _this7.menuWrap.parentElement.getBoundingClientRect().top;
var currentMenuHeight = currentMenu.offsetHeight;
var currentMenuMaxTop = clientHeight - menuWrapTop - currentMenuHeight - menusEdgeBuffer;
var currentMenuTop = function () {
if (currentMenuMaxTop <= 0) {
return 0;
}
return prevMenuItemsTopSum > currentMenuMaxTop ? currentMenuMaxTop : prevMenuItemsTopSum;
}();
currentMenu.style.top = (currentMenuTop < 0 ? 0 : currentMenuTop) + 'px';
}
};
for (var i = 1; i < optionsLength; i++) {
_loop2();
}
if (typeof callback === 'function') {
callback();
}
}
}, {
key: "handleMenuScrollChange",
value: function handleMenuScrollChange(menuScrollOpen) {
this.setState({
menuScrollOpen: menuScrollOpen
});
}
}, {
key: "render",
value: function render() {
var _this8 = this;
var _this$props5 = this.props,
prefixCls = _this$props5.prefixCls,
transitionName = _this$props5.transitionName,
visible = _this$props5.visible,
virtual = _this$props5.virtual,
hoveredValue = _this$props5.hoveredValue,
dropdownMenuRender = _this$props5.dropdownMenuRender,
dropdownMenuColumnStyle = _this$props5.dropdownMenuColumnStyle,
size = _this$props5.size,
mode = _this$props5.mode;
var showOptions = this.getShowOptions();
var isMulti = mode === 'multiple';
var sizeCls = classnames(_defineProperty(_defineProperty({}, "".concat(prefixCls, "-menu-lg"), size === 'large'), "".concat(prefixCls, "-menu-sm"), size === 'small'));
var menuClas = classnames("".concat(prefixCls, "-menu"), _defineProperty(_defineProperty({}, "".concat(prefixCls, "-menu-multi"), isMulti), sizeCls, sizeCls));
var menu = showOptions.map(function (options, menuIndex) {
var menuKey = "u + ".concat(menuIndex);
var menuProps = {
key: menuKey,
className: menuClas,
ref: _this8.saveMenus(menuIndex),
style: dropdownMenuColumnStyle
};
var getMenu = function getMenu(menuProps) {
return /*#__PURE__*/React.createElement("ul", menuProps, /*#__PURE__*/React.createElement(List, {
itemKey: "value",
ref: _this8.saveVMenus(menuIndex),
data: options,
height: 256,
itemHeight: 32,
fullHeight: false,
virtual: virtual,
onMouseDown: function onMouseDown(e) {
return e.preventDefault();
},
onScroll: _this8.handleMenuScroll(menuIndex)
}, function (option, optionIndex) {
var optionComp = _this8.getOption(option, menuIndex);
if (optionIndex === 0) {
return /*#__PURE__*/React.createElement(React.Fragment, null, _this8.getCheckAllOption(menuIndex), optionComp);
}
return optionComp;
}));
};
if (dropdownMenuRender) {
return /*#__PURE__*/React.createElement("div", menuProps, dropdownMenuRender(getMenu(), menuIndex, hoveredValue));
}
return getMenu(menuProps);
});
return /*#__PURE__*/React.createElement(CSSMotion, {
visible: visible,
motionName: transitionName,
removeOnLeave: false,
leavedClassName: "".concat(prefixCls, "-menu-wrap-hidden"),
onAppearActive: this.onShowActive,
onEnterActive: this.onShowActive,
onLeaveEnd: this.onShowEnd
}, function (_ref2) {
var className = _ref2.className,
style = _ref2.style;
return /*#__PURE__*/React.createElement("div", {
ref: _this8.saveMenuWrap,
className: className,
style: _extends({
position: 'relative'
}, style)
}, menu);
});
}
}]);
}(React.Component);
Menus.defaultProps = {
options: [],
value: [],
activeValue: [],
onSelect: function onSelect() {},
prefixCls: 'rc-cascader-menus',
visible: false,
virtual: false,
expandTrigger: 'click',
menusEdgeBuffer: 20
};
export default Menus;