UNPKG

@matthew.ngo/reform

Version:

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

86 lines (79 loc) 2.6 kB
import * as yup from 'yup'; import { ObjectSchema, AnyObject, Schema } from 'yup'; /** * Type representing the Reform data structure */ export type ReformSchema<T> = { groups: Array<{ data: T }> }; /** * Creates a Yup schema compatible with Reform's data structure * Supports multiple ways of defining schemas to match user preferences * * @template T - The type of form data * @param schemaDefinition - Schema definition in various formats * @returns Yup schema for the entire Reform structure * * @example * // Method 1: Using field-by-field schema definition * const userSchema = createReformSchema({ * name: yup.string().required(), * age: yup.number().min(18), * tags: yup.array().of(yup.string()) * }); * * @example * // Method 2: Using a pre-defined Yup object schema * const fieldSchema = yup.object({ * name: yup.string().required(), * age: yup.number().min(18) * }); * const userSchema = createReformSchema(fieldSchema); * * @example * // Method 3: Using a schema builder function * const userSchema = createReformSchema(fields => ({ * name: fields.string().required(), * email: fields.string().email(), * preferences: fields.object({ * theme: fields.string(), * notifications: fields.boolean() * }) * })); */ export function createReformSchema<T extends Record<string, any>>( schemaDefinition: | Record<string, Schema<any>> | ObjectSchema<T> | ((fields: typeof yup) => Record<string, Schema<any>>) ): ObjectSchema<{ groups: Array<{ data: T }> }, AnyObject, any> { // Determine the data schema based on the input type let dataSchema: ObjectSchema<T>; if (typeof schemaDefinition === 'function') { // Handle schema builder function const fieldSchemas = schemaDefinition(yup); dataSchema = yup.object().shape(fieldSchemas) as ObjectSchema<T>; } else if (schemaDefinition instanceof yup.ObjectSchema) { // Handle pre-defined object schema dataSchema = schemaDefinition; } else { // Handle field-by-field schema definition dataSchema = yup.object().shape(schemaDefinition) as ObjectSchema<T>; } // Create the schema for a group (which contains data) const groupSchema = yup.object({ data: dataSchema, }); // Create the full Reform schema (which contains groups) const schema = yup.object({ groups: yup .array() .of(groupSchema) .required() .min(1), }); // Use a more explicit type assertion to ensure compatibility return (schema as unknown) as ObjectSchema< { groups: Array<{ data: T }> }, AnyObject, any >; }