UNPKG

@sinchsmb/ui-kit

Version:

UI kit for SinchSMB frontend

105 lines (96 loc) 3.15 kB
import { useField } from 'formik'; import { useCallback } from 'react'; import type { Except } from 'type-fest'; import { FormFieldProps } from '../../form/FormField/FormField'; import { GeneralFormControlProps } from '../../form/types'; import { useId } from '../../hooks/useId'; import { CommonFormikProps } from '../common/types'; /** Result of {@link useFormikFieldsProps} */ export interface UseFormikFieldsPropsResult< Value, OnChangeValue, ControlProps extends GeneralFormControlProps<any, any>, > { /** Auto-generated field identificator */ id: string; /** Props that should be used in {@link FormField} */ formFieldProps: Omit<FormFieldProps, 'children' | 'id' | 'direction' | 'ariaDescribedBy'>; /** Props that should be used in form control that expect {@link GeneralFormControlProps}. */ controlProps: Except< ControlProps & GeneralFormControlProps<Value, OnChangeValue>, 'className' | 'id' | 'testId' >; } /** * Return general props for {@link FormField} and some form control that expect {@link GeneralFormControlProps} * based on current formik field state. */ export function useFormikFieldsProps< ControlProps extends GeneralFormControlProps<any, any>, Value = ControlProps extends GeneralFormControlProps<infer T, any> ? T : never, OnChange = (ControlProps extends GeneralFormControlProps<any, infer T> ? T : unknown) extends unknown ? Value : ControlProps extends GeneralFormControlProps<any, infer T> ? T : never, >(props: CommonFormikProps<OnChange>): UseFormikFieldsPropsResult<Value, OnChange, ControlProps> { const { disabled, description, requirement, hintText, onHintClick, name, label, noVisualLabel, className, onChange, testId, ariaDescribedBy, ...otherProps } = props; const [field, meta, helpers] = useField(name); const id = useId(); const errorMessageId = useId(); const descriptionMessageId = useId(); const handleOnChange = useCallback( (value: OnChange) => { if (onChange) { onChange(value); } helpers.setValue(value); }, [helpers, onChange], ); const handleOnBlur = useCallback(() => { helpers.setTouched(true); }, [helpers]); return { id, formFieldProps: { errorMessageId: meta.error ? errorMessageId : undefined, descriptionMessageId: !!description ? descriptionMessageId : undefined, label: noVisualLabel ? undefined : label, description, requirement, hintText, onHintClick, className, error: meta.error ? meta.error : undefined, testId, }, controlProps: { ...otherProps, value: field.value, ariaLabel: noVisualLabel ? label : undefined, ariaErrorMessage: meta.error ? errorMessageId : undefined, ariaDescribedBy: ariaDescribedBy ?? (!!description ? descriptionMessageId : undefined), ariaInvalid: !!meta.error, ariaRequired: requirement ?? undefined, required: requirement ?? undefined, disabled: !!disabled, onChange: handleOnChange, onBlur: handleOnBlur, } as ControlProps, }; }