import { Autocomplete, type AutocompleteProps, type AutocompleteRenderInputParams, CircularProgress, InputAdornment, type InputProps, useTheme } from '@mui/material'; import type { AutocompleteRenderOptionState, AutocompleteSlotsAndSlotProps } from '@mui/material/Autocomplete'; import type { TextFieldSlotsAndSlotProps } from '@mui/material/TextField'; import type { UseAutocompleteProps } from '@mui/material/useAutocomplete'; import { equals, isEmpty, isNil, pick } from 'ramda'; import { type ForwardedRef, forwardRef, type HTMLAttributes, type ReactElement, ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; import { getNormalizedId } from '../../../utils'; import TextField from '../../Text'; import { labelClear, labelOpen, searchLabel } from '../../translatedLabels'; import type { SelectEntry } from '..'; import Option from '../Option'; import { useAutoCompleteStyles } from './autoComplete.styles'; export type Props = { autoFocus?: boolean; autoSize?: boolean; helperText?: ReactNode; autoSizeCustomPadding?: number; autoSizeDefaultWidth?: number; dataTestId?: string; displayOptionThumbnail?: boolean; displayPopupIcon?: boolean; endAdornment?: ReactElement; error?: string; getOptionItemLabel?: (option: SelectEntry | undefined) => string | undefined; hideInput?: boolean; renderOption?: ( renderProps: HTMLAttributes, option: SelectEntry, state: AutocompleteRenderOptionState ) => ReactElement; label: string; loading?: boolean; onTextChange?: (event: React.ChangeEvent) => void; placeholder?: string | undefined; required?: boolean; forceInputRenderValue?: boolean; textFieldSlotsAndSlotProps?: TextFieldSlotsAndSlotProps; autocompleteSlotsAndSlotProps?: AutocompleteSlotsAndSlotProps< SelectEntry, Multiple, DisableClearable, FreeSolo >; } & Omit< AutocompleteProps, 'renderInput' > & UseAutocompleteProps; const LoadingIndicator = (): ReactElement => { const { classes } = useAutoCompleteStyles({}); return (
); }; type Multiple = boolean; type DisableClearable = boolean; type FreeSolo = boolean; const AutocompleteField = forwardRef( ( { options, label, placeholder, loading = false, onTextChange = (): void => undefined, endAdornment = undefined, inputValue, displayOptionThumbnail = false, required = false, error, displayPopupIcon = true, autoFocus = false, hideInput = false, helperText, dataTestId, autoSize = false, autoSizeDefaultWidth = 0, autoSizeCustomPadding, getOptionItemLabel = (option) => option?.name, forceInputRenderValue = false, textFieldSlotsAndSlotProps, autocompleteSlotsAndSlotProps, renderOption, ...autocompleteProps }: Props, ref?: ForwardedRef ): ReactElement => { const { classes, cx } = useAutoCompleteStyles({ hideInput }); const { t } = useTranslation(); const theme = useTheme(); const areSelectEntriesEqual = ( option: SelectEntry, value: SelectEntry ): boolean => { const identifyingProps: Array = ['id', 'name']; return equals( pick(identifyingProps, option), pick(identifyingProps, value) ); }; const renderOptions = renderOption ? renderOption : ( props: HTMLAttributes, option: SelectEntry ): ReactElement => { return (
  • )} >
  • ); }; const renderInput = ( params: AutocompleteRenderInputParams ): ReactElement => { return ( {endAdornment && ( {endAdornment} )} {params.InputProps.endAdornment} ), style: { background: 'transparent', minWidth: 0, padding: theme.spacing( 0.75, isEmpty(placeholder) ? 0 : 5, 0.75, 0.75 ) } }, inputLabel: { classes: { marginDense: classes.inputLabel, shrink: classes.inputLabelShrink } as unknown as Record } }} value={ inputValue || (forceInputRenderValue ? getOptionItemLabel( (autocompleteProps?.value as SelectEntry | undefined) || undefined ) : undefined) || undefined } /> ); }; return ( (option as SelectEntry)?.name?.toString() || '' } isOptionEqualToValue={areSelectEntriesEqual} loading={loading} loadingText={} options={options} ref={ref} renderInput={renderInput} renderOption={renderOptions} size="small" slotProps={{ ...autocompleteSlotsAndSlotProps?.slotProps, clearIndicator: { title: t(labelClear) }, popupIndicator: { title: t(labelOpen) } }} {...autocompleteProps} /> ); } ); export default AutocompleteField;