vue3-form-validation
Advanced tools
Comparing version 5.0.0-beta.2 to 5.0.0-beta.3
@@ -307,3 +307,3 @@ 'use strict'; | ||
class Config { | ||
class ValidationConfig { | ||
constructor() { | ||
@@ -324,3 +324,3 @@ Object.defineProperty(this, "defaultValidationBehavior", { | ||
const lazy = ({ touched }) => touched; | ||
const lazier = ({ touched, hasError }) => touched && hasError; | ||
const lazier = ({ force, touched, hasError }) => force || (touched && hasError); | ||
this.defaultValidationBehavior = 'lazier'; | ||
@@ -337,7 +337,7 @@ this.validationBehavior = new Map([ | ||
} | ||
const CONFIG = new Config(); | ||
const VALIDATION_CONFIG = new ValidationConfig(); | ||
function registerField(form, name, field, disposables) { | ||
var _a, _b; | ||
const defaultValidationBehavior = CONFIG.getDefaultValidationBehavior(); | ||
const defaultValidationBehavior = VALIDATION_CONFIG.getDefaultValidationBehavior(); | ||
const rules = (_b = (_a = field.$rules) === null || _a === void 0 ? void 0 : _a.map(fieldRule => { | ||
@@ -353,3 +353,3 @@ if (typeof fieldRule === 'function') { | ||
else { | ||
const validationBehavior = CONFIG.validationBehavior.get(fieldValidationBehavior); | ||
const validationBehavior = VALIDATION_CONFIG.validationBehavior.get(fieldValidationBehavior); | ||
if (validationBehavior !== undefined) { | ||
@@ -363,3 +363,3 @@ return [validationBehavior, rule]; | ||
} | ||
throw Error('Invalid rule provided'); | ||
throw Error('[useValidation] Invalid rule provided'); | ||
})) !== null && _b !== void 0 ? _b : []; | ||
@@ -369,2 +369,3 @@ const uid$1 = uid(); | ||
const stop = vue.watch(formField.modelValue, () => { | ||
formField.dirty = true; | ||
form.validate(uid$1); | ||
@@ -379,6 +380,6 @@ }, { deep: true }); | ||
$validating: formField.validating, | ||
async $setTouched(forceValidation = true) { | ||
formField.touched = true; | ||
if (forceValidation) { | ||
await form.validate(uid$1, forceValidation); | ||
async $setTouched(touched = true, forceValidate = true) { | ||
formField.touched = touched; | ||
if (forceValidate) { | ||
await form.validate(uid$1, forceValidate); | ||
} | ||
@@ -433,4 +434,4 @@ } | ||
} | ||
function resetFields(formData, transformedFormData) { | ||
Object.entries(formData).forEach(([key, value]) => { | ||
function resetFields(data, transformedFormData) { | ||
Object.entries(data).forEach(([key, value]) => { | ||
const transformedValue = transformedFormData[key]; | ||
@@ -506,2 +507,8 @@ if (isTransformedField(transformedValue)) { | ||
}); | ||
Object.defineProperty(this, "dirty", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: false | ||
}); | ||
Object.defineProperty(this, "modelValue", { | ||
@@ -549,10 +556,15 @@ enumerable: true, | ||
} | ||
async validate(ruleNumber, modelValues, form, force) { | ||
if (!(force || this._shouldValidate(ruleNumber, form))) { | ||
return; | ||
} | ||
const rule = this._rules[ruleNumber]; | ||
async validate(ruleNumber, modelValues, form, force, submit) { | ||
const shouldValidate = this.getValidationBehavior(ruleNumber)({ | ||
submitCount: form.submitCount.value, | ||
hasError: this._errors[ruleNumber] !== null, | ||
touched: this.touched, | ||
dirty: this.dirty, | ||
submit, | ||
force | ||
}); | ||
const buffer = this._buffers[ruleNumber]; | ||
let error; | ||
if (!rule) { | ||
const rule = this._rules[ruleNumber]; | ||
if (!rule || !shouldValidate) { | ||
return; | ||
@@ -588,2 +600,3 @@ } | ||
this.touched = false; | ||
this.dirty = false; | ||
if (toDefaultValues) { | ||
@@ -618,10 +631,2 @@ if (vue.isRef(this.modelValue)) { | ||
} | ||
_shouldValidate(ruleNumber, form) { | ||
return this.getValidationBehavior(ruleNumber)({ | ||
submitCount: form.submitCount.value, | ||
errorMessages: this.errors.value, | ||
hasError: this.errors.value.length > 0, | ||
touched: this.touched | ||
}); | ||
} | ||
_setError(ruleNumber, error) { | ||
@@ -736,3 +741,3 @@ if (typeof error === 'string') { | ||
rules.forEach(([, rule], ruleNumber) => { | ||
const validator = (modelValues, force) => field.validate(ruleNumber, modelValues, this, force); | ||
const validator = (modelValues, force, submit) => field.validate(ruleNumber, modelValues, this, force, submit); | ||
if (isSimpleRule(rule)) { | ||
@@ -745,3 +750,5 @@ simpleValidators.validators.push(validator); | ||
validator, | ||
meta: { field, ruleNumber } | ||
meta: { | ||
field | ||
} | ||
}; | ||
@@ -771,15 +778,7 @@ const rollback = () => { | ||
const simpleValidators = this._simpleValidators.get(uid); | ||
if (simpleValidators) { | ||
const { validators, meta } = simpleValidators; | ||
if (force) { | ||
return Promise.allSettled([ | ||
...validators.map(v => v([meta.field.modelValue], true)), | ||
...this._getValidationResultsForKeys(meta.keys, true) | ||
]); | ||
} | ||
return Promise.allSettled([ | ||
...validators.map(v => v([meta.field.modelValue], false)), | ||
...this._getValidationResultsForKeys(meta.keys, false) | ||
]); | ||
} | ||
const { validators, meta } = simpleValidators; | ||
return Promise.allSettled([ | ||
...validators.map(v => v([meta.field.modelValue], force, false)), | ||
...this._getValidationResultsForKeys(meta.keys, force, false) | ||
]); | ||
} | ||
@@ -809,15 +808,11 @@ async validateAll(names) { | ||
} | ||
_getValidationResultsForKeys(keys, force, skipShouldValidate = false) { | ||
_getValidationResultsForKeys(keys, force, submit, skipTouchedCheck = false) { | ||
const validationResults = []; | ||
for (const key of keys) { | ||
this.tryGetKeyedValidators({ | ||
success: keyedValidators => { | ||
if (skipShouldValidate || | ||
this._shouldEveryFieldValidate(keyedValidators)) { | ||
const values = [...keyedValidators.values()]; | ||
const modelValues = values.map(({ meta }) => meta.field.modelValue); | ||
validationResults.push(...values.map(({ validator }) => validator(modelValues, force))); | ||
} | ||
} | ||
})(key); | ||
const keyedValidators = this._keyedValidators.get(key); | ||
if (skipTouchedCheck || this._isEveryFieldTouched(keyedValidators)) { | ||
const values = [...keyedValidators.values()]; | ||
const modelValues = values.map(({ meta }) => meta.field.modelValue); | ||
validationResults.push(...values.map(({ validator }) => validator(modelValues, force, submit))); | ||
} | ||
} | ||
@@ -831,5 +826,5 @@ return validationResults; | ||
meta.field.touched = true; | ||
validationResults.push(...validators.map(v => v([meta.field.modelValue], true))); | ||
validationResults.push(...validators.map(v => v([meta.field.modelValue], true, true))); | ||
} | ||
validationResults.push(...this._getValidationResultsForKeys(this._keyedValidators.keys(), true, true)); | ||
validationResults.push(...this._getValidationResultsForKeys(this._keyedValidators.keys(), true, true, true)); | ||
} | ||
@@ -841,4 +836,4 @@ else if (names.length > 0) { | ||
if (uniqueNames.has(meta.field.name)) { | ||
validationResults.push(...validators.map(v => v([meta.field.modelValue], true))); | ||
validationResults.push(...this._getValidationResultsForKeys(meta.keys, true, true)); | ||
validationResults.push(...validators.map(v => v([meta.field.modelValue], true, true))); | ||
validationResults.push(...this._getValidationResultsForKeys(meta.keys, true, true, true)); | ||
} | ||
@@ -849,5 +844,5 @@ } | ||
} | ||
_shouldEveryFieldValidate(keyedValidators) { | ||
for (const { meta: { field } } of keyedValidators) { | ||
if (!field.touched) { | ||
_isEveryFieldTouched(keyedValidators) { | ||
for (const { meta } of keyedValidators) { | ||
if (!meta.field.touched) { | ||
return false; | ||
@@ -960,15 +955,16 @@ } | ||
*/ | ||
function configureValidation(configuration = {}) { | ||
function createValidation(configuration) { | ||
return { | ||
install() { | ||
var _a, _b; | ||
CONFIG.defaultValidationBehavior = | ||
(_a = configuration.defaultValidationBehavior) !== null && _a !== void 0 ? _a : 'lazier'; | ||
for (const [key, validationBehavior] of Object.entries((_b = configuration.validationBehavior) !== null && _b !== void 0 ? _b : {})) { | ||
trySet(CONFIG.validationBehavior)({ | ||
failure() { | ||
console.warn(`Validation behavior with name '${key}' already exists`); | ||
} | ||
})(key, validationBehavior); | ||
for (const [key, validationBehavior] of Object.entries((_a = configuration.validationBehavior) !== null && _a !== void 0 ? _a : {})) { | ||
VALIDATION_CONFIG.validationBehavior.set(key, validationBehavior); | ||
} | ||
if (VALIDATION_CONFIG.validationBehavior.has(configuration.defaultValidationBehavior)) { | ||
VALIDATION_CONFIG.defaultValidationBehavior = | ||
(_b = configuration.defaultValidationBehavior) !== null && _b !== void 0 ? _b : 'lazier'; | ||
} | ||
else { | ||
console.warn(`[useValidation] Default validation behavior is not valid. Valid values are`, VALIDATION_CONFIG.validationBehavior.keys()); | ||
} | ||
} | ||
@@ -979,3 +975,3 @@ }; | ||
exports.ValidationError = ValidationError; | ||
exports.configureValidation = configureValidation; | ||
exports.createValidation = createValidation; | ||
exports.useValidation = useValidation; |
@@ -1,17 +0,32 @@ | ||
import { ComputedRef } from 'vue'; | ||
import { Plugin as Plugin_2 } from 'vue'; | ||
import { reactive } from 'vue'; | ||
import { Ref } from 'vue'; | ||
import { ref } from 'vue'; | ||
import { UnwrapRef } from 'vue'; | ||
import { ComputedRef } from 'vue' | ||
import { Plugin as Plugin_2 } from 'vue' | ||
import { reactive } from 'vue' | ||
import { Ref } from 'vue' | ||
import { ref } from 'vue' | ||
import { UnwrapRef } from 'vue' | ||
declare function cleanupForm(form: Form, deletedFormData: any, disposables: DisposableMap): void; | ||
declare function cleanupForm( | ||
form: Form, | ||
deletedFormData: any, | ||
disposables: DisposableMap | ||
): void | ||
export declare type Configuration = { | ||
defaultValidationBehavior?: ValidationBehaviorString; | ||
validationBehavior?: { | ||
[key: string]: ValidationBehavior; | ||
}; | ||
}; | ||
export declare type Configuration = | ||
keyof UseValidation_CustomValidationBehavior extends never | ||
? { | ||
defaultValidationBehavior?: ValidationBehaviorString | ||
validationBehavior?: ConfigurationValidationBehavior | ||
} | ||
: { | ||
defaultValidationBehavior?: ValidationBehaviorString | ||
validationBehavior: ConfigurationValidationBehavior | ||
} | ||
export declare type ConfigurationValidationBehavior = n_domain.Optional< | ||
{ | ||
[K in ValidationBehaviorString]: ValidationBehavior | ||
}, | ||
DefaultValidationBehaviorString | ||
> | ||
/** | ||
@@ -23,294 +38,417 @@ * | ||
*/ | ||
export declare function configureValidation(configuration?: Configuration): Plugin_2; | ||
export declare function createValidation(configuration: Configuration): Plugin_2 | ||
declare function deepCopy<T>(toClone: T): T; | ||
declare function deepCopy<T>(toClone: T): T | ||
declare type DeepIndex<T, Ks extends readonly Key[], R = unknown> = Ks extends [ | ||
infer First, | ||
...infer Rest | ||
] ? First extends keyof T ? Rest extends readonly Key[] ? DeepIndex<T[First], Rest> : R : R : T; | ||
infer First, | ||
...infer Rest | ||
] | ||
? First extends keyof T | ||
? Rest extends readonly Key[] | ||
? DeepIndex<T[First], Rest> | ||
: R | ||
: R | ||
: T | ||
declare function deepIterator(obj: object, predicate?: (value: object) => boolean): Generator<DeepIteratorResult, void>; | ||
declare function deepIterator( | ||
obj: object, | ||
predicate?: (value: object) => boolean | ||
): Generator<DeepIteratorResult, void> | ||
declare type DeepIteratorResult = { | ||
key: string; | ||
value: any; | ||
parent: any; | ||
path: string[]; | ||
isLeaf: boolean; | ||
}; | ||
key: string | ||
value: any | ||
parent: any | ||
path: string[] | ||
isLeaf: boolean | ||
} | ||
declare type DeepMaybeRef<T> = T extends Ref ? T | UnwrapRef<T> : T extends Record<string, unknown> ? DeepMaybeRefObject<T> : MaybeRef<T>; | ||
declare type DeepMaybeRef<T> = T extends Ref | ||
? T | UnwrapRef<T> | ||
: T extends Record<string, unknown> | ||
? DeepMaybeRefObject<T> | ||
: MaybeRef<T> | ||
declare type DeepMaybeRefObject<T extends Record<string, unknown>> = { | ||
[K in keyof T]: T[K] extends Ref ? T[K] | UnwrapRef<T[K]> : T[K] extends any[] ? MaybeRef<T[K]> : T[K] extends Record<string, unknown> ? DeepMaybeRefObject<T[K]> : MaybeRef<T[K]>; | ||
}; | ||
[K in keyof T]: T[K] extends Ref | ||
? T[K] | UnwrapRef<T[K]> | ||
: T[K] extends any[] | ||
? MaybeRef<T[K]> | ||
: T[K] extends Record<string, unknown> | ||
? DeepMaybeRefObject<T[K]> | ||
: MaybeRef<T[K]> | ||
} | ||
declare type DisposableMap = Map<number, (() => void)[]>; | ||
declare type DefaultValidationBehaviorString = 'aggresive' | 'lazy' | 'lazier' | ||
declare type DisposableMap = Map<number, (() => void)[]> | ||
export declare type Field<TValue> = { | ||
$value: n_domain.DeepMaybeRef<TValue>; | ||
$rules?: FieldRule<TValue>[]; | ||
}; | ||
$value: n_domain.DeepMaybeRef<TValue> | ||
$rules?: FieldRule<TValue>[] | ||
} | ||
declare type FieldNames<T> = T extends (infer TArray)[] ? FieldNames<TArray> : { | ||
[K in keyof T]-?: T[K] extends { | ||
$value: any; | ||
} | undefined ? K : FieldNames<T[K]>; | ||
}[keyof T]; | ||
declare type FieldNames<T> = T extends (infer TArray)[] | ||
? FieldNames<TArray> | ||
: { | ||
[K in keyof T]-?: T[K] extends | ||
| { | ||
$value: any | ||
} | ||
| undefined | ||
? K | ||
: FieldNames<T[K]> | ||
}[keyof T] | ||
declare type FieldRule<TSimpleParameter, TKeyedParameters extends readonly any[] = any[]> = FieldSimpleRule<TSimpleParameter extends any[] ? TSimpleParameter : UnwrapRef<TSimpleParameter>> | FieldRuleWithKey<TKeyedParameters>; | ||
declare type FieldRule< | ||
TSimpleParameter, | ||
TKeyedParameters extends readonly any[] = any[] | ||
> = | ||
| FieldSimpleRule< | ||
TSimpleParameter extends any[] | ||
? TSimpleParameter | ||
: UnwrapRef<TSimpleParameter> | ||
> | ||
| FieldRuleWithKey<TKeyedParameters> | ||
declare type FieldRuleWithKey<TParameters extends readonly any[]> = RuleWithKey<TParameters> | [FieldValidationBehavior, RuleWithKey<TParameters>]; | ||
declare type FieldRuleWithKey<TParameters extends readonly any[]> = | ||
| RuleWithKey<TParameters> | ||
| [FieldValidationBehavior, RuleWithKey<TParameters>] | ||
declare type FieldSimpleRule<TParameter = any> = SimpleRule<TParameter> | [FieldValidationBehavior, SimpleRule<TParameter>]; | ||
declare type FieldSimpleRule<TParameter = any> = | ||
| SimpleRule<TParameter> | ||
| [FieldValidationBehavior, SimpleRule<TParameter>] | ||
declare type FieldValidationBehavior = ValidationBehaviorString | ValidationBehavior; | ||
declare type FieldValidationBehavior = | ||
| ValidationBehaviorString | ||
| ValidationBehavior | ||
declare class Form { | ||
private _simpleValidators; | ||
private _keyedValidators; | ||
private _reactiveFieldMap; | ||
tryGetSimpleValidators: ({ success, failure }: { | ||
success(value: SimpleValidators): void; | ||
failure?(): void; | ||
}) => (key: number) => void; | ||
trySetKeyedValidators: ({ success, failure }: { | ||
success?(value: KeyedValidators): void; | ||
failure?(value: KeyedValidators): void; | ||
}) => (key: string, value: KeyedValidators) => void; | ||
tryGetKeyedValidators: ({ success, failure }: { | ||
success(value: KeyedValidators): void; | ||
failure?(): void; | ||
}) => (key: string) => void; | ||
ruleValidating: Ref<number>; | ||
submitCount: Ref<number>; | ||
submitting: Ref<boolean>; | ||
validating: ComputedRef<boolean>; | ||
hasError: ComputedRef<boolean>; | ||
errors: ComputedRef<string[]>; | ||
registerField(uid: number, name: string, modelValue: unknown, rules: ValidationBehaviorRuleTupel[]): FormField; | ||
validate(uid: number, force?: boolean): Promise<PromiseSettledResult<string | void>[]> | undefined; | ||
validateAll(names?: readonly n_domain.Key[]): Promise<void>; | ||
onDelete(uid: number): void; | ||
resetFields(toDefaultValues: boolean): void; | ||
private _getValidationResultsForKeys; | ||
private _getValidationResultsForNames; | ||
private _shouldEveryFieldValidate; | ||
private _simpleValidators | ||
private _keyedValidators | ||
private _reactiveFieldMap | ||
tryGetSimpleValidators: ({ | ||
success, | ||
failure | ||
}: { | ||
success(value: SimpleValidators): void | ||
failure?(): void | ||
}) => (key: number) => void | ||
trySetKeyedValidators: ({ | ||
success, | ||
failure | ||
}: { | ||
success?(value: KeyedValidators): void | ||
failure?(value: KeyedValidators): void | ||
}) => (key: string, value: KeyedValidators) => void | ||
tryGetKeyedValidators: ({ | ||
success, | ||
failure | ||
}: { | ||
success(value: KeyedValidators): void | ||
failure?(): void | ||
}) => (key: string) => void | ||
ruleValidating: Ref<number> | ||
submitCount: Ref<number> | ||
submitting: Ref<boolean> | ||
validating: ComputedRef<boolean> | ||
hasError: ComputedRef<boolean> | ||
errors: ComputedRef<string[]> | ||
registerField( | ||
uid: number, | ||
name: string, | ||
modelValue: unknown, | ||
rules: ValidationBehaviorRuleTupel[] | ||
): FormField | ||
validate( | ||
uid: number, | ||
force?: boolean | ||
): Promise<PromiseSettledResult<string | void>[]> | ||
validateAll(names?: readonly n_domain.Key[]): Promise<void> | ||
onDelete(uid: number): void | ||
resetFields(toDefaultValues: boolean): void | ||
private _getValidationResultsForKeys | ||
private _getValidationResultsForNames | ||
private _isEveryFieldTouched | ||
} | ||
declare class FormField { | ||
private _rules; | ||
private _validationBehaviors; | ||
private _buffers; | ||
private _errors; | ||
private _rulesValidating; | ||
initialModelValue: unknown; | ||
name: string; | ||
touched: boolean; | ||
modelValue: ReturnType<typeof ref> | ReturnType<typeof reactive>; | ||
errors: ComputedRef<string[]>; | ||
validating: ComputedRef<boolean>; | ||
hasError: ComputedRef<boolean>; | ||
constructor(name: string, modelValue: any, rules: ValidationBehaviorRuleTupel[]); | ||
validate(ruleNumber: number, modelValues: unknown[], form: Form, force: boolean): Promise<void>; | ||
reset(toDefaultValues: boolean): void; | ||
dispose(): void; | ||
getValidationBehavior(ruleNumber: number): ValidationBehavior; | ||
private _shouldValidate; | ||
private _setError; | ||
private _rules | ||
private _validationBehaviors | ||
private _buffers | ||
private _errors | ||
private _rulesValidating | ||
initialModelValue: unknown | ||
name: string | ||
touched: boolean | ||
dirty: boolean | ||
modelValue: ReturnType<typeof ref> | ReturnType<typeof reactive> | ||
errors: ComputedRef<string[]> | ||
validating: ComputedRef<boolean> | ||
hasError: ComputedRef<boolean> | ||
constructor( | ||
name: string, | ||
modelValue: any, | ||
rules: ValidationBehaviorRuleTupel[] | ||
) | ||
validate( | ||
ruleNumber: number, | ||
modelValues: unknown[], | ||
form: Form, | ||
force: boolean, | ||
submit: boolean | ||
): Promise<void> | ||
reset(toDefaultValues: boolean): void | ||
dispose(): void | ||
getValidationBehavior(ruleNumber: number): ValidationBehavior | ||
private _setError | ||
} | ||
declare function getResultFormData(transformedFormData: any): any; | ||
declare function getResultFormData(transformedFormData: any): any | ||
declare const isArray: (x: unknown) => x is any[]; | ||
declare const isArray: (x: unknown) => x is any[] | ||
declare const isDefined: <T>(x: T | null | undefined) => x is T; | ||
declare const isDefined: <T>(x: T | null | undefined) => x is T | ||
declare const isField: <T>(x: unknown) => x is Field<T>; | ||
declare const isField: <T>(x: unknown) => x is Field<T> | ||
declare const isObject: (x: unknown) => x is Record<Key, any>; | ||
declare const isObject: (x: unknown) => x is Record<Key, any> | ||
declare const isRecord: (x: unknown) => x is Record<Key, any>; | ||
declare const isRecord: (x: unknown) => x is Record<Key, any> | ||
declare const isSimpleRule: (rule: SimpleRule | RuleWithKey) => rule is SimpleRule<any>; | ||
declare const isSimpleRule: ( | ||
rule: SimpleRule | RuleWithKey | ||
) => rule is SimpleRule<any> | ||
declare const isTransformedField: <T>(x: unknown) => x is TransformedField<T>; | ||
declare const isTransformedField: <T>(x: unknown) => x is TransformedField<T> | ||
declare type Key = string | number; | ||
declare type Key = string | number | ||
export declare type KeyedRule<TParameters extends readonly any[] = any[]> = (...values: [...TParameters]) => any; | ||
export declare type KeyedRule<TParameters extends readonly any[] = any[]> = ( | ||
...values: [...TParameters] | ||
) => any | ||
declare type KeyedValidator = { | ||
validator: Validator; | ||
meta: { | ||
field: FormField; | ||
ruleNumber: number; | ||
}; | ||
}; | ||
validator: Validator | ||
meta: { | ||
field: FormField | ||
} | ||
} | ||
declare type KeyedValidators = Set<KeyedValidator>; | ||
declare type KeyedValidators = Set<KeyedValidator> | ||
declare class LinkedList<T> { | ||
first: LinkedListNode<T> | null; | ||
last: LinkedListNode<T> | null; | ||
count: number; | ||
addFirst(value: T): LinkedListNode<T>; | ||
addLast(value: T): LinkedListNode<T>; | ||
remove(node: LinkedListNode<T>): void; | ||
removeFirst(): void; | ||
removeLast(): void; | ||
nodesForwards(): { | ||
[Symbol.iterator](): Generator<LinkedListNode<T>, void, unknown>; | ||
}; | ||
nodesBackwards(): { | ||
[Symbol.iterator](): Generator<LinkedListNode<T>, void, unknown>; | ||
}; | ||
first: LinkedListNode<T> | null | ||
last: LinkedListNode<T> | null | ||
count: number | ||
addFirst(value: T): LinkedListNode<T> | ||
addLast(value: T): LinkedListNode<T> | ||
remove(node: LinkedListNode<T>): void | ||
removeFirst(): void | ||
removeLast(): void | ||
nodesForwards(): { | ||
[Symbol.iterator](): Generator<LinkedListNode<T>, void, unknown> | ||
} | ||
nodesBackwards(): { | ||
[Symbol.iterator](): Generator<LinkedListNode<T>, void, unknown> | ||
} | ||
} | ||
declare class LinkedListNode<T> { | ||
value: T; | ||
next: LinkedListNode<T> | null; | ||
prev: LinkedListNode<T> | null; | ||
constructor(value: T); | ||
value: T | ||
next: LinkedListNode<T> | null | ||
prev: LinkedListNode<T> | null | ||
constructor(value: T) | ||
} | ||
declare type MaybeRef<T> = Ref<T> | T; | ||
declare type MaybeRef<T> = Ref<T> | T | ||
declare namespace n_domain { | ||
export { | ||
deepCopy, | ||
deepIterator, | ||
tryGet, | ||
trySet, | ||
path, | ||
set, | ||
uid, | ||
isArray, | ||
isDefined, | ||
isObject, | ||
isRecord, | ||
LinkedList, | ||
PromiseCancel, | ||
Key, | ||
DeepMaybeRef, | ||
MaybeRef, | ||
DeepIndex, | ||
Tuple | ||
} | ||
export { | ||
deepCopy, | ||
deepIterator, | ||
tryGet, | ||
trySet, | ||
path, | ||
set, | ||
uid, | ||
isArray, | ||
isDefined, | ||
isObject, | ||
isRecord, | ||
LinkedList, | ||
PromiseCancel, | ||
Key, | ||
DeepMaybeRef, | ||
MaybeRef, | ||
DeepIndex, | ||
Tuple, | ||
Optional | ||
} | ||
} | ||
declare namespace n_form { | ||
export { | ||
DisposableMap, | ||
cleanupForm, | ||
getResultFormData, | ||
resetFields, | ||
transformFormData, | ||
Form, | ||
FormField, | ||
ValidationError, | ||
isField, | ||
isSimpleRule, | ||
isTransformedField, | ||
FieldRule, | ||
KeyedRule, | ||
SimpleRule, | ||
RuleWithKey, | ||
ValidationBehavior, | ||
ValidationBehaviorInfo, | ||
ValidationBehaviorRuleTupel, | ||
ValidationBehaviorString, | ||
Field, | ||
TransformedField, | ||
TransformedFormData, | ||
FieldNames, | ||
ResultFormData | ||
} | ||
export { | ||
DisposableMap, | ||
cleanupForm, | ||
getResultFormData, | ||
resetFields, | ||
transformFormData, | ||
Form, | ||
FormField, | ||
ValidationError, | ||
isField, | ||
isSimpleRule, | ||
isTransformedField, | ||
FieldRule, | ||
KeyedRule, | ||
SimpleRule, | ||
RuleWithKey, | ||
ValidationBehavior, | ||
ValidationBehaviorInfo, | ||
DefaultValidationBehaviorString, | ||
ValidationBehaviorString, | ||
ValidationBehaviorRuleTupel, | ||
Field, | ||
TransformedField, | ||
TransformedFormData, | ||
FieldNames, | ||
ResultFormData | ||
} | ||
} | ||
declare function path(path: readonly Key[], obj: Record<Key, unknown>): any; | ||
declare type Optional<T, K extends keyof T> = Partial<Pick<T, K>> & Omit<T, K> | ||
declare function path(path: readonly Key[], obj: Record<Key, unknown>): any | ||
declare class PromiseCancel<T = unknown> { | ||
private promise; | ||
private resolve; | ||
private reject; | ||
constructor(); | ||
cancelResolve(value: T | PromiseLike<T>): void; | ||
cancelReject(reason?: any): void; | ||
race<Ps extends readonly Promise<any>[]>(...promises: [...Ps]): Promise<T | ([...Ps][number] extends PromiseLike<infer U> ? U : [...Ps][number])>; | ||
private assign; | ||
private promise | ||
private resolve | ||
private reject | ||
constructor() | ||
cancelResolve(value: T | PromiseLike<T>): void | ||
cancelReject(reason?: any): void | ||
race<Ps extends readonly Promise<any>[]>( | ||
...promises: [...Ps] | ||
): Promise< | ||
T | ([...Ps][number] extends PromiseLike<infer U> ? U : [...Ps][number]) | ||
> | ||
private assign | ||
} | ||
declare function resetFields(formData: any, transformedFormData: any): void; | ||
declare function resetFields(data: any, transformedFormData: any): void | ||
declare type ResultFormData<FormData extends object> = FormData extends any ? { | ||
[K in keyof FormData]: FormData[K] extends { | ||
$value: infer TValue; | ||
} | undefined ? UnwrapRef<TValue> : FormData[K] extends object ? ResultFormData<FormData[K]> : FormData[K]; | ||
} : never; | ||
declare type ResultFormData<FormData extends object> = FormData extends any | ||
? { | ||
[K in keyof FormData]: FormData[K] extends | ||
| { | ||
$value: infer TValue | ||
} | ||
| undefined | ||
? UnwrapRef<TValue> | ||
: FormData[K] extends object | ||
? ResultFormData<FormData[K]> | ||
: FormData[K] | ||
} | ||
: never | ||
declare type RuleWithKey<T extends readonly any[] = any[]> = { | ||
key: string; | ||
rule?: KeyedRule<T>; | ||
}; | ||
key: string | ||
rule?: KeyedRule<T> | ||
} | ||
declare function set(obj: any, keys: readonly Key[], value: any): void; | ||
declare function set(obj: any, keys: readonly Key[], value: any): void | ||
export declare type SimpleRule<TParameter = any> = (...values: TParameter[]) => any; | ||
export declare type SimpleRule<TParameter = any> = ( | ||
...value: TParameter[] | ||
) => any | ||
declare type SimpleValidators = { | ||
validators: Validator[]; | ||
meta: { | ||
field: FormField; | ||
keys: string[]; | ||
rollbacks: (() => void)[]; | ||
}; | ||
}; | ||
validators: Validator[] | ||
meta: { | ||
field: FormField | ||
keys: string[] | ||
rollbacks: (() => void)[] | ||
} | ||
} | ||
export declare type TransformedField<T> = { | ||
$uid: number; | ||
$value: T; | ||
$errors: string[]; | ||
$hasError: boolean; | ||
$validating: boolean; | ||
$setTouched(forceValidation?: boolean): Promise<void>; | ||
}; | ||
$uid: number | ||
$value: T | ||
$errors: string[] | ||
$hasError: boolean | ||
$validating: boolean | ||
$setTouched(touched?: boolean, forceValidate?: boolean): Promise<void> | ||
} | ||
declare type TransformedFormData<FormData extends object> = FormData extends any ? { | ||
[K in keyof FormData]: FormData[K] extends { | ||
$value: infer TValue; | ||
} | undefined ? FormData[K] extends undefined ? undefined : TransformedField<UnwrapRef<TValue>> : FormData[K] extends object ? TransformedFormData<FormData[K]> : FormData[K]; | ||
} : never; | ||
declare type TransformedFormData<FormData extends object> = FormData extends any | ||
? { | ||
[K in keyof FormData]: FormData[K] extends | ||
| { | ||
$value: infer TValue | ||
} | ||
| undefined | ||
? FormData[K] extends undefined | ||
? undefined | ||
: TransformedField<UnwrapRef<TValue>> | ||
: FormData[K] extends object | ||
? TransformedFormData<FormData[K]> | ||
: FormData[K] | ||
} | ||
: never | ||
declare function transformFormData(form: Form, formData: object): DisposableMap; | ||
declare function transformFormData(form: Form, formData: object): DisposableMap | ||
declare const tryGet: <K, V>(map: Map<K, V>) => ({ success, failure }: { | ||
success(value: V): void; | ||
failure?(): void; | ||
}) => (key: K) => void; | ||
declare const tryGet: <K, V>( | ||
map: Map<K, V> | ||
) => ({ | ||
success, | ||
failure | ||
}: { | ||
success(value: V): void | ||
failure?(): void | ||
}) => (key: K) => void | ||
declare const trySet: <K, V>(map: Map<K, V>) => ({ success, failure }: { | ||
success?(value: V): void; | ||
failure?(value: V): void; | ||
}) => (key: K, value: V) => void; | ||
declare const trySet: <K, V>( | ||
map: Map<K, V> | ||
) => ({ | ||
success, | ||
failure | ||
}: { | ||
success?(value: V): void | ||
failure?(value: V): void | ||
}) => (key: K, value: V) => void | ||
declare type Tuple<T, N extends number> = number extends N ? T[] : _Tuple<T, N, []>; | ||
declare type Tuple<T, N extends number> = number extends N | ||
? T[] | ||
: _Tuple<T, N, []> | ||
declare type _Tuple<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _Tuple<T, N, [T, ...R]>; | ||
declare type _Tuple< | ||
T, | ||
N extends number, | ||
R extends unknown[] | ||
> = R['length'] extends N ? R : _Tuple<T, N, [T, ...R]> | ||
declare function uid(): number; | ||
declare function uid(): number | ||
export declare type UseValidation<FormData extends object> = { | ||
form: n_form.TransformedFormData<FormData>; | ||
submitting: Ref<boolean>; | ||
submitCount: Ref<number>; | ||
validating: ComputedRef<boolean>; | ||
hasError: ComputedRef<boolean>; | ||
errors: ComputedRef<string[]>; | ||
validateFields(names?: n_form.FieldNames<FormData>[] | string[]): Promise<n_form.ResultFormData<FormData>>; | ||
resetFields(formData?: Partial<n_form.ResultFormData<FormData>>): void; | ||
add<Ks extends readonly n_domain.Key[]>(path: readonly [...Ks], value: n_domain.DeepIndex<FormData, Ks> extends (infer TArray)[] ? TArray : n_domain.DeepIndex<FormData, Ks>): void; | ||
remove(path: n_domain.Key[]): void; | ||
}; | ||
form: n_form.TransformedFormData<FormData> | ||
submitting: Ref<boolean> | ||
submitCount: Ref<number> | ||
validating: ComputedRef<boolean> | ||
hasError: ComputedRef<boolean> | ||
errors: ComputedRef<string[]> | ||
validateFields( | ||
names?: n_form.FieldNames<FormData>[] | string[] | ||
): Promise<n_form.ResultFormData<FormData>> | ||
resetFields(formData?: Partial<n_form.ResultFormData<FormData>>): void | ||
add<Ks extends readonly n_domain.Key[]>( | ||
path: readonly [...Ks], | ||
value: n_domain.DeepIndex<FormData, Ks> extends (infer TArray)[] | ||
? TArray | ||
: n_domain.DeepIndex<FormData, Ks> | ||
): void | ||
remove(path: n_domain.Key[]): void | ||
} | ||
@@ -336,28 +474,45 @@ /** | ||
*/ | ||
export declare function useValidation<FormData extends object>(formData: FormData): UseValidation<FormData>; | ||
export declare function useValidation<FormData extends object>( | ||
formData: FormData | ||
): UseValidation<FormData> | ||
declare type ValidationBehavior = (info: ValidationBehaviorInfo) => boolean | void; | ||
declare type ValidationBehavior = ( | ||
info: ValidationBehaviorInfo | ||
) => boolean | void | ||
declare type ValidationBehaviorInfo = { | ||
submitCount: number; | ||
errorMessages: string[]; | ||
hasError: boolean; | ||
touched: boolean; | ||
}; | ||
submitCount: number | ||
hasError: boolean | ||
touched: boolean | ||
dirty: boolean | ||
force: boolean | ||
submit: boolean | ||
} | ||
declare type ValidationBehaviorRuleTupel = [ | ||
ValidationBehavior, | ||
SimpleRule | RuleWithKey | ||
]; | ||
ValidationBehavior, | ||
SimpleRule | RuleWithKey | ||
] | ||
export declare type ValidationBehaviorString = string; | ||
declare type ValidationBehaviorString = | ||
| DefaultValidationBehaviorString | ||
| keyof UseValidation_CustomValidationBehavior | ||
export declare class ValidationError extends Error { | ||
constructor(); | ||
constructor() | ||
} | ||
declare type ValidationResult = Promise<void | string>; | ||
declare type ValidationResult = Promise<void | string> | ||
declare type Validator = (modelValues: unknown[], force: boolean) => ValidationResult; | ||
declare type Validator = ( | ||
modelValues: unknown[], | ||
force: boolean, | ||
submit: boolean | ||
) => ValidationResult | ||
export { } | ||
export {} | ||
declare global { | ||
// eslint-disable-next-line @typescript-eslint/no-empty-interface | ||
interface UseValidation_CustomValidationBehavior {} | ||
} |
@@ -303,3 +303,3 @@ import { isRef, isReactive, watch, ref, computed, reactive, unref, shallowReactive } from 'vue'; | ||
class Config { | ||
class ValidationConfig { | ||
constructor() { | ||
@@ -320,3 +320,3 @@ Object.defineProperty(this, "defaultValidationBehavior", { | ||
const lazy = ({ touched }) => touched; | ||
const lazier = ({ touched, hasError }) => touched && hasError; | ||
const lazier = ({ force, touched, hasError }) => force || (touched && hasError); | ||
this.defaultValidationBehavior = 'lazier'; | ||
@@ -333,7 +333,7 @@ this.validationBehavior = new Map([ | ||
} | ||
const CONFIG = new Config(); | ||
const VALIDATION_CONFIG = new ValidationConfig(); | ||
function registerField(form, name, field, disposables) { | ||
var _a, _b; | ||
const defaultValidationBehavior = CONFIG.getDefaultValidationBehavior(); | ||
const defaultValidationBehavior = VALIDATION_CONFIG.getDefaultValidationBehavior(); | ||
const rules = (_b = (_a = field.$rules) === null || _a === void 0 ? void 0 : _a.map(fieldRule => { | ||
@@ -349,3 +349,3 @@ if (typeof fieldRule === 'function') { | ||
else { | ||
const validationBehavior = CONFIG.validationBehavior.get(fieldValidationBehavior); | ||
const validationBehavior = VALIDATION_CONFIG.validationBehavior.get(fieldValidationBehavior); | ||
if (validationBehavior !== undefined) { | ||
@@ -359,3 +359,3 @@ return [validationBehavior, rule]; | ||
} | ||
throw Error('Invalid rule provided'); | ||
throw Error('[useValidation] Invalid rule provided'); | ||
})) !== null && _b !== void 0 ? _b : []; | ||
@@ -365,2 +365,3 @@ const uid$1 = uid(); | ||
const stop = watch(formField.modelValue, () => { | ||
formField.dirty = true; | ||
form.validate(uid$1); | ||
@@ -375,6 +376,6 @@ }, { deep: true }); | ||
$validating: formField.validating, | ||
async $setTouched(forceValidation = true) { | ||
formField.touched = true; | ||
if (forceValidation) { | ||
await form.validate(uid$1, forceValidation); | ||
async $setTouched(touched = true, forceValidate = true) { | ||
formField.touched = touched; | ||
if (forceValidate) { | ||
await form.validate(uid$1, forceValidate); | ||
} | ||
@@ -429,4 +430,4 @@ } | ||
} | ||
function resetFields(formData, transformedFormData) { | ||
Object.entries(formData).forEach(([key, value]) => { | ||
function resetFields(data, transformedFormData) { | ||
Object.entries(data).forEach(([key, value]) => { | ||
const transformedValue = transformedFormData[key]; | ||
@@ -502,2 +503,8 @@ if (isTransformedField(transformedValue)) { | ||
}); | ||
Object.defineProperty(this, "dirty", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: false | ||
}); | ||
Object.defineProperty(this, "modelValue", { | ||
@@ -545,10 +552,15 @@ enumerable: true, | ||
} | ||
async validate(ruleNumber, modelValues, form, force) { | ||
if (!(force || this._shouldValidate(ruleNumber, form))) { | ||
return; | ||
} | ||
const rule = this._rules[ruleNumber]; | ||
async validate(ruleNumber, modelValues, form, force, submit) { | ||
const shouldValidate = this.getValidationBehavior(ruleNumber)({ | ||
submitCount: form.submitCount.value, | ||
hasError: this._errors[ruleNumber] !== null, | ||
touched: this.touched, | ||
dirty: this.dirty, | ||
submit, | ||
force | ||
}); | ||
const buffer = this._buffers[ruleNumber]; | ||
let error; | ||
if (!rule) { | ||
const rule = this._rules[ruleNumber]; | ||
if (!rule || !shouldValidate) { | ||
return; | ||
@@ -584,2 +596,3 @@ } | ||
this.touched = false; | ||
this.dirty = false; | ||
if (toDefaultValues) { | ||
@@ -614,10 +627,2 @@ if (isRef(this.modelValue)) { | ||
} | ||
_shouldValidate(ruleNumber, form) { | ||
return this.getValidationBehavior(ruleNumber)({ | ||
submitCount: form.submitCount.value, | ||
errorMessages: this.errors.value, | ||
hasError: this.errors.value.length > 0, | ||
touched: this.touched | ||
}); | ||
} | ||
_setError(ruleNumber, error) { | ||
@@ -732,3 +737,3 @@ if (typeof error === 'string') { | ||
rules.forEach(([, rule], ruleNumber) => { | ||
const validator = (modelValues, force) => field.validate(ruleNumber, modelValues, this, force); | ||
const validator = (modelValues, force, submit) => field.validate(ruleNumber, modelValues, this, force, submit); | ||
if (isSimpleRule(rule)) { | ||
@@ -741,3 +746,5 @@ simpleValidators.validators.push(validator); | ||
validator, | ||
meta: { field, ruleNumber } | ||
meta: { | ||
field | ||
} | ||
}; | ||
@@ -767,15 +774,7 @@ const rollback = () => { | ||
const simpleValidators = this._simpleValidators.get(uid); | ||
if (simpleValidators) { | ||
const { validators, meta } = simpleValidators; | ||
if (force) { | ||
return Promise.allSettled([ | ||
...validators.map(v => v([meta.field.modelValue], true)), | ||
...this._getValidationResultsForKeys(meta.keys, true) | ||
]); | ||
} | ||
return Promise.allSettled([ | ||
...validators.map(v => v([meta.field.modelValue], false)), | ||
...this._getValidationResultsForKeys(meta.keys, false) | ||
]); | ||
} | ||
const { validators, meta } = simpleValidators; | ||
return Promise.allSettled([ | ||
...validators.map(v => v([meta.field.modelValue], force, false)), | ||
...this._getValidationResultsForKeys(meta.keys, force, false) | ||
]); | ||
} | ||
@@ -805,15 +804,11 @@ async validateAll(names) { | ||
} | ||
_getValidationResultsForKeys(keys, force, skipShouldValidate = false) { | ||
_getValidationResultsForKeys(keys, force, submit, skipTouchedCheck = false) { | ||
const validationResults = []; | ||
for (const key of keys) { | ||
this.tryGetKeyedValidators({ | ||
success: keyedValidators => { | ||
if (skipShouldValidate || | ||
this._shouldEveryFieldValidate(keyedValidators)) { | ||
const values = [...keyedValidators.values()]; | ||
const modelValues = values.map(({ meta }) => meta.field.modelValue); | ||
validationResults.push(...values.map(({ validator }) => validator(modelValues, force))); | ||
} | ||
} | ||
})(key); | ||
const keyedValidators = this._keyedValidators.get(key); | ||
if (skipTouchedCheck || this._isEveryFieldTouched(keyedValidators)) { | ||
const values = [...keyedValidators.values()]; | ||
const modelValues = values.map(({ meta }) => meta.field.modelValue); | ||
validationResults.push(...values.map(({ validator }) => validator(modelValues, force, submit))); | ||
} | ||
} | ||
@@ -827,5 +822,5 @@ return validationResults; | ||
meta.field.touched = true; | ||
validationResults.push(...validators.map(v => v([meta.field.modelValue], true))); | ||
validationResults.push(...validators.map(v => v([meta.field.modelValue], true, true))); | ||
} | ||
validationResults.push(...this._getValidationResultsForKeys(this._keyedValidators.keys(), true, true)); | ||
validationResults.push(...this._getValidationResultsForKeys(this._keyedValidators.keys(), true, true, true)); | ||
} | ||
@@ -837,4 +832,4 @@ else if (names.length > 0) { | ||
if (uniqueNames.has(meta.field.name)) { | ||
validationResults.push(...validators.map(v => v([meta.field.modelValue], true))); | ||
validationResults.push(...this._getValidationResultsForKeys(meta.keys, true, true)); | ||
validationResults.push(...validators.map(v => v([meta.field.modelValue], true, true))); | ||
validationResults.push(...this._getValidationResultsForKeys(meta.keys, true, true, true)); | ||
} | ||
@@ -845,5 +840,5 @@ } | ||
} | ||
_shouldEveryFieldValidate(keyedValidators) { | ||
for (const { meta: { field } } of keyedValidators) { | ||
if (!field.touched) { | ||
_isEveryFieldTouched(keyedValidators) { | ||
for (const { meta } of keyedValidators) { | ||
if (!meta.field.touched) { | ||
return false; | ||
@@ -956,15 +951,16 @@ } | ||
*/ | ||
function configureValidation(configuration = {}) { | ||
function createValidation(configuration) { | ||
return { | ||
install() { | ||
var _a, _b; | ||
CONFIG.defaultValidationBehavior = | ||
(_a = configuration.defaultValidationBehavior) !== null && _a !== void 0 ? _a : 'lazier'; | ||
for (const [key, validationBehavior] of Object.entries((_b = configuration.validationBehavior) !== null && _b !== void 0 ? _b : {})) { | ||
trySet(CONFIG.validationBehavior)({ | ||
failure() { | ||
console.warn(`Validation behavior with name '${key}' already exists`); | ||
} | ||
})(key, validationBehavior); | ||
for (const [key, validationBehavior] of Object.entries((_a = configuration.validationBehavior) !== null && _a !== void 0 ? _a : {})) { | ||
VALIDATION_CONFIG.validationBehavior.set(key, validationBehavior); | ||
} | ||
if (VALIDATION_CONFIG.validationBehavior.has(configuration.defaultValidationBehavior)) { | ||
VALIDATION_CONFIG.defaultValidationBehavior = | ||
(_b = configuration.defaultValidationBehavior) !== null && _b !== void 0 ? _b : 'lazier'; | ||
} | ||
else { | ||
console.warn(`[useValidation] Default validation behavior is not valid. Valid values are`, VALIDATION_CONFIG.validationBehavior.keys()); | ||
} | ||
} | ||
@@ -974,2 +970,2 @@ }; | ||
export { ValidationError, configureValidation, useValidation }; | ||
export { ValidationError, createValidation, useValidation }; |
{ | ||
"name": "vue3-form-validation", | ||
"version": "5.0.0-beta.2", | ||
"version": "5.0.0-beta.3", | ||
"description": "Vue composition function for Form Validation", | ||
@@ -10,2 +10,3 @@ "author": { | ||
"type": "module", | ||
"sideEffects": false, | ||
"main": "dist/vue3-form-validation.cjs.js", | ||
@@ -12,0 +13,0 @@ "types": "dist/vue3-form-validation.d.ts", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
88079
2319