Local modifications to ClusterLabs/Anvil by Alteeve
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
4.9 KiB

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<MessageBoxProps>;
};
type AutocompleteProps<
T,
Multiple extends boolean | undefined,
DisableClearable extends boolean | undefined,
FreeSolo extends boolean | undefined,
> = AutocompleteOptionalProps & { label: string } & Omit<
MUIAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>,
'renderInput'
> &
Partial<
Pick<
MUIAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>,
'renderInput'
>
>;
const GrowPaper = (paperProps: MUIPaperProps): JSX.Element => (
<MUIGrow in>
<MUIPaper {...paperProps} />
</MUIGrow>
);
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<T, Multiple, DisableClearable, FreeSolo>,
): 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<T, Multiple, DisableClearable, FreeSolo>['renderGroup']
>(() => {
if (renderGroup) return renderGroup;
return (
getGroupLabel &&
((params) => (
<li key={params.key}>
<GroupHeader
component="div"
className={muiAutocompleteClasses.groupLabel}
>
{getGroupLabel(params.group)}
</GroupHeader>
<GroupChildren className={muiAutocompleteClasses.groupUl}>
{params.children}
</GroupChildren>
</li>
))
);
}, [getGroupLabel, renderGroup]);
const combinedRenderInput = useMemo<
Exclude<
AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>['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 <OutlinedInputWithLabel {...inputWithLabelProps} />;
}),
[extendRenderInput, label, renderInput],
);
const combinedSx = useMemo<
AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>['sx']
>(
() => ({
[`& .${muiOutlinedInputClasses.root} .${muiAutocompleteClasses.endAdornment}`]:
{
right: `7px`,
[`& .${muiSvgIconClasses.root}`]: {
color: GREY,
},
},
...sx,
}),
[sx],
);
return (
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<MUIAutocomplete
PaperComponent={GrowPaper}
{...autocompleteRestProps}
componentsProps={combinedComponentsProps}
renderGroup={combinedRenderGroup}
renderInput={combinedRenderInput}
sx={combinedSx}
/>
<InputMessageBox {...messageBoxProps} />
</Box>
);
};
export type { AutocompleteProps };
export default Autocomplete;