UNPKG

@vorms/core

Version:

Vue Form Validation with Composition API

274 lines (265 loc) 11.1 kB
import { Ref, UnwrapNestedRefs, WritableComputedRef, ComputedRef } from 'vue'; type MaybeRef<T> = T | Ref<T>; type FormValues = Record<string, any>; type FieldValidator<Value> = (value: Value) => string | void | Promise<string | void>; type FieldArrayValidator<Value extends Array<any>> = (value: Value) => FormErrors<Value> | void | Promise<FormErrors<Value> | void>; type FormTouched<Values> = { [K in keyof Values]?: Values[K] extends any[] ? Values[K][number] extends object ? FormTouched<Values[K][number]>[] | boolean : boolean | boolean[] : Values[K] extends object ? FormTouched<Values[K]> : boolean; }; type FormErrors<Values> = { [K in keyof Values]?: Values[K] extends any[] ? Values[K][number] extends object ? FormErrors<Values[K][number]>[] | string | string[] : string | string[] : Values[K] extends object ? FormErrors<Values[K]> : string; }; interface FormState<Values extends FormValues> { values: UnwrapNestedRefs<Values>; touched: Ref<FormTouched<Values>>; errors: Ref<FormErrors<Values>>; submitCount: Ref<number>; isSubmitting: Ref<boolean>; isValidating: Ref<boolean>; } interface FormEventHandler { handleBlur: { (event: Event, name?: string): void; <T = string | Event>(name: T): T extends string ? () => void : void; }; handleChange: () => void; handleInput: () => void; } interface FieldRegisterOptions<Values> { validate?: FieldValidator<Values>; } type UseFormRegisterReturn<Value> = FieldMeta & { value: WritableComputedRef<Value>; attrs: ComputedRef<FieldAttrs>; }; type SetFieldArrayValue = <T extends (...args: any) => any>(name: string, value: any[], method?: T, args?: Partial<{ argA: Parameters<T>[1]; argB: Parameters<T>[2]; }>, shouldSetValue?: boolean) => void; type UseFormRegister<Values extends FormValues> = <Name extends Path<Values>, Value = PathValue<Values, Name>>(name: MaybeRef<Name>, options?: FieldRegisterOptions<Value>) => UseFormRegisterReturn<Value>; type UseFormSetFieldValue<Values extends FormValues> = <Name extends Path<Values>, FieldValue extends PathValue<Values, Name>>(name: Name, value: FieldValue, shouldValidate?: boolean) => void; type ValidateForm<Values extends FormValues> = (values?: Values) => Promise<FormErrors<Values>>; type ValidateField<Values extends FormValues> = <Name extends Path<Values>>(name: Name) => Promise<void>; interface FormResetState<Values extends FormValues = FormValues> { values: Values; touched: FormTouched<Values>; errors: FormErrors<Values>; submitCount: number; } type ResetForm<Values extends FormValues> = (nextState?: Partial<FormResetState<Values>>) => void; interface UseFormReturn<Values extends FormValues> { values: UnwrapNestedRefs<Values>; touched: ComputedRef<FormTouched<Values>>; errors: ComputedRef<FormErrors<Values>>; submitCount: ComputedRef<number>; isSubmitting: Ref<boolean>; isValidating: ComputedRef<boolean>; dirty: ComputedRef<boolean>; register: UseFormRegister<Values>; setValues: (values: Values, shouldValidate?: boolean) => void; setFieldValue: UseFormSetFieldValue<Values>; handleSubmit: (event?: Event) => void; handleReset: (event?: Event) => void; resetForm: ResetForm<Values>; validateForm: ValidateForm<Values>; validateField: ValidateField<Values>; } type FieldAttrs = { name: string; onBlur: (event: Event) => void; onChange: () => void; onInput: () => void; }; type FieldMeta = { dirty: ComputedRef<boolean>; error: ComputedRef<string | undefined>; touched: ComputedRef<boolean | undefined>; }; type Primitive = null | undefined | string | number | boolean | symbol | bigint; type IsTuple<T extends ReadonlyArray<any>> = number extends T['length'] ? false : true; type PathImpl<K extends string | number, V> = V extends Primitive ? `${K}` : `${K}` | `${K}.${Path<V>}`; type TupleKeys<T extends ReadonlyArray<any>> = Exclude<keyof T, keyof any[]>; type Path<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? { [K in TupleKeys<T>]-?: PathImpl<K & string, T[K]>; }[TupleKeys<T>] : PathImpl<number, V> : { [K in keyof T]-?: PathImpl<K & string, T[K]>; }[keyof T]; type ArrayPathImpl<K extends string | number, V> = V extends Primitive ? never : V extends ReadonlyArray<infer U> ? U extends Primitive ? never : `${K}` | `${K}.${ArrayPath<V>}` : `${K}.${ArrayPath<V>}`; type ArrayPath<T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? { [K in TupleKeys<T>]-?: ArrayPathImpl<K & string, T[K]>; }[TupleKeys<T>] : ArrayPathImpl<number, V> : { [K in keyof T]-?: ArrayPathImpl<K & string, T[K]>; }[keyof T]; type PathValue<T, P extends Path<T> | ArrayPath<T>> = T extends any ? P extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? Rest extends Path<T[Key]> ? PathValue<T[Key], Rest> : never : Key extends `${number}` ? T extends ReadonlyArray<infer V> ? PathValue<V, Rest & Path<V>> : never : never : P extends keyof T ? T[P] : P extends `${number}` ? T extends ReadonlyArray<infer V> ? V : never : never : never; interface FormSubmitHelper<Values extends FormValues> { setSubmitting: (isSubmitting: boolean) => void; readonly initialValues: Values; } type ValidateMode = 'blur' | 'input' | 'change' | 'submit'; interface UseFormOptions<Values extends FormValues> { initialValues: Values; initialErrors?: FormErrors<Values>; initialTouched?: FormTouched<Values>; validateMode?: ValidateMode; reValidateMode?: ValidateMode; validateOnMounted?: boolean; onSubmit: (values: Values, helper: FormSubmitHelper<Values>) => void | Promise<any>; onInvalid?: (errors: FormErrors<Values>) => void; validate?: (values: Values) => void | object | Promise<FormErrors<Values>>; } /** * Custom composition API to mange the entire form. * * @param options - form configuration and validation parameters. {@link UseFormOptions} * * @returns methods and state of this form. {@link UseFormReturn} * * @example * ```vue * <script setup lang="ts"> * const { register, handleSubmit } = useForm({ * initialValues: { * name: 'Alex', * age: 18, * }, * onSubmit (values) { * console.log({ values }) * }, * }); * * const { value: name, attrs: nameAttrs } = register('name') * const { value: age, attrs: ageAttrs } = register('name') * </script> * * <template> * <form v-on:submit="handleSubmit"> * <input v-model="name" type="text" v-bind="nameAttrs" /> * <input v-model.number="age" type="text" v-bind="ageAttrs" /> * <input type="submit" /> * </form> * </template> * ``` */ declare function useForm<Values extends FormValues = FormValues>(options: UseFormOptions<Values>): UseFormReturn<Values>; type UseFieldOptions<Value> = { validate?: FieldValidator<Value>; }; /** * Custom composition API that will return specific field value, meta (state) and attributes. * * @param name - field name * * @param options - field configuration and validation parameters. {@link UseFieldOptions} * * @returns field value, meta (state) and attributes. {@link UseFormRegisterReturn} * * @example * ```vue * <script setup lang="ts"> * const { handleSubmit } = useForm({ * initialValues: { * name: '', * }, * onSubmit(values) { * console.log({ values }); * }, * }); * * const { value: name, attrs: nameAttrs } = useField('name') * </script> * * <template> * <form v-on:submit="handleSubmit"> * <input v-model="name" type="text" v-bind="nameAttrs" /> * <input type="submit" /> * </form> * </template> * ``` */ declare function useField<Value>(name: MaybeRef<string>, options?: UseFieldOptions<Value>): UseFormRegisterReturn<Value>; interface FieldEntry<Value> { key: number; value: Value; name: string; error: FormErrors<Value>; touched: Value extends Primitive ? boolean : FormTouched<Value> | undefined; dirty: boolean; attrs: Omit<FieldAttrs, 'name'>; } interface UseFieldArrayOptions<Value> { validate?: FieldArrayValidator<Value[]>; } type UseFieldArrayReturn<Value> = { fields: Ref<FieldEntry<Value>[]>; append: (value: Value) => void; prepend: (value: Value) => void; swap: (indexA: number, indexB: number) => void; remove: (index?: number) => void; move: (from: number, to: number) => void; insert: (index: number, value: Value) => void; update: (index: number, value: Value) => void; replace: (values: Value[]) => void; }; /** * Custom composition API that exposes convenient to perform operations with a list of fields. * * @param name - field name * * @param options - field array configuration and validation parameters {@link UseFieldArrayOptions} * * @returns fields state and methods. {@link UseFieldArrayReturn} * * @example * ```vue * <script setup lang="ts"> * import { useForm, useFieldArray } from '@vorms/core'; * * const { values, handleSubmit } = useForm({ * initialValues: { * list: ['vue', 'vue-router'], * }, * onSubmit(values) { * console.log({ values }); * }, * }); * * const { fields, append } = useFieldArray('list'); * </script> * * <template> * <pre>{{ values }}</pre> * <form v-on:submit="handleSubmit"> * <template v-for="field in fields" :key="field.key"> * <input v-model="field.value" :name="field.name" v-bind="field.attrs" /> * </template> * <button type="button" v-on:click="append('pinia')">Append</button> * <input type="submit" /> * </form> * </template> * ``` */ declare function useFieldArray<Value>(name: MaybeRef<string>, options?: UseFieldArrayOptions<Value>): UseFieldArrayReturn<Value>; type FormContextValues<Values extends FormValues = FormValues> = UseFormReturn<Values>; /** * Custom composition API that return form context * * @returns methods and state of form (As same as useForm). {@link FormContextValues} * * @example * ```vue * <script setup lang="ts"> * import { useFormContext } from '@vorms/core' * * const { validateField } = useFormContext() * const { value, attrs } = useField('drink') // You can also use `register` return from `useFormContext()` * </script> * * <template> * <input v-model="value" type="text" v-bind="attrs" /> * </template> * ``` */ declare function useFormContext<Values extends FormValues = FormValues>(): FormContextValues<Values>; declare const _default$1: (obj: Record<string, any>, path: string, value?: any) => Record<string, any>; declare const _default: <T>(obj: T, path: string, defaultValue?: unknown) => any; export { ArrayPath, FieldArrayValidator, FieldAttrs, FieldMeta, FieldRegisterOptions, FieldValidator, FormErrors, FormEventHandler, FormResetState, FormState, FormSubmitHelper, FormTouched, FormValues, IsTuple, MaybeRef, Path, PathValue, Primitive, ResetForm, SetFieldArrayValue, TupleKeys, UseFieldArrayOptions, UseFormOptions, UseFormRegister, UseFormRegisterReturn, UseFormReturn, UseFormSetFieldValue, ValidateField, ValidateForm, ValidateMode, _default as get, _default$1 as set, useField, useFieldArray, useForm, useFormContext };