UNPKG

validierung

Version:

Vue composition function for form validation

372 lines (362 loc) 9.2 kB
import { Ref, UnwrapRef, ComputedRef } from 'vue-demi' type AnyFunction = (...args: any[]) => any type DeepIndex< T, Keys extends readonly PropertyKey[], R = unknown > = Keys extends [infer First, ...infer Rest] ? First extends keyof T ? Rest extends readonly PropertyKey[] ? DeepIndex<T[First], Rest> : R : R : T type MaybeRef<T> = T extends Ref<infer V> ? T | V : Ref<T> | T type ExcludePrimitives<T> = T extends AnyFunction ? never : T extends object ? T : never type DeepPartial<T extends object> = T extends readonly any[] ? { [K in keyof T]: DeepPartialImpl<T[K]> } : { [K in keyof T]?: DeepPartialImpl<T[K]> | undefined } type DeepPartialImpl<T> = T extends AnyFunction ? T : T extends object ? DeepPartial<T> : T type ValidationBehaviorString = keyof ValidationBehaviorFunctions interface ValidationBehaviorFunctions {} type ValidationBehaviorInfo<T = any> = { /** * `True` if the paired rule of this behavior has an error. */ hasError: boolean /** * The touched state of the field. */ touched: boolean /** * The dirty state of the field. */ dirty: boolean /** * `True` if the validation was triggered with the `force` flag. */ force: boolean /** * `True` if the validation was triggered with the `submit` flag. */ submit: boolean /** * The `$value` property of the field. */ value: T } type ValidationBehaviorFunction = (info: ValidationBehaviorInfo) => boolean type ValidationBehavior = ValidationBehaviorString | ValidationBehaviorFunction type SimpleRule<TParam = any> = (value: TParam) => any type KeyedRule<TParams extends readonly any[] = any[]> = ( ...values: [...TParams] ) => any type RuleWithKey<T extends readonly any[] = any[]> = { key: string rule?: KeyedRule<T> } type FieldSimpleRule<TParam = any> = | SimpleRule<TParam> | [ validationBehavior: ValidationBehavior, rule: SimpleRule<TParam>, debounce?: number ] | [rule: SimpleRule<TParam>, debounce: number] type FieldKeyedRule<TParams extends readonly any[]> = | RuleWithKey<TParams> | [ validationBehavior: ValidationBehavior, rule: RuleWithKey<TParams>, debounce?: number ] | [rule: RuleWithKey<TParams>, debounce: number] type FieldRule<TSimpleParams, TKeyedParams extends readonly any[] = any[]> = | FieldSimpleRule<UnwrapRef<TSimpleParams>> | FieldKeyedRule<TKeyedParams> type ValidateFieldsPredicateParameter = { key: string value: any path: string[] } type ValidateFieldsPredicate = ( value: ValidateFieldsPredicateParameter ) => boolean type Field<T, E extends object = Record<string, never>> = { /** * The field's default value. */ $value: MaybeRef<T> /** * Rules to use for validation. */ $rules?: FieldRule<T>[] } & (E extends Record<string, never> ? unknown : E) type ValidateOptions = { /** * Set the field touched when called. * * @default true */ setTouched?: boolean /** * Validate with the `force` flag set. * * @default true */ force?: boolean } type TransformedField<T, E extends object = Record<string, never>> = { /** * The unique id of this field. */ $uid: number /** * The current field's value. */ $value: T /** * A list of validation error messages. */ $errors: string[] /** * The error status of this field. */ $hasError: boolean /** * `True` while this field has any pending rules. */ $validating: boolean /** * `True` if the field is touched. In most cases, * this value should be set together with the `blur` event. * Either through `$validate` or manually. */ $touched: boolean /** * `True` if the `$value` of this field has changed at least once. */ $dirty: boolean /** * Validate this field. * * @param options - Validate options to use * @default * ``` * { setTouched: true, force: true } * ``` */ $validate(options?: ValidateOptions): Promise<void> } & (E extends Record<string, never> ? unknown : UnwrapRef<E>) /** * Unwrap the `$value` property of all fields in `FormData`. */ type ResultFormData<FormData> = FormData extends any ? { [K in keyof FormData]: ResultFormDataImpl<FormData[K]> } : never type ResultFormDataImpl<T> = T extends { $value: infer V } ? UnwrapRef<Exclude<MaybeRef<V>, Ref>> : T extends object ? ResultFormData<T> : T /** * Receive the name of every field in `FormData` as a union of strings. */ type FieldNames<FormData extends object> = FieldNamesImpl<FormData, never> type FieldNamesImpl<FormData, K> = ExcludePrimitives<FormData> extends never ? never : FormData extends { $value: any } ? K : FormData extends readonly (infer A)[] ? FieldNamesImpl<A, K> : { [K in keyof FormData]-?: ExcludePrimitives<FormData[K]> extends { $value: any } ? K : FieldNamesImpl<ExcludePrimitives<FormData[K]>, K> }[keyof FormData] /** * Transforms every field in `FormData` into transformed fields. */ type TransformFormData<FormData> = FormData extends any ? { [K in keyof FormData]: TransformFormDataImpl<FormData[K]> } : never type TransformFormDataImpl<T> = T extends { $value: infer V } ? TransformedField< UnwrapRef<Exclude<MaybeRef<V>, Ref>>, Omit<T, '$value' | '$rules'> > : T extends object ? TransformFormData<T> : T /** * Vue composition function for form validation. * For type inference in `useValidation` make sure to define the structure of your * form data upfront and pass it as the generic parameter `FormData`. * * @param formData - The structure of your form data * * @example * ``` * type FormData = { * name: Field<string>, * password: Field<string> * } * * const { form } = useValidation<FormData>({ * name: { * $value: '', * $rules: [] * }, * password: { * $value: '', * $rules: [] * } * }) * ``` */ declare function useValidation<FormData extends object>( formData: FormData ): UseValidation<FormData> type UseValidation<FormData extends object> = { /** * A transformed reactive form data object. */ form: TransformFormData<FormData> /** * `True` during validation after calling `validateFields` when there were rules returning a `Promise`. */ submitting: Ref<boolean> /** * `True` while the form has any pending rules. */ validating: ComputedRef<boolean> /** * `True` if the form has any error. */ hasError: ComputedRef<boolean> /** * All current validation error messages. */ errors: ComputedRef<string[]> /** * Validate all fields and return a `Promise` containing the resulting form data. * * @param options - Options to use for validation * @throws `ValidationError` */ validateFields(options?: { /** * A list of field names to validate. * * @default * ``` * undefined // meaning validate all * ``` */ names?: FieldNames<FormData>[] /** * Filter which values to keep in the resulting form data. * Used like `Array.prototype.filter` but for objects. * * @default * ``` * () => true // meaning keep all * ``` */ predicate?: ValidateFieldsPredicate }): Promise<ResultFormData<FormData>> /** * Reset all fields to their default value or pass an object to set specific values. * It will not create new fields not present in the form data initially. * * @param formData - Form data to set specific values. It has the same structure as the object passed to `useValidation` */ resetFields(formData?: DeepPartial<ResultFormData<FormData>>): void /** * Adds a new value to the form data. * * @param path - A path for the new value * @param value - The value to add */ add<Keys extends readonly (string | number)[]>( path: readonly [...Keys], value: DeepIndex<FormData, Keys> extends (infer TArray)[] ? TArray : DeepIndex<FormData, Keys> ): void /** * Removes a value from the form data. * * @param path - A path to the value to remove */ remove(path: (string | number)[]): void } type Configuration = { defaultValidationBehavior: ValidationBehaviorString validationBehavior: { [K in ValidationBehaviorString]: ValidationBehaviorFunction } } type Validation = { install(): void } /** * Configure the validation behavior of `useValidation`. * * @param configuration - The form validation configuration */ declare function createValidation(configuration: Configuration): Validation declare class ValidationError extends Error { constructor() } export { AnyFunction, DeepPartial, ExcludePrimitives, Field, FieldKeyedRule, FieldNames, FieldSimpleRule, KeyedRule, ResultFormData, SimpleRule, TransformFormData, TransformedField, UseValidation, ValidateFieldsPredicate, ValidateFieldsPredicateParameter, ValidateOptions, Validation, ValidationBehavior, ValidationBehaviorFunction, ValidationBehaviorFunctions, ValidationBehaviorInfo, ValidationBehaviorString, ValidationError, createValidation, useValidation }