@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
TypeScript
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;