import React, { ChangeEvent, useMemo } from "react"; import classNames from "classnames"; import { Box } from "../Box"; import { Flex } from "../Flex"; import { SelectState, OptionInterface, combineReducers, createBaseReducer, createSingleValueReducer, searchReducer, useSelect, } from "./useSelect"; import { Option, surfaceClassName, selectInputCn, NoOptions, Container, Listbox, ClearButton, Arrow, ComboboxSharedProps, } from "./ui"; const initialState: SelectState = { value: { value: "", label: "", }, isOpen: false, searchValue: "", hoverIndex: 0, }; const reducers = [ createBaseReducer(initialState), searchReducer, createSingleValueReducer(initialState), ]; const rootReducer = combineReducers(reducers); function reducer( state: SelectState = initialState, action: any, ) { const nextState = rootReducer(state, action); return nextState; } export const Combobox = ({ options, placeholder = "Select…", isCreatable = false, isClearable = false, isSearchable = true, disabled = false, className, onCreate = () => {}, onChange = () => {}, }: ComboboxSharedProps) => { const { state, availableOptions, ref, onKeyPress, select, close, hover, clear, create, open, search, comboboxRef, listboxStyles, } = useSelect({ options, reducer, initialState, onChange, onCreate }); const { isOpen, searchValue, value, hoverIndex } = state; const hasOptions = availableOptions.length > 0; const allowInput = isSearchable || isCreatable; const canCreate = isCreatable && !!searchValue; const canClear = isClearable && !!value.value; const showOptions = useMemo(() => { return availableOptions.map((opt, index) => { const isSelected = opt.value === value.value; return ( ); }); }, [availableOptions, value.value, hoverIndex, hover, select]); const noOptions = ( ); return ( {allowInput ? ( <> {searchValue ? "" : value.value} ): void => search(event.currentTarget.value) } value={searchValue} className={selectInputCn} ref={ref} onKeyDown={onKeyPress} placeholder={value.value ? "" : placeholder} disabled={disabled} /> ) : ( {value.value || placeholder} )} {isOpen && ( {hasOptions ? showOptions : noOptions} )} ); };