mirror of
https://github.com/chenasraf/dotfiles.git
synced 2026-05-17 17:28:07 +00:00
77 lines
2.6 KiB
TypeScript
77 lines
2.6 KiB
TypeScript
import Autocomplete, { AutocompleteProps } from '@mui/material/Autocomplete'
|
|
import TextField from '@mui/material/TextField'
|
|
import React from 'react'
|
|
import { Controller, Control, Path } from 'react-hook-form'
|
|
import { CustomComponent, Option } from '../../core/types'
|
|
import { optionFrom } from '../../core/utils/object_utils'
|
|
|
|
export interface ControlledAutocompleteProps<T, K extends Path<T>, Multiple extends boolean = false>
|
|
extends CustomComponent<Partial<AutocompleteProps<Option, Multiple, false, false>>> {
|
|
control: Control<T>
|
|
name: K
|
|
options: Option[]
|
|
helperText?: React.ReactNode
|
|
placeholder?: string
|
|
required?: boolean
|
|
multiple?: Multiple
|
|
}
|
|
|
|
export const ControlledAutocomplete = <T, K extends Path<T>, Multiple extends boolean = false>(
|
|
props: ControlledAutocompleteProps<T, K, Multiple>,
|
|
) => {
|
|
const { control, name, options, helperText, placeholder, onChange, multiple, ...rest } = props
|
|
|
|
const _value = React.useMemo(
|
|
(): Multiple extends true ? Option<string>[] : Option<string> | null =>
|
|
control._formValues[name]
|
|
? multiple
|
|
? control._formValues[name].map(optionFrom)
|
|
: optionFrom(control._formValues[name])
|
|
: multiple
|
|
? []
|
|
: null,
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
[control._formValues[name]],
|
|
)
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const [value, setValue] = React.useState(_value ?? (multiple ? ([] as string[]) : ('' as any)))
|
|
React.useEffect(
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
() => setValue(_value ?? (multiple ? ([] as string[]) : ('' as any))),
|
|
[_value, multiple],
|
|
)
|
|
|
|
return (
|
|
<Controller<T, K>
|
|
control={control}
|
|
name={name}
|
|
rules={{ required: props.required }}
|
|
render={({ field, formState: { errors } }) => (
|
|
<Autocomplete
|
|
onChange={(e, d, r) => {
|
|
setValue(d as typeof _value)
|
|
field.onChange(Array.isArray(d) ? d.map((d) => d?.value) : d?.value)
|
|
onChange?.(e, d, r)
|
|
}}
|
|
value={value}
|
|
options={options}
|
|
getOptionLabel={(opt) => opt?.label}
|
|
isOptionEqualToValue={(opt, value) => opt.value === value.value}
|
|
multiple={multiple}
|
|
renderInput={(params) => (
|
|
<TextField
|
|
{...params}
|
|
fullWidth
|
|
placeholder={placeholder}
|
|
helperText={helperText}
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
error={Boolean((errors as any)[name])}
|
|
/>
|
|
)}
|
|
{...rest}
|
|
/>
|
|
)}
|
|
/>
|
|
)
|
|
}
|