2023-04-19 12:07:27 +02:00

113 lines
3.3 KiB
TypeScript

import classNames from "classnames";
import React from "react";
import ReactSelect, { ActionMeta, MultiValue, Options, PropsValue } from "react-select";
import { IOption } from "../Select";
import Typography, { ITypo } from "../Typography";
import classes from "./classes.module.scss";
import { styles } from "./styles";
type IProps = {
options: IOption[];
label?: string | JSX.Element;
placeholder?: string;
onChange?: (newValue: MultiValue<IOption>, actionMeta: ActionMeta<IOption>) => void;
defaultValue?: PropsValue<IOption>;
value?: PropsValue<IOption>;
isMulti?: boolean;
shouldCloseMenuOnSelect: boolean;
isOptionDisabled?: (option: IOption, selectValue: Options<IOption>) => boolean;
};
type IState = {
isFocused: boolean;
selectedOptions: MultiValue<IOption>;
};
export default class MultiSelect extends React.Component<IProps, IState> {
public static defaultProps: Partial<IProps> = {
placeholder: "Sélectionner une option...",
shouldCloseMenuOnSelect: false,
};
constructor(props: IProps) {
super(props);
this.state = {
isFocused: false,
selectedOptions: [],
};
this.onChange = this.onChange.bind(this);
this.onEmptyResearch = this.onEmptyResearch.bind(this);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}
public override render(): JSX.Element {
return (
<div className={classes["root"]}>
<div className={classNames(classes["label-container"], this.state.selectedOptions.length >= 1 && classes["active"])}>
{this.props.label && <div className={classes["label"]}>{this.props.label}</div>}
{this.props.placeholder && (
<div
className={classes["placeholder"]}
data-selected={(this.state.isFocused || this.state.selectedOptions.length >= 1).toString()}>
<Typography typo={ITypo.NAV_INPUT_16}>{this.props.placeholder}</Typography>
</div>
)}
<div className={classes["input-container"]}>
<ReactSelect
placeholder={""}
options={this.props.options}
styles={styles}
onChange={this.onChange}
value={this.props.value}
defaultValue={this.props.defaultValue}
closeMenuOnSelect={this.props.shouldCloseMenuOnSelect}
isMulti
isOptionDisabled={this.props.isOptionDisabled}
noOptionsMessage={this.onEmptyResearch}
onFocus={this.onFocus}
onBlur={this.onBlur}
classNamePrefix="react-select"
/>
</div>
</div>
</div>
);
}
public override componentDidMount(): void {
if (this.props.defaultValue) {
// If default value contains multiple IOptions
if (Array.isArray(this.props.defaultValue)) {
this.setState({ selectedOptions: this.props.defaultValue });
}
// If default value is a single IOption
if ("label" in this.props.defaultValue) {
this.setState({ selectedOptions: [this.props.defaultValue] });
}
}
}
private onFocus() {
this.setState({ isFocused: true });
}
private onBlur() {
this.setState({ isFocused: false });
}
private onChange(newValue: MultiValue<IOption>, actionMeta: ActionMeta<IOption>) {
this.props.onChange && this.props.onChange(newValue, actionMeta);
this.setState({
selectedOptions: newValue,
});
}
private onEmptyResearch() {
if (this.state.selectedOptions.length === this.props.options.length) {
return null;
}
return "Aucune option trouvée";
}
}