@tanstack/form-core 1.6.2 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import type { GlobalFormValidationError, ValidationCause } from './types'\nimport type { FormValidators } from './FormApi'\nimport type { AnyFieldMeta, FieldValidators } from './FieldApi'\n\nexport type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\n/**\n * @private\n */\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n * @private\n */\nexport function getBy(obj: any, path: any) {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart: any) => {\n if (current === null) return null\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n * @private\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (\n typeof key === 'string' ||\n (typeof key === 'number' && !Array.isArray(parent))\n ) {\n if (typeof parent === 'object') {\n if (parent === null) {\n parent = {}\n }\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (Array.isArray(parent) && typeof key === 'number') {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n return doSet(obj)\n}\n\n/**\n * Delete a field on an object using a path, including dot notation.\n * @private\n */\nexport function deleteBy(obj: any, _path: any) {\n const path = makePathArray(_path)\n\n function doDelete(parent: any): any {\n if (!parent) return\n if (path.length === 1) {\n const finalPath = path[0]!\n if (Array.isArray(parent) && typeof finalPath === 'number') {\n return parent.filter((_, i) => i !== finalPath)\n }\n const { [finalPath]: remove, ...rest } = parent\n return rest\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doDelete(parent[key]),\n }\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n if (key >= parent.length) {\n return parent\n }\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doDelete(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n }\n\n throw new Error('It seems we have created an infinite loop in deleteBy. ')\n }\n\n return doDelete(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\n/**\n * @private\n */\nexport function makePathArray(str: string | Array<string | number>) {\n if (Array.isArray(str)) {\n return [...str]\n }\n\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replace(/\\[/g, '.')\n .replace(/\\]/g, '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\n/**\n * @private\n */\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\ninterface AsyncValidatorArrayPartialOptions<T> {\n validators?: T\n asyncDebounceMs?: number\n}\n\n/**\n * @private\n */\nexport interface AsyncValidator<T> {\n cause: ValidationCause\n validate: T\n debounceMs: number\n}\n\n/**\n * @private\n */\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<\n T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<any, any, any, any, any, any, any, any, any, any>\n | FormValidators<any, any, any, any, any, any, any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const changeValidator = {\n cause: 'change',\n validate: onChangeAsync,\n debounceMs: onChangeAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const blurValidator = {\n cause: 'blur',\n validate: onBlurAsync,\n debounceMs: onBlurAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const submitValidator = {\n cause: 'submit',\n validate: onSubmitAsync,\n debounceMs: 0,\n } as const\n\n const noopValidator = (\n validator:\n | typeof changeValidator\n | typeof blurValidator\n | typeof submitValidator,\n ) => ({ ...validator, debounceMs: 0 }) as const\n\n switch (cause) {\n case 'submit':\n return [\n noopValidator(changeValidator),\n noopValidator(blurValidator),\n submitValidator,\n ] as never\n case 'blur':\n return [blurValidator] as never\n case 'change':\n return [changeValidator] as never\n case 'server':\n default:\n return [] as never\n }\n}\n\ninterface SyncValidatorArrayPartialOptions<T> {\n validators?: T\n}\n\n/**\n * @private\n */\nexport interface SyncValidator<T> {\n cause: ValidationCause\n validate: T\n}\n\n/**\n * @private\n */\nexport function getSyncValidatorArray<T>(\n cause: ValidationCause,\n options: SyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<\n T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']\n >\n >\n : never {\n const { onChange, onBlur, onSubmit, onMount } = (options.validators || {}) as\n | FieldValidators<any, any, any, any, any, any, any, any, any, any>\n | FormValidators<any, any, any, any, any, any, any, any>\n\n const changeValidator = { cause: 'change', validate: onChange } as const\n const blurValidator = { cause: 'blur', validate: onBlur } as const\n const submitValidator = { cause: 'submit', validate: onSubmit } as const\n const mountValidator = { cause: 'mount', validate: onMount } as const\n\n // Allows us to clear onServer errors\n const serverValidator = {\n cause: 'server',\n validate: () => undefined,\n } as const\n\n switch (cause) {\n case 'mount':\n return [mountValidator] as never\n case 'submit':\n return [\n changeValidator,\n blurValidator,\n submitValidator,\n serverValidator,\n ] as never\n case 'server':\n return [serverValidator] as never\n case 'blur':\n return [blurValidator, serverValidator] as never\n case 'change':\n default:\n return [changeValidator, serverValidator] as never\n }\n}\n\nexport const isGlobalFormValidationError = (\n error: unknown,\n): error is GlobalFormValidationError<unknown> => {\n return !!error && typeof error === 'object' && 'fields' in error\n}\n\nexport function shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false\n for (const [k, v] of objA) {\n if (!objB.has(k) || !Object.is(v, objB.get(k))) return false\n }\n return true\n }\n\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false\n for (const v of objA) {\n if (!objB.has(v)) return false\n }\n return true\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (let i = 0; i < keysA.length; i++) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||\n !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import type {\n GlobalFormValidationError,\n ValidationCause,\n ValidationError,\n ValidationSource,\n} from './types'\nimport type { FormValidators } from './FormApi'\nimport type { AnyFieldMeta, FieldValidators } from './FieldApi'\n\nexport type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\n/**\n * @private\n */\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n * @private\n */\nexport function getBy(obj: any, path: any) {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart: any) => {\n if (current === null) return null\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n * @private\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (\n typeof key === 'string' ||\n (typeof key === 'number' && !Array.isArray(parent))\n ) {\n if (typeof parent === 'object') {\n if (parent === null) {\n parent = {}\n }\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (Array.isArray(parent) && typeof key === 'number') {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n return doSet(obj)\n}\n\n/**\n * Delete a field on an object using a path, including dot notation.\n * @private\n */\nexport function deleteBy(obj: any, _path: any) {\n const path = makePathArray(_path)\n\n function doDelete(parent: any): any {\n if (!parent) return\n if (path.length === 1) {\n const finalPath = path[0]!\n if (Array.isArray(parent) && typeof finalPath === 'number') {\n return parent.filter((_, i) => i !== finalPath)\n }\n const { [finalPath]: remove, ...rest } = parent\n return rest\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doDelete(parent[key]),\n }\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n if (key >= parent.length) {\n return parent\n }\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doDelete(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n }\n\n throw new Error('It seems we have created an infinite loop in deleteBy. ')\n }\n\n return doDelete(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\n/**\n * @private\n */\nexport function makePathArray(str: string | Array<string | number>) {\n if (Array.isArray(str)) {\n return [...str]\n }\n\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replace(/\\[/g, '.')\n .replace(/\\]/g, '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\n/**\n * @private\n */\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\ninterface AsyncValidatorArrayPartialOptions<T> {\n validators?: T\n asyncDebounceMs?: number\n}\n\n/**\n * @private\n */\nexport interface AsyncValidator<T> {\n cause: ValidationCause\n validate: T\n debounceMs: number\n}\n\n/**\n * @private\n */\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<\n T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<any, any, any, any, any, any, any, any, any, any>\n | FormValidators<any, any, any, any, any, any, any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const changeValidator = {\n cause: 'change',\n validate: onChangeAsync,\n debounceMs: onChangeAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const blurValidator = {\n cause: 'blur',\n validate: onBlurAsync,\n debounceMs: onBlurAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const submitValidator = {\n cause: 'submit',\n validate: onSubmitAsync,\n debounceMs: 0,\n } as const\n\n const noopValidator = (\n validator:\n | typeof changeValidator\n | typeof blurValidator\n | typeof submitValidator,\n ) => ({ ...validator, debounceMs: 0 }) as const\n\n switch (cause) {\n case 'submit':\n return [\n noopValidator(changeValidator),\n noopValidator(blurValidator),\n submitValidator,\n ] as never\n case 'blur':\n return [blurValidator] as never\n case 'change':\n return [changeValidator] as never\n case 'server':\n default:\n return [] as never\n }\n}\n\ninterface SyncValidatorArrayPartialOptions<T> {\n validators?: T\n}\n\n/**\n * @private\n */\nexport interface SyncValidator<T> {\n cause: ValidationCause\n validate: T\n}\n\n/**\n * @private\n */\nexport function getSyncValidatorArray<T>(\n cause: ValidationCause,\n options: SyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<\n T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']\n >\n >\n : never {\n const { onChange, onBlur, onSubmit, onMount } = (options.validators || {}) as\n | FieldValidators<any, any, any, any, any, any, any, any, any, any>\n | FormValidators<any, any, any, any, any, any, any, any>\n\n const changeValidator = { cause: 'change', validate: onChange } as const\n const blurValidator = { cause: 'blur', validate: onBlur } as const\n const submitValidator = { cause: 'submit', validate: onSubmit } as const\n const mountValidator = { cause: 'mount', validate: onMount } as const\n\n // Allows us to clear onServer errors\n const serverValidator = {\n cause: 'server',\n validate: () => undefined,\n } as const\n\n switch (cause) {\n case 'mount':\n return [mountValidator] as never\n case 'submit':\n return [\n changeValidator,\n blurValidator,\n submitValidator,\n serverValidator,\n ] as never\n case 'server':\n return [serverValidator] as never\n case 'blur':\n return [blurValidator, serverValidator] as never\n case 'change':\n default:\n return [changeValidator, serverValidator] as never\n }\n}\n\nexport const isGlobalFormValidationError = (\n error: unknown,\n): error is GlobalFormValidationError<unknown> => {\n return !!error && typeof error === 'object' && 'fields' in error\n}\n\nexport function shallow<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false\n for (const [k, v] of objA) {\n if (!objB.has(k) || !Object.is(v, objB.get(k))) return false\n }\n return true\n }\n\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false\n for (const v of objA) {\n if (!objB.has(v)) return false\n }\n return true\n }\n\n const keysA = Object.keys(objA)\n if (keysA.length !== Object.keys(objB).length) {\n return false\n }\n\n for (let i = 0; i < keysA.length; i++) {\n if (\n !Object.prototype.hasOwnProperty.call(objB, keysA[i] as string) ||\n !Object.is(objA[keysA[i] as keyof T], objB[keysA[i] as keyof T])\n ) {\n return false\n }\n }\n return true\n}\n\n/**\n * Determines the logic for determining the error source and value to set on the field meta within the form level sync/async validation.\n * @private\n */\nexport const determineFormLevelErrorSourceAndValue = ({\n newFormValidatorError,\n isPreviousErrorFromFormValidator,\n previousErrorValue,\n}: {\n newFormValidatorError: ValidationError\n isPreviousErrorFromFormValidator: boolean\n previousErrorValue: ValidationError\n}): {\n newErrorValue: ValidationError\n newSource: ValidationSource | undefined\n} => {\n // All falsy values are not considered errors\n if (newFormValidatorError) {\n return { newErrorValue: newFormValidatorError, newSource: 'form' }\n }\n\n // Clears form level error since it's now stale\n if (isPreviousErrorFromFormValidator) {\n return { newErrorValue: undefined, newSource: undefined }\n }\n\n // At this point, we have a preivous error which must have been set by the field validator, keep as is\n if (previousErrorValue) {\n return { newErrorValue: previousErrorValue, newSource: 'field' }\n }\n\n // No new or previous error, clear the error\n return { newErrorValue: undefined, newSource: undefined }\n}\n\n/**\n * Determines the logic for determining the error source and value to set on the field meta within the field level sync/async validation.\n * @private\n */\nexport const determineFieldLevelErrorSourceAndValue = ({\n formLevelError,\n fieldLevelError,\n}: {\n formLevelError: ValidationError\n fieldLevelError: ValidationError\n}): {\n newErrorValue: ValidationError\n newSource: ValidationSource | undefined\n} => {\n // At field level, we prioritize the field level error\n if (fieldLevelError) {\n return { newErrorValue: fieldLevelError, newSource: 'field' }\n }\n\n // If there is no field level error, and there is a form level error, we set the form level error\n if (formLevelError) {\n return { newErrorValue: formLevelError, newSource: 'form' }\n }\n\n return { newErrorValue: undefined, newSource: undefined }\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { GlobalFormValidationError, ValidationCause } from './types.cjs';
1
+ import { GlobalFormValidationError, ValidationCause, ValidationError, ValidationSource } from './types.cjs';
2
2
  import { FormValidators } from './FormApi.cjs';
3
3
  import { FieldValidators } from './FieldApi.cjs';
4
4
  export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput;
@@ -62,4 +62,27 @@ export interface SyncValidator<T> {
62
62
  export declare function getSyncValidatorArray<T>(cause: ValidationCause, options: SyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any, any, any, any, any, any, any, any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>> : T extends FormValidators<any, any, any, any, any, any, any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount']>> : never;
63
63
  export declare const isGlobalFormValidationError: (error: unknown) => error is GlobalFormValidationError<unknown>;
64
64
  export declare function shallow<T>(objA: T, objB: T): boolean;
65
+ /**
66
+ * Determines the logic for determining the error source and value to set on the field meta within the form level sync/async validation.
67
+ * @private
68
+ */
69
+ export declare const determineFormLevelErrorSourceAndValue: ({ newFormValidatorError, isPreviousErrorFromFormValidator, previousErrorValue, }: {
70
+ newFormValidatorError: ValidationError;
71
+ isPreviousErrorFromFormValidator: boolean;
72
+ previousErrorValue: ValidationError;
73
+ }) => {
74
+ newErrorValue: ValidationError;
75
+ newSource: ValidationSource | undefined;
76
+ };
77
+ /**
78
+ * Determines the logic for determining the error source and value to set on the field meta within the field level sync/async validation.
79
+ * @private
80
+ */
81
+ export declare const determineFieldLevelErrorSourceAndValue: ({ formLevelError, fieldLevelError, }: {
82
+ formLevelError: ValidationError;
83
+ fieldLevelError: ValidationError;
84
+ }) => {
85
+ newErrorValue: ValidationError;
86
+ newSource: ValidationSource | undefined;
87
+ };
65
88
  export {};
@@ -2,7 +2,7 @@ import { Derived } from '@tanstack/store';
2
2
  import { DeepKeys, DeepValue, UnwrapOneLevelOfArray } from './util-types.js';
3
3
  import { StandardSchemaV1, StandardSchemaV1Issue, TStandardSchemaValidatorValue } from './standardSchemaValidator.js';
4
4
  import { FieldInfo, FormApi, FormAsyncValidateOrFn, FormValidateAsyncFn, FormValidateFn, FormValidateOrFn } from './FormApi.js';
5
- import { ListenerCause, UpdateMetaOptions, ValidationCause, ValidationError, ValidationErrorMap } from './types.js';
5
+ import { ListenerCause, UpdateMetaOptions, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapSource } from './types.js';
6
6
  import { Updater } from './utils.js';
7
7
  /**
8
8
  * @private
@@ -183,6 +183,10 @@ export type FieldMetaBase<TParentData, TName extends DeepKeys<TParentData>, TDat
183
183
  * A map of errors related to the field value.
184
184
  */
185
185
  errorMap: ValidationErrorMap<UnwrapFieldValidateOrFn<TName, TOnMount, TFormOnMount>, UnwrapFieldValidateOrFn<TName, TOnChange, TFormOnChange>, UnwrapFieldAsyncValidateOrFn<TName, TOnChangeAsync, TFormOnChangeAsync>, UnwrapFieldValidateOrFn<TName, TOnBlur, TFormOnBlur>, UnwrapFieldAsyncValidateOrFn<TName, TOnBlurAsync, TFormOnBlurAsync>, UnwrapFieldValidateOrFn<TName, TOnSubmit, TFormOnSubmit>, UnwrapFieldAsyncValidateOrFn<TName, TOnSubmitAsync, TFormOnSubmitAsync>>;
186
+ /**
187
+ * @private allows tracking the source of the errors in the error map
188
+ */
189
+ errorSourceMap: ValidationErrorMapSource;
186
190
  /**
187
191
  * A flag indicating whether the field is currently being validated.
188
192
  */
@@ -1,7 +1,7 @@
1
1
  import { batch, Derived } from "@tanstack/store";
2
2
  import { standardSchemaValidators, isStandardSchemaValidator } from "./standardSchemaValidator.js";
3
3
  import { defaultFieldMeta } from "./metaHelper.js";
4
- import { getBy, getSyncValidatorArray, getAsyncValidatorArray } from "./utils.js";
4
+ import { getBy, getSyncValidatorArray, getAsyncValidatorArray, determineFieldLevelErrorSourceAndValue } from "./utils.js";
5
5
  class FieldApi {
6
6
  /**
7
7
  * Initializes a new `FieldApi` instance.
@@ -35,7 +35,12 @@ class FieldApi {
35
35
  (prev) => ({
36
36
  ...prev,
37
37
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
38
- errorMap: { ...prev == null ? void 0 : prev.errorMap, onMount: error }
38
+ errorMap: { ...prev == null ? void 0 : prev.errorMap, onMount: error },
39
+ errorSourceMap: {
40
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
41
+ ...prev == null ? void 0 : prev.errorSourceMap,
42
+ onMount: "field"
43
+ }
39
44
  })
40
45
  );
41
46
  }
@@ -118,6 +123,7 @@ class FieldApi {
118
123
  return linkedFields;
119
124
  };
120
125
  this.validateSync = (cause, errorFromForm) => {
126
+ var _a;
121
127
  const validates = getSyncValidatorArray(cause, this.options);
122
128
  const linkedFields = this.getLinkedFields(cause);
123
129
  const linkedFieldValidates = linkedFields.reduce(
@@ -133,39 +139,38 @@ class FieldApi {
133
139
  let hasErrored = false;
134
140
  batch(() => {
135
141
  const validateFieldFn = (field, validateObj) => {
142
+ var _a2;
136
143
  const errorMapKey = getErrorMapKey(validateObj.cause);
137
- const error = (
138
- /*
139
- If `validateObj.validate` is `undefined`, then the field doesn't have
140
- a validator for this event, but there still could be an error that
141
- needs to be cleaned up related to the current event left by the
142
- form's validator.
143
- */
144
- validateObj.validate ? normalizeError(
145
- field.runValidator({
146
- validate: validateObj.validate,
147
- value: {
148
- value: field.store.state.value,
149
- validationSource: "field",
150
- fieldApi: field
151
- },
152
- type: "validate"
153
- })
154
- ) : errorFromForm[errorMapKey]
155
- );
156
- if (field.state.meta.errorMap[errorMapKey] !== error) {
144
+ const fieldLevelError = validateObj.validate ? normalizeError(
145
+ field.runValidator({
146
+ validate: validateObj.validate,
147
+ value: {
148
+ value: field.store.state.value,
149
+ validationSource: "field",
150
+ fieldApi: field
151
+ },
152
+ type: "validate"
153
+ })
154
+ ) : void 0;
155
+ const formLevelError = errorFromForm[errorMapKey];
156
+ const { newErrorValue, newSource } = determineFieldLevelErrorSourceAndValue({
157
+ formLevelError,
158
+ fieldLevelError
159
+ });
160
+ if (((_a2 = field.state.meta.errorMap) == null ? void 0 : _a2[errorMapKey]) !== newErrorValue) {
157
161
  field.setMeta((prev) => ({
158
162
  ...prev,
159
163
  errorMap: {
160
164
  ...prev.errorMap,
161
- [getErrorMapKey(validateObj.cause)]: (
162
- // Prefer the error message from the field validators if they exist
163
- error ? error : errorFromForm[errorMapKey]
164
- )
165
+ [errorMapKey]: newErrorValue
166
+ },
167
+ errorSourceMap: {
168
+ ...prev.errorSourceMap,
169
+ [errorMapKey]: newSource
165
170
  }
166
171
  }));
167
172
  }
168
- if (error || errorFromForm[errorMapKey]) {
173
+ if (newErrorValue) {
169
174
  hasErrored = true;
170
175
  }
171
176
  };
@@ -178,12 +183,19 @@ class FieldApi {
178
183
  }
179
184
  });
180
185
  const submitErrKey = getErrorMapKey("submit");
181
- if (this.state.meta.errorMap[submitErrKey] && cause !== "submit" && !hasErrored) {
186
+ if (
187
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
188
+ ((_a = this.state.meta.errorMap) == null ? void 0 : _a[submitErrKey]) && cause !== "submit" && !hasErrored
189
+ ) {
182
190
  this.setMeta((prev) => ({
183
191
  ...prev,
184
192
  errorMap: {
185
193
  ...prev.errorMap,
186
194
  [submitErrKey]: void 0
195
+ },
196
+ errorSourceMap: {
197
+ ...prev.errorSourceMap,
198
+ [submitErrKey]: void 0
187
199
  }
188
200
  }));
189
201
  }
@@ -255,20 +267,27 @@ class FieldApi {
255
267
  rawError = e;
256
268
  }
257
269
  if (controller.signal.aborted) return resolve(void 0);
258
- const error = normalizeError(rawError);
259
- const fieldErrorFromForm = (_a = asyncFormValidationResults[this.name]) == null ? void 0 : _a[errorMapKey];
260
- const fieldError = error || fieldErrorFromForm;
270
+ const fieldLevelError = normalizeError(rawError);
271
+ const formLevelError = (_a = asyncFormValidationResults[this.name]) == null ? void 0 : _a[errorMapKey];
272
+ const { newErrorValue, newSource } = determineFieldLevelErrorSourceAndValue({
273
+ formLevelError,
274
+ fieldLevelError
275
+ });
261
276
  field.setMeta((prev) => {
262
277
  return {
263
278
  ...prev,
264
279
  errorMap: {
265
280
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
266
281
  ...prev == null ? void 0 : prev.errorMap,
267
- [errorMapKey]: fieldError
282
+ [errorMapKey]: newErrorValue
283
+ },
284
+ errorSourceMap: {
285
+ ...prev.errorSourceMap,
286
+ [errorMapKey]: newSource
268
287
  }
269
288
  };
270
289
  });
271
- resolve(fieldError);
290
+ resolve(newErrorValue);
272
291
  })
273
292
  );
274
293
  };
@@ -392,8 +411,12 @@ class FieldApi {
392
411
  );
393
412
  }
394
413
  triggerOnBlurListener() {
395
- var _a, _b, _c;
414
+ var _a, _b, _c, _d, _e;
396
415
  const debounceMs = (_a = this.options.listeners) == null ? void 0 : _a.onBlurDebounceMs;
416
+ (_c = (_b = this.form.options.listeners) == null ? void 0 : _b.onBlur) == null ? void 0 : _c.call(_b, {
417
+ formApi: this.form,
418
+ fieldApi: this
419
+ });
397
420
  if (debounceMs && debounceMs > 0) {
398
421
  if (this.timeoutIds.listeners.blur) {
399
422
  clearTimeout(this.timeoutIds.listeners.blur);
@@ -406,15 +429,19 @@ class FieldApi {
406
429
  });
407
430
  }, debounceMs);
408
431
  } else {
409
- (_c = (_b = this.options.listeners) == null ? void 0 : _b.onBlur) == null ? void 0 : _c.call(_b, {
432
+ (_e = (_d = this.options.listeners) == null ? void 0 : _d.onBlur) == null ? void 0 : _e.call(_d, {
410
433
  value: this.state.value,
411
434
  fieldApi: this
412
435
  });
413
436
  }
414
437
  }
415
438
  triggerOnChangeListener() {
416
- var _a, _b, _c;
439
+ var _a, _b, _c, _d, _e;
417
440
  const debounceMs = (_a = this.options.listeners) == null ? void 0 : _a.onChangeDebounceMs;
441
+ (_c = (_b = this.form.options.listeners) == null ? void 0 : _b.onChange) == null ? void 0 : _c.call(_b, {
442
+ formApi: this.form,
443
+ fieldApi: this
444
+ });
418
445
  if (debounceMs && debounceMs > 0) {
419
446
  if (this.timeoutIds.listeners.change) {
420
447
  clearTimeout(this.timeoutIds.listeners.change);
@@ -427,7 +454,7 @@ class FieldApi {
427
454
  });
428
455
  }, debounceMs);
429
456
  } else {
430
- (_c = (_b = this.options.listeners) == null ? void 0 : _b.onChange) == null ? void 0 : _c.call(_b, {
457
+ (_e = (_d = this.options.listeners) == null ? void 0 : _d.onChange) == null ? void 0 : _e.call(_d, {
431
458
  value: this.state.value,
432
459
  fieldApi: this
433
460
  });