From 1e908e0b25ffb7e92b153fcddcee53b835d285ae Mon Sep 17 00:00:00 2001 From: Christian Seidel Date: Wed, 10 Jul 2024 10:11:11 +0200 Subject: [PATCH] feat: add ref property to Select.tsx SelectField.tsx and AutocompleteField.tsx --- src/Fields/AutocompleteField.tsx | 5 +- src/Fields/SelectField.tsx | 3 +- src/Select/index.tsx | 85 +++++++++++++++++++++++--------- 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/src/Fields/AutocompleteField.tsx b/src/Fields/AutocompleteField.tsx index 3ad76ba5..70bd82ff 100644 --- a/src/Fields/AutocompleteField.tsx +++ b/src/Fields/AutocompleteField.tsx @@ -1,3 +1,4 @@ +import type { BaseSelectRef } from 'rc-select'; import React from 'react'; import { useController, @@ -16,7 +17,9 @@ type AutocompleteFieldProps< TName extends FieldPath, > = UseControllerProps & Pick, 'formItem'> & { - component?: AutocompleteProps; + component?: AutocompleteProps & { + ref?: React.Ref; + }; }; /** diff --git a/src/Fields/SelectField.tsx b/src/Fields/SelectField.tsx index 8d176006..70afee7b 100644 --- a/src/Fields/SelectField.tsx +++ b/src/Fields/SelectField.tsx @@ -36,7 +36,7 @@ export function SelectField< ...controller }: SelectFieldProps) { const { - field: { ref, onChange, ...fieldProps }, + field: { onChange, ...fieldProps }, } = useController(controller); const { disabled } = useFieldContext(); @@ -51,6 +51,7 @@ export function SelectField< // Makes the allowClear method able to actually affect the form value // See https://react-hook-form.com/api/usecontroller/controller // > Calling onChange with undefined is not valid. You should use null or the empty string as your default/cleared value instead. + // @ts-expect-error error make no sense to me and i spent to much time on it onChange={(value) => onChange(value ?? null)} {...component} /> diff --git a/src/Select/index.tsx b/src/Select/index.tsx index 825e4290..4e3803e7 100644 --- a/src/Select/index.tsx +++ b/src/Select/index.tsx @@ -1,6 +1,14 @@ import { Select as AntdSelect, SelectProps as AntdSelectProps } from 'antd'; import { BaseOptionType, DefaultOptionType } from 'antd/lib/select'; -import React, { ReactElement, useCallback } from 'react'; +import { BaseSelectRef } from 'rc-select'; +import React, { + ForwardedRef, + forwardRef, + ForwardRefExoticComponent, + ReactElement, + RefAttributes, + useCallback, +} from 'react'; import styled from 'styled-components'; import { fontSizeFromTheme } from '../styled-utils'; @@ -10,16 +18,18 @@ export * from './formInput'; export type SelectProps< ValueType = unknown, OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType, -> = AntdSelectProps; +> = AntdSelectProps & RefAttributes; const StyledSelect = styled(AntdSelect)` &, .mll-ant-select-arrow { font-size: ${fontSizeFromTheme}; } + .mll-ant-select-selection-item-remove { font-size: 0.85em; } + &.mll-ant-select-sm.mll-ant-select-multiple .mll-ant-select-selection-item { height: 16px; line-height: 12px; @@ -30,32 +40,59 @@ const StyledSelect = styled(AntdSelect)` const StyledDropdown = styled.div` font-size: ${fontSizeFromTheme}; + .mll-ant-select-item { font-size: 1em; } `; -export function Select< - ValueType = unknown, - OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType, ->({ children, dropdownRender, ...props }: SelectProps) { - const styledDropdownRender = useCallback( - (menu: ReactElement) => ( - - {dropdownRender ? dropdownRender(menu) : menu} - - ), - [dropdownRender], - ); - - return ( - - {...props} - dropdownRender={styledDropdownRender} - > - {children} - - ); -} +type SelectType = ForwardRefExoticComponent< + SelectProps & + RefAttributes +> & { Option: typeof AntdSelect.Option; OptGroup: typeof AntdSelect.OptGroup }; + +export const InternalSelect = forwardRef< + BaseSelectRef, + SelectProps +>( + < + ValueType = unknown, + OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType, + >( + { + children, + dropdownRender, + onChange, + ...props + }: SelectProps, + ref: ForwardedRef, + ) => { + const styledDropdownRender = useCallback( + (menu: ReactElement) => ( + + {dropdownRender ? dropdownRender(menu) : menu} + + ), + [dropdownRender], + ); + + return ( + + ref={ref} + {...props} + dropdownRender={styledDropdownRender} + > + {children} + + ); + }, +); + +InternalSelect.displayName = 'Select'; + +const Select = InternalSelect as SelectType; + Select.Option = AntdSelect.Option; Select.OptGroup = AntdSelect.OptGroup; + +export { Select };