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