import React, { ReactElement, useEffect, useState } from 'react' import CreatableSelect from 'react-select/creatable' import { OnChangeValue } from 'react-select' import { useField } from 'formik' import { InputProps } from '.' import { getTagsList } from '@utils/aquarius' import { chainIds } from 'app.config' import { useCancelToken } from '@hooks/useCancelToken' import styles from './TagsAutoComplete.module.css' import { matchSorter } from 'match-sorter' interface AutoCompleteOption { readonly value: string readonly label: string } export default function TagsAutoComplete({ ...props }: InputProps): ReactElement { const { name, placeholder } = props const [tagsList, setTagsList] = useState() const [matchedTagsList, setMatchedTagsList] = useState( [] ) const [field, meta, helpers] = useField(name) const [input, setInput] = useState() const newCancelToken = useCancelToken() const generateAutocompleteOptions = ( options: string[] ): AutoCompleteOption[] => { return options?.map((tag) => ({ value: tag, label: tag })) } const defaultTags = !field.value ? undefined : generateAutocompleteOptions(field.value) useEffect(() => { const generateTagsList = async () => { const tags = await getTagsList(chainIds, newCancelToken()) const autocompleteOptions = generateAutocompleteOptions(tags) setTagsList(autocompleteOptions) } generateTagsList() }, [newCancelToken]) const handleChange = (userInput: OnChangeValue) => { const normalizedInput = userInput.map((input) => input.value) helpers.setValue(normalizedInput) helpers.setTouched(true) } const handleOptionsFilter = ( options: AutoCompleteOption[], input: string ): void => { setInput(input) const matchedTagsList = matchSorter(options, input, { keys: ['value'] }) setMatchedTagsList(matchedTagsList) } return ( null, IndicatorSeparator: () => null }} className={styles.select} defaultValue={defaultTags} hideSelectedOptions isMulti isClearable={false} noOptionsMessage={() => 'Start typing to get suggestions based on tags from all published assets.' } onChange={(value: AutoCompleteOption[]) => handleChange(value)} onInputChange={(value) => handleOptionsFilter(tagsList, value)} openMenuOnClick options={!input || input?.length < 1 ? [] : matchedTagsList} placeholder={placeholder} theme={(theme) => ({ ...theme, colors: { ...theme.colors, primary25: 'var(--border-color)' } })} /> ) }