UNPKG

rsuite

Version:

A suite of react components

186 lines (171 loc) 7.54 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; import SpinnerIcon from '@rsuite/icons/legacy/Spinner'; import AngleLeftIcon from '@rsuite/icons/legacy/AngleLeft'; import AngleRightIcon from '@rsuite/icons/legacy/AngleRight'; import { useClassNames, shallowEqual, useCustom } from '../utils'; import { DropdownMenuCheckItem } from '../Picker'; import { isSomeParentChecked, isSomeChildChecked } from './utils'; var emptyArray = []; /** * TODO: reuse Menu from Cascader for consistent behavior */ var DropdownMenu = /*#__PURE__*/React.forwardRef(function (props, ref) { var _props$as = props.as, Component = _props$as === void 0 ? 'div' : _props$as, _props$classPrefix = props.classPrefix, classPrefix = _props$classPrefix === void 0 ? 'menu' : _props$classPrefix, className = props.className, cascade = props.cascade, _props$cascadeData = props.cascadeData, cascadeData = _props$cascadeData === void 0 ? emptyArray : _props$cascadeData, _props$cascadePaths = props.cascadePaths, cascadePaths = _props$cascadePaths === void 0 ? emptyArray : _props$cascadePaths, _props$childrenKey = props.childrenKey, childrenKey = _props$childrenKey === void 0 ? 'children' : _props$childrenKey, _props$disabledItemVa = props.disabledItemValues, disabledItemValues = _props$disabledItemVa === void 0 ? emptyArray : _props$disabledItemVa, _props$menuWidth = props.menuWidth, menuWidth = _props$menuWidth === void 0 ? 156 : _props$menuWidth, _props$menuHeight = props.menuHeight, menuHeight = _props$menuHeight === void 0 ? 200 : _props$menuHeight, _props$uncheckableIte = props.uncheckableItemValues, uncheckableItemValues = _props$uncheckableIte === void 0 ? emptyArray : _props$uncheckableIte, value = props.value, _props$valueKey = props.valueKey, valueKey = _props$valueKey === void 0 ? 'value' : _props$valueKey, _props$labelKey = props.labelKey, labelKey = _props$labelKey === void 0 ? 'label' : _props$labelKey, renderMenuItem = props.renderMenuItem, renderMenu = props.renderMenu, _onCheck = props.onCheck, onSelect = props.onSelect, rest = _objectWithoutPropertiesLoose(props, ["as", "classPrefix", "className", "cascade", "cascadeData", "cascadePaths", "childrenKey", "disabledItemValues", "menuWidth", "menuHeight", "uncheckableItemValues", "value", "valueKey", "labelKey", "renderMenuItem", "renderMenu", "onCheck", "onSelect"]); var _useClassNames = useClassNames(classPrefix), merge = _useClassNames.merge, prefix = _useClassNames.prefix; var classes = merge(className, prefix('items')); var _useCustom = useCustom('DropdownMenu'), rtl = _useCustom.rtl; var getCascadePaths = useCallback(function (layer, node) { var paths = []; for (var i = 0; i < cascadeData.length && i < layer; i += 1) { if (i < layer - 1 && cascadePaths) { paths.push(cascadePaths[i]); } } paths.push(node); return paths; }, [cascadeData, cascadePaths]); var handleSelect = useCallback(function (layer, node, event) { var cascadePaths = getCascadePaths(layer + 1, node); onSelect === null || onSelect === void 0 ? void 0 : onSelect(node, cascadePaths, event); }, [getCascadePaths, onSelect]); var renderCascadeNode = function renderCascadeNode(node, index, layer, focus, uncheckable) { var children = node[childrenKey]; var nodeValue = node[valueKey]; var nodeLabel = node[labelKey]; var disabled = disabledItemValues.some(function (disabledValue) { return shallowEqual(disabledValue, nodeValue); }); // Use `value` in keys when If `value` is string or number var onlyKey = typeof value === 'number' || typeof value === 'string' ? value : index; var Icon = node.loading ? SpinnerIcon : rtl ? AngleLeftIcon : AngleRightIcon; var active = value.some(function (v) { return v === nodeValue; }); if (cascade) { active = active || isSomeParentChecked(node, value, { valueKey: valueKey }); } return /*#__PURE__*/React.createElement(DropdownMenuCheckItem, { as: "li", key: layer + "-" + onlyKey, disabled: disabled, active: active, focus: focus // Pass the node as a value to Item, and use it in event callbacks. , value: nodeValue, className: children ? prefix('has-children') : undefined, indeterminate: cascade && !active && isSomeChildChecked(node, value, { valueKey: valueKey, childrenKey: childrenKey }), onSelectItem: function onSelectItem(_value, event) { return handleSelect(layer, node, event); }, onCheck: function onCheck(_value, event, checked) { return _onCheck === null || _onCheck === void 0 ? void 0 : _onCheck(node, event, checked); }, checkable: !uncheckable }, renderMenuItem ? renderMenuItem(nodeLabel, node) : nodeLabel, children ? /*#__PURE__*/React.createElement(Icon, { className: prefix('caret'), spin: node.loading }) : null); }; var renderCascade = function renderCascade() { var styles = { width: cascadeData.length * menuWidth }; var columnStyles = { height: menuHeight, width: menuWidth }; var cascadeNodes = cascadeData.map(function (children, layer) { var uncheckableCount = 0; var onlyKey = layer + "_" + children.length; var menu = /*#__PURE__*/React.createElement("ul", { role: "listbox" }, children.map(function (item, index) { var uncheckable = uncheckableItemValues.some(function (uncheckableValue) { return shallowEqual(uncheckableValue, item[valueKey]); }); if (uncheckable) { uncheckableCount++; } return renderCascadeNode(item, index, layer, cascadePaths[layer] && shallowEqual(cascadePaths[layer][valueKey], item[valueKey]), uncheckable); })); var parentNode = cascadePaths[layer - 1]; var columnClasses = prefix('column', { 'column-uncheckable': uncheckableCount === children.length }); return /*#__PURE__*/React.createElement("div", { key: onlyKey, className: columnClasses, "data-layer": layer, style: columnStyles }, renderMenu ? renderMenu(children, menu, parentNode, layer) : menu); }); return /*#__PURE__*/React.createElement("div", { style: styles }, cascadeNodes); }; return /*#__PURE__*/React.createElement(Component, _extends({}, rest, { ref: ref, className: classes }), renderCascade()); }); DropdownMenu.displayName = 'DropdownMenu'; DropdownMenu.propTypes = { classPrefix: PropTypes.string, data: PropTypes.array, disabledItemValues: PropTypes.array, value: PropTypes.array, childrenKey: PropTypes.string, valueKey: PropTypes.string, labelKey: PropTypes.string, menuWidth: PropTypes.number, menuHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), className: PropTypes.string, cascade: PropTypes.bool, cascadeData: PropTypes.array, cascadePaths: PropTypes.array, uncheckableItemValues: PropTypes.array, renderMenuItem: PropTypes.func, renderMenu: PropTypes.func, onSelect: PropTypes.func, onCheck: PropTypes.func }; export default DropdownMenu;