/** * Form module types and interfaces. * * @module bquery/forms */ import type { Computed, Signal } from '../reactive/index'; /** * Result of a single validation rule. * A string indicates an error message; `true` or `undefined` means valid. */ export type ValidationResult = string | true | undefined; /** * Synchronous validator function. * * @param value - The current field value * @returns A validation result — `true` / `undefined` for valid, or an error string */ export type SyncValidator = (value: T) => ValidationResult; /** * Asynchronous validator function. * * @param value - The current field value * @returns A promise resolving to a validation result */ export type AsyncValidator = (value: T) => Promise; /** * Either a sync or async validator. */ export type Validator = SyncValidator | AsyncValidator; /** * Configuration for a single form field. * * @template T - The type of the field value */ export type FieldConfig = { /** Initial value for this field */ initialValue: T; /** Validation rules applied in order; stops at first failure */ validators?: Validator[]; }; /** * Reactive state for a single form field. * * @template T - The type of the field value */ export type FormField = { /** Reactive signal holding the current value */ value: Signal; /** Reactive signal for the first validation error (empty string when valid) */ error: Signal; /** Whether the field value differs from its initial value */ isDirty: Computed; /** Whether the field has been interacted with (blur / explicit touch) */ isTouched: Signal; /** Whether the field has never been modified */ isPristine: Computed; /** Mark the field as touched */ touch: () => void; /** Reset the field to its initial value and clear errors */ reset: () => void; }; /** * Controls when {@link useFormField} runs validation automatically. */ export type FormFieldValidationMode = 'manual' | 'change' | 'blur' | 'both'; /** * Configuration for {@link useFormField}. * * @template T - The type of the field value */ export type UseFormFieldOptions = { /** Validation rules applied in order; stops at first failure */ validators?: Validator[]; /** When validation should run automatically. Defaults to `'manual'`. */ validateOn?: FormFieldValidationMode; /** Delay automatic validation by the given milliseconds. Defaults to `0`. */ debounceMs?: number; /** Initial error message for the field. Defaults to an empty string. */ initialError?: string; }; /** * Return value of {@link useFormField}. * * Extends the standard field state with validation helpers for standalone field usage. * * @template T - The type of the field value */ export type UseFormFieldReturn = FormField & { /** Whether the current field has no validation error */ isValid: Computed; /** Reactive signal: `true` while async validation is still running */ isValidating: Signal; /** Validate the current field value immediately */ validate: () => Promise; /** Cancel pending timers and automatic validation subscriptions */ destroy: () => void; }; /** * Map of field names to their reactive field state. */ export type FormFields> = { [K in keyof T]: FormField; }; /** * Map of field names to their error strings (reactive signals). */ export type FormErrors> = { [K in keyof T]: Signal; }; /** * Cross-field validation function. * Receives all current field values and returns a map of field name → error message, * or an empty object / undefined if all fields are valid. */ export type CrossFieldValidator> = (values: T) => Partial> | undefined | Promise> | undefined>; /** * Submit handler function. * * @template T - Shape of the form values */ export type SubmitHandler> = (values: T) => void | Promise; /** * Configuration for `createForm()`. * * @template T - Shape of the form values * * @example * ```ts * const config: FormConfig<{ name: string; age: number }> = { * fields: { * name: { initialValue: '', validators: [required('Name is required')] }, * age: { initialValue: 0, validators: [min(1, 'Must be positive')] }, * }, * onSubmit: (values) => console.log(values), * }; * ``` */ export type FormConfig> = { /** Per-field configuration with initial values and validators */ fields: { [K in keyof T]: FieldConfig; }; /** Optional cross-field validators run after per-field validation */ crossValidators?: CrossFieldValidator[]; /** Callback invoked on successful form submission */ onSubmit?: SubmitHandler; }; /** * Return value of `createForm()`. * * @template T - Shape of the form values */ export type Form> = { /** Reactive field objects keyed by field name */ fields: FormFields; /** Shorthand error signals keyed by field name */ errors: FormErrors; /** Computed signal: `true` when all fields pass validation */ isValid: Computed; /** Computed signal: `true` when any field value differs from initial */ isDirty: Computed; /** Reactive signal: `true` while the submit handler is executing */ isSubmitting: Signal; /** Validate all fields and, if valid, call the `onSubmit` handler */ handleSubmit: () => Promise; /** Validate a single field by name */ validateField: (name: keyof T & string) => Promise; /** Validate all fields without submitting */ validate: () => Promise; /** Reset the entire form to initial values */ reset: () => void; /** Get a snapshot of all current field values */ getValues: () => T; /** * Bulk-set field values from a partial object. * Only fields present in the object are updated; missing keys are left unchanged. */ setValues: (values: Partial) => void; /** * Bulk-set field error messages from a partial object. * Useful for applying server-side validation errors. */ setErrors: (errors: Partial>) => void; }; //# sourceMappingURL=types.d.ts.map