UNPKG

@nestledjs/forms

Version:

A flexible React form library supporting both declarative and imperative usage patterns with TypeScript support

137 lines (136 loc) 5.01 kB
import { default as React } from 'react'; import { UseFormProps, FieldValues } from 'react-hook-form'; import { FormField } from './form-types'; import { FormTheme } from './form-theme'; import { ZodTypeAny } from 'zod'; export interface FormProps<T extends FieldValues = Record<string, unknown>> extends UseFormProps<T> { id: string; fields?: (FormField | null)[]; children?: React.ReactNode; submit: (values: T) => void | Promise<unknown>; className?: string; /** * If true, the entire form is in read-only mode. */ readOnly?: boolean; /** * Determines how the fields should appear when in read-only mode. * 'value': Renders the data as plain text. (Default) * 'disabled': Renders the UI component in a disabled state. */ readOnlyStyle?: 'value' | 'disabled'; theme?: Partial<FormTheme>; /** * Controls the visibility of field labels globally across the form. * - 'default': Shows labels for all fields except Checkbox (default behavior). * - 'all': Shows labels for all fields, including Checkbox. * - 'none': Hides all labels. */ labelDisplay?: 'all' | 'default' | 'none'; /** * Optional Zod schema for form-level validation. * When provided, this schema will validate the entire form's data structure. * Can be used alongside field-level schemas for comprehensive validation. * * @example * ```tsx * import { z } from 'zod' * * const schema = z.object({ * username: z.string().min(3), * email: z.string().email(), * age: z.number().min(18) * }) * * <Form * id="user-form" * schema={schema} * fields={[...]} * submit={handleSubmit} * /> * ``` */ schema?: ZodTypeAny; /** * Current validation group to validate. * When specified, only fields belonging to this group will be validated. * Useful for multi-step forms where you want to validate only the current step. * * @example * ```tsx * // Validate only step 1 fields * <Form * id="multi-step-form" * validationGroup="step-1" * fields={[...]} * submit={handleSubmit} * /> * ``` */ validationGroup?: string; /** * All possible validation groups in this form. * Used for validation group management and step-by-step validation. * * @example * ```tsx * <Form * id="multi-step-form" * validationGroups={['personal-info', 'contact-info', 'preferences']} * validationGroup={currentStep} * fields={[...]} * submit={handleSubmit} * /> * ``` */ validationGroups?: string[]; } /** * Main form component that provides both declarative and imperative form usage patterns. * * Supports declarative usage via the `fields` prop and imperative usage via children. * Provides form context for field components and handles form submission. * * @template T - The type of the form values object * @param id - Unique identifier for the form element * @param fields - Array of field definitions for declarative usage (optional) * @param children - React children for imperative usage (optional) * @param submit - Function called when form is submitted with validated values * @param defaultValues - Initial values for form fields * @param className - CSS classes to apply to the form element * @param readOnly - Whether the entire form should be in read-only mode * @param readOnlyStyle - How read-only fields should be displayed ('value' | 'disabled') * @param theme - Partial theme object to customize form appearance * @param labelDisplay - Global label visibility setting ('all' | 'default' | 'none') * @returns A form element with context providers for field components * * @example * ```tsx * // Declarative usage * <Form * id="user-form" * fields={[ * FormFieldClass.text('username', { label: 'Username', required: true }), * FormFieldClass.email('email', { label: 'Email', required: true }), * ]} * submit={(values) => console.log(values)} * /> * * // Imperative usage * <Form id="custom-form" submit={(values) => handleSubmit(values)}> * <RenderFormField field={FormFieldClass.text('name', { label: 'Name' })} /> * <button type="submit">Submit</button> * </Form> * * // Mixed usage * <Form * id="mixed-form" * fields={[FormFieldClass.text('username', { label: 'Username' })]} * submit={(values) => handleSubmit(values)} * > * <RenderFormField field={FormFieldClass.password('password', { label: 'Password' })} /> * <button type="submit">Submit</button> * </Form> * ``` */ export declare function Form<T extends FieldValues = Record<string, unknown>>({ id, fields, children, submit, defaultValues, className, readOnly, readOnlyStyle, theme: userTheme, labelDisplay, schema, validationGroup, validationGroups, }: Readonly<FormProps<T>>): import("react/jsx-runtime").JSX.Element;