declare module "usetheform/types" { export type ReducerFn = ( state: Value, prevState: Value, formState: FormState ) => Value; export type ValidatorFn = ( value: Value, formState: FormState ) => string | undefined; export type AsyncValidatorFn = ( value: Value, ) => Promise; export type OnSubmitFormFn = ( state: FormState, isFormValid: boolean ) => Promise | boolean | void; export type OnInitFormFn = ( state: FormState, isFormValid: boolean ) => void; export type OnChangeFormFn = ( state: FormState, isFormValid: boolean ) => void; export type OnResetFormFn = ( state: FormState, isFormValid: boolean ) => void; } declare module "usetheform" { import { AsyncValidatorFn, ReducerFn, OnSubmitFormFn, OnInitFormFn, OnChangeFormFn, OnResetFormFn, ValidatorFn } from "usetheform/types"; type InputType = | "button" | "checkbox" | "color" | "date" | "datetime-local" | "email" | "file" | "hidden" | "image" | "month" | "number" | "password" | "radio" | "range" | "reset" | "search" | "submit" | "tel" | "text" | "time" | "url" | "week" | "custom"; interface FormStore { getState: () => FormState; update: (formState: FormState, shouldNotify?: boolean) => void; } interface FormProps{ children?: React.ReactNode; initialState?: Partial; onChange?: OnChangeFormFn; onInit?: OnInitFormFn; onReset?: OnResetFormFn; onSubmit?: OnSubmitFormFn; onValidation?: (errors: string[], isValid: boolean) => void; resetSyncErr?: () => void; validators?: Array>; asyncValidator?: AsyncValidatorFn; onAsyncValidation?: (status: AsyncStatus) => void; resetAsyncErr?: () => void; touched?: boolean; reducers?: ReducerFn | ReducerFn[]; name?: string; action?: string; formStore?: FormStore; innerRef?: React.Ref; } interface UseFieldPropsReturnBase { name?: string; value?: InputValue; multiple?: boolean; checked?: boolean; onChange?: (event: React.FocusEvent) => void; onBlur?: (event: React.FocusEvent) => void; onFocus?: (event: React.FocusEvent) => void; } interface UseFieldReturnCustom extends UseFieldPropsReturnBase { type: "custom"; setValue: (value: InputValue) => void; } interface UseFieldReturnStandard extends UseFieldPropsReturnBase { type: Exclude; } interface CommonInputProps { name?: string; value?: InputValue; index?: number | string; validators?: Array>; asyncValidator?: AsyncValidatorFn onValidation?: (errors: string[], isValid: boolean) => void; onAsyncValidation?: (status: AsyncStatus) => void; resetSyncErr?: () => void; resetAsyncErr?: () => void; touched?: boolean; multiple?: boolean; reducers?: ReducerFn | ReducerFn[]; onChange?: (value: InputValue, event: React.ChangeEvent) => void; onBlur?: (event: React.FocusEvent) => void; onFocus?: (event: React.FocusEvent) => void; innerRef?: React.Ref; } interface CheckedInputProps extends CommonInputProps { type: "checkbox" | "radio"; checked?: boolean; } interface NonCheckedInputProps extends CommonInputProps { type: Exclude; checked?: never; } type InputProps = | CheckedInputProps | NonCheckedInputProps; type SelectProps = CommonInputProps & React.SelectHTMLAttributes; // Base props for Collection component interface UseCollectionPropsBase { type: "object" | "array"; touched?: boolean; value?: CollectionValue; reducers?: ReducerFn | ReducerFn[]; onValidation?: (errors: string[], isValid: boolean) => void; validators?: Array>; asyncValidator?: AsyncValidatorFn; onAsyncValidation?: (status: AsyncStatus) => void; resetAsyncErr?: () => void; } // Props when 'name' is provided interface UseCollectionPropsWithName extends UseCollectionPropsBase { name: string; // `name` is required index?: never; // `index` should never be provided when `name` is present } // Props when 'index' is provided interface UseCollectionPropsWithIndex extends UseCollectionPropsBase { index: number | string; // `index` is required name?: never; // `name` should never be provided when `index` is present } type UseCollectionProps = UseCollectionPropsWithName | UseCollectionPropsWithIndex interface UseFieldCustomInputProps extends CommonInputProps { type: "custom"; } type useCollectionReturnType = { value: CollectionValue; updateCollection: ( key: CollectionValue extends Array ? number : keyof CollectionValue, value: unknown ) => void; state: FormState; }; // Base props for Collection component interface CollectionPropsBase { children?: React.ReactNode; as?: string // Allow string element as 'as' object?: boolean; array?: boolean; touched?: boolean; value?: Partial; reducers?: ReducerFn | ReducerFn[]; onValidation?: (errors: string[], isValid: boolean) => void; validators?: Array>; asyncValidator?: AsyncValidatorFn; onAsyncValidation?: (status: AsyncStatus) => void; resetAsyncErr?: () => void; } // Props when 'name' is provided interface CollectionPropsWithName extends CollectionPropsBase { name: string; // `name` is required index?: never; // `index` should never be provided when `name` is present } // Props when 'index' is provided interface CollectionPropsWithIndex extends CollectionPropsBase { index: number | string; // `index` is required name?: never; // `name` should never be provided when `index` is present } // Union type that ensures either 'name' or 'index' is provided, but not both type CollectionProps = CollectionPropsWithName | CollectionPropsWithIndex interface PersistStateOnUnmountProps { children: React.ReactNode; } type InputHTMLAttributes = Omit, "onChange" | "value"> type FormHTMLAttributes = Omit, "onChange" | "onInit" | "onReset" | "onSubmit"> type SelectHTMLAttributes = Omit, "onChange" | "value"> type TextareaHTMLAttributes = Omit, "onChange" | "value"> // Utility to split a string like "a.b.c" into ["a", "b", "c"] type Split = string extends S ? string[] : S extends `${infer T}${D}${infer U}` ? [T, ...Split] : [S]; // Recursively go into the object using path parts type PathValue = P extends [infer Head, ...infer Rest] ? Head extends keyof T ? Rest extends string[] ? PathValue : never : never : T; // Resolves a string path like "a.b" to its value type in T type GetValueByPath = PathValue>; type AsyncStatus = { status?: "asyncStart" | "asyncSuccess" | "asyncError"; value?: T }; export enum STATUS { ON_RESET = "ON_RESET", READY = "READY", RESETTED = "RESETTED", ON_CHANGE = "ON_CHANGE", ON_INIT = "ON_INIT", ON_SUBMIT = "ON_SUBMIT", ON_INIT_ASYNC = "ON_INIT_ASYNC", ON_RUN_ASYNC = "ON_RUN_ASYNC", ON_ASYNC_END = "ON_ASYNC_END" } export const Form: (props: FormProps & FormHTMLAttributes) => React.ReactElement; export const Input: (props: InputProps & InputHTMLAttributes) => React.ReactElement; export const Select: (props: SelectProps & SelectHTMLAttributes) => React.ReactElement; export const TextArea: (props: InputProps & TextareaHTMLAttributes) => React.ReactElement; export const Collection: (props: CollectionProps) => React.ReactElement; export const PersistStateOnUnmount: React.FC; export const FormContext: (props: Omit, "innerRef">) => React.ReactElement; export function useForm(): { state: FormState; reset: () => void; isValid: boolean; pristine: boolean; submitted: number; submitAttempts: number; isSubmitting: boolean; formStatus: keyof typeof STATUS; dispatch: (state: FormState | ((prevState: FormState) => FormState)) => void; onSubmitForm: (e: React.FormEvent) => void; }; export function useField( props: UseFieldCustomInputProps ): UseFieldReturnCustom; export function useField( props: InputProps ): UseFieldReturnStandard; export function useAsyncValidation(asyncValidator:AsyncValidatorFn): [ AsyncStatus, { onAsyncValidation: (status: AsyncStatus) => void; asyncValidator: AsyncValidatorFn; resetAsyncErr: () => void } ]; export function useValidation(validators: Array>): [ { error?: string; isValid: boolean }, { onValidation: (errors: string[], isValid: boolean) => void; validators: Array>; resetSyncErr: () => void } ]; export function useSelector>(selector: (state: FormState) => T): [T, (value: T | ((prev: T) => T)) => void]; export function useCollection>(props: UseCollectionProps): useCollectionReturnType; export function useChildren(initialValue?: T[], onReset?: () => void): [T[], React.Dispatch>]; export function useMultipleForm(onChange?: (state: Record) => void): [() => Record, Record]; export function withIndex(Component: React.ComponentType): React.FC; export function createFormStore( initialState?: Partial ): [ FormStore, ( selector: (state: FormState) => GetValueByPath ) => [ GetValueByPath, (value: GetValueByPath | ((prev: GetValueByPath) => GetValueByPath)) => void ] ]; }