@tanstack/form-core 1.27.1 → 1.27.3
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.
- package/dist/cjs/FieldApi.cjs.map +1 -1
- package/dist/cjs/FieldGroupApi.cjs.map +1 -1
- package/dist/cjs/FormApi.cjs +1 -11
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/utils.cjs +12 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +2 -1
- package/dist/esm/FieldApi.js.map +1 -1
- package/dist/esm/FieldGroupApi.js.map +1 -1
- package/dist/esm/FormApi.js +2 -12
- package/dist/esm/FormApi.js.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/utils.d.ts +2 -1
- package/dist/esm/utils.js +12 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/FieldApi.ts +13 -13
- package/src/FieldGroupApi.ts +1 -2
- package/src/FormApi.ts +10 -19
- package/src/util-types.ts +3 -2
- package/src/utils.ts +14 -2
package/dist/esm/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import { defaultValidationLogic } from './ValidationLogic'\nimport type { ValidationLogicProps } from './ValidationLogic'\nimport type { FieldValidators } from './FieldApi'\nimport type { FormValidators } from './FormApi'\nimport type {\n GlobalFormValidationError,\n ValidationCause,\n ValidationError,\n ValidationSource,\n} from './types'\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: unknown, path: string | (string | number)[]): any {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart) => {\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 (\n typeof key === 'string' ||\n (typeof key === 'number' && !Array.isArray(parent))\n ) {\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 reLineOfOnlyDigits = /^(\\d+)$/gm\n// the second dot must be in a lookahead or the engine\n// will skip subsequent numbers (like foo.0.1.)\nconst reDigitsBetweenDots = /\\.(\\d+)(?=\\.)/gm\nconst reStartWithDigitThenDot = /^(\\d+)\\./gm\nconst reDotWithDigitsToEnd = /\\.(\\d+$)/gm\nconst reMultipleDots = /\\.{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 (\n str\n // Leading `[` may lead to wrong parsing down the line\n // (Example: '[0][1]' should be '0.1', not '.0.1')\n .replace(/(^\\[)|]/gm, '')\n .replace(/\\[/g, '.')\n .replace(reLineOfOnlyDigits, intReplace)\n .replace(reDigitsBetweenDots, `.${intReplace}.`)\n .replace(reStartWithDigitThenDot, `${intReplace}.`)\n .replace(reDotWithDigitsToEnd, `.${intReplace}`)\n .replace(reMultipleDots, '.')\n .split('.')\n .map((d) => {\n if (d.startsWith(intPrefix)) {\n const numStr = d.substring(intPrefix.length)\n const num = parseInt(numStr, 10)\n\n if (String(num) === numStr) {\n return num\n }\n return numStr\n }\n return d\n })\n )\n}\n\n/**\n * @private\n */\nexport function concatenatePaths(path1: string, path2: string): string {\n if (path1.length === 0) return path2\n if (path2.length === 0) return path1\n\n if (path2.startsWith('[')) {\n return path1 + path2\n }\n\n // In cases where parent and child withFieldGroup forms are both nested\n if (path2.startsWith('.')) {\n return path1 + path2\n }\n\n return `${path1}.${path2}`\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\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 validationLogic?: any\n form?: any\n },\n): T extends FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n ? Array<\n SyncValidator<\n | T['onChange']\n | T['onBlur']\n | T['onSubmit']\n | T['onMount']\n | T['onDynamic']\n >\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<\n | T['onChange']\n | T['onBlur']\n | T['onSubmit']\n | T['onMount']\n | T['onDynamic']\n >\n >\n : never {\n const runValidation = (\n props: Parameters<ValidationLogicProps['runValidation']>[0],\n ) => {\n return props.validators.filter(Boolean).map((validator) => {\n return {\n cause: validator!.cause,\n validate: validator!.fn,\n }\n })\n }\n\n return options.validationLogic({\n form: options.form,\n validators: options.validators,\n event: { type: cause, async: false },\n runValidation,\n })\n}\n\n/**\n * @private\n */\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T> & {\n validationLogic?: any\n form?: any\n },\n): T extends FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n ? Array<\n AsyncValidator<\n | T['onChangeAsync']\n | T['onBlurAsync']\n | T['onSubmitAsync']\n | T['onDynamicAsync']\n >\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<\n | T['onChangeAsync']\n | T['onBlurAsync']\n | T['onSubmitAsync']\n | T['onDynamicAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n onDynamicAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n | FormValidators<any, any, any, any, any, any, any, any, any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const runValidation = (\n props: Parameters<ValidationLogicProps['runValidation']>[0],\n ) => {\n return props.validators.filter(Boolean).map((validator) => {\n const validatorCause = validator?.cause || cause\n\n let debounceMs = defaultDebounceMs\n\n switch (validatorCause) {\n case 'change':\n debounceMs = onChangeAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'blur':\n debounceMs = onBlurAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'dynamic':\n debounceMs = onDynamicAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'submit':\n debounceMs = 0 // submit validators are always run immediately\n break\n default:\n break\n }\n\n if (cause === 'submit') {\n debounceMs = 0\n }\n\n return {\n cause: validatorCause,\n validate: validator!.fn,\n debounceMs: debounceMs,\n }\n })\n }\n\n return options.validationLogic({\n form: options.form,\n validators: options.validators,\n event: { type: cause, async: true },\n runValidation,\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 evaluate<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 Date && objB instanceof Date) {\n return objA.getTime() === objB.getTime()\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 const keysB = Object.keys(objB)\n\n if (keysA.length !== keysB.length) {\n return false\n }\n\n for (const key of keysA) {\n // performs recursive search down the object tree\n\n if (\n !keysB.includes(key) ||\n !evaluate(objA[key as keyof T], objB[key as keyof T])\n ) {\n return false\n }\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\nexport function createFieldMap<T>(values: Readonly<T>): { [K in keyof T]: K } {\n const output: { [K in keyof T]: K } = {} as any\n\n for (const key in values) {\n output[key] = key\n }\n\n return output\n}\n\n/**\n * Merge the first parameter with the given overrides.\n * @private\n */\nexport function mergeOpts<T>(\n originalOpts: T | undefined | null,\n overrides: T,\n): T {\n if (originalOpts === undefined || originalOpts === null) {\n return overrides\n }\n\n return { ...originalOpts, ...overrides }\n}\n\n/*\n/ credit is due to https://github.com/lukeed/uuid for this code, with current npm\n/ attacks we didn't feel comfortable installing directly from npm. But big appreciation\n/ from the TanStack Form team <3.\n*/\n\nlet IDX = 256\nconst HEX: string[] = []\nlet BUFFER: number[] | undefined\n\nwhile (IDX--) {\n HEX[IDX] = (IDX + 256).toString(16).substring(1)\n}\n\nexport function uuid(): string {\n let i = 0\n let num: number\n let out = ''\n\n if (!BUFFER || IDX + 16 > 256) {\n BUFFER = new Array<number>(256)\n i = 256\n while (i--) {\n BUFFER[i] = (256 * Math.random()) | 0\n }\n i = 0\n IDX = 0\n }\n\n for (; i < 16; i++) {\n num = BUFFER[IDX + i] as number\n if (i === 6) out += HEX[(num & 15) | 64]\n else if (i === 8) out += HEX[(num & 63) | 128]\n else out += HEX[num]\n\n if (i & 1 && i > 1 && i < 11) out += '-'\n }\n\n IDX++\n return out\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import { liteThrottle } from '@tanstack/pacer-lite'\nimport { formEventClient } from './EventClient'\nimport type { ValidationLogicProps } from './ValidationLogic'\nimport type { FieldValidators } from './FieldApi'\nimport type { AnyFormApi, FormValidators } from './FormApi'\nimport type {\n GlobalFormValidationError,\n ValidationCause,\n ValidationError,\n ValidationSource,\n} from './types'\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: unknown, path: string | (string | number)[]): any {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart) => {\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 (\n typeof key === 'string' ||\n (typeof key === 'number' && !Array.isArray(parent))\n ) {\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 reLineOfOnlyDigits = /^(\\d+)$/gm\n// the second dot must be in a lookahead or the engine\n// will skip subsequent numbers (like foo.0.1.)\nconst reDigitsBetweenDots = /\\.(\\d+)(?=\\.)/gm\nconst reStartWithDigitThenDot = /^(\\d+)\\./gm\nconst reDotWithDigitsToEnd = /\\.(\\d+$)/gm\nconst reMultipleDots = /\\.{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 (\n str\n // Leading `[` may lead to wrong parsing down the line\n // (Example: '[0][1]' should be '0.1', not '.0.1')\n .replace(/(^\\[)|]/gm, '')\n .replace(/\\[/g, '.')\n .replace(reLineOfOnlyDigits, intReplace)\n .replace(reDigitsBetweenDots, `.${intReplace}.`)\n .replace(reStartWithDigitThenDot, `${intReplace}.`)\n .replace(reDotWithDigitsToEnd, `.${intReplace}`)\n .replace(reMultipleDots, '.')\n .split('.')\n .map((d) => {\n if (d.startsWith(intPrefix)) {\n const numStr = d.substring(intPrefix.length)\n const num = parseInt(numStr, 10)\n\n if (String(num) === numStr) {\n return num\n }\n return numStr\n }\n return d\n })\n )\n}\n\n/**\n * @private\n */\nexport function concatenatePaths(path1: string, path2: string): string {\n if (path1.length === 0) return path2\n if (path2.length === 0) return path1\n\n if (path2.startsWith('[')) {\n return path1 + path2\n }\n\n // In cases where parent and child withFieldGroup forms are both nested\n if (path2.startsWith('.')) {\n return path1 + path2\n }\n\n return `${path1}.${path2}`\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\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 validationLogic?: any\n form?: any\n },\n): T extends FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n ? Array<\n SyncValidator<\n | T['onChange']\n | T['onBlur']\n | T['onSubmit']\n | T['onMount']\n | T['onDynamic']\n >\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<\n | T['onChange']\n | T['onBlur']\n | T['onSubmit']\n | T['onMount']\n | T['onDynamic']\n >\n >\n : never {\n const runValidation = (\n props: Parameters<ValidationLogicProps['runValidation']>[0],\n ) => {\n return props.validators.filter(Boolean).map((validator) => {\n return {\n cause: validator!.cause,\n validate: validator!.fn,\n }\n })\n }\n\n return options.validationLogic({\n form: options.form,\n validators: options.validators,\n event: { type: cause, async: false },\n runValidation,\n })\n}\n\n/**\n * @private\n */\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T> & {\n validationLogic?: any\n form?: any\n },\n): T extends FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n ? Array<\n AsyncValidator<\n | T['onChangeAsync']\n | T['onBlurAsync']\n | T['onSubmitAsync']\n | T['onDynamicAsync']\n >\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<\n | T['onChangeAsync']\n | T['onBlurAsync']\n | T['onSubmitAsync']\n | T['onDynamicAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n onDynamicAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n | FormValidators<any, any, any, any, any, any, any, any, any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const runValidation = (\n props: Parameters<ValidationLogicProps['runValidation']>[0],\n ) => {\n return props.validators.filter(Boolean).map((validator) => {\n const validatorCause = validator?.cause || cause\n\n let debounceMs = defaultDebounceMs\n\n switch (validatorCause) {\n case 'change':\n debounceMs = onChangeAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'blur':\n debounceMs = onBlurAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'dynamic':\n debounceMs = onDynamicAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'submit':\n debounceMs = 0 // submit validators are always run immediately\n break\n default:\n break\n }\n\n if (cause === 'submit') {\n debounceMs = 0\n }\n\n return {\n cause: validatorCause,\n validate: validator!.fn,\n debounceMs: debounceMs,\n }\n })\n }\n\n return options.validationLogic({\n form: options.form,\n validators: options.validators,\n event: { type: cause, async: true },\n runValidation,\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 evaluate<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 Date && objB instanceof Date) {\n return objA.getTime() === objB.getTime()\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 const keysB = Object.keys(objB)\n\n if (keysA.length !== keysB.length) {\n return false\n }\n\n for (const key of keysA) {\n // performs recursive search down the object tree\n\n if (\n !keysB.includes(key) ||\n !evaluate(objA[key as keyof T], objB[key as keyof T])\n ) {\n return false\n }\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\nexport function createFieldMap<T>(values: Readonly<T>): { [K in keyof T]: K } {\n const output: { [K in keyof T]: K } = {} as any\n\n for (const key in values) {\n output[key] = key\n }\n\n return output\n}\n\n/**\n * Merge the first parameter with the given overrides.\n * @private\n */\nexport function mergeOpts<T>(\n originalOpts: T | undefined | null,\n overrides: T,\n): T {\n if (originalOpts === undefined || originalOpts === null) {\n return overrides\n }\n\n return { ...originalOpts, ...overrides }\n}\n\n/*\n/ credit is due to https://github.com/lukeed/uuid for this code, with current npm\n/ attacks we didn't feel comfortable installing directly from npm. But big appreciation\n/ from the TanStack Form team <3.\n*/\n\nlet IDX = 256\nconst HEX: string[] = []\nlet BUFFER: number[] | undefined\n\nwhile (IDX--) {\n HEX[IDX] = (IDX + 256).toString(16).substring(1)\n}\n\nexport function uuid(): string {\n let i = 0\n let num: number\n let out = ''\n\n if (!BUFFER || IDX + 16 > 256) {\n BUFFER = new Array<number>(256)\n i = 256\n while (i--) {\n BUFFER[i] = (256 * Math.random()) | 0\n }\n i = 0\n IDX = 0\n }\n\n for (; i < 16; i++) {\n num = BUFFER[IDX + i] as number\n if (i === 6) out += HEX[(num & 15) | 64]\n else if (i === 8) out += HEX[(num & 63) | 128]\n else out += HEX[num]\n\n if (i & 1 && i > 1 && i < 11) out += '-'\n }\n\n IDX++\n return out\n}\n\nexport const throttleFormState = liteThrottle(\n (form: AnyFormApi) =>\n formEventClient.emit('form-state', {\n id: form.formId,\n state: form.store.state,\n }),\n {\n wait: 300,\n },\n)\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/form-core",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.3",
|
|
4
4
|
"description": "Powerful, type-safe, framework agnostic forms.",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/TanStack/form.git",
|
|
9
|
+
"url": "git+https://github.com/TanStack/form.git",
|
|
10
10
|
"directory": "packages/form-core"
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://tanstack.com/form",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@tanstack/devtools-event-client": "^0.3.5",
|
|
41
|
-
"@tanstack/pacer": "^0.
|
|
41
|
+
"@tanstack/pacer-lite": "^0.1.1",
|
|
42
42
|
"@tanstack/store": "^0.7.7"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
package/src/FieldApi.ts
CHANGED
|
@@ -535,19 +535,19 @@ export interface FieldApiOptions<
|
|
|
535
535
|
in out TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,
|
|
536
536
|
in out TParentSubmitMeta,
|
|
537
537
|
> extends FieldOptions<
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
538
|
+
TParentData,
|
|
539
|
+
TName,
|
|
540
|
+
TData,
|
|
541
|
+
TOnMount,
|
|
542
|
+
TOnChange,
|
|
543
|
+
TOnChangeAsync,
|
|
544
|
+
TOnBlur,
|
|
545
|
+
TOnBlurAsync,
|
|
546
|
+
TOnSubmit,
|
|
547
|
+
TOnSubmitAsync,
|
|
548
|
+
TOnDynamic,
|
|
549
|
+
TOnDynamicAsync
|
|
550
|
+
> {
|
|
551
551
|
form: FormApi<
|
|
552
552
|
TParentData,
|
|
553
553
|
TFormOnMount,
|
package/src/FieldGroupApi.ts
CHANGED
|
@@ -126,8 +126,7 @@ export class FieldGroupApi<
|
|
|
126
126
|
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
127
127
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
128
128
|
in out TSubmitMeta = never,
|
|
129
|
-
> implements FieldManipulator<TFieldGroupData, TSubmitMeta>
|
|
130
|
-
{
|
|
129
|
+
> implements FieldManipulator<TFieldGroupData, TSubmitMeta> {
|
|
131
130
|
/**
|
|
132
131
|
* The form that called this field group.
|
|
133
132
|
*/
|
package/src/FormApi.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Derived, Store, batch } from '@tanstack/store'
|
|
2
|
-
import { throttle } from '@tanstack/pacer'
|
|
3
2
|
import {
|
|
4
3
|
deleteBy,
|
|
5
4
|
determineFormLevelErrorSourceAndValue,
|
|
@@ -12,16 +11,18 @@ import {
|
|
|
12
11
|
isNonEmptyArray,
|
|
13
12
|
mergeOpts,
|
|
14
13
|
setBy,
|
|
14
|
+
throttleFormState,
|
|
15
15
|
uuid,
|
|
16
16
|
} from './utils'
|
|
17
17
|
import { defaultValidationLogic } from './ValidationLogic'
|
|
18
|
-
|
|
19
18
|
import {
|
|
20
19
|
isStandardSchemaValidator,
|
|
21
20
|
standardSchemaValidators,
|
|
22
21
|
} from './standardSchemaValidator'
|
|
23
22
|
import { defaultFieldMeta, metaHelper } from './metaHelper'
|
|
24
23
|
import { formEventClient } from './EventClient'
|
|
24
|
+
|
|
25
|
+
// types
|
|
25
26
|
import type { ValidationLogicFn } from './ValidationLogic'
|
|
26
27
|
import type {
|
|
27
28
|
StandardSchemaV1,
|
|
@@ -748,7 +749,9 @@ export interface FormState<
|
|
|
748
749
|
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
749
750
|
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
750
751
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
751
|
-
>
|
|
752
|
+
>
|
|
753
|
+
extends
|
|
754
|
+
BaseFormState<
|
|
752
755
|
TFormData,
|
|
753
756
|
TOnMount,
|
|
754
757
|
TOnChange,
|
|
@@ -895,8 +898,7 @@ export class FormApi<
|
|
|
895
898
|
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
896
899
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
897
900
|
in out TSubmitMeta = never,
|
|
898
|
-
> implements FieldManipulator<TFormData, TSubmitMeta>
|
|
899
|
-
{
|
|
901
|
+
> implements FieldManipulator<TFormData, TSubmitMeta> {
|
|
900
902
|
/**
|
|
901
903
|
* The options for the form.
|
|
902
904
|
*/
|
|
@@ -1184,8 +1186,8 @@ export class FormApi<
|
|
|
1184
1186
|
const hasOnMountError = Boolean(
|
|
1185
1187
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1186
1188
|
currBaseStore.errorMap?.onMount ||
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1190
|
+
fieldMetaValues.some((f) => f?.errorMap?.onMount),
|
|
1189
1191
|
)
|
|
1190
1192
|
|
|
1191
1193
|
const isValidating = !!isFieldsValidating
|
|
@@ -1309,20 +1311,9 @@ export class FormApi<
|
|
|
1309
1311
|
|
|
1310
1312
|
this.update(opts || {})
|
|
1311
1313
|
|
|
1312
|
-
const debouncedDevtoolState = throttle(
|
|
1313
|
-
(state: AnyFormState) =>
|
|
1314
|
-
formEventClient.emit('form-state', {
|
|
1315
|
-
id: this._formId,
|
|
1316
|
-
state: state,
|
|
1317
|
-
}),
|
|
1318
|
-
{
|
|
1319
|
-
wait: 300,
|
|
1320
|
-
},
|
|
1321
|
-
)
|
|
1322
|
-
|
|
1323
1314
|
// devtool broadcasts
|
|
1324
1315
|
this.store.subscribe(() => {
|
|
1325
|
-
|
|
1316
|
+
throttleFormState(this)
|
|
1326
1317
|
})
|
|
1327
1318
|
|
|
1328
1319
|
// devtool requests
|
package/src/util-types.ts
CHANGED
|
@@ -119,8 +119,9 @@ export type DeepKeyAndValueObject<
|
|
|
119
119
|
export type UnknownAccessor<TParent extends AnyDeepKeyAndValue> =
|
|
120
120
|
TParent['key'] extends never ? string : `${TParent['key']}.${string}`
|
|
121
121
|
|
|
122
|
-
export interface UnknownDeepKeyAndValue<
|
|
123
|
-
extends AnyDeepKeyAndValue
|
|
122
|
+
export interface UnknownDeepKeyAndValue<
|
|
123
|
+
TParent extends AnyDeepKeyAndValue,
|
|
124
|
+
> extends AnyDeepKeyAndValue {
|
|
124
125
|
key: UnknownAccessor<TParent>
|
|
125
126
|
value: unknown
|
|
126
127
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { liteThrottle } from '@tanstack/pacer-lite'
|
|
2
|
+
import { formEventClient } from './EventClient'
|
|
2
3
|
import type { ValidationLogicProps } from './ValidationLogic'
|
|
3
4
|
import type { FieldValidators } from './FieldApi'
|
|
4
|
-
import type { FormValidators } from './FormApi'
|
|
5
|
+
import type { AnyFormApi, FormValidators } from './FormApi'
|
|
5
6
|
import type {
|
|
6
7
|
GlobalFormValidationError,
|
|
7
8
|
ValidationCause,
|
|
@@ -603,3 +604,14 @@ export function uuid(): string {
|
|
|
603
604
|
IDX++
|
|
604
605
|
return out
|
|
605
606
|
}
|
|
607
|
+
|
|
608
|
+
export const throttleFormState = liteThrottle(
|
|
609
|
+
(form: AnyFormApi) =>
|
|
610
|
+
formEventClient.emit('form-state', {
|
|
611
|
+
id: form.formId,
|
|
612
|
+
state: form.store.state,
|
|
613
|
+
}),
|
|
614
|
+
{
|
|
615
|
+
wait: 300,
|
|
616
|
+
},
|
|
617
|
+
)
|