diff --git a/web-app/client/src/components/Inputs/MultiSelect/ControlledMultiSelect.tsx b/web-app/client/src/components/Inputs/MultiSelect/ControlledMultiSelect.tsx index 4dbf58b4..5f6cfd9b 100644 --- a/web-app/client/src/components/Inputs/MultiSelect/ControlledMultiSelect.tsx +++ b/web-app/client/src/components/Inputs/MultiSelect/ControlledMultiSelect.tsx @@ -1,6 +1,7 @@ import { ComponentProps } from 'react'; import { Control, Controller, FieldValues, Path } from 'react-hook-form'; -import MultiSelect, { MultiSelectProps as SelectProps } from './MultiSelect'; +import { Option } from 'types/inputs'; +import MultiSelect, { MultiSelectProps } from './MultiSelect'; type ControlRules = ComponentProps< typeof Controller @@ -12,41 +13,34 @@ type ControlProps = { rules?: ControlRules; }; -const getSelectValues: ( - opt: ReadonlyArray<{ label: string; value: number }>, -) => number[] = (opt) => { +const getSelectValues: ( + opt: ReadonlyArray>, +) => TValue[] = (opt) => { return opt.map((element) => element.value); }; -const getSelectOptions: ( - options: ReadonlyArray<{ label: string; value: number }>, - value: ReadonlyArray, -) => ReadonlyArray<{ label: string; value: number }> = (options, values) => { - return options.filter(({ value }) => values.includes(value)); +const getSelectOptions: ( + options: ReadonlyArray> | undefined, + value: TValue[], +) => ReadonlyArray> | undefined = (options, values) => { + return options?.filter(({ value }) => values.includes(value)); }; -const ControlledMultiSelect = ({ +const ControlledMultiSelect = ({ controlName, control, rules, ...rest -}: SelectProps & ControlProps) => ( +}: MultiSelectProps & ControlProps) => ( ( - {...field} - onChange={(newValue) => - field.onChange( - getSelectValues(newValue as { label: string; value: number }[]), - ) - } - value={getSelectOptions( - rest.options as ReadonlyArray<{ label: string; value: number }>, - field.value, - )} + onChange={(newValue) => field.onChange(getSelectValues(newValue))} + value={getSelectOptions(rest.options, field.value)} {...rest} /> )} diff --git a/web-app/client/src/components/Inputs/MultiSelect/MultiSelect.tsx b/web-app/client/src/components/Inputs/MultiSelect/MultiSelect.tsx index d475f7f8..01d2c60f 100644 --- a/web-app/client/src/components/Inputs/MultiSelect/MultiSelect.tsx +++ b/web-app/client/src/components/Inputs/MultiSelect/MultiSelect.tsx @@ -1,19 +1,27 @@ import cn from 'classnames'; -import { forwardRef, ForwardRefRenderFunction, ReactNode } from 'react'; +import { + ForwardedRef, + forwardRef, + ForwardRefRenderFunction, + ReactNode, +} from 'react'; import ReactSelect, { Props as ReactSelectProps } from 'react-select'; import { InputPropsBase } from '@components/Inputs'; import Tooltip from '@components/Tooltip'; +import { Option } from 'types/inputs'; import customComponents, { colorStyles } from './customComponents'; import styles from './MultiSelect.module.scss'; -export type MultiSelectProps = InputPropsBase & - ReactSelectProps & { +export type MultiSelectProps = InputPropsBase & + ReactSelectProps, true> & { tooltip?: ReactNode; }; // Can't recreate explicit type // eslint-disable-next-line @typescript-eslint/no-explicit-any -const MultiSelect: ForwardRefRenderFunction = ( +type RefElement = any; + +const MultiSelect: ForwardRefRenderFunction = ( { label, error, tooltip, className, id, components, ...props }, ref, ) => { @@ -49,4 +57,6 @@ const MultiSelect: ForwardRefRenderFunction = ( ); }; -export default forwardRef(MultiSelect); +export default forwardRef(MultiSelect) as ( + props: MultiSelectProps & { ref?: ForwardedRef }, +) => ReturnType; diff --git a/web-app/client/src/components/Inputs/MultiSelect/customComponents.tsx b/web-app/client/src/components/Inputs/MultiSelect/customComponents.tsx index d59225b9..3d833626 100644 --- a/web-app/client/src/components/Inputs/MultiSelect/customComponents.tsx +++ b/web-app/client/src/components/Inputs/MultiSelect/customComponents.tsx @@ -19,17 +19,20 @@ import ChevronDownIcon from '@assets/icons/arrow-down.svg?component'; import EmptyButton from '@assets/icons/close.svg?component'; import { InputPropsBase } from '@components/Inputs'; import badgeStyles from '@components/Inputs/MultiSelect/OptionBadge/OptionBadge.module.scss'; +import { Option as OptionType } from 'types/inputs'; import { OptionWithBadges } from 'types/multiSelect'; import { OptionBadge } from './OptionBadge'; import styles from './MultiSelect.module.scss'; -export const colorStyles: StylesConfig = { +export const colorStyles: StylesConfig = { control: () => ({}), valueContainer: (styles) => ({ ...styles, padding: 0 }), indicatorSeparator: (styles) => ({ ...styles, margin: 0 }), }; -const Control: ComponentType = (props) => ( +const Control: ComponentType< + ControlProps & InputPropsBase +> = (props) => ( = (props) => ( ); const MultiValueContainer: ComponentType< - MultiValueGenericProps & InputPropsBase + MultiValueGenericProps & InputPropsBase > = (props) => ; -const MultiValue: ComponentType = (props) => ( +const MultiValue: ComponentType< + MultiValueProps & InputPropsBase +> = (props) => ( ); const MultiValueLabel: ComponentType< - MultiValueGenericProps & InputPropsBase + MultiValueGenericProps & InputPropsBase > = (props) => (
& InputPropsBase > = (props) => (
); -const Placeholder: ComponentType = ( - props, -) => ; +const Placeholder: ComponentType< + PlaceholderProps & InputPropsBase +> = (props) => ( + +); -const Input: ComponentType = (props) => ( +const Input: ComponentType & InputPropsBase> = ( + props, +) => ( ); -const ClearIndicator: ComponentType = ({ - innerProps, -}) => ( +const ClearIndicator: ComponentType< + ClearIndicatorProps & InputPropsBase +> = ({ innerProps }) => (
); const DropdownIndicator: ComponentType< - DropdownIndicatorProps & InputPropsBase + DropdownIndicatorProps & InputPropsBase > = ({ innerProps }) => (
@@ -101,7 +110,7 @@ const DropdownIndicator: ComponentType< ); const IndicatorsContainer: ComponentType< - IndicatorsContainerProps & InputPropsBase + IndicatorsContainerProps & InputPropsBase > = (props) => ( ); -export const Option: ComponentType = ({ - innerProps, - innerRef, - children, - isFocused, - isSelected, - data, -}) => { +export const Option: ComponentType< + OptionProps & InputPropsBase +> = ({ innerProps, innerRef, children, isFocused, isSelected, data }) => { const optionData = data as OptionWithBadges; return ( @@ -148,19 +152,17 @@ export const Option: ComponentType = ({ ); }; -const NoOptionsMessage: ComponentType = ({ - innerProps, - children, -}) => ( +const NoOptionsMessage: ComponentType< + NoticeProps & InputPropsBase +> = ({ innerProps, children }) => (
{children}
); -const LoadingMessage: ComponentType = ({ - innerProps, - children, -}) => ( +const LoadingMessage: ComponentType< + NoticeProps & InputPropsBase +> = ({ innerProps, children }) => (
{children}
diff --git a/web-app/client/src/components/Inputs/Select/ControlledSelect.tsx b/web-app/client/src/components/Inputs/Select/ControlledSelect.tsx index db71f40f..eb15b470 100644 --- a/web-app/client/src/components/Inputs/Select/ControlledSelect.tsx +++ b/web-app/client/src/components/Inputs/Select/ControlledSelect.tsx @@ -11,25 +11,21 @@ type ControlProps = { control: Control; rules?: ControlRules; }; -const ControlledSelect = ({ +const ControlledSelect = ({ controlName, control, rules, ...rest -}: SelectProps & ControlProps) => ( +}: SelectProps & ControlProps) => ( ( -