@wix/design-system
Version:
@wix/design-system
174 lines • 6.29 kB
JavaScript
import React from 'react';
import InputWithOptions from '../InputWithOptions';
import Input from '../Input';
import { classes } from './MultiSelectCheckbox.st.css.js';
import { listItemSelectBuilder } from '../ListItemSelect';
import { listItemSectionBuilder } from '../ListItemSection';
const OPEN_DROPDOWN_CHARS = ['Enter', 'ArrowDown', 'Space', ' '];
class MultiSelectCheckbox extends InputWithOptions {
createOptions(options) {
return options.map(option => {
if (this._isUsingCustomRenderFunction(option)) {
return this._patchOptionWithSelectionMechanism(option);
}
else if (this._isDivider(option)) {
return listItemSectionBuilder({
type: 'divider',
...option,
});
}
else {
const builder = listItemSelectBuilder({
...option,
checkbox: true,
title: option.value,
label: option.label,
});
return this._patchOptionWithSelectionMechanism(builder);
}
});
}
_patchOptionWithSelectionMechanism(option) {
const value = option.value;
return {
...option,
value: props => value({
...props,
selected: this.isSelectedId(option.id),
}),
};
}
_isUsingCustomRenderFunction({ value }) {
return typeof value === 'function';
}
_isDivider({ value }) {
return value === '-';
}
isSelectedId(optionId) {
return this.props.selectedOptions.indexOf(optionId) !== -1;
}
dropdownAdditionalProps() {
const { predicate, emptyStateMessage, enableSearch } = this.props;
const filterFunc = this.state.isEditing ? predicate : () => true;
let options = enableSearch
? this.createOptions(this.props.options.filter(filterFunc))
: this.createOptions(this.props.options);
if (options.length === 0 && emptyStateMessage) {
options = [
{
id: 'empty-state-message',
value: emptyStateMessage,
disabled: true,
},
];
}
return {
options,
closeOnSelect: false,
selectedHighlight: false,
};
}
selectedOptionsToText() {
return this.props.selectedOptions
.map(selectedOption => this.props.options.find(option => option.id === selectedOption))
.filter(selectedOption => selectedOption)
.map(this.props.valueParser)
.join(this.props.delimiter);
}
inputAdditionalProps() {
if (this.props.enableSearch) {
const { selectedOptions, getSelectedOptionsText } = this.props;
const selectedOptionsText = !!getSelectedOptionsText
? getSelectedOptionsText(selectedOptions.length)
: this.selectedOptionsToText();
const value = !this._focused && selectedOptions.length > 0
? selectedOptionsText
: this.props.value;
return {
readOnly: this.props.readOnly,
disableEditing: false,
value,
placeholder: selectedOptions.length > 0
? selectedOptionsText
: this.props.placeholder,
};
}
else {
const value = this.props.value !== undefined
? this.props.value
: this.selectedOptionsToText();
return {
readOnly: this.props.readOnly,
disableEditing: this.props.disableEditing,
inputElement: this.props.inputElement ?? (React.createElement(Input, { textOverflow: "ellipsis", disableEditing: this.props.disableEditing })),
value,
};
}
}
inputClasses() {
return this.props.enableSearch ? '' : classes.showPointer;
}
_onSelect(option) {
this.showOptions();
if (this.closeOnSelect()) {
this.setState({ showOptions: false });
}
// The option object is not the original since it was injected a checkbox
const originalOption = this.props.options.find(op => option.id === op.id);
if (this.isSelectedId(originalOption.id)) {
this.props.onDeselect &&
this.props.onDeselect(originalOption.id, originalOption);
}
else {
this.props.onSelect &&
this.props.onSelect(originalOption.id, originalOption);
}
if (this.props.enableSearch && this.props.onChange) {
this.props.onChange({ target: { value: '' } });
this.setState({ isEditing: false });
}
}
_onOpenChange(event) {
if (!this.props.readOnly) {
this.state.showOptions ? this.hideOptions() : this.showOptions();
}
}
_onKeyDown(event) {
if (OPEN_DROPDOWN_CHARS.includes(event.key) &&
!(this.state.isEditing && event.key === ' ')) {
event.preventDefault();
this.showOptions();
}
else if (this.props.enableSearch &&
event.key !== 'ArrowDown' &&
event.key !== 'ArrowUp') {
this.setState({ isEditing: true });
}
this.dropdownLayout && this.dropdownLayout._onSelectListKeyDown(event);
}
_onFocus(e) {
if (this.props.disabled) {
return;
}
this._focused = true;
if (this.props.onFocus) {
this.props.onFocus(e);
this.setState({ isEditing: false });
}
}
}
MultiSelectCheckbox.displayName = 'MultiSelectCheckbox';
MultiSelectCheckbox.defaultProps = {
...InputWithOptions.defaultProps,
delimiter: ', ',
selectedOptions: [],
closeOnSelect: false,
valueParser: option => option.label || option.value,
readOnly: false,
disableEditing: true,
clearOnBlur: true,
predicate: () => true,
enableSearch: false,
};
export default MultiSelectCheckbox;
//# sourceMappingURL=MultiSelectCheckbox.js.map