rsuite
Version:
A suite of react components
360 lines (313 loc) • 15 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
exports.__esModule = true;
exports.default = void 0;
var _taggedTemplateLiteralLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/taggedTemplateLiteralLoose"));
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 _pick = _interopRequireDefault(require("lodash/pick"));
var _isUndefined = _interopRequireDefault(require("lodash/isUndefined"));
var _isNil = _interopRequireDefault(require("lodash/isNil"));
var _isFunction = _interopRequireDefault(require("lodash/isFunction"));
var _omit = _interopRequireDefault(require("lodash/omit"));
var _utils = require("../utils");
var _Picker = require("../Picker");
var _templateObject;
var emptyArray = [];
var SelectPicker = /*#__PURE__*/_react.default.forwardRef(function (props, ref) {
var _props$as = props.as,
Component = _props$as === void 0 ? 'div' : _props$as,
_props$appearance = props.appearance,
appearance = _props$appearance === void 0 ? 'default' : _props$appearance,
_props$data = props.data,
data = _props$data === void 0 ? emptyArray : _props$data,
_props$valueKey = props.valueKey,
valueKey = _props$valueKey === void 0 ? 'value' : _props$valueKey,
_props$labelKey = props.labelKey,
labelKey = _props$labelKey === void 0 ? 'label' : _props$labelKey,
valueProp = props.value,
_props$classPrefix = props.classPrefix,
classPrefix = _props$classPrefix === void 0 ? 'picker' : _props$classPrefix,
placeholder = props.placeholder,
defaultValue = props.defaultValue,
disabled = props.disabled,
_props$cleanable = props.cleanable,
cleanable = _props$cleanable === void 0 ? true : _props$cleanable,
_props$placement = props.placement,
placement = _props$placement === void 0 ? 'bottomStart' : _props$placement,
menuClassName = props.menuClassName,
_props$menuAutoWidth = props.menuAutoWidth,
menuAutoWidth = _props$menuAutoWidth === void 0 ? true : _props$menuAutoWidth,
_props$menuMaxHeight = props.menuMaxHeight,
menuMaxHeight = _props$menuMaxHeight === void 0 ? 320 : _props$menuMaxHeight,
menuStyle = props.menuStyle,
groupBy = props.groupBy,
overrideLocale = props.locale,
toggleAs = props.toggleAs,
style = props.style,
_props$searchable = props.searchable,
searchable = _props$searchable === void 0 ? true : _props$searchable,
_props$disabledItemVa = props.disabledItemValues,
disabledItemValues = _props$disabledItemVa === void 0 ? emptyArray : _props$disabledItemVa,
virtualized = props.virtualized,
listProps = props.listProps,
id = props.id,
onGroupTitleClick = props.onGroupTitleClick,
searchBy = props.searchBy,
onEntered = props.onEntered,
onExited = props.onExited,
onClean = props.onClean,
onChange = props.onChange,
onSelect = props.onSelect,
onSearch = props.onSearch,
onClose = props.onClose,
onOpen = props.onOpen,
sort = props.sort,
renderValue = props.renderValue,
renderMenu = props.renderMenu,
renderMenuGroup = props.renderMenuGroup,
renderMenuItem = props.renderMenuItem,
renderExtraFooter = props.renderExtraFooter,
rest = (0, _objectWithoutPropertiesLoose2.default)(props, ["as", "appearance", "data", "valueKey", "labelKey", "value", "classPrefix", "placeholder", "defaultValue", "disabled", "cleanable", "placement", "menuClassName", "menuAutoWidth", "menuMaxHeight", "menuStyle", "groupBy", "locale", "toggleAs", "style", "searchable", "disabledItemValues", "virtualized", "listProps", "id", "onGroupTitleClick", "searchBy", "onEntered", "onExited", "onClean", "onChange", "onSelect", "onSearch", "onClose", "onOpen", "sort", "renderValue", "renderMenu", "renderMenuGroup", "renderMenuItem", "renderExtraFooter"]);
var triggerRef = (0, _react.useRef)(null);
var targetRef = (0, _react.useRef)(null);
var overlayRef = (0, _react.useRef)(null);
var searchInputRef = (0, _react.useRef)(null);
var _useCustom = (0, _utils.useCustom)('Picker', overrideLocale),
locale = _useCustom.locale;
var _ref = (0, _utils.useControlled)(valueProp, defaultValue),
value = _ref[0],
setValue = _ref[1]; // Used to hover the focus item when trigger `onKeydown`
var _useFocusItemValue = (0, _Picker.useFocusItemValue)(value, {
data: data,
valueKey: valueKey,
target: function target() {
return overlayRef.current;
}
}),
focusItemValue = _useFocusItemValue.focusItemValue,
setFocusItemValue = _useFocusItemValue.setFocusItemValue,
onFocusItem = _useFocusItemValue.onKeyDown; // Use search keywords to filter options.
var _useSearch = (0, _Picker.useSearch)({
labelKey: labelKey,
data: data,
searchBy: searchBy,
callback: function callback(searchKeyword, filteredData, event) {
var _filteredData$;
// The first option after filtering is the focus.
setFocusItemValue(filteredData === null || filteredData === void 0 ? void 0 : (_filteredData$ = filteredData[0]) === null || _filteredData$ === void 0 ? void 0 : _filteredData$[valueKey]);
onSearch === null || onSearch === void 0 ? void 0 : onSearch(searchKeyword, event);
}
}),
searchKeyword = _useSearch.searchKeyword,
filteredData = _useSearch.filteredData,
updateFilteredData = _useSearch.updateFilteredData,
setSearchKeyword = _useSearch.setSearchKeyword,
handleSearch = _useSearch.handleSearch;
(0, _react.useEffect)(function () {
updateFilteredData(data);
}, [data, updateFilteredData]); // Use component active state to support keyboard events.
var _useState = (0, _react.useState)(false),
active = _useState[0],
setActive = _useState[1];
var handleClose = (0, _react.useCallback)(function () {
var _triggerRef$current, _triggerRef$current$c;
(_triggerRef$current = triggerRef.current) === null || _triggerRef$current === void 0 ? void 0 : (_triggerRef$current$c = _triggerRef$current.close) === null || _triggerRef$current$c === void 0 ? void 0 : _triggerRef$current$c.call(_triggerRef$current);
}, []);
var handleSelect = (0, _react.useCallback)(function (value, item, event) {
var _targetRef$current;
onSelect === null || onSelect === void 0 ? void 0 : onSelect(value, item, event);
(_targetRef$current = targetRef.current) === null || _targetRef$current === void 0 ? void 0 : _targetRef$current.focus();
}, [onSelect]);
var handleChangeValue = (0, _react.useCallback)(function (value, event) {
onChange === null || onChange === void 0 ? void 0 : onChange(value, event);
}, [onChange]);
var handleMenuPressEnter = (0, _react.useCallback)(function (event) {
if (!focusItemValue) {
return;
} // Find active `MenuItem` by `value`
var focusItem = data.find(function (item) {
return (0, _utils.shallowEqual)(item[valueKey], focusItemValue);
});
setValue(focusItemValue);
handleSelect(focusItemValue, focusItem, event);
handleChangeValue(focusItemValue, event);
handleClose();
}, [data, focusItemValue, handleChangeValue, handleClose, handleSelect, setValue, valueKey]);
var handleItemSelect = (0, _react.useCallback)(function (value, item, event) {
setValue(value);
setFocusItemValue(value);
handleSelect(value, item, event);
handleChangeValue(value, event);
handleClose();
}, [setValue, setFocusItemValue, handleSelect, handleChangeValue, handleClose]);
var handleClean = (0, _react.useCallback)(function (event) {
if (disabled || !cleanable) {
return;
}
setValue(null);
setFocusItemValue(value);
handleChangeValue(null, event);
}, [value, disabled, cleanable, setValue, handleChangeValue, setFocusItemValue]);
var onPickerKeyDown = (0, _Picker.useToggleKeyDownEvent)((0, _extends2.default)({
toggle: !focusItemValue || !active,
triggerRef: triggerRef,
targetRef: targetRef,
overlayRef: overlayRef,
searchInputRef: searchInputRef,
active: active,
onExit: handleClean,
onMenuKeyDown: onFocusItem,
onMenuPressEnter: handleMenuPressEnter,
onClose: function onClose() {
setFocusItemValue(null);
}
}, rest));
var handleExited = (0, _react.useCallback)(function () {
setSearchKeyword('');
setActive(false);
onSearch === null || onSearch === void 0 ? void 0 : onSearch('');
onClose === null || onClose === void 0 ? void 0 : onClose();
}, [onClose, setSearchKeyword, onSearch]);
var handleEntered = (0, _react.useCallback)(function () {
setActive(true);
setFocusItemValue(value);
onOpen === null || onOpen === void 0 ? void 0 : onOpen();
}, [onOpen, setFocusItemValue, value]);
(0, _Picker.usePublicMethods)(ref, {
triggerRef: triggerRef,
overlayRef: overlayRef,
targetRef: targetRef
}); // Find active `MenuItem` by `value`
var activeItem = data.find(function (item) {
return (0, _utils.shallowEqual)(item[valueKey], value);
});
/**
* 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 = !!activeItem || !(0, _isNil.default)(value) && (0, _isFunction.default)(renderValue);
var _useClassNames = (0, _utils.useClassNames)(classPrefix),
prefix = _useClassNames.prefix,
merge = _useClassNames.merge;
var selectedElement = placeholder;
if (activeItem !== null && activeItem !== void 0 && activeItem[labelKey]) {
selectedElement = activeItem[labelKey];
}
if (!(0, _isNil.default)(value) && (0, _isFunction.default)(renderValue)) {
selectedElement = renderValue(value, activeItem, selectedElement); // If renderValue returns null or undefined, hasValue is false.
if ((0, _isNil.default)(selectedElement)) {
hasValue = false;
}
}
var renderDropdownMenu = function renderDropdownMenu(positionProps, speakerRef) {
var left = positionProps.left,
top = positionProps.top,
className = positionProps.className;
var classes = merge(className, menuClassName, prefix('select-menu'));
var styles = (0, _extends2.default)({}, menuStyle, {
left: left,
top: top
});
var items = filteredData; // Create a tree structure data when set `groupBy`
if (groupBy) {
items = (0, _utils.getDataGroupBy)(items, groupBy, sort);
} else if (typeof sort === 'function') {
items = items.sort(sort(false));
}
var menu = items.length ? /*#__PURE__*/_react.default.createElement(_Picker.DropdownMenu, {
id: id ? id + "-listbox" : undefined,
listProps: listProps,
disabledItemValues: disabledItemValues,
valueKey: valueKey,
labelKey: labelKey,
renderMenuGroup: renderMenuGroup,
renderMenuItem: renderMenuItem,
maxHeight: menuMaxHeight,
classPrefix: 'picker-select-menu',
dropdownMenuItemClassPrefix: 'picker-select-menu-item',
dropdownMenuItemAs: _Picker.DropdownMenuItem,
activeItemValues: [value],
focusItemValue: focusItemValue,
data: items,
group: !(0, _isUndefined.default)(groupBy),
onSelect: handleItemSelect,
onGroupTitleClick: onGroupTitleClick,
virtualized: virtualized
}) : /*#__PURE__*/_react.default.createElement("div", {
className: prefix(_templateObject || (_templateObject = (0, _taggedTemplateLiteralLoose2.default)(["none"])))
}, locale === null || locale === void 0 ? void 0 : locale.noResultsText);
return /*#__PURE__*/_react.default.createElement(_Picker.PickerOverlay, {
ref: (0, _utils.mergeRefs)(overlayRef, speakerRef),
autoWidth: menuAutoWidth,
className: classes,
style: styles,
onKeyDown: onPickerKeyDown,
target: triggerRef
}, searchable && /*#__PURE__*/_react.default.createElement(_Picker.SearchBar, {
placeholder: locale === null || locale === void 0 ? void 0 : locale.searchPlaceholder,
onChange: handleSearch,
value: searchKeyword,
inputRef: searchInputRef
}), renderMenu ? renderMenu(menu) : menu, renderExtraFooter === null || renderExtraFooter === void 0 ? void 0 : renderExtraFooter());
};
var _usePickerClassName = (0, _Picker.usePickerClassName)((0, _extends2.default)({}, props, {
classPrefix: classPrefix,
appearance: appearance,
hasValue: hasValue,
name: 'select',
cleanable: cleanable
})),
classes = _usePickerClassName[0],
usedClassNamePropKeys = _usePickerClassName[1];
return /*#__PURE__*/_react.default.createElement(_Picker.PickerToggleTrigger, {
pickerProps: (0, _pick.default)(props, _Picker.pickTriggerPropKeys),
ref: triggerRef,
placement: placement,
onEntered: (0, _utils.createChainedFunction)(handleEntered, onEntered),
onExited: (0, _utils.createChainedFunction)(handleExited, onExited),
speaker: renderDropdownMenu
}, /*#__PURE__*/_react.default.createElement(Component, {
className: classes,
style: style
}, /*#__PURE__*/_react.default.createElement(_Picker.PickerToggle, (0, _extends2.default)({}, (0, _omit.default)(rest, [].concat(_Picker.omitTriggerPropKeys, usedClassNamePropKeys)), {
id: id,
ref: targetRef,
appearance: appearance,
onClean: (0, _utils.createChainedFunction)(handleClean, onClean),
onKeyDown: onPickerKeyDown,
as: toggleAs,
disabled: disabled,
cleanable: cleanable && !disabled,
hasValue: hasValue,
inputValue: value !== null && value !== void 0 ? value : '',
active: active,
placement: placement
}), selectedElement || (locale === null || locale === void 0 ? void 0 : locale.placeholder))));
});
SelectPicker.displayName = 'SelectPicker';
SelectPicker.propTypes = (0, _extends2.default)({}, _Picker.listPickerPropTypes, {
locale: _propTypes.default.any,
appearance: _propTypes.default.oneOf(['default', 'subtle']),
menuAutoWidth: _propTypes.default.bool,
menuMaxHeight: _propTypes.default.number,
renderMenu: _propTypes.default.func,
renderMenuItem: _propTypes.default.func,
renderMenuGroup: _propTypes.default.func,
onSelect: _propTypes.default.func,
onGroupTitleClick: _propTypes.default.func,
onSearch: _propTypes.default.func,
/**
* group by key in `data`
*/
groupBy: _propTypes.default.any,
sort: _propTypes.default.func,
searchable: _propTypes.default.bool,
virtualized: _propTypes.default.bool,
searchBy: _propTypes.default.func
});
var _default = SelectPicker;
exports.default = _default;