diff --git a/striker-ui/components/InputWithRef.tsx b/striker-ui/components/InputWithRef.tsx index 7600e3d7..89c016f4 100644 --- a/striker-ui/components/InputWithRef.tsx +++ b/striker-ui/components/InputWithRef.tsx @@ -20,17 +20,19 @@ type InputWithRefOptionalPropsWithDefault< > = { createInputOnChangeHandlerOptions?: CreateInputOnChangeHandlerOptions; required?: boolean; - valueKey?: string; valueType?: TypeName; }; -type InputWithRefOptionalPropsWithoutDefault = { +type InputWithRefOptionalPropsWithoutDefault< + TypeName extends keyof MapToInputType, +> = { inputTestBatch?: InputTestBatch; onFirstRender?: (args: { isRequired: boolean }) => void; + valueKey?: CreateInputOnChangeHandlerOptions['valueKey']; }; type InputWithRefOptionalProps = InputWithRefOptionalPropsWithDefault & - InputWithRefOptionalPropsWithoutDefault; + InputWithRefOptionalPropsWithoutDefault; type InputWithRefProps< TypeName extends keyof MapToInputType, @@ -48,6 +50,7 @@ type InputForwardedRefContent = { const INPUT_TEST_ID = 'input'; const MAP_TO_INITIAL_VALUE: MapToInputType = { + boolean: false, number: 0, string: '', }; @@ -55,38 +58,44 @@ const MAP_TO_INITIAL_VALUE: MapToInputType = { const INPUT_WITH_REF_DEFAULT_PROPS: Required< InputWithRefOptionalPropsWithDefault<'string'> > & - InputWithRefOptionalPropsWithoutDefault = { + InputWithRefOptionalPropsWithoutDefault<'string'> = { createInputOnChangeHandlerOptions: {}, required: false, - valueKey: 'value', valueType: 'string', }; const InputWithRef = forwardRef( ( { - createInputOnChangeHandlerOptions: { - postSet: postSetAppend, - ...restCreateInputOnChangeHandlerOptions - } = INPUT_WITH_REF_DEFAULT_PROPS.createInputOnChangeHandlerOptions as CreateInputOnChangeHandlerOptions, input, inputTestBatch, onFirstRender, required: isRequired = INPUT_WITH_REF_DEFAULT_PROPS.required, - valueKey = INPUT_WITH_REF_DEFAULT_PROPS.valueKey, + valueKey, valueType = INPUT_WITH_REF_DEFAULT_PROPS.valueType as TypeName, + // Props with initial value that depend on others. + createInputOnChangeHandlerOptions: { + postSet: postSetAppend, + valueKey: onChangeValueKey = valueKey, + ...restCreateInputOnChangeHandlerOptions + } = INPUT_WITH_REF_DEFAULT_PROPS.createInputOnChangeHandlerOptions as CreateInputOnChangeHandlerOptions, }: InputWithRefProps, ref: ForwardedRef>, ) => { + const { props: inputProps } = input; + + const vKey = useMemo( + () => onChangeValueKey ?? ('checked' in inputProps ? 'checked' : 'value'), + [inputProps, onChangeValueKey], + ); + const { - props: { - onBlur: initOnBlur, - onChange: initOnChange, - onFocus: initOnFocus, - value: initValue = MAP_TO_INITIAL_VALUE[valueType], - ...restInitProps - }, - } = input; + onBlur: initOnBlur, + onChange: initOnChange, + onFocus: initOnFocus, + [vKey]: initValue = MAP_TO_INITIAL_VALUE[valueType], + ...restInitProps + } = inputProps; const isFirstRender = useIsFirstRender(); @@ -136,6 +145,7 @@ const InputWithRef = forwardRef( }, set: setValue, setType: valueType, + valueKey: vKey, ...restCreateInputOnChangeHandlerOptions, }), [ @@ -143,6 +153,7 @@ const InputWithRef = forwardRef( postSetAppend, restCreateInputOnChangeHandlerOptions, setValue, + vKey, valueType, ], ); @@ -179,7 +190,7 @@ const InputWithRef = forwardRef( onChange, onFocus, required: isRequired, - [valueKey]: inputValue, + [vKey]: inputValue, }); }, ); diff --git a/striker-ui/lib/createInputOnChangeHandler.ts b/striker-ui/lib/createInputOnChangeHandler.ts index e6b33c37..b560e05f 100644 --- a/striker-ui/lib/createInputOnChangeHandler.ts +++ b/striker-ui/lib/createInputOnChangeHandler.ts @@ -1,4 +1,4 @@ -import { InputProps as MUIInputProps } from '@mui/material'; +import { ChangeEventHandler } from 'react'; import MAP_TO_VALUE_CONVERTER from './consts/MAP_TO_VALUE_CONVERTER'; @@ -8,10 +8,11 @@ const createInputOnChangeHandler = preSet, set, setType = 'string' as TypeName, - }: CreateInputOnChangeHandlerOptions = {}): MUIInputProps['onChange'] => + valueKey = 'value', + }: CreateInputOnChangeHandlerOptions = {}): ChangeEventHandler => (event) => { const { - target: { value }, + target: { [valueKey]: value }, } = event; const postConvertValue = MAP_TO_VALUE_CONVERTER[setType]( value, diff --git a/striker-ui/types/CreateInputOnChangeHandlerFunction.d.ts b/striker-ui/types/CreateInputOnChangeHandlerFunction.d.ts index 5999c37d..0c72595d 100644 --- a/striker-ui/types/CreateInputOnChangeHandlerFunction.d.ts +++ b/striker-ui/types/CreateInputOnChangeHandlerFunction.d.ts @@ -1,4 +1,4 @@ -type MapToInputType = Pick; +type MapToInputType = Pick; type InputOnChangeParameters = Parameters< Exclude @@ -12,4 +12,8 @@ type CreateInputOnChangeHandlerOptions = preSet?: (...args: InputOnChangeParameters) => void; set?: StateSetter; setType?: TypeName; + valueKey?: Extract< + keyof import('react').ChangeEvent['target'], + 'checked' | 'value' + >; };