UNPKG

rsuite

Version:

A suite of react components

170 lines (157 loc) 7.17 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose"; import React, { useCallback, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import SpinnerIcon from '@rsuite/icons/legacy/Spinner'; import isUndefined from 'lodash/isUndefined'; import isNil from 'lodash/isNil'; import { shallowEqual, useClassNames, mergeRefs, useCustom } from '../utils'; import { DropdownMenuItem } from '../Picker'; import AngleLeftIcon from '@rsuite/icons/legacy/AngleLeft'; import AngleRightIcon from '@rsuite/icons/legacy/AngleRight'; import getPosition from 'dom-lib/getPosition'; import scrollTop from 'dom-lib/scrollTop'; var emptyArray = []; var DropdownMenu = /*#__PURE__*/React.forwardRef(function (props, ref) { var _props$as = props.as, Component = _props$as === void 0 ? 'div' : _props$as, activeItemValue = props.activeItemValue, classPrefix = props.classPrefix, className = props.className, _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 ? 120 : _props$menuWidth, _props$menuHeight = props.menuHeight, menuHeight = _props$menuHeight === void 0 ? 200 : _props$menuHeight, _props$valueKey = props.valueKey, valueKey = _props$valueKey === void 0 ? 'value' : _props$valueKey, _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$labelKey = props.labelKey, labelKey = _props$labelKey === void 0 ? 'label' : _props$labelKey, renderMenu = props.renderMenu, renderMenuItem = props.renderMenuItem, onSelect = props.onSelect, rest = _objectWithoutPropertiesLoose(props, ["as", "activeItemValue", "classPrefix", "className", "childrenKey", "disabledItemValues", "menuWidth", "menuHeight", "valueKey", "cascadeData", "cascadePaths", "labelKey", "renderMenu", "renderMenuItem", "onSelect"]); var _useClassNames = useClassNames(classPrefix), merge = _useClassNames.merge, prefix = _useClassNames.prefix; var classes = merge(className, prefix('items')); var rootRef = useRef(); var rtl = useCustom('DropdownMenu'); useEffect(function () { var _rootRef$current; var columns = ((_rootRef$current = rootRef.current) === null || _rootRef$current === void 0 ? void 0 : _rootRef$current.querySelectorAll('[data-type="column"]')) || []; columns.forEach(function (column) { if (!column) { return; } var activeItem = column.querySelector("." + prefix('item-focus')); if (!activeItem) { activeItem = column.querySelector("." + prefix('item-active')); } if (activeItem) { var position = getPosition(activeItem, column); // Let the active option scroll into view. scrollTop(column, position === null || position === void 0 ? void 0 : position.top); } }); }, [prefix]); 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 = function handleSelect(layer, node, event) { var isLeafNode = isNil(node[childrenKey]); var cascadePaths = getCascadePaths(layer + 1, node); onSelect === null || onSelect === void 0 ? void 0 : onSelect(node, cascadePaths, isLeafNode, event); }; var renderCascadeNode = function renderCascadeNode(node, index, layer, focus) { var children = node[childrenKey]; var value = node[valueKey]; var label = node[labelKey]; var disabled = disabledItemValues.some(function (disabledValue) { return shallowEqual(disabledValue, value); }); // 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 ? AngleRightIcon : AngleLeftIcon; return /*#__PURE__*/React.createElement(DropdownMenuItem, { classPrefix: "picker-cascader-menu-item", as: 'li', role: "treeitem", key: layer + "-" + onlyKey, disabled: disabled, active: !isUndefined(activeItemValue) && shallowEqual(activeItemValue, value), focus: focus, value: value, "aria-owns": node.children ? 'treeitem-' + value + '-children' : undefined, className: children ? prefix('has-children') : undefined, onSelect: function onSelect(_value, event) { return handleSelect(layer, node, event); } }, renderMenuItem ? renderMenuItem(label, node) : label, children ? /*#__PURE__*/React.createElement(Icon, { className: prefix('caret'), spin: node.loading }) : null); }; var styles = { width: cascadeData.length * menuWidth }; var cascadeNodes = cascadeData.map(function (children, layer) { var onlyKey = layer + "_" + children.length; var parentNode = cascadePaths[layer - 1]; var menu = /*#__PURE__*/React.createElement("ul", { role: layer === 0 ? 'none presentation' : 'group', id: parentNode ? 'treeitem-' + parentNode[valueKey] + '-children' : undefined }, children.map(function (item, index) { return renderCascadeNode(item, index, layer, cascadePaths[layer] && shallowEqual(cascadePaths[layer][valueKey], item[valueKey])); })); return /*#__PURE__*/React.createElement("div", { key: onlyKey, className: prefix('column'), "data-layer": layer, "data-type": 'column', style: { height: menuHeight, width: menuWidth } }, renderMenu ? renderMenu(children, menu, parentNode, layer) : menu); }); return /*#__PURE__*/React.createElement(Component, _extends({ role: "tree" }, rest, { ref: mergeRefs(rootRef, ref), className: classes }), /*#__PURE__*/React.createElement("div", { style: styles }, cascadeNodes)); }); export var dropdownMenuPropTypes = { classPrefix: PropTypes.string, disabledItemValues: PropTypes.array, activeItemValue: PropTypes.any, childrenKey: PropTypes.string, valueKey: PropTypes.string, labelKey: PropTypes.string, menuWidth: PropTypes.number, menuHeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), className: PropTypes.string, renderMenuItem: PropTypes.func, renderMenu: PropTypes.func, onSelect: PropTypes.func, cascadeData: PropTypes.array, cascadePaths: PropTypes.array }; DropdownMenu.displayName = 'DropdownMenu'; DropdownMenu.propTypes = dropdownMenuPropTypes; export default DropdownMenu;