portainer/app/react/components/form-components/AutocompleteSelect/AutocompleteSelect.tsx

87 lines
2.2 KiB
TypeScript

import '@reach/combobox/styles.css';
import { useState, ChangeEvent } from 'react';
import {
Combobox,
ComboboxInput,
ComboboxList,
ComboboxOption,
ComboboxPopover,
} from '@reach/combobox';
import clsx from 'clsx';
import { useDebounce } from '@/react/hooks/useDebounce';
import { Option } from '@@/form-components/PortainerSelect';
import styles from './AutocompleteSelect.module.css';
export function AutocompleteSelect({
value,
onChange,
placeholder,
searchResults,
readOnly,
inputId,
}: {
value: string;
/**
* onChange is called whenever the input is changed or an option is selected
*
* when the input is changed, the call is debounced
*/
onChange(value: string): void;
placeholder?: string;
searchResults?: Option<string>[];
readOnly?: boolean;
inputId: string;
}) {
const [searchTerm, setSearchTerm] = useDebounce(value, onChange);
const [selected, setSelected] = useState(false);
return (
<Combobox
className={styles.root}
aria-label="compose"
onSelect={onSelect}
data-cy="component-gitComposeInput"
>
<ComboboxInput
value={searchTerm}
className="form-control"
onChange={handleChange}
placeholder={placeholder}
readOnly={readOnly}
id={inputId}
/>
{!selected && searchResults && searchResults.length > 0 && (
<ComboboxPopover>
<ComboboxList>
{searchResults.map((option: Option<string>) => (
<ComboboxOption
key={option.value}
value={option.value}
className={clsx(
`[&[aria-selected="true"]]:th-highcontrast:!bg-black [&[aria-selected="true"]]:th-dark:!bg-black`,
`hover:th-highcontrast:!bg-black hover:th-dark:!bg-black`,
'th-highcontrast:bg-gray-10 th-dark:bg-gray-10 '
)}
/>
))}
</ComboboxList>
</ComboboxPopover>
)}
</Combobox>
);
function handleChange(e: ChangeEvent<HTMLInputElement>) {
setSearchTerm(e.target.value);
setSelected(false);
}
function onSelect(value: string) {
onChange(value);
setSelected(true);
}
}