UNPKG

acud

Version:

acg react 组件库

545 lines • 23.2 kB
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;