parent
7ad4ad725e
commit
cbad0ebf5e
1 changed files with 86 additions and 0 deletions
@ -0,0 +1,86 @@ |
||||
import { ForwardedRef, forwardRef, useImperativeHandle, useState } from 'react'; |
||||
|
||||
import createInputOnChangeHandler, { |
||||
CreateInputOnChangeHandlerOptions, |
||||
MapToStateSetter, |
||||
} from '../lib/createInputOnChangeHandler'; |
||||
import OutlinedInputWithLabel, { |
||||
OutlinedInputWithLabelProps, |
||||
} from './OutlinedInputWithLabel'; |
||||
|
||||
type InputWithRefOptionalProps<TypeName extends keyof MapToType> = { |
||||
createInputOnChangeHandlerOptions?: Omit< |
||||
CreateInputOnChangeHandlerOptions<TypeName>, |
||||
'set' |
||||
>; |
||||
valueType?: TypeName | 'string'; |
||||
}; |
||||
|
||||
type InputWithRefProps<TypeName extends keyof MapToType> = |
||||
OutlinedInputWithLabelProps & InputWithRefOptionalProps<TypeName>; |
||||
|
||||
type InputForwardedRefContent<TypeName extends keyof MapToType> = { |
||||
isChangedByUser?: boolean; |
||||
setValue?: MapToStateSetter[TypeName]; |
||||
value?: MapToType[TypeName]; |
||||
}; |
||||
|
||||
const MAP_TO_INITIAL_VALUE: MapToType = { |
||||
number: 0, |
||||
string: '', |
||||
}; |
||||
|
||||
const INPUT_WITH_REF_DEFAULT_PROPS: Required< |
||||
InputWithRefOptionalProps<'string'> |
||||
> = { |
||||
createInputOnChangeHandlerOptions: {}, |
||||
valueType: 'string', |
||||
}; |
||||
|
||||
const InputWithRef = forwardRef( |
||||
<TypeName extends keyof MapToType>( |
||||
{ |
||||
createInputOnChangeHandlerOptions: { |
||||
postSet: postSetAppend, |
||||
...restCreateInputOnChangeHandlerOptions |
||||
} = INPUT_WITH_REF_DEFAULT_PROPS.createInputOnChangeHandlerOptions, |
||||
valueType = INPUT_WITH_REF_DEFAULT_PROPS.valueType, |
||||
...restProps |
||||
}: InputWithRefProps<TypeName>, |
||||
ref: ForwardedRef<InputForwardedRefContent<TypeName>>, |
||||
) => { |
||||
const [value, setValue] = useState<MapToType[TypeName]>( |
||||
MAP_TO_INITIAL_VALUE[valueType] as MapToType[TypeName], |
||||
) as [MapToType[TypeName], MapToStateSetter[TypeName]]; |
||||
const [isChangedByUser, setIsChangedByUser] = useState<boolean>(false); |
||||
|
||||
const onChange = createInputOnChangeHandler<TypeName>({ |
||||
postSet: (...args) => { |
||||
setIsChangedByUser(true); |
||||
postSetAppend?.call(null, ...args); |
||||
}, |
||||
set: setValue, |
||||
setType: valueType, |
||||
...restCreateInputOnChangeHandlerOptions, |
||||
}); |
||||
|
||||
useImperativeHandle( |
||||
ref, |
||||
() => ({ |
||||
isChangedByUser, |
||||
setValue, |
||||
value, |
||||
}), |
||||
[isChangedByUser, value], |
||||
); |
||||
|
||||
return <OutlinedInputWithLabel {...{ onChange, value, ...restProps }} />; |
||||
}, |
||||
); |
||||
|
||||
InputWithRef.defaultProps = INPUT_WITH_REF_DEFAULT_PROPS; |
||||
InputWithRef.displayName = 'InputWithRef'; |
||||
|
||||
export type { InputForwardedRefContent, InputWithRefProps }; |
||||
|
||||
export default InputWithRef; |
Loading…
Reference in new issue