UNPKG

@matthew.ngo/reform

Version:

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

230 lines (229 loc) 6.62 kB
import { UseFormStateReturn } from "react-hook-form"; import { FormGroup } from "../../core/form/form-groups"; /** * Callback function type for field value changes * * @template T - Form data type * @template K - Field key type * @param value - Current field value * @param previousValue - Previous field value (undefined if first change) * @param groupIndex - Index of the group containing the field * @param formData - Complete form data */ export declare type FieldWatchCallback<T, K extends keyof T> = (value: T[K], previousValue: T[K] | undefined, groupIndex: number, formData: { groups: FormGroup<T>[]; }) => void; /** * Configuration for field watching * * @template T - Form data type * @template K - Field key type */ export interface FieldWatchConfig<T, K extends keyof T> { /** * Field name to watch */ field: K; /** * Optional group index to limit watching to a specific group * If not provided, watches the field across all groups */ groupIndex?: number; /** * Callback function triggered when field value changes */ callback: FieldWatchCallback<T, K>; /** * Debounce time in milliseconds * Useful for expensive operations or to limit API calls */ debounce?: number; /** * Whether to trigger the callback immediately with current value * @default false */ immediate?: boolean; } /** * Field watcher manager return type * * @template T - Form data type */ export interface FieldWatcherReturn<T> { /** * Register a new field watcher * * @returns Unsubscribe function to remove the watcher * * @example * // Watch a specific field in all groups * const unsubscribe = watchField({ * field: 'email', * callback: (value, prevValue, groupIndex) => { * console.log(`Email changed to ${value} in group ${groupIndex}`); * } * }); * * // Later, when no longer needed * unsubscribe(); */ watchField: <K extends keyof T>(config: FieldWatchConfig<T, K>) => () => void; /** * Register multiple field watchers at once * * @returns Function to unsubscribe all registered watchers * * @example * // Watch multiple fields * const unsubscribeAll = watchFields([ * { * field: 'firstName', * callback: (value) => updateDisplayName(value) * }, * { * field: 'email', * callback: (value) => validateEmailAsync(value), * debounce: 500 * } * ]); */ watchFields: <K extends keyof T>(configs: FieldWatchConfig<T, K>[]) => () => void; /** * Get the current value of a field * * @example * const email = getFieldValue('email', 0); // Get email from first group */ getFieldValue: <K extends keyof T>(field: K, groupIndex: number) => T[K] | undefined; /** * Manually trigger callbacks for a specific field * Useful when you need to force an update */ triggerFieldWatch: <K extends keyof T>(field: K, groupIndex?: number) => void; } /** * Handler for form state changes * * @template T - Form data type */ export declare type FormStateChangeHandler<T> = (state: UseFormStateReturn<{ groups: FormGroup<T>[]; }>, previousState: Partial<UseFormStateReturn<{ groups: FormGroup<T>[]; }>> | null) => void; /** * Form state subscription object */ export interface FormStateSubscription { /** * Unsubscribe from form state changes */ unsubscribe: () => void; } /** * Configuration options for form state observer * * @template T - Form data type */ export interface FormStateObserverOptions<T> { /** * Called on any form state change */ onChange?: FormStateChangeHandler<T>; /** * Called when form dirty state changes * Useful for auto-save functionality */ onDirtyChange?: (isDirty: boolean) => void; /** * Called when form errors change * Useful for custom error handling or analytics */ onErrorsChange?: (hasErrors: boolean, errors: Record<string, any>) => void; /** * Called when form submit count changes * Useful for tracking submission attempts */ onSubmitCountChange?: (submitCount: number) => void; /** * Called when touched fields change * Useful for progressive validation */ onTouchedChange?: (isTouched: boolean, touchedFields: UseFormStateReturn<{ groups: FormGroup<T>[]; }>['touchedFields']) => void; /** * Called when form becomes valid or invalid */ onValidChange?: (isValid: boolean) => void; /** * Called when form submission state changes */ onSubmittingChange?: (isSubmitting: boolean) => void; } /** * Form state observer return type * * @template T - Form data type */ export interface FormStateObserverReturn<T> { /** * Subscribe to form state changes * * @returns Subscription object with unsubscribe method * * @example * const subscription = formStateObserver.subscribe((state, prevState) => { * if (state.isDirty && !prevState?.isDirty) { * saveFormDraft(form.getValues()); * } * }); * * // Later, when no longer needed * subscription.unsubscribe(); */ subscribe: (handler: FormStateChangeHandler<T>) => FormStateSubscription; /** * Get current form state */ getState: () => UseFormStateReturn<{ groups: FormGroup<T>[]; }>; /** * Get previous form state */ getPreviousState: () => Partial<UseFormStateReturn<{ groups: FormGroup<T>[]; }>> | null; /** * Check if form is currently dirty */ isDirty: () => boolean; /** * Check if form has any errors */ hasErrors: () => boolean; /** * Check if form is currently being submitted */ isSubmitting: () => boolean; /** * Check if form is valid */ isValid: () => boolean; } /** * Combined return type for React Hook Form enhanced features * * @template T - Form data type */ export interface ReformHookFormEnhancementsReturn<T> { /** * Field watcher functionality */ fieldWatcher: FieldWatcherReturn<T>; /** * Form state observer functionality */ stateObserver: FormStateObserverReturn<T>; }