import { ValidationError } from "class-validator"; import classNames from "classnames"; import React from "react"; import ReactSelect, { ActionMeta, MultiValue, Options, PropsValue } from "react-select"; import { IOptionOld } from "../Form/SelectFieldOld"; import Typography, { ETypo, ETypoColor } from "../Typography"; import classes from "./classes.module.scss"; import { styles } from "./styles"; type IProps = { options: IOptionOld[]; label?: string | JSX.Element; placeholder?: string; onChange?: (newValue: MultiValue, actionMeta: ActionMeta) => void; defaultValue?: PropsValue; value?: PropsValue; isMulti?: boolean; shouldCloseMenuOnSelect: boolean; isOptionDisabled?: (option: IOptionOld, selectValue: Options) => boolean; validationError?: ValidationError; }; type IState = { isFocused: boolean; selectedOptions: MultiValue; validationError: ValidationError | null; }; export default class MultiSelect extends React.Component { public static defaultProps: Partial = { placeholder: "Sélectionner une option...", shouldCloseMenuOnSelect: false, }; constructor(props: IProps) { super(props); this.state = { isFocused: false, selectedOptions: [], validationError: this.props.validationError ?? null, }; this.hasError = this.hasError.bind(this); this.onChange = this.onChange.bind(this); this.onEmptyResearch = this.onEmptyResearch.bind(this); this.onFocus = this.onFocus.bind(this); this.onBlur = this.onBlur.bind(this); this.renderErrors = this.renderErrors.bind(this); } public override render(): JSX.Element { return (
= 1 && classes["active"])}> {this.props.label &&
{this.props.label}
} {this.props.placeholder && (
= 1).toString()}> {this.props.placeholder}
)}
{this.hasError() &&
{this.renderErrors()}
}
); } 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] }); } } } public override componentDidUpdate(prevProps: IProps): void { if (this.props.validationError !== prevProps.validationError) { this.setState({ validationError: this.props.validationError ?? null, }); } if (this.props.defaultValue && this.props.defaultValue !== prevProps.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, actionMeta: ActionMeta) { this.props.onChange && this.props.onChange(newValue, actionMeta); this.setState({ selectedOptions: newValue, validationError: null, }); } private onEmptyResearch() { if (this.state.selectedOptions.length === this.props.options.length) { return null; } return "Aucune option trouvée"; } protected hasError(): boolean { return this.state.validationError !== null; } protected renderErrors(): JSX.Element[] | null { if (!this.state.validationError || !this.state.validationError.constraints) return null; let errors: JSX.Element[] = []; Object.entries(this.state.validationError.constraints).forEach(([key, value]) => { errors.push( {value} , ); }); return errors; } }