rsuite
Version:
A suite of react components
605 lines (499 loc) • 18.9 kB
JavaScript
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.default = void 0;
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inheritsLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/inheritsLoose"));
var React = _interopRequireWildcard(require("react"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _classnames = _interopRequireDefault(require("classnames"));
var _compose = _interopRequireDefault(require("recompose/compose"));
var _lodash = _interopRequireDefault(require("lodash"));
var _utils = require("rsuite-utils/lib/utils");
var _utils2 = require("../utils");
var _IntlProvider = _interopRequireDefault(require("../IntlProvider"));
var _FormattedMessage = _interopRequireDefault(require("../IntlProvider/FormattedMessage"));
var _Picker = require("../Picker");
var _constants = require("../constants");
var CheckPicker =
/*#__PURE__*/
function (_React$Component) {
(0, _inheritsLoose2.default)(CheckPicker, _React$Component);
function CheckPicker(props) {
var _this;
_this = _React$Component.call(this, props) || this;
_this.positionRef = void 0;
_this.menuContainerRef = void 0;
_this.toggleRef = void 0;
_this.triggerRef = void 0;
_this.getFocusableMenuItems = function () {
var labelKey = _this.props.labelKey;
var menuItems = _this.menuContainerRef.current.menuItems;
if (!menuItems) {
return [];
}
var items = Object.values(menuItems).map(function (item) {
return item.props.getItemData();
});
return (0, _utils.filterNodesOfTree)(items, function (item) {
return _this.shouldDisplay(item[labelKey]);
});
};
_this.setStickyItems = function () {
var _this$props = _this.props,
sticky = _this$props.sticky,
data = _this$props.data,
valueKey = _this$props.valueKey;
var value = _this.getValue();
if (!sticky) {
return;
}
var stickyItems = [];
if (data && value.length) {
stickyItems = data.filter(function (item) {
return value.some(function (v) {
return v === item[valueKey];
});
});
}
_this.setState({
stickyItems: stickyItems
});
};
_this.focusNextMenuItem = function () {
var valueKey = _this.props.valueKey;
_this.findNode(function (items, index) {
var focusItem = items[index + 1];
if (!_lodash.default.isUndefined(focusItem)) {
_this.setState({
focusItemValue: focusItem[valueKey]
});
}
});
};
_this.focusPrevMenuItem = function () {
var valueKey = _this.props.valueKey;
_this.findNode(function (items, index) {
var focusItem = items[index - 1];
if (!_lodash.default.isUndefined(focusItem)) {
_this.setState({
focusItemValue: focusItem[valueKey]
});
}
});
};
_this.selectFocusMenuItem = function (event) {
var value = _this.getValue();
var _this$props2 = _this.props,
data = _this$props2.data,
valueKey = _this$props2.valueKey;
var focusItemValue = _this.state.focusItemValue;
if (!focusItemValue) {
return;
}
if (!value.some(function (v) {
return (0, _utils.shallowEqual)(v, focusItemValue);
})) {
value.push(focusItemValue);
} else {
_lodash.default.remove(value, function (itemVal) {
return (0, _utils.shallowEqual)(itemVal, focusItemValue);
});
}
var focusItem = data.find(function (item) {
return (0, _utils.shallowEqual)(_lodash.default.get(item, valueKey), focusItemValue);
});
_this.setState({
value: value
}, function () {
_this.handleSelect(value, focusItem, event);
_this.handleChangeValue(value, event);
});
};
_this.handleKeyDown = function (event) {
var _this$state = _this.state,
focusItemValue = _this$state.focusItemValue,
active = _this$state.active; // enter
if ((!focusItemValue || !active) && event.keyCode === 13) {
_this.handleToggleDropdown();
} // delete
if (event.keyCode === 8 && event.target === _lodash.default.get((0, _assertThisInitialized2.default)(_this), 'toggle.toggle')) {
_this.handleClean(event);
}
if (!_this.menuContainerRef.current) {
return;
}
(0, _Picker.onMenuKeyDown)(event, {
down: _this.focusNextMenuItem,
up: _this.focusPrevMenuItem,
enter: _this.selectFocusMenuItem,
esc: _this.handleCloseDropdown
});
};
_this.handleItemSelect = function (nextItemValue, item, event, checked) {
var value = _this.getValue();
if (checked) {
value.push(nextItemValue);
} else {
_lodash.default.remove(value, function (itemVal) {
return (0, _utils.shallowEqual)(itemVal, nextItemValue);
});
}
var nextState = {
value: value,
focusItemValue: nextItemValue
};
_this.setState(nextState, function () {
_this.handleSelect(value, item, event);
_this.handleChangeValue(value, event);
});
};
_this.handleSelect = function (nextItemValue, item, event) {
var onSelect = _this.props.onSelect;
onSelect && onSelect(nextItemValue, item, event);
};
_this.handleChangeValue = function (value, event) {
var onChange = _this.props.onChange;
onChange && onChange(value, event);
};
_this.handleSearch = function (searchKeyword, event) {
var onSearch = _this.props.onSearch;
_this.setState({
searchKeyword: searchKeyword,
focusItemValue: undefined
});
onSearch && onSearch(searchKeyword, event);
};
_this.handleCloseDropdown = function () {
var value = _this.getValue();
if (_this.triggerRef.current) {
_this.triggerRef.current.hide();
}
_this.setState({
focusItemValue: value ? value[0] : undefined
});
};
_this.handleOpenDropdown = function () {
if (_this.triggerRef.current) {
_this.triggerRef.current.show();
}
};
_this.handleToggleDropdown = function () {
var active = _this.state.active;
if (active) {
_this.handleCloseDropdown();
return;
}
_this.handleOpenDropdown();
};
_this.handleClean = function (event) {
var _this$props3 = _this.props,
disabled = _this$props3.disabled,
cleanable = _this$props3.cleanable;
if (disabled || !cleanable) {
return;
}
_this.setState({
value: []
}, function () {
_this.handleChangeValue([], event);
});
};
_this.handleExit = function () {
var onClose = _this.props.onClose;
onClose && onClose();
_this.setState({
searchKeyword: '',
focusItemValue: null,
active: false
});
};
_this.handleOpen = function () {
var onOpen = _this.props.onOpen;
onOpen && onOpen();
_this.setState({
active: true
});
};
_this.addPrefix = function (name) {
return (0, _utils2.prefix)(_this.props.classPrefix)(name);
};
_this.menuContainer = {
menuItems: null
};
_this.getPositionInstance = function () {
return _this.positionRef.current;
};
_this.getToggleInstance = function () {
return _this.toggleRef.current;
};
var _value = props.value,
defaultValue = props.defaultValue,
groupBy = props.groupBy,
_valueKey = props.valueKey,
_labelKey = props.labelKey;
var nextValue = _lodash.default.clone(_value || defaultValue) || [];
_this.state = {
value: nextValue,
// Used to hover the active item when trigger `onKeydown`
focusItemValue: nextValue ? nextValue[0] : undefined,
searchKeyword: ''
};
_this.positionRef = React.createRef();
_this.menuContainerRef = React.createRef();
_this.toggleRef = React.createRef();
_this.triggerRef = React.createRef();
if (groupBy === _valueKey || groupBy === _labelKey) {
throw Error('`groupBy` can not be equal to `valueKey` and `labelKey`');
}
return _this;
}
var _proto = CheckPicker.prototype;
_proto.getValue = function getValue() {
var value = this.props.value;
var nextValue = _lodash.default.isUndefined(value) ? this.state.value : value;
return _lodash.default.clone(nextValue) || [];
};
/**
* Index of keyword in `label`
* @param {node} label
*/
_proto.shouldDisplay = function shouldDisplay(label) {
var searchKeyword = this.state.searchKeyword;
if (!_lodash.default.trim(searchKeyword)) {
return true;
}
var keyword = searchKeyword.toLocaleLowerCase();
if (typeof label === 'string' || typeof label === 'number') {
return ("" + label).toLocaleLowerCase().indexOf(keyword) >= 0;
} else if (React.isValidElement(label)) {
var nodes = (0, _utils.reactToString)(label);
return nodes.join('').toLocaleLowerCase().indexOf(keyword) >= 0;
}
return false;
};
_proto.findNode = function findNode(focus) {
var items = this.getFocusableMenuItems();
var valueKey = this.props.valueKey;
var focusItemValue = this.state.focusItemValue;
for (var i = 0; i < items.length; i += 1) {
if ((0, _utils.shallowEqual)(focusItemValue, items[i][valueKey])) {
focus(items, i);
return;
}
}
focus(items, -1);
};
_proto.renderDropdownMenu = function renderDropdownMenu() {
var _this2 = this;
var _this$props4 = this.props,
data = _this$props4.data,
labelKey = _this$props4.labelKey,
valueKey = _this$props4.valueKey,
groupBy = _this$props4.groupBy,
searchable = _this$props4.searchable,
renderExtraFooter = _this$props4.renderExtraFooter,
locale = _this$props4.locale,
renderMenu = _this$props4.renderMenu,
menuClassName = _this$props4.menuClassName,
menuStyle = _this$props4.menuStyle,
menuAutoWidth = _this$props4.menuAutoWidth,
sort = _this$props4.sort;
var _this$state2 = this.state,
focusItemValue = _this$state2.focusItemValue,
stickyItems = _this$state2.stickyItems;
var classes = (0, _classnames.default)(this.addPrefix('check-menu'), menuClassName);
var filteredData = [];
var filteredStickyItems = [];
if (stickyItems) {
filteredStickyItems = (0, _utils.filterNodesOfTree)(stickyItems, function (item) {
return _this2.shouldDisplay(item[labelKey]);
});
filteredData = (0, _utils.filterNodesOfTree)(data, function (item) {
return _this2.shouldDisplay(item[labelKey]) && !stickyItems.some(function (v) {
return v[valueKey] === item[valueKey];
});
});
} else {
filteredData = (0, _utils.filterNodesOfTree)(data, function (item) {
return _this2.shouldDisplay(item[labelKey]);
});
} // Create a tree structure data when set `groupBy`
if (groupBy) {
filteredData = (0, _utils2.getDataGroupBy)(filteredData, groupBy, sort);
} else if (typeof sort === 'function') {
filteredData = filteredData.sort(sort(false));
}
var menuProps = _lodash.default.pick(this.props, Object.keys(_lodash.default.omit(_Picker.DropdownMenu.propTypes, ['className', 'style', 'classPrefix'])));
var menu = filteredData.length ? React.createElement(_Picker.DropdownMenu, (0, _extends2.default)({}, menuProps, {
classPrefix: this.addPrefix('check-menu'),
dropdownMenuItemComponentClass: _Picker.DropdownMenuCheckItem,
ref: this.menuContainerRef,
activeItemValues: this.getValue(),
focusItemValue: focusItemValue,
data: [].concat(filteredStickyItems, filteredData),
group: !_lodash.default.isUndefined(groupBy),
onSelect: this.handleItemSelect
})) : React.createElement("div", {
className: this.addPrefix('none')
}, locale.noResultsText);
return React.createElement(_Picker.MenuWrapper, {
autoWidth: menuAutoWidth,
className: classes,
style: menuStyle,
onKeyDown: this.handleKeyDown,
getToggleInstance: this.getToggleInstance,
getPositionInstance: this.getPositionInstance
}, searchable && React.createElement(_Picker.SearchBar, {
placeholder: locale.searchPlaceholder,
onChange: this.handleSearch,
value: this.state.searchKeyword
}), renderMenu ? renderMenu(menu) : menu, renderExtraFooter && renderExtraFooter());
};
_proto.render = function render() {
var _this$props5 = this.props,
data = _this$props5.data,
valueKey = _this$props5.valueKey,
labelKey = _this$props5.labelKey,
placeholder = _this$props5.placeholder,
renderValue = _this$props5.renderValue,
disabled = _this$props5.disabled,
cleanable = _this$props5.cleanable,
locale = _this$props5.locale,
toggleComponentClass = _this$props5.toggleComponentClass,
style = _this$props5.style,
onEnter = _this$props5.onEnter,
onEntered = _this$props5.onEntered,
onExited = _this$props5.onExited,
onClean = _this$props5.onClean,
countable = _this$props5.countable,
rest = (0, _objectWithoutPropertiesLoose2.default)(_this$props5, ["data", "valueKey", "labelKey", "placeholder", "renderValue", "disabled", "cleanable", "locale", "toggleComponentClass", "style", "onEnter", "onEntered", "onExited", "onClean", "countable"]);
var unhandled = (0, _utils2.getUnhandledProps)(CheckPicker, rest);
var value = this.getValue();
var selectedItems = data.filter(function (item) {
return value.some(function (val) {
return (0, _utils.shallowEqual)(item[valueKey], val);
});
}) || [];
var count = selectedItems.length;
var hasValue = !!count;
var selectedElement = placeholder;
if (count > 0) {
selectedElement = React.createElement(_Picker.SelectedElement, {
selectedItems: selectedItems,
countable: countable,
valueKey: valueKey,
labelKey: labelKey,
prefix: this.addPrefix
});
if (renderValue) {
selectedElement = renderValue(value, selectedItems, selectedElement);
}
}
var classes = (0, _Picker.getToggleWrapperClassName)('check', this.addPrefix, this.props, hasValue);
return React.createElement(_IntlProvider.default, {
locale: locale
}, React.createElement(_Picker.PickerToggleTrigger, {
pickerProps: this.props,
ref: this.triggerRef,
positionRef: this.positionRef,
onEnter: (0, _utils2.createChainedFunction)(this.setStickyItems, onEnter),
onEntered: (0, _utils2.createChainedFunction)(this.handleOpen, onEntered),
onExit: (0, _utils2.createChainedFunction)(this.handleExit, onExited),
speaker: this.renderDropdownMenu()
}, React.createElement("div", {
className: classes,
style: style
}, React.createElement(_Picker.PickerToggle, (0, _extends2.default)({}, unhandled, {
ref: this.toggleRef,
onClean: (0, _utils2.createChainedFunction)(this.handleClean, onClean),
onKeyDown: this.handleKeyDown,
componentClass: toggleComponentClass,
cleanable: cleanable && !disabled,
hasValue: hasValue,
active: this.state.active
}), selectedElement || React.createElement(_FormattedMessage.default, {
id: "placeholder"
})))));
};
return CheckPicker;
}(React.Component);
CheckPicker.propTypes = {
appearance: _propTypes.default.oneOf(['default', 'subtle']),
data: _propTypes.default.array,
locale: _propTypes.default.object,
classPrefix: _propTypes.default.string,
className: _propTypes.default.string,
container: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.func]),
containerPadding: _propTypes.default.number,
block: _propTypes.default.bool,
toggleComponentClass: _propTypes.default.elementType,
menuClassName: _propTypes.default.string,
menuStyle: _propTypes.default.object,
menuAutoWidth: _propTypes.default.bool,
disabled: _propTypes.default.bool,
disabledItemValues: _propTypes.default.array,
maxHeight: _propTypes.default.number,
valueKey: _propTypes.default.string,
labelKey: _propTypes.default.string,
value: _propTypes.default.array,
defaultValue: _propTypes.default.array,
renderMenu: _propTypes.default.func,
renderMenuItem: _propTypes.default.func,
renderMenuGroup: _propTypes.default.func,
renderValue: _propTypes.default.func,
renderExtraFooter: _propTypes.default.func,
onChange: _propTypes.default.func,
onSelect: _propTypes.default.func,
onGroupTitleClick: _propTypes.default.func,
onSearch: _propTypes.default.func,
onClean: _propTypes.default.func,
onOpen: _propTypes.default.func,
onClose: _propTypes.default.func,
onHide: _propTypes.default.func,
onEnter: _propTypes.default.func,
onEntering: _propTypes.default.func,
onEntered: _propTypes.default.func,
onExit: _propTypes.default.func,
onExiting: _propTypes.default.func,
onExited: _propTypes.default.func,
groupBy: _propTypes.default.any,
sort: _propTypes.default.func,
placeholder: _propTypes.default.node,
searchable: _propTypes.default.bool,
cleanable: _propTypes.default.bool,
countable: _propTypes.default.bool,
open: _propTypes.default.bool,
defaultOpen: _propTypes.default.bool,
placement: _propTypes.default.oneOf(_constants.PLACEMENT),
style: _propTypes.default.object,
sticky: _propTypes.default.bool,
preventOverflow: _propTypes.default.bool
};
CheckPicker.defaultProps = {
appearance: 'default',
data: [],
disabledItemValues: [],
maxHeight: 320,
valueKey: 'value',
labelKey: 'label',
locale: {
placeholder: 'Select',
searchPlaceholder: 'Search',
noResultsText: 'No results found'
},
searchable: true,
cleanable: true,
countable: true,
menuAutoWidth: true,
placement: 'bottomStart'
};
var enhance = (0, _compose.default)((0, _utils2.defaultProps)({
classPrefix: 'picker'
}), (0, _utils2.withPickerMethods)());
var _default = enhance(CheckPicker);
exports.default = _default;
module.exports = exports.default;