@d3vtool/hooks
Version: 
Collection of custom React hooks to simplify tasks in your React projects.
106 lines (105 loc) • 4.39 kB
TypeScript
import { ObjectValidator, VInfer } from "@d3vtool/utils";
import React, { FormEvent } from "react";
/**
 * Type definition for form errors, where each key in the FormType
 * corresponds to a string representing the error message for that field.
 */
export type FormError<FormType> = {
    [P in keyof FormType]: string;
};
/**
 * Type definition for a form submission action. This function accepts a form event
 * and returns a Promise that resolves when the submission process is complete.
 */
export type FormAction = (event: FormEvent) => Promise<void>;
/**
 * Type definition for a middleware action in the form submission process.
 * This function returns a Promise that resolves when the middleware logic is complete.
 */
export type FormMiddlewareAction = () => void | Promise<void>;
/**
 * Type definition for a submit action that forceRenders a form submission and
 * allows you to specify a middleware action to run before submission.
 */
export type SubmitAction = (callback: FormMiddlewareAction) => FormAction;
export type SetFormDataAction<F> = (key: keyof F, data: F[keyof F], hideErrorMsg?: boolean) => void;
export type GetFormDataAction<F> = (key: keyof F) => F[keyof F];
export type RefAction = (instance: HTMLInputElement | HTMLTextAreaElement | null) => void;
export type Listeners = {
    onChange: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
    onBlur: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
    ref: RefAction;
};
export type ResetFieldAction = (keepErrorMsgs?: boolean) => void;
/**
 * Type definition for the hook that provides the form state (F),
 * the form submission handler (SubmitAction), form error handling (FormError),
 * and the input reference setup action (SetupInputRefsAction).
 */
export type UseForm<F> = {
    formData: F;
    onSubmit: SubmitAction;
    formErrors: FormError<F>;
    setFormData: SetFormDataAction<F>;
    getFormData: GetFormDataAction<F>;
    listeners: Listeners;
    resetFields: ResetFieldAction;
};
/**
 * useForm is a custom React hook for managing form state with validation. It provides
 * an efficient way to handle form input values, perform validation based on a schema, and
 * manage errors and submission logic.
 *
 * @template FormSchema - The schema used to validate the form, based on an object validator.
 *
 * @param defaultFormData - The initial form data object that matches the shape of the form schema.
 * @param formSchema - The schema used to validate the form fields. This ensures that form values adhere to the schema's validation rules.
 *
 * @returns An object containing:
 * - formData: The current form data as an object that matches the schema shape.
 * - onSubmit: A function to handle form submission. Pass a callback to execute when the form is successfully validated and submitted.
 * - formErrors: An object that contains error messages for each form field, keyed by the field name.
 * - setFormData: A function that allows you to set the form data for a specific field.
 * - getFormData: A function that allows you to retrieve the form data for a specific field.
 * - listeners: Event listeners to be passed to the input fields for handling user interactions.
 *
 * @example
 * const schema = Validator.object({
 *   email: Validator.string().email(),
 *   password: Validator.string().password(),
 * });
 *
 * const {
 *   formData, onSubmit, formErrors, setFormData, listeners
 * } = useForm({
 *   email: "",
 *   password: "",
 * }, schema);
 *
 * @example
 * const handleOnSubmit = async () => {
 *   // Handle form submission logic here
 * };
 *
 * <form onSubmit={onSubmit(handleOnSubmit)}>
 *   <input
 *     name="email" // name should be same as in schema key
 *     {...listeners}  // Attach listeners here
 *     type="text"
 *   />
 *   {formErrors.email && <span>{formErrors.email}</span>}
 *
 *   <input
 *     name="password" // name should be same as in schema key
 *     {...listeners}  // Attach listeners here
 *     type="password"
 *   />
 *   {formErrors.password && <span>{formErrors.password}</span>}
 *
 *   <button type="submit">Submit</button>
 * </form>
 *
 * // Access individual form data
 * const email = getFormData('email');
 */
export declare function useForm<FormSchema extends ObjectValidator<any>>(defaultFormData: VInfer<FormSchema>, formSchema: FormSchema): UseForm<VInfer<FormSchema>>;