import { isArray } from "lodash"; import React, { useCallback, useMemo } from "react"; import ReactSelect from "react-select"; import { SelectComponents } from "react-select/src/components"; import "./selector.scss"; export interface SelectorProps { className?: string; placeholder?: string; options: readonly SelectorOption[]; disabled?: boolean; clearable?: boolean; loading?: boolean; multiple?: M; onChange?: (k: SelectorValueType) => void; onFocus?: (e: React.FocusEvent) => void; label?: (item: T) => string; defaultValue?: SelectorValueType; value?: SelectorValueType; components?: Partial>; } export function Selector( props: SelectorProps ) { const { className, placeholder, label, disabled, clearable, loading, options, multiple, onChange, onFocus, defaultValue, components, value, } = props; const nameFromItems = useCallback( (item: T) => { return options.find((v) => v.value === item)?.label; }, [options] ); // TODO: Force as any const wrapper = useCallback( (value: SelectorValueType | undefined | null): any => { if (value !== null && value !== undefined) { if (multiple) { return (value as SelectorValueType).map((v) => ({ label: label ? label(v) : nameFromItems(v) ?? "Unknown", value: v, })); } else { const v = value as T; return { label: label ? label(v) : nameFromItems(v) ?? "Unknown", value: v, }; } } return value; }, [label, multiple, nameFromItems] ); const defaultWrapper = useMemo(() => wrapper(defaultValue), [ defaultValue, wrapper, ]); const valueWrapper = useMemo(() => wrapper(value), [wrapper, value]); return ( = 10} isMulti={multiple} closeMenuOnSelect={!multiple} defaultValue={defaultWrapper} value={valueWrapper} isClearable={clearable} isDisabled={disabled} options={options} components={components} className={`custom-selector w-100 ${className ?? ""}`} classNamePrefix="selector" onFocus={onFocus} onChange={(v) => { if (onChange) { let res: T | T[] | null = null; if (isArray(v)) { res = (v as ReadonlyArray>).map( (val) => val.value ); } else { res = (v as SelectorOption)?.value ?? null; } // TODO: Force as any onChange(res as any); } }} > ); }