UNPKG

@matthew.ngo/reform

Version:

A flexible and powerful React form management library with advanced validation, state observation, and multi-group support

188 lines (170 loc) 4.54 kB
// @ts-nocheck import { DeepPartial, ExtractObjects, useForm } from 'react-hook-form'; import { AnyObjectSchema } from 'yup'; import { useReformGroups } from './useReformGroups'; // import { useFormValidation } from '../validation/base/useFormValidation'; import { useFormState } from './useFormState'; // import { useFormHandlers } from './useFormHandlers'; import { DynamicFormConfig, ReformReturn } from '../../types'; import { yupResolver } from '@hookform/resolvers/yup'; import { useFormController } from './useFormController'; import { useFieldArrayHelpers } from '../../features/field-array/useFieldArrayHelpers'; import { useConditionalFields } from '../../features/conditional/useConditionalFields'; import { useFormReset } from './useFormReset'; import { useMemo } from 'react'; import { useReformYupIntegration } from '../validation/yup/useReformYupIntegration'; import { FormGroup } from './form-groups'; import { ValidationConfig } from '../validation'; export const useReform = <T extends Record<string, any>>( config: DynamicFormConfig<T> & ValidationConfig<T> ): ReformReturn<T> => { const memoizedConfig = useMemo(() => { const { value, onChange, minGroups = 1, maxGroups = Infinity, defaultData = {} as T, schema, validationMode = 'onChange', reValidateMode = 'onChange', criteriaMode = 'firstError', labels, yupConfig = {}, } = config; return { value, onChange, minGroups, maxGroups, defaultData, schema, validationMode, reValidateMode, criteriaMode, labels, yupConfig, }; }, [ config.value, config.onChange, config.minGroups, config.maxGroups, JSON.stringify(config.defaultData), config.schema, config.validationMode, config.reValidateMode, config.criteriaMode, JSON.stringify(config.labels), JSON.stringify(config.yupConfig), ]); const { value, onChange, minGroups, maxGroups, defaultData, schema, validationMode, reValidateMode, criteriaMode, labels, yupConfig, } = memoizedConfig; type FormType = { groups: FormGroup<T>[] }; const defaultValues = useMemo(() => { return { groups: value ?? Array(minGroups) .fill(null) .map(() => ({ id: Math.random() .toString(36) .substr(2, 9), data: defaultData as ExtractObjects<T> extends never ? T : DeepPartial<T>, })), }; }, [value, minGroups, defaultData]); const methods = useForm<FormType>({ defaultValues, mode: validationMode, reValidateMode, criteriaMode, resolver: schema ? yupResolver((schema as unknown) as AnyObjectSchema) : undefined, shouldUnregister: false, delayError: 0, }); // const validation = useFormValidation( // { schema, validationMode, reValidateMode, criteriaMode, labels }, // methods // ); const groupsManager = useReformGroups({ methods, minGroups, maxGroups, defaultData, onChange, }); const formState = useFormState(methods); // const handlers = useFormHandlers({ // methods, // config, // validation, // }); const controller = useFormController<T>(methods); const fieldArrayHelpers = useFieldArrayHelpers({ methods, onChange, }); const conditionalFields = useConditionalFields({ methods, }); const resetManager = useFormReset({ methods, defaultData, minGroups, }); const partialReform = useMemo( () => ({ getGroups: () => methods.getValues().groups, getGroupData: (index: number) => methods.getValues().groups[index]?.data, config: memoizedConfig, }), [methods, memoizedConfig] ); const yupIntegration = useReformYupIntegration(partialReform as any); return useMemo(() => { const reformReturn: ReformReturn<T> = { formMethods: methods, ...groupsManager, // ...validation, ...formState, // ...handlers, ...controller, ...fieldArrayHelpers, ...conditionalFields, ...resetManager, config: memoizedConfig, // @ts-ignore yup: yupIntegration, }; return reformReturn; }, [ methods, groupsManager, // validation, formState, // handlers, controller, fieldArrayHelpers, conditionalFields, resetManager, memoizedConfig, yupIntegration, ]); };