import { Autocomplete as MUIAutocomplete, autocompleteClasses as muiAutocompleteClasses, AutocompleteProps as MUIAutocompleteProps, AutocompleteRenderInputParams as MUIAutocompleteRenderInputParams, Box, Grow as MUIGrow, ListSubheader, outlinedInputClasses as muiOutlinedInputClasses, Paper as MUIPaper, PaperProps as MUIPaperProps, svgIconClasses as muiSvgIconClasses, styled, } from '@mui/material'; import { useMemo } from 'react'; import { GREY, TEXT } from '../lib/consts/DEFAULT_THEME'; import InputMessageBox from './InputMessageBox'; import { MessageBoxProps } from './MessageBox'; import OutlinedInputWithLabel, { OutlinedInputWithLabelProps, } from './OutlinedInputWithLabel'; type AutocompleteOptionalProps = { extendRenderInput?: ( inputWithLabelProps: OutlinedInputWithLabelProps, renderInputParams?: MUIAutocompleteRenderInputParams, ) => void; getGroupLabel?: (group: string) => React.ReactNode; messageBoxProps?: Partial; }; type AutocompleteProps< T, Multiple extends boolean | undefined, DisableClearable extends boolean | undefined, FreeSolo extends boolean | undefined, > = AutocompleteOptionalProps & { label: string } & Omit< MUIAutocompleteProps, 'renderInput' > & Partial< Pick< MUIAutocompleteProps, 'renderInput' > >; const GrowPaper = (paperProps: MUIPaperProps): JSX.Element => ( ); const GroupChildren = styled('ul')({ padding: 0, }); const GroupHeader = ListSubheader; const Autocomplete = < T, Multiple extends boolean | undefined = undefined, DisableClearable extends boolean | undefined = undefined, FreeSolo extends boolean | undefined = undefined, >( autocompleteProps: AutocompleteProps, ): JSX.Element => { const { componentsProps, extendRenderInput, getGroupLabel, label, messageBoxProps, renderGroup, renderInput, sx, ...autocompleteRestProps } = autocompleteProps; const combinedComponentsProps = useMemo< AutocompleteProps< T, Multiple, DisableClearable, FreeSolo >['componentsProps'] >( () => ({ paper: { sx: { backgroundColor: TEXT, [`& .${muiAutocompleteClasses.groupLabel}`]: { backgroundColor: TEXT, }, }, }, ...componentsProps, }), [componentsProps], ); const combinedRenderGroup = useMemo< AutocompleteProps['renderGroup'] >(() => { if (renderGroup) return renderGroup; return ( getGroupLabel && ((params) => (
  • {getGroupLabel(params.group)} {params.children}
  • )) ); }, [getGroupLabel, renderGroup]); const combinedRenderInput = useMemo< Exclude< AutocompleteProps['renderInput'], undefined > >( () => renderInput ?? ((params) => { const { fullWidth, InputProps, InputLabelProps, inputProps } = params; const inputWithLabelProps: OutlinedInputWithLabelProps = { formControlProps: { fullWidth, ref: InputProps.ref, }, inputLabelProps: InputLabelProps, inputProps: { className: InputProps.className, endAdornment: InputProps.endAdornment, inputProps, startAdornment: InputProps.startAdornment, }, label, }; extendRenderInput?.call(null, inputWithLabelProps, params); return ; }), [extendRenderInput, label, renderInput], ); const combinedSx = useMemo< AutocompleteProps['sx'] >( () => ({ [`& .${muiOutlinedInputClasses.root} .${muiAutocompleteClasses.endAdornment}`]: { right: `7px`, [`& .${muiSvgIconClasses.root}`]: { color: GREY, }, }, ...sx, }), [sx], ); return ( ); }; export type { AutocompleteProps }; export default Autocomplete;