UNPKG

svelte-simple-form

Version:

A lightweight, **type-safe**, and **reactive** form state management hook for **Svelte 5**, featuring:

147 lines (146 loc) 8.22 kB
type Primitive = string | number | boolean | symbol | null | undefined | bigint | File | Blob | FileList | Date | RegExp | ArrayBuffer | DataView | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array | Map<any, any> | Set<any> | WeakMap<any, any> | WeakSet<any>; type Paths<T, Prev extends string = ''> = T extends Primitive ? Prev : T extends (infer U)[] ? [U] extends [never] ? Prev | `${Prev}.${number}` : U extends Primitive ? Prev | `${Prev}.${number}` : Prev | `${Prev}.${number}` | Paths<U, `${Prev}.${number}`> : T extends object ? string extends keyof T ? any : number extends keyof T ? any : { [K in keyof T & string]: Prev extends '' ? Paths<T[K], K> : Paths<T[K], `${Prev}.${K}`>; }[keyof T & string] : Prev; type FlatPaths<T> = Exclude<Paths<T, ''>, ''> extends infer P ? [P] extends [never] ? string : Extract<P, string> : string; type IsArrayLike<T> = T extends readonly (infer _I)[] ? true : NonNullable<T> extends readonly (infer _I)[] ? true : false; type Split<S extends string> = S extends `${infer A}.${infer B}` ? [A, ...Split<B>] : [S]; type _ValueFromParts<T, Parts extends readonly string[]> = Parts extends [] ? T : Parts extends [infer Head extends string, ...infer Rest extends string[]] ? Head extends `${number}` ? T extends readonly (infer U)[] | (infer U)[] ? _ValueFromParts<U, Rest> : never : Head extends keyof T ? _ValueFromParts<T[Head], Rest> : never : never; type ValueFromPath<T, P extends FlatPaths<T>> = _ValueFromParts<T, Split<P>>; type ArrayPaths<T> = { [P in FlatPaths<T>]: IsArrayLike<ValueFromPath<T, P>> extends true ? P : never; }[FlatPaths<T>]; type ArrayItem<T, P extends FlatPaths<T>> = NonNullable<ValueFromPath<T, P>> extends readonly (infer I)[] ? I : never; export type Validator<T = any> = { validateField(field: FlatPaths<T>, form: FormControlContext<T>, force?: boolean, config?: { validateOn?: string[]; validateAfter?: string; validateDebounce?: number; }): boolean | Promise<boolean>; validateForm(form: FormControlContext<T>): boolean | Promise<boolean>; }; export type FormContext<T = Record<string, any>> = { initialValues: T; data: T; reset: () => void; submit: (callback?: (data: T) => any) => Promise<void>; }; export type FormControlContext<T = Record<string, any>> = { initialValues: T; data: T; errors: Record<FlatPaths<T>, string[] | undefined>; touched: Record<FlatPaths<T>, boolean | undefined>; dirty: Record<FlatPaths<T>, boolean | undefined>; isValid: boolean; isValidating: boolean; isSubmitting: boolean; isDirty: boolean; reset: () => void; resetField: (path: FlatPaths<T>) => void; submit: (callback?: (data: T) => any) => Promise<void>; setInitialValues: (values: T, props?: { reset?: boolean; }) => void; setData: { (values: T): void; <P extends Exclude<Paths<T, ''>, ''>>(field: P, value: _ValueFromParts<T, Split<P>>): void; }; setIsValid: (isValid: boolean) => void; setIsValidating: (isValidating: boolean) => void; setTouched: (field: FlatPaths<T>, value?: boolean) => void; removeTouched: (field: FlatPaths<T>) => void; setDirty: (field: FlatPaths<T>, value?: boolean) => void; removeDirty: (field: FlatPaths<T>) => void; arrayAdd: <P extends ArrayPaths<T>>(path: P, value: NonNullable<ValueFromPath<T, P>> extends readonly (infer I)[] ? I : never, idx?: number | undefined, opts?: FieldOptions) => void; arrayRemove: <P extends ArrayPaths<T>>(path: P, index: number, opts?: FieldOptions) => void; arraySwap: <P extends ArrayPaths<T>>(path: P, i: number, j: number, opts?: FieldOptions) => void; arrayMove: <P extends ArrayPaths<T>>(path: P, from: number, to: number, opts?: FieldOptions) => void; arrayRemoveBy: <P extends ArrayPaths<T>>(path: P, predicate: (item: ArrayItem<T, P>) => boolean, opts?: FieldOptions) => void; arrayUpdateBy: <P extends ArrayPaths<T>>(path: P, predicate: (item: ArrayItem<T, P>) => boolean, value: ArrayItem<T, P> | ((prev: ArrayItem<T, P>) => ArrayItem<T, P>), opts: FieldOptions) => void; setErrors: (errors: Record<string, string[] | undefined>) => void; setError: (field: FlatPaths<T>, error: string | string[]) => void; removeError: (field: FlatPaths<T>) => void; validateField: (field: FlatPaths<T>) => Promise<boolean>; validate: () => Promise<boolean>; handler: (node: HTMLFormElement) => void; }; type FormProps<T> = { initialValues: T; onSubmit?: (data: T) => Promise<void>; onReset?: () => void; onSubmitError?: (error: unknown) => void; }; type FormControlProps<T> = Omit<FormProps<T>, 'onSubmitError'> & { validator?: Validator<T>; validateOn?: ('change' | 'blur' | 'submit')[]; validateAfter?: 'touched' | 'dirty' | 'touched-or-dirty' | 'touched-and-dirty'; validateDebounce?: number; onSubmitErrorValidation?: (errors: Record<string, string[] | undefined>) => void; onSubmitError?: (error: unknown, errors: Record<string, string[] | undefined>) => void; }; type FieldOptions = { shouldTouch?: boolean; shouldDirty?: boolean; shouldValidate?: boolean; }; export declare function useForm<T>(props: FormProps<T>): { form: { initialValues: T; data: T; isSubmitting: boolean; reset(): void; submit(callback?: (data: T) => any): Promise<void>; handler(node: HTMLFormElement): void; }; }; export declare function useFormControl<T>(props: FormControlProps<T>): { readonly form: { initialValues: T; data: T; errors: Record<FlatPaths<T>, string[] | undefined>; touched: Record<FlatPaths<T>, boolean | undefined>; dirty: Record<FlatPaths<T>, boolean | undefined>; isValid: boolean; isValidating: boolean; isSubmitting: boolean; isDirty: boolean; reset(): void; resetField(path: FlatPaths<T>): void; submit(callback?: (data: T) => any): Promise<void>; setInitialValues: (values: T, props?: { reset?: boolean; }) => void; setData: { (values: T, props?: { shouldValidate?: boolean; } | undefined): void; <P extends FlatPaths<T>>(field: P, value: _ValueFromParts<T, Split<P>>, props?: FieldOptions): void; }; setIsValid(isValid: boolean): void; setIsValidating(isValidating: boolean): void; setTouched(field: FlatPaths<T>, value?: boolean): void; removeTouched(field: FlatPaths<T>): void; setDirty(field: FlatPaths<T>, value?: boolean): void; removeDirty(field: FlatPaths<T>): void; arrayAdd<P extends ArrayPaths<T>>(path: P, value: NonNullable<ValueFromPath<T, P>> extends readonly (infer I)[] ? I : never, idx?: number | undefined, opts?: FieldOptions): void; arrayRemove<P extends ArrayPaths<T>>(path: P, index: number, opts?: FieldOptions): void; arraySwap<P extends ArrayPaths<T>>(path: P, i: number, j: number, opts?: FieldOptions): void; arrayMove<P extends ArrayPaths<T>>(path: P, from: number, to: number, opts?: FieldOptions): void; arrayRemoveBy<P extends ArrayPaths<T>>(path: P, predicate: (item: ArrayItem<T, P>) => boolean, opts?: FieldOptions): void; arrayUpdateBy<P extends ArrayPaths<T>>(path: P, predicate: (item: ArrayItem<T, P>) => boolean, value: ArrayItem<T, P> | ((prev: ArrayItem<T, P>) => ArrayItem<T, P>), opts?: FieldOptions): void; setErrors(errors: Record<FlatPaths<T>, string[] | undefined>): void; setError(field: FlatPaths<T>, error: string | string[]): void; removeError(field: FlatPaths<T>): void; validateField(field: FlatPaths<T>, force?: boolean): Promise<boolean>; validate(): Promise<boolean>; handler(node: HTMLFormElement): void; }; readonly control: (node: any, data: { field: FlatPaths<T>; valueAsNumber?: boolean; setValueAs?: (v: any) => Promise<void> | void; } | FlatPaths<T>) => { destroy(): void; } | undefined; }; export {};