UNPKG

rsuite

Version:

A suite of react components

446 lines (433 loc) 20.9 kB
'use client'; "use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose")); var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _omit = _interopRequireDefault(require("lodash/omit")); var _pick = _interopRequireDefault(require("lodash/pick")); var _isNil = _interopRequireDefault(require("lodash/isNil")); var _isFunction = _interopRequireDefault(require("lodash/isFunction")); var _TreeView = _interopRequireDefault(require("../CascadeTree/TreeView")); var _SearchView = _interopRequireDefault(require("../CascadeTree/SearchView")); var _hooks = require("../CascadeTree/hooks"); var _utils = require("../Tree/utils"); var _utils2 = require("../internals/Tree/utils"); var _propTypes2 = require("../internals/propTypes"); var _hooks2 = require("../internals/hooks"); var _utils3 = require("../internals/utils"); var _Picker = require("../internals/Picker"); var _CustomProvider = require("../CustomProvider"); var _useActive2 = _interopRequireDefault(require("./useActive")); var _excluded = ["as", "data", "classPrefix", "childrenKey", "valueKey", "labelKey", "defaultValue", "placeholder", "disabled", "disabledItemValues", "appearance", "cleanable", "locale", "toggleAs", "style", "value", "popupClassName", "popupStyle", "columnHeight", "columnWidth", "searchable", "parentSelectable", "placement", "id", "renderColumn", "renderTreeNode", "renderSearchItem", "renderValue", "renderExtraFooter", "onEntered", "onExited", "onClean", "onChange", "onSelect", "onSearch", "getChildren", "menuClassName", "menuStyle", "menuWidth", "menuHeight", "renderMenuItem", "renderMenu"]; function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } var emptyArray = []; /** * The `Cascader` component displays a hierarchical list of options. * @see https://rsuitejs.com/components/cascader */ var Cascader = /*#__PURE__*/_react.default.forwardRef(function (props, ref) { var _useCustom = (0, _CustomProvider.useCustom)('Cascader', props), rtl = _useCustom.rtl, propsWithDefaults = _useCustom.propsWithDefaults; var _propsWithDefaults$as = propsWithDefaults.as, Component = _propsWithDefaults$as === void 0 ? 'div' : _propsWithDefaults$as, _propsWithDefaults$da = propsWithDefaults.data, data = _propsWithDefaults$da === void 0 ? emptyArray : _propsWithDefaults$da, _propsWithDefaults$cl = propsWithDefaults.classPrefix, classPrefix = _propsWithDefaults$cl === void 0 ? 'picker' : _propsWithDefaults$cl, _propsWithDefaults$ch = propsWithDefaults.childrenKey, childrenKey = _propsWithDefaults$ch === void 0 ? 'children' : _propsWithDefaults$ch, _propsWithDefaults$va = propsWithDefaults.valueKey, valueKey = _propsWithDefaults$va === void 0 ? 'value' : _propsWithDefaults$va, _propsWithDefaults$la = propsWithDefaults.labelKey, labelKey = _propsWithDefaults$la === void 0 ? 'label' : _propsWithDefaults$la, defaultValue = propsWithDefaults.defaultValue, placeholder = propsWithDefaults.placeholder, disabled = propsWithDefaults.disabled, _propsWithDefaults$di = propsWithDefaults.disabledItemValues, disabledItemValues = _propsWithDefaults$di === void 0 ? emptyArray : _propsWithDefaults$di, _propsWithDefaults$ap = propsWithDefaults.appearance, appearance = _propsWithDefaults$ap === void 0 ? 'default' : _propsWithDefaults$ap, _propsWithDefaults$cl2 = propsWithDefaults.cleanable, cleanable = _propsWithDefaults$cl2 === void 0 ? true : _propsWithDefaults$cl2, locale = propsWithDefaults.locale, toggleAs = propsWithDefaults.toggleAs, style = propsWithDefaults.style, valueProp = propsWithDefaults.value, popupClassName = propsWithDefaults.popupClassName, popupStyle = propsWithDefaults.popupStyle, columnHeight = propsWithDefaults.columnHeight, columnWidth = propsWithDefaults.columnWidth, _propsWithDefaults$se = propsWithDefaults.searchable, searchable = _propsWithDefaults$se === void 0 ? true : _propsWithDefaults$se, parentSelectable = propsWithDefaults.parentSelectable, _propsWithDefaults$pl = propsWithDefaults.placement, placement = _propsWithDefaults$pl === void 0 ? 'bottomStart' : _propsWithDefaults$pl, id = propsWithDefaults.id, renderColumn = propsWithDefaults.renderColumn, renderTreeNode = propsWithDefaults.renderTreeNode, renderSearchItem = propsWithDefaults.renderSearchItem, renderValue = propsWithDefaults.renderValue, renderExtraFooter = propsWithDefaults.renderExtraFooter, onEntered = propsWithDefaults.onEntered, onExited = propsWithDefaults.onExited, onClean = propsWithDefaults.onClean, onChange = propsWithDefaults.onChange, onSelect = propsWithDefaults.onSelect, onSearch = propsWithDefaults.onSearch, getChildren = propsWithDefaults.getChildren, DEPRECATED_menuClassName = propsWithDefaults.menuClassName, DEPRECATED_menuStyle = propsWithDefaults.menuStyle, DEPRECATED_menuWidth = propsWithDefaults.menuWidth, DEPRECATED_menuHeight = propsWithDefaults.menuHeight, DEPRECATED_renderMenuItem = propsWithDefaults.renderMenuItem, DEPRECATED_renderMenu = propsWithDefaults.renderMenu, rest = (0, _objectWithoutPropertiesLoose2.default)(propsWithDefaults, _excluded); var _usePickerRef = (0, _Picker.usePickerRef)(ref), trigger = _usePickerRef.trigger, root = _usePickerRef.root, target = _usePickerRef.target, overlay = _usePickerRef.overlay, searchInput = _usePickerRef.searchInput; var _ref = (0, _hooks2.useControlled)(valueProp, defaultValue), value = _ref[0], setValue = _ref[1]; // Store the children of each node var childrenMap = (0, _hooks2.useMap)(); // Store the parent of each node var parentMap = (0, _react.useMemo)(function () { return (0, _utils2.getParentMap)(data, function (item) { var _childrenMap$get; return (_childrenMap$get = childrenMap.get(item)) !== null && _childrenMap$get !== void 0 ? _childrenMap$get : item[childrenKey]; }); }, [childrenMap, childrenKey, data]); // Flatten the tree data var flattenedData = (0, _react.useMemo)(function () { return (0, _utils.flattenTree)(data, function (item) { var _childrenMap$get2; return (_childrenMap$get2 = childrenMap.get(item)) !== null && _childrenMap$get2 !== void 0 ? _childrenMap$get2 : item[childrenKey]; }); }, [childrenMap, childrenKey, data]); // The selected item var selectedItem = flattenedData.find(function (item) { return item[valueKey] === value; }); // Callback function after selecting the node var onSelectCallback = function onSelectCallback(node, event) { var _trigger$current; var isLeafNode = node.isLeafNode, cascadePaths = node.cascadePaths, itemData = node.itemData; onSelect === null || onSelect === void 0 || onSelect(itemData, cascadePaths, event); var nextValue = itemData[valueKey]; if (isLeafNode) { // Determines whether the option is a leaf node, and if so, closes the picker. handleClose(); setValue(nextValue); return; } // When the parent is optional, the value and the displayed path are updated. if (parentSelectable && !(0, _utils3.shallowEqual)(value, nextValue)) { setValue(nextValue); onChange === null || onChange === void 0 || onChange(nextValue, event); } // Update menu position (_trigger$current = trigger.current) === null || _trigger$current === void 0 || _trigger$current.updatePosition(); }; var _useSelect = (0, _hooks.useSelect)({ value: value, valueKey: valueKey, childrenKey: childrenKey, childrenMap: childrenMap, selectedItem: selectedItem, getChildren: getChildren, onChange: onChange, onSelect: onSelectCallback }), activeItem = _useSelect.activeItem, setActiveItem = _useSelect.setActiveItem, loadingItemsSet = _useSelect.loadingItemsSet, handleSelect = _useSelect.handleSelect; var _usePaths = (0, _hooks.usePaths)({ data: data, activeItem: activeItem, selectedItem: selectedItem, getParent: function getParent(item) { return parentMap.get(item); }, getChildren: function getChildren(item) { var _childrenMap$get3; return (_childrenMap$get3 = childrenMap.get(item)) !== null && _childrenMap$get3 !== void 0 ? _childrenMap$get3 : item[childrenKey]; } }), columns = _usePaths.columns, pathTowardsActiveItem = _usePaths.pathTowardsActiveItem, pathTowardsSelectedItem = _usePaths.pathTowardsSelectedItem; /** * 1.Have a value and the value is valid. * 2.Regardless of whether the value is valid, as long as renderValue is set, it is judged to have a value. */ var hasValue = pathTowardsSelectedItem.length > 0 || !(0, _isNil.default)(value) && (0, _isFunction.default)(renderValue); var _useClassNames = (0, _hooks2.useClassNames)(classPrefix), prefix = _useClassNames.prefix, merge = _useClassNames.merge; var onFocusItemCallback = (0, _react.useCallback)(function (value) { setActiveItem(flattenedData.find(function (item) { return item[valueKey] === value; })); }, [flattenedData, setActiveItem, valueKey]); // Used to hover the focuse item when trigger `onKeydown` var _useFocusItemValue = (0, _Picker.useFocusItemValue)(value, { rtl: rtl, data: flattenedData, valueKey: valueKey, defaultLayer: pathTowardsSelectedItem !== null && pathTowardsSelectedItem !== void 0 && pathTowardsSelectedItem.length ? pathTowardsSelectedItem.length - 1 : 0, target: function target() { return overlay.current; }, getParent: function getParent(item) { return parentMap.get(item); }, callback: onFocusItemCallback }), focusItemValue = _useFocusItemValue.focusItemValue, setFocusItemValue = _useFocusItemValue.setFocusItemValue, setLayer = _useFocusItemValue.setLayer, setKeys = _useFocusItemValue.setKeys, onFocusItem = _useFocusItemValue.onKeyDown; var onSearchCallback = function onSearchCallback(value, items, event) { onSearch === null || onSearch === void 0 || onSearch(value, event); if (!value || items.length === 0) { setFocusItemValue(undefined); return; } if (items.length > 0) { setFocusItemValue(items[0][valueKey]); setLayer(0); setKeys([]); } }; var _useSearch = (0, _hooks.useSearch)({ labelKey: labelKey, childrenKey: childrenKey, parentMap: parentMap, flattenedData: flattenedData, parentSelectable: parentSelectable, onSearch: onSearchCallback }), items = _useSearch.items, searchKeyword = _useSearch.searchKeyword, setSearchKeyword = _useSearch.setSearchKeyword, handleSearch = _useSearch.handleSearch; var _useActive = (0, _useActive2.default)({ onEntered: onEntered, onExited: onExited, target: target, setSearchKeyword: setSearchKeyword }), active = _useActive.active, handleEntered = _useActive.handleEntered, handleExited = _useActive.handleExited; var handleClose = (0, _hooks2.useEventCallback)(function () { var _trigger$current2, _target$current, _target$current$focus; (_trigger$current2 = trigger.current) === null || _trigger$current2 === void 0 || _trigger$current2.close(); // The focus is on the trigger button after closing (_target$current = target.current) === null || _target$current === void 0 || (_target$current$focus = _target$current.focus) === null || _target$current$focus === void 0 || _target$current$focus.call(_target$current); }); var handleClean = (0, _hooks2.useEventCallback)(function (event) { if (disabled || !target.current) { return; } setValue(null); onChange === null || onChange === void 0 || onChange(null, event); }); var handleMenuPressEnter = (0, _hooks2.useEventCallback)(function (event) { var focusItem = (0, _utils2.findNodeOfTree)(data, function (item) { return item[valueKey] === focusItemValue; }); var isLeafNode = focusItem && !focusItem[childrenKey]; if (isLeafNode) { setValue(focusItemValue); if (pathTowardsActiveItem.length) { setLayer(pathTowardsActiveItem.length - 1); } if (!(0, _utils3.shallowEqual)(value, focusItemValue)) { onSelect === null || onSelect === void 0 || onSelect(focusItem, pathTowardsActiveItem, event); onChange === null || onChange === void 0 || onChange(focusItemValue !== null && focusItemValue !== void 0 ? focusItemValue : null, event); } handleClose(); } }); var onPickerKeyDown = (0, _Picker.useToggleKeyDownEvent)((0, _extends2.default)({ toggle: !focusItemValue || !active, trigger: trigger, target: target, overlay: overlay, searchInput: searchInput, active: active, onExit: handleClean, onMenuKeyDown: onFocusItem, onMenuPressEnter: handleMenuPressEnter }, rest)); /** * The search structure option is processed after being selected. */ var handleSearchRowSelect = (0, _hooks2.useEventCallback)(function (itemData, nodes, event) { var nextValue = itemData[valueKey]; handleClose(); setSearchKeyword(''); setValue(nextValue); onSelect === null || onSelect === void 0 || onSelect(itemData, nodes, event); onChange === null || onChange === void 0 || onChange(nextValue, event); }); var renderCascadeColumn = function renderCascadeColumn(childNodes, column) { var items = column.items, parentItem = column.parentItem, layer = column.layer; if (typeof renderColumn === 'function') { return renderColumn(childNodes, column); } else if (typeof DEPRECATED_renderMenu === 'function') { return DEPRECATED_renderMenu(items, childNodes, parentItem, layer); } return childNodes; }; var renderCascadeTreeNode = function renderCascadeTreeNode(node, itemData) { var render = typeof renderTreeNode === 'function' ? renderTreeNode : DEPRECATED_renderMenuItem; if (typeof render === 'function') { return render(node, itemData); } return node; }; var renderTreeView = function renderTreeView(positionProps, speakerRef) { var _ref2 = positionProps || {}, left = _ref2.left, top = _ref2.top, className = _ref2.className; var styles = (0, _extends2.default)({}, DEPRECATED_menuStyle, popupStyle, { left: left, top: top }); var classes = merge(className, DEPRECATED_menuClassName, popupClassName, prefix('popup-cascader')); return /*#__PURE__*/_react.default.createElement(_Picker.PickerPopup, { ref: (0, _utils3.mergeRefs)(overlay, speakerRef), className: classes, style: styles, target: trigger, onKeyDown: onPickerKeyDown }, searchable && /*#__PURE__*/_react.default.createElement(_SearchView.default, { data: items, searchKeyword: searchKeyword, valueKey: valueKey, labelKey: labelKey, locale: locale, parentMap: parentMap, disabledItemValues: disabledItemValues, focusItemValue: focusItemValue, inputRef: searchInput, renderSearchItem: renderSearchItem, onSelect: handleSearchRowSelect, onSearch: handleSearch }), searchKeyword === '' && /*#__PURE__*/_react.default.createElement(_TreeView.default, { columnWidth: columnWidth !== null && columnWidth !== void 0 ? columnWidth : DEPRECATED_menuWidth, columnHeight: columnHeight !== null && columnHeight !== void 0 ? columnHeight : DEPRECATED_menuHeight, disabledItemValues: disabledItemValues, loadingItemsSet: loadingItemsSet, valueKey: valueKey, labelKey: labelKey, childrenKey: childrenKey, classPrefix: 'cascade-tree', data: columns, cascadePaths: pathTowardsActiveItem, activeItemValue: value, onSelect: handleSelect, renderColumn: renderCascadeColumn, renderTreeNode: renderCascadeTreeNode }), renderExtraFooter === null || renderExtraFooter === void 0 ? void 0 : renderExtraFooter()); }; var selectedElement = placeholder; if (pathTowardsSelectedItem.length > 0) { selectedElement = []; pathTowardsSelectedItem.forEach(function (item, index) { var key = item[valueKey] || item[labelKey]; selectedElement.push(/*#__PURE__*/_react.default.createElement("span", { key: key }, item[labelKey])); if (index < pathTowardsSelectedItem.length - 1) { selectedElement.push(/*#__PURE__*/_react.default.createElement("span", { className: "separator", key: key + "-separator" }, ' / ')); } }); } if (!(0, _isNil.default)(value) && (0, _isFunction.default)(renderValue)) { selectedElement = renderValue(value, pathTowardsSelectedItem, selectedElement); // If renderValue returns null or undefined, hasValue is false. if ((0, _isNil.default)(selectedElement)) { hasValue = false; } } var _usePickerClassName = (0, _Picker.usePickerClassName)((0, _extends2.default)({}, props, { classPrefix: classPrefix, hasValue: hasValue, name: 'cascader', appearance: appearance, cleanable: cleanable })), classes = _usePickerClassName[0], usedClassNamePropKeys = _usePickerClassName[1]; return /*#__PURE__*/_react.default.createElement(_Picker.PickerToggleTrigger, { id: id, popupType: "tree", pickerProps: (0, _pick.default)(props, _Picker.pickTriggerPropKeys), ref: trigger, placement: placement, onEntered: handleEntered, onExited: handleExited, speaker: renderTreeView }, /*#__PURE__*/_react.default.createElement(Component, { className: classes, style: style, ref: root }, /*#__PURE__*/_react.default.createElement(_Picker.PickerToggle, (0, _extends2.default)({}, (0, _omit.default)(rest, [].concat(_Picker.omitTriggerPropKeys, usedClassNamePropKeys)), { ref: target, as: toggleAs, appearance: appearance, disabled: disabled, onClean: (0, _utils3.createChainedFunction)(handleClean, onClean), onKeyDown: onPickerKeyDown, cleanable: cleanable && !disabled, hasValue: hasValue, active: active, placement: placement, inputValue: value !== null && value !== void 0 ? value : '', focusItemValue: focusItemValue }), selectedElement || (locale === null || locale === void 0 ? void 0 : locale.placeholder)))); }); Cascader.displayName = 'Cascader'; Cascader.propTypes = (0, _extends2.default)({}, _Picker.listPickerPropTypes, { disabledItemValues: _propTypes.default.array, locale: _propTypes.default.any, appearance: (0, _propTypes2.oneOf)(['default', 'subtle']), onSelect: _propTypes.default.func, onSearch: _propTypes.default.func, cleanable: _propTypes.default.bool, renderColumn: _propTypes.default.func, renderTreeNode: _propTypes.default.func, renderSearchItem: _propTypes.default.func, columnWidth: _propTypes.default.number, columnHeight: _propTypes.default.number, searchable: _propTypes.default.bool, parentSelectable: _propTypes.default.bool, inline: (0, _propTypes2.deprecatePropTypeNew)(_propTypes.default.bool, 'Use `<CascadeTree>` instead.'), renderMenu: (0, _propTypes2.deprecatePropTypeNew)(_propTypes.default.func, 'Use "renderColumn" property instead.'), renderMenuItem: (0, _propTypes2.deprecatePropTypeNew)(_propTypes.default.func, 'Use "renderTreeNode" property instead.'), menuWidth: (0, _propTypes2.deprecatePropTypeNew)(_propTypes.default.number, 'Use "columnWidth" property instead.'), menuHeight: (0, _propTypes2.deprecatePropTypeNew)(_propTypes.default.number, 'Use "columnHeight" property instead.') }); var _default = exports.default = Cascader;