import React, { useState, useRef, useEffect } from 'react'; import styles from './SelectInput.module.css'; interface Option { label: string; value: any; } interface Props { onChange: (value: string | string[] | null) => void; options: Option[]; isMultiple?: boolean; value?: string | string[]; } export default function SelectInput({ options, isMultiple = false, onChange, value = [], }: Props): JSX.Element { const [selected, setSelected] = useState([]); const [filteredOptions, setFilteredOptions] = useState([]); const [isOptionsOpen, setIsOptionsOpen] = useState(false); const inputRef = useRef(null); useEffect(() => { setFilteredOptions(options); }, [options]); useEffect(() => { if (selected.length === 0) { onChange(null); return; } onChange(isMultiple ? selected : selected[0]); }, [selected]); const handleFocusInput = (): void => { setIsOptionsOpen(true); inputRef.current?.focus(); }; const handleAddElement = (item: any): void => { setSelected((prev) => { if (isMultiple) { return [...prev, item]; } return [item]; }); setIsOptionsOpen(false); if (inputRef.current === null) return; inputRef.current.value = ''; }; const handleRemoveElement = (idx: number): void => { setIsOptionsOpen(false); setSelected((prev) => { prev.splice(idx, 1); return [...prev]; }); }; const handleLooseFocus = (e: React.FocusEvent): void => { if (!e.currentTarget.contains(e.relatedTarget)) { // Not triggered when swapping focus between children setIsOptionsOpen(false); } }; const handleFilterOptions = ({ target, }: React.ChangeEvent): void => { if (target.value === '') { setFilteredOptions(options); return; } const newOptions = options.filter( (item) => item.label.toLowerCase().search(target.value.toLowerCase()) !== -1, ); setFilteredOptions(newOptions); }; return (
{ handleFocusInput(); }} > {selected.map((item, idx) => (
{item}
{ handleRemoveElement(idx); }} > {'X'}
))}
); }