import React, { useEffect, useRef, useState } from 'react'; import { Layer, Search } from '@carbon/react'; import classNames from 'classnames'; import styles from './autosuggest.scss'; type SearchProps = React.ComponentProps; interface AutosuggestProps extends SearchProps { getDisplayValue: (suggestion: Suggestion) => string; getFieldValue: (suggestion: Suggestion) => string; getSearchResults: (query: string) => Promise>; onSuggestionSelected: (field: string, value: string) => void; invalid?: boolean | undefined; invalidText?: string | undefined; } export const Autosuggest = ({ getDisplayValue, getFieldValue, getSearchResults, onSuggestionSelected, invalid, invalidText, ...searchProps }: AutosuggestProps) => { const [suggestions, setSuggestions] = useState>([]); const searchBox = useRef(null); const wrapper = useRef(null); const { id: name, labelText } = searchProps; useEffect(() => { document.addEventListener('mousedown', handleClickOutsideComponent); return () => { document.removeEventListener('mousedown', handleClickOutsideComponent); }; }, [wrapper]); const handleClickOutsideComponent = (e: MouseEvent) => { if (wrapper.current && !wrapper.current.contains(e.target as Node)) { setSuggestions([]); } }; const handleChange = (e: React.ChangeEvent) => { const query = e.target.value; onSuggestionSelected(name, undefined); if (query) { getSearchResults(query).then((suggestions) => { setSuggestions(suggestions); }); } else { setSuggestions([]); } }; const handleClear = () => { onSuggestionSelected(name, undefined); }; const handleClick = (index: number) => { const display = getDisplayValue(suggestions[index]); const value = getFieldValue(suggestions[index]); searchBox.current.value = display; onSuggestionSelected(name, value); setSuggestions([]); }; return (
{suggestions.length > 0 && (
    {suggestions.map((suggestion, index) => (
  • handleClick(index)}> {getDisplayValue(suggestion)}
  • ))}
)} {invalid ? : <>}
); };