UNPKG

svelte-common-hooks

Version:
180 lines (179 loc) 6.27 kB
import { z } from 'zod/v4'; /** * The props for `createFormState`. * * @template {z.ZodObject<any>} T The zod schema that will validate the form state. * @template {z.infer<T>} Initial The initial value of the form state. */ export type FormStateProps<T extends z.ZodObject<any>, Initial extends z.infer<T> = z.infer<T>> = { /** * zod/v4 schema * @link https://zod.dev/v4 */ schema: T; /** * initial value of the form state, the property that is not exist in the schema is allowed but ignored */ initial?: Initial; /** * attributes that will be applied to the form fields, use `createAttribute` to help you create the attributes */ attribute?: FormAttribute<T>; }; /** * Attributes for a form field */ type FormAttribute<T extends z.ZodObject<any>> = { [K in keyof z.infer<T>]?: ReturnType<typeof createAttribute>; }; /** * The config of the form state */ type FormStateConfig<T extends z.ZodObject<any>> = { [K in keyof z.infer<T>]: { /** * errors of the form field */ errors: string[]; /** * whether the form field has error */ hasError: boolean; }; }; /** * Necessary attributes for a form field */ type FormStateAttribute<T extends z.ZodObject<any>> = { [K in keyof z.infer<T>]: { /** * aria-invalid attribute */ 'aria-invalid': boolean; /** * oninput event, it will validate the form field on input if the result has error */ oninput: (event: Event & { currentTarget: EventTarget & HTMLElement; }) => void; /** * onblur event, it will validate the form field on blur */ onblur: (event: Event & { currentTarget: EventTarget & HTMLElement; }) => void; }; }; /** * The helper to create attributes for a form field * @example * ```svelte * <script lang="ts"> * import type { HTMLInputAttributes } from 'svelte/elements'; * import { createAttribute } from 'svelte-common-hooks'; * const attribute = createAttribute<HTMLInputAttributes>({ * type: 'text', * placeholder: 'Enter your name', * required: true, * customAttribute: 'customAttribute', * }); * </script> * ``` * @param attribute the attributes that will be applied to the form field */ export declare function createAttribute<InputAttribute extends Record<string, any>>(attribute: InputAttribute & Record<string, unknown>): InputAttribute & Record<string, unknown>; /** * Creates and manages the state of a form based on a Zod schema. * * @example * ```svelte * <script lang="ts"> * import { createFormState } from 'svelte-common-hooks'; * import { z } from 'zod/v4'; * const formState = createFormState({ * schema: z.object({ * name: z.string().min(1), * email: z.string().email(), * age: z.number().min(18) * }), * // optionally set the initial value * initial: { * name: '', * email: '', * age: 0 * }, * // optionally append more attribute to the form field * attribute: { * name: createAttribute<HTMLInputAttributes>({ * type: 'text', * placeholder: 'Enter your name', * required: true, * customAttribute: 'customAttribute', * }), * email: createAttribute<HTMLInputAttributes>({ * type: 'email', * required: true * }), * age: createAttribute<HTMLInputAttributes>({ * type: 'number', * required: true * }) * } * }); * </script> * <form action="" method="post"> * <div> * <label for="name">Name</label> * <input bind:value={formState.value.name} {...formState.attribute.name} /> * {#if formState.result.name.errors.length} * {#each formState.result.name.errors as error} * <span>{error}</span> * {/each} * {/if} * </div> * <div> * <label for="email">Email</label> * <input bind:value={formState.value.email} {...formState.attribute.email} /> * {#if formState.result.email.errors.length} * {#each formState.result.email.errors as error} * <span>{error}</span> * {/each} * {/if} * </div> * <div> * <label for="age">Age</label> * <input bind:value={formState.value.age} {...formState.attribute.age} /> * {#if formState.result.age.errors.length} * {#each formState.result.age.errors as error} * <span>{error}</span> * {/each} * {/if} * </div> * </form> * ``` * @template T - The Zod object schema defining the structure of the form. * @template Initial - The initial values of the form state, inferred from the schema. * @param {FormStateProps<T, Initial>} props - The configuration properties for the form state. * @property {FormStateValue<Initial>} value - The current values of the form fields. * @property {FormStateAttribute<T>} attribute - The attributes for each form field. * @property {FormStateConfig<T>} result - The validation result for each form field. * @property {Function} addErrors - Function to add errors to a specific form field. * @property {Function} setValue - Function to set the value of a specific form field. * @property {Function} validate - Function to validate a specific form field. * @property {Function} validateAll - Function to validate the entire form. */ export declare function createFormState<T extends z.ZodObject<any>, Initial extends z.infer<T> = z.infer<T>>(props: FormStateProps<T, Initial>): { value: Initial; readonly attribute: FormStateAttribute<T> extends infer T_1 ? { [K in keyof T_1]: FormStateAttribute<T>[K]; } : never; readonly result: FormStateConfig<T> extends infer T_1 ? { [K in keyof T_1]: FormStateConfig<T>[K]; } : never; addErrors: (key: keyof z.infer<T>, errors: string[]) => void; setValue: <K extends keyof Initial>(key: K, newValue: Initial[K], config?: { validateFirst?: boolean; addErrorIfInvalid: boolean; }) => Initial[K] | undefined; validate: (key: keyof z.infer<T>) => z.ZodSafeParseResult<Record<string, unknown>>; validateAll: <ExtendedData extends Initial>(extendedData?: ExtendedData) => z.ZodSafeParseResult<z.core.output<T>>; resetError: () => void; setErrors: (newErrors: { [K in keyof Initial]?: string[]; }) => void; }; export {};