UNPKG

@vtaits/react-hook-form-schema

Version:

Integration of react-hook-form and @vtaits/form-schema

323 lines (317 loc) 7.87 kB
// src/core/constants.ts var CLIENT_ERROR = "__CLIENT_ERROR__"; var SERVER_ERROR = "__SERVER_ERROR__"; // src/core/getFieldPath.ts function getFieldPath(fieldName, parents) { if (!parents || parents.length === 0) { return fieldName; } return [ ...parents.map(({ name }) => name).filter((name) => ["string", "number"].includes(typeof name)), fieldName ].join("."); } // src/core/renderBySchema.tsx import { isEqual, isPromise } from "es-toolkit"; import { useEffect, useMemo, useRef, useState } from "react"; import { useAsync } from "react-async-hook"; import { jsx } from "react/jsx-runtime"; function FieldProxy({ formResult, getFieldSchema, getFieldType, getValues, name, payload = void 0, parents = void 0 }) { const fieldSchema = getFieldSchema(name); const fieldType = getFieldType(fieldSchema); const { createGetFieldSchema } = fieldType; const render = fieldSchema.render || fieldType.render; const values = getValues(); const providedParents = parents || [ { values } ]; if (fieldSchema.getDependencies) { formResult.watch(); } const dependencies = fieldSchema.getDependencies?.({ values, phase: "render", getFieldSchema, getFieldType, parents: providedParents }); const countCreateGetFieldSchema = () => { if (createGetFieldSchema) { return createGetFieldSchema({ fieldSchema, getFieldSchema, getFieldType, values, phase: "render", parents: providedParents, dependencies }); } return getFieldSchema; }; const [createGetFieldSchemaResult, setCreateGetFieldSchemaResult] = useState( () => countCreateGetFieldSchema() ); const { result: createGetFieldSchemaResultAsync } = useAsync(async () => { const res = await createGetFieldSchemaResult; return res; }, [createGetFieldSchemaResult]); const childGetFieldSchema = useMemo(() => { if (isPromise(createGetFieldSchemaResult)) { return createGetFieldSchemaResultAsync; } return createGetFieldSchemaResult; }, [createGetFieldSchemaResult, createGetFieldSchemaResultAsync]); const isFirstRenderCheckDependenciesRef = useRef(true); const prevDependenciesRef = useRef(dependencies); useEffect(() => { if (isFirstRenderCheckDependenciesRef.current) { isFirstRenderCheckDependenciesRef.current = false; return; } if (!isEqual(prevDependenciesRef.current, dependencies)) { setCreateGetFieldSchemaResult(countCreateGetFieldSchema()); prevDependenciesRef.current = dependencies; } }, [dependencies]); if (!childGetFieldSchema) { return null; } return render( { fieldPath: getFieldPath(name, providedParents), name, payload, parents: providedParents, getFieldSchema: childGetFieldSchema, getFieldType, fieldSchema, dependencies }, formResult ); } function renderBySchema(formResult, getFieldSchema, getFieldType, getValues, name, payload, parents) { return /* @__PURE__ */ jsx( FieldProxy, { formResult, getFieldSchema, getFieldType, getValues, name, payload, parents } ); } // src/core/useFormSchema.ts import { parse, serialize, setFieldErrors, setValues as setValuesBase, validateBeforeSubmit } from "@vtaits/form-schema"; import { useCallback, useMemo as useMemo2 } from "react"; import { useForm } from "react-hook-form"; // src/core/makeSetError.ts function makeSetError(setError, errorType, onError) { return (fieldName, parents, error) => { onError(); if (parents) { setError( `${[ ...parents.filter((parent) => typeof parent.name !== "undefined").map((parent) => parent.name), fieldName ].join(".")}`, { type: errorType, message: error } ); } else { setError(fieldName, { type: errorType, message: error }); } }; } // src/core/useFormSchema.ts var defaultGetFieldSchema = (fieldSchema) => fieldSchema; var defaultMapErrors = (errors) => errors; function useFormSchema(props) { const { defaultValues, getFieldSchema = defaultGetFieldSchema, getFieldType, mapErrors = defaultMapErrors, names, ...rest } = props; const parseValues = useCallback( (values) => parse({ values, names, getFieldSchema, getFieldType, parents: [ { values } ] }), [getFieldSchema, getFieldType, names] ); const parsedDefaultValues = useMemo2(() => { if (typeof defaultValues === "function") { const asyncDefaultValues = defaultValues; return () => asyncDefaultValues().then((rawInitialValues2) => parseValues(rawInitialValues2)).then((result) => result || {}); } const rawInitialValues = defaultValues || {}; const parseResult = parseValues(rawInitialValues); return () => parseResult; }, [defaultValues, parseValues]); const formResult = useForm({ ...rest, defaultValues: parsedDefaultValues }); const { handleSubmit, ...restResult } = formResult; const { getValues, setValue, setError } = restResult; const setValues = useCallback( (values) => setValuesBase({ setValue, values, names, getFieldSchema, getFieldType, parents: [ { values } ] }), [getFieldSchema, getFieldType, names, setValue] ); const parseAndSetValues = useCallback( async (rawValues) => { const values = await parseValues(rawValues); setValues(values); }, [parseValues, setValues] ); const onSubmitBySchema = useCallback( async (onSubmit, values, event) => { let hasCleintError = false; await validateBeforeSubmit({ setError: makeSetError(setError, CLIENT_ERROR, () => { hasCleintError = true; }), values, names, getFieldSchema, getFieldType, parents: [ { values } ] }); if (hasCleintError) { return; } const valuesForSubmit = await serialize({ values, names, getFieldSchema, getFieldType, parents: [ { values } ] }); const rawErrors = await onSubmit(valuesForSubmit, values, event); if (!rawErrors) { return; } const preparedErrors = mapErrors( rawErrors, valuesForSubmit, values ); await setFieldErrors({ setError: makeSetError(setError, SERVER_ERROR, () => { }), errors: preparedErrors, names, getFieldSchema, getFieldType, values: valuesForSubmit, rawValues: values, parents: [ { values } ] }); }, [names, getFieldSchema, getFieldType, mapErrors, setError] ); const handleSubmitBySchema = useCallback( (onSubmit, onError) => { const submitHandler = (values, event) => onSubmitBySchema(onSubmit, values, event); return handleSubmit( submitHandler, onError ); }, [handleSubmit, onSubmitBySchema] ); const renderField = useCallback( (name, payload, parents) => renderBySchema( formResult, getFieldSchema, getFieldType, getValues, name, payload, parents ), [formResult, getFieldSchema, getFieldType, getValues] ); return { ...restResult, handleSubmit: handleSubmitBySchema, parseValues, setValues, parseAndSetValues, renderField }; } export { CLIENT_ERROR, SERVER_ERROR, getFieldPath, renderBySchema, useFormSchema }; //# sourceMappingURL=chunk-VHBMH3GH.js.map