@tanstack/form-core 0.23.2 → 0.24.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.
- package/dist/cjs/FieldApi.cjs +6 -4
- package/dist/cjs/FieldApi.cjs.map +1 -1
- package/dist/cjs/FieldApi.d.cts +220 -2
- package/dist/cjs/FormApi.cjs +6 -0
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/FormApi.d.cts +228 -0
- package/dist/cjs/mergeForm.cjs.map +1 -1
- package/dist/cjs/mergeForm.d.cts +3 -0
- package/dist/cjs/types.d.cts +14 -0
- package/dist/cjs/util-types.d.cts +18 -3
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +24 -0
- package/dist/esm/FieldApi.d.ts +220 -2
- package/dist/esm/FieldApi.js +6 -4
- package/dist/esm/FieldApi.js.map +1 -1
- package/dist/esm/FormApi.d.ts +228 -0
- package/dist/esm/FormApi.js +6 -0
- package/dist/esm/FormApi.js.map +1 -1
- package/dist/esm/mergeForm.d.ts +3 -0
- package/dist/esm/mergeForm.js.map +1 -1
- package/dist/esm/types.d.ts +14 -0
- package/dist/esm/util-types.d.ts +18 -3
- package/dist/esm/utils.d.ts +24 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/FieldApi.ts +222 -9
- package/src/FormApi.ts +228 -12
- package/src/mergeForm.ts +3 -0
- package/src/types.ts +14 -2
- package/src/util-types.ts +18 -4
- package/src/utils.ts +24 -0
- package/src/tests/FieldApi.spec.ts +0 -1184
- package/src/tests/FieldApi.test-d.ts +0 -149
- package/src/tests/FormApi.spec.ts +0 -1523
- package/src/tests/formOptions.test.ts +0 -25
- package/src/tests/mutateMergeDeep.spec.ts +0 -32
- package/src/tests/util-types.test-d.ts +0 -171
- package/src/tests/utils.spec.ts +0 -131
- package/src/tests/utils.ts +0 -5
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
type Nullable<T> = T | null;
|
|
2
2
|
type IsNullable<T> = [null] extends [T] ? true : false;
|
|
3
|
+
/**
|
|
4
|
+
* @private
|
|
5
|
+
*/
|
|
3
6
|
export type RequiredByKey<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
|
|
4
7
|
type Narrowable = string | number | bigint | boolean;
|
|
5
8
|
type NarrowRaw<A> = (A extends [] ? [] : never) | (A extends Narrowable ? A : never) | {
|
|
6
9
|
[K in keyof A]: A[K] extends Function ? A[K] : NarrowRaw<A[K]>;
|
|
7
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
8
14
|
export type NoInfer<T> = [T][T extends any ? 0 : never];
|
|
15
|
+
/**
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
9
18
|
export type Narrow<A> = Try<A, [], NarrowRaw<A>>;
|
|
10
19
|
type Try<A1, A2, Catch = never> = A1 extends A2 ? A1 : Catch;
|
|
20
|
+
/**
|
|
21
|
+
* Hack to get TypeScript to show simplified types in error messages
|
|
22
|
+
* @private
|
|
23
|
+
*/
|
|
11
24
|
export type Pretty<T> = {
|
|
12
25
|
[K in keyof T]: T[K];
|
|
13
26
|
} & {};
|
|
@@ -26,11 +39,13 @@ type PrefixTupleAccessor<T extends any[], TIndex extends number, TDepth extends
|
|
|
26
39
|
type PrefixObjectAccessor<T extends object, TDepth extends any[]> = {
|
|
27
40
|
[K in keyof T]-?: K extends string | number ? PrefixFromDepth<K, TDepth> | `${PrefixFromDepth<K, TDepth>}${DeepKeys<T[K], [TDepth]>}` : never;
|
|
28
41
|
}[keyof T];
|
|
42
|
+
/**
|
|
43
|
+
* The keys of an object or array, deeply nested.
|
|
44
|
+
*/
|
|
29
45
|
export type DeepKeys<T, TDepth extends any[] = []> = TDepth['length'] extends 5 ? never : unknown extends T ? PrefixFromDepth<string, TDepth> : T extends readonly any[] & IsTuple<T> ? PrefixTupleAccessor<T, AllowedIndexes<T>, TDepth> : T extends any[] ? PrefixArrayAccessor<T, [...TDepth, any]> : T extends Date ? never : T extends object ? PrefixObjectAccessor<T, TDepth> : T extends string | number | boolean | bigint ? '' : never;
|
|
30
46
|
type PrefixFromDepth<T extends string | number, TDepth extends any[]> = TDepth['length'] extends 0 ? T : `.${T}`;
|
|
31
47
|
/**
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*/
|
|
48
|
+
* Infer the type of a deeply nested property within an object or an array.
|
|
49
|
+
*/
|
|
35
50
|
export type DeepValue<TValue, TAccessor, TNullable extends boolean = IsNullable<TValue>> = unknown extends TValue ? TValue : TValue extends ReadonlyArray<any> ? TAccessor extends `[${infer TBrackets}].${infer TAfter}` ? DeepValue<DeepValue<TValue, TBrackets>, TAfter> : TAccessor extends `[${infer TBrackets}]` ? DeepValue<TValue, TBrackets> : TAccessor extends keyof TValue ? TValue[TAccessor] : TValue[TAccessor & number] : TValue extends Record<string | number, any> ? TAccessor extends `${infer TBefore}[${infer TEverythingElse}` ? DeepValue<DeepValue<TValue, TBefore>, `[${TEverythingElse}`> : TAccessor extends `[${infer TBrackets}]` ? DeepValue<TValue, TBrackets> : TAccessor extends `${infer TBefore}.${infer TAfter}` ? DeepValue<DeepValue<TValue, TBefore>, TAfter> : TAccessor extends string ? TNullable extends true ? Nullable<TValue[TAccessor]> : TValue[TAccessor] : never : never;
|
|
36
51
|
export {};
|
package/dist/cjs/utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import type { ValidationCause } from './types'\nimport type { FormValidators } from './FormApi'\nimport type { 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\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 */\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 */\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 (typeof key === 'string') {\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) && key !== undefined) {\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 */\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\nexport function makePathArray(str: string) {\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replaceAll('[', '.')\n .replaceAll(']', '')\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\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\nexport interface AsyncValidator<T> {\n cause: ValidationCause\n validate: T\n debounceMs: number\n}\n\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any>\n ? Array<\n AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>\n >\n : T extends FormValidators<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>\n | FormValidators<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\nexport interface SyncValidator<T> {\n cause: ValidationCause\n validate: T\n}\n\nexport function getSyncValidatorArray<T>(\n cause: ValidationCause,\n options: SyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any>\n ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>>\n : T extends FormValidators<any, any>\n ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>>\n : never {\n const { onChange, onBlur, onSubmit } = (options.validators || {}) as\n | FieldValidators<any, any>\n | FormValidators<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\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 '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"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import type { ValidationCause } from './types'\nimport type { FormValidators } from './FormApi'\nimport type { 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 (typeof key === 'string') {\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) && key !== undefined) {\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) {\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replaceAll('[', '.')\n .replaceAll(']', '')\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>\n ? Array<\n AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>\n >\n : T extends FormValidators<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>\n | FormValidators<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>\n ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>>\n : T extends FormValidators<any, any>\n ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>>\n : never {\n const { onChange, onBlur, onSubmit } = (options.validators || {}) as\n | FieldValidators<any, any>\n | FormValidators<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\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 '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"],"names":[],"mappings":"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"}
|
package/dist/cjs/utils.d.cts
CHANGED
|
@@ -4,37 +4,61 @@ import { FieldValidators } from './FieldApi.cjs';
|
|
|
4
4
|
|
|
5
5
|
export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput;
|
|
6
6
|
export type Updater<TInput, TOutput = TInput> = TOutput | UpdaterFn<TInput, TOutput>;
|
|
7
|
+
/**
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
7
10
|
export declare function functionalUpdate<TInput, TOutput = TInput>(updater: Updater<TInput, TOutput>, input: TInput): TOutput;
|
|
8
11
|
/**
|
|
9
12
|
* Get a value from an object using a path, including dot notation.
|
|
13
|
+
* @private
|
|
10
14
|
*/
|
|
11
15
|
export declare function getBy(obj: any, path: any): any;
|
|
12
16
|
/**
|
|
13
17
|
* Set a value on an object using a path, including dot notation.
|
|
18
|
+
* @private
|
|
14
19
|
*/
|
|
15
20
|
export declare function setBy(obj: any, _path: any, updater: Updater<any>): any;
|
|
16
21
|
/**
|
|
17
22
|
* Delete a field on an object using a path, including dot notation.
|
|
23
|
+
* @private
|
|
18
24
|
*/
|
|
19
25
|
export declare function deleteBy(obj: any, _path: any): any;
|
|
26
|
+
/**
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
20
29
|
export declare function makePathArray(str: string): (string | number)[];
|
|
30
|
+
/**
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
21
33
|
export declare function isNonEmptyArray(obj: any): boolean;
|
|
22
34
|
interface AsyncValidatorArrayPartialOptions<T> {
|
|
23
35
|
validators?: T;
|
|
24
36
|
asyncDebounceMs?: number;
|
|
25
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* @private
|
|
40
|
+
*/
|
|
26
41
|
export interface AsyncValidator<T> {
|
|
27
42
|
cause: ValidationCause;
|
|
28
43
|
validate: T;
|
|
29
44
|
debounceMs: number;
|
|
30
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
31
49
|
export declare function getAsyncValidatorArray<T>(cause: ValidationCause, options: AsyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any> ? Array<AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>> : T extends FormValidators<any, any> ? Array<AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>> : never;
|
|
32
50
|
interface SyncValidatorArrayPartialOptions<T> {
|
|
33
51
|
validators?: T;
|
|
34
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* @private
|
|
55
|
+
*/
|
|
35
56
|
export interface SyncValidator<T> {
|
|
36
57
|
cause: ValidationCause;
|
|
37
58
|
validate: T;
|
|
38
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* @private
|
|
62
|
+
*/
|
|
39
63
|
export declare function getSyncValidatorArray<T>(cause: ValidationCause, options: SyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>> : T extends FormValidators<any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>> : never;
|
|
40
64
|
export {};
|
package/dist/esm/FieldApi.d.ts
CHANGED
|
@@ -4,65 +4,223 @@ import { ValidationCause, ValidationError, ValidationErrorMap, Validator } from
|
|
|
4
4
|
import { Updater } from './utils.js';
|
|
5
5
|
import { DeepKeys, DeepValue, NoInfer } from './util-types.js';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
7
10
|
export type FieldValidateFn<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = (props: {
|
|
8
11
|
value: TData;
|
|
9
12
|
fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
10
13
|
}) => ValidationError;
|
|
14
|
+
/**
|
|
15
|
+
* @private
|
|
16
|
+
*/
|
|
11
17
|
export type FieldValidateOrFn<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = TFieldValidator extends Validator<TData, infer TFN> ? TFN | FieldValidateFn<TParentData, TName, TFieldValidator, TFormValidator, TData> : TFormValidator extends Validator<TParentData, infer FFN> ? FFN | FieldValidateFn<TParentData, TName, TFieldValidator, TFormValidator, TData> : FieldValidateFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
18
|
+
/**
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
12
21
|
export type FieldValidateAsyncFn<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = (options: {
|
|
13
22
|
value: TData;
|
|
14
23
|
fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
15
24
|
signal: AbortSignal;
|
|
16
25
|
}) => ValidationError | Promise<ValidationError>;
|
|
26
|
+
/**
|
|
27
|
+
* @private
|
|
28
|
+
*/
|
|
17
29
|
export type FieldAsyncValidateOrFn<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = TFieldValidator extends Validator<TData, infer TFN> ? TFN | FieldValidateAsyncFn<TParentData, TName, TFieldValidator, TFormValidator, TData> : TFormValidator extends Validator<TParentData, infer FFN> ? FFN | FieldValidateAsyncFn<TParentData, TName, TFieldValidator, TFormValidator, TData> : FieldValidateAsyncFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
18
30
|
export interface FieldValidators<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
|
|
31
|
+
/**
|
|
32
|
+
* An optional function that takes a param of `formApi` which is a generic type of `TData` and `TParentData`
|
|
33
|
+
*/
|
|
19
34
|
onMount?: FieldValidateOrFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
35
|
+
/**
|
|
36
|
+
* An optional property that takes a `ValidateFn` which is a generic of `TData` and `TParentData`.
|
|
37
|
+
* If `validatorAdapter` is passed, this may also accept a property from the respective adapter
|
|
38
|
+
*
|
|
39
|
+
* @example `z.string().min(1)` if `zodAdapter` is passed
|
|
40
|
+
*/
|
|
20
41
|
onChange?: FieldValidateOrFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
42
|
+
/**
|
|
43
|
+
* An optional property similar to `onChange` but async validation. If `validatorAdapter`
|
|
44
|
+
* is passed, this may also accept a property from the respective adapter
|
|
45
|
+
*
|
|
46
|
+
* @example `z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' })` if `zodAdapter` is passed
|
|
47
|
+
*/
|
|
21
48
|
onChangeAsync?: FieldAsyncValidateOrFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
49
|
+
/**
|
|
50
|
+
* An optional number to represent how long the `onChangeAsync` should wait before running
|
|
51
|
+
*
|
|
52
|
+
* If set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds
|
|
53
|
+
*/
|
|
22
54
|
onChangeAsyncDebounceMs?: number;
|
|
55
|
+
/**
|
|
56
|
+
* An optional list of field names that should trigger this field's `onChange` and `onChangeAsync` events when its value changes
|
|
57
|
+
*/
|
|
23
58
|
onChangeListenTo?: DeepKeys<TParentData>[];
|
|
59
|
+
/**
|
|
60
|
+
* An optional function, that when run when subscribing to blur event of input.
|
|
61
|
+
* If `validatorAdapter` is passed, this may also accept a property from the respective adapter
|
|
62
|
+
*
|
|
63
|
+
* @example `z.string().min(1)` if `zodAdapter` is passed
|
|
64
|
+
*/
|
|
24
65
|
onBlur?: FieldValidateOrFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
66
|
+
/**
|
|
67
|
+
* An optional property similar to `onBlur` but async validation. If `validatorAdapter`
|
|
68
|
+
* is passed, this may also accept a property from the respective adapter
|
|
69
|
+
*
|
|
70
|
+
* @example `z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' })` if `zodAdapter` is passed
|
|
71
|
+
*/
|
|
25
72
|
onBlurAsync?: FieldAsyncValidateOrFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
73
|
+
/**
|
|
74
|
+
* An optional number to represent how long the `onBlurAsync` should wait before running
|
|
75
|
+
*
|
|
76
|
+
* If set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds
|
|
77
|
+
*/
|
|
26
78
|
onBlurAsyncDebounceMs?: number;
|
|
79
|
+
/**
|
|
80
|
+
* An optional list of field names that should trigger this field's `onBlur` and `onBlurAsync` events when its value changes
|
|
81
|
+
*/
|
|
27
82
|
onBlurListenTo?: DeepKeys<TParentData>[];
|
|
83
|
+
/**
|
|
84
|
+
* An optional function, that when run when subscribing to submit event of input.
|
|
85
|
+
* If `validatorAdapter` is passed, this may also accept a property from the respective adapter
|
|
86
|
+
*
|
|
87
|
+
* @example `z.string().min(1)` if `zodAdapter` is passed
|
|
88
|
+
*/
|
|
28
89
|
onSubmit?: FieldValidateOrFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
90
|
+
/**
|
|
91
|
+
* An optional property similar to `onSubmit` but async validation. If `validatorAdapter`
|
|
92
|
+
* is passed, this may also accept a property from the respective adapter
|
|
93
|
+
*
|
|
94
|
+
* @example `z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' })` if `zodAdapter` is passed
|
|
95
|
+
*/
|
|
29
96
|
onSubmitAsync?: FieldAsyncValidateOrFn<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
30
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* An object type representing the options for a field in a form.
|
|
100
|
+
*/
|
|
31
101
|
export interface FieldOptions<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
|
|
102
|
+
/**
|
|
103
|
+
* The field name. The type will be `DeepKeys<TParentData>` to ensure your name is a deep key of the parent dataset.
|
|
104
|
+
*/
|
|
32
105
|
name: TName;
|
|
106
|
+
/**
|
|
107
|
+
* An optional default value for the field.
|
|
108
|
+
*/
|
|
33
109
|
defaultValue?: NoInfer<TData>;
|
|
110
|
+
/**
|
|
111
|
+
* The default time to debounce async validation if there is not a more specific debounce time passed.
|
|
112
|
+
*/
|
|
34
113
|
asyncDebounceMs?: number;
|
|
114
|
+
/**
|
|
115
|
+
* If `true`, always run async validation, even if there are errors emitted during synchronous validation.
|
|
116
|
+
*/
|
|
35
117
|
asyncAlways?: boolean;
|
|
36
|
-
|
|
118
|
+
/**
|
|
119
|
+
* A validator provided by an extension, like `yupValidator` from `@tanstack/yup-form-adapter`
|
|
120
|
+
*/
|
|
37
121
|
validatorAdapter?: TFieldValidator;
|
|
122
|
+
/**
|
|
123
|
+
* A list of validators to pass to the field
|
|
124
|
+
*/
|
|
38
125
|
validators?: FieldValidators<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
126
|
+
/**
|
|
127
|
+
* An optional object with default metadata for the field.
|
|
128
|
+
*/
|
|
39
129
|
defaultMeta?: Partial<FieldMeta>;
|
|
40
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* An object type representing the required options for the FieldApi class.
|
|
133
|
+
*/
|
|
41
134
|
export interface FieldApiOptions<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> extends FieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData> {
|
|
42
135
|
form: FormApi<TParentData, TFormValidator>;
|
|
43
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* An object type representing the metadata of a field in a form.
|
|
139
|
+
*/
|
|
44
140
|
export type FieldMeta = {
|
|
141
|
+
/**
|
|
142
|
+
* A flag indicating whether the field has been touched.
|
|
143
|
+
*/
|
|
45
144
|
isTouched: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* A flag that is `true` if the field's value has not been modified by the user. Opposite of `isDirty`.
|
|
147
|
+
*/
|
|
46
148
|
isPristine: boolean;
|
|
149
|
+
/**
|
|
150
|
+
* A flag that is `true` if the field's value has been modified by the user. Opposite of `isPristine`.
|
|
151
|
+
*/
|
|
47
152
|
isDirty: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* An array of errors related to the touched state of the field.
|
|
155
|
+
*/
|
|
48
156
|
touchedErrors: ValidationError[];
|
|
157
|
+
/**
|
|
158
|
+
* An array of errors related to the field value.
|
|
159
|
+
*/
|
|
49
160
|
errors: ValidationError[];
|
|
161
|
+
/**
|
|
162
|
+
* A map of errors related to the field value.
|
|
163
|
+
*/
|
|
50
164
|
errorMap: ValidationErrorMap;
|
|
165
|
+
/**
|
|
166
|
+
* A flag indicating whether the field is currently being validated.
|
|
167
|
+
*/
|
|
51
168
|
isValidating: boolean;
|
|
52
169
|
};
|
|
170
|
+
/**
|
|
171
|
+
* An object type representing the state of a field.
|
|
172
|
+
*/
|
|
53
173
|
export type FieldState<TData> = {
|
|
174
|
+
/**
|
|
175
|
+
* The current value of the field.
|
|
176
|
+
*/
|
|
54
177
|
value: TData;
|
|
178
|
+
/**
|
|
179
|
+
* The current metadata of the field.
|
|
180
|
+
*/
|
|
55
181
|
meta: FieldMeta;
|
|
56
182
|
};
|
|
57
|
-
|
|
183
|
+
/**
|
|
184
|
+
* A class representing the API for managing a form field.
|
|
185
|
+
*
|
|
186
|
+
* Normally, you will not need to create a new `FieldApi` instance directly.
|
|
187
|
+
* Instead, you will use a framework hook/function like `useField` or `createField`
|
|
188
|
+
* to create a new instance for you that uses your framework's reactivity model.
|
|
189
|
+
* However, if you need to create a new instance manually, you can do so by calling
|
|
190
|
+
* the `new FieldApi` constructor.
|
|
191
|
+
*/
|
|
58
192
|
export declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
|
|
193
|
+
/**
|
|
194
|
+
* A reference to the form API instance.
|
|
195
|
+
*/
|
|
59
196
|
form: FieldApiOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>['form'];
|
|
197
|
+
/**
|
|
198
|
+
* The field name.
|
|
199
|
+
*/
|
|
60
200
|
name: DeepKeys<TParentData>;
|
|
201
|
+
/**
|
|
202
|
+
* The field options.
|
|
203
|
+
*/
|
|
61
204
|
options: FieldApiOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
205
|
+
/**
|
|
206
|
+
* The field state store.
|
|
207
|
+
*/
|
|
62
208
|
store: Store<FieldState<TData>>;
|
|
209
|
+
/**
|
|
210
|
+
* The current field state.
|
|
211
|
+
*/
|
|
63
212
|
state: FieldState<TData>;
|
|
213
|
+
/**
|
|
214
|
+
* @private
|
|
215
|
+
*/
|
|
64
216
|
prevState: FieldState<TData>;
|
|
217
|
+
/**
|
|
218
|
+
* Initializes a new `FieldApi` instance.
|
|
219
|
+
*/
|
|
65
220
|
constructor(opts: FieldApiOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>);
|
|
221
|
+
/**
|
|
222
|
+
* @private
|
|
223
|
+
*/
|
|
66
224
|
runValidator<TValue extends {
|
|
67
225
|
value: TData;
|
|
68
226
|
fieldApi: FieldApi<any, any, any, any>;
|
|
@@ -71,41 +229,101 @@ export declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>,
|
|
|
71
229
|
value: TValue;
|
|
72
230
|
type: TType;
|
|
73
231
|
}): ReturnType<ReturnType<Validator<any>>[TType]>;
|
|
232
|
+
/**
|
|
233
|
+
* Mounts the field instance to the form.
|
|
234
|
+
*/
|
|
74
235
|
mount: () => () => void;
|
|
236
|
+
/**
|
|
237
|
+
* Updates the field instance with new options.
|
|
238
|
+
*/
|
|
75
239
|
update: (opts: FieldApiOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>) => void;
|
|
240
|
+
/**
|
|
241
|
+
* Gets the current field value.
|
|
242
|
+
*/
|
|
76
243
|
getValue: () => TData;
|
|
244
|
+
/**
|
|
245
|
+
* Sets the field value and run the `change` validator.
|
|
246
|
+
*/
|
|
77
247
|
setValue: (updater: Updater<TData>, options?: {
|
|
78
248
|
touch?: boolean;
|
|
79
249
|
notify?: boolean;
|
|
80
250
|
}) => void;
|
|
251
|
+
/**
|
|
252
|
+
* @private
|
|
253
|
+
*/
|
|
81
254
|
_getMeta: () => FieldMeta | undefined;
|
|
255
|
+
/**
|
|
256
|
+
* Gets the current field metadata.
|
|
257
|
+
*/
|
|
82
258
|
getMeta: () => FieldMeta;
|
|
259
|
+
/**
|
|
260
|
+
* Sets the field metadata.
|
|
261
|
+
*/
|
|
83
262
|
setMeta: (updater: Updater<FieldMeta>) => void;
|
|
263
|
+
/**
|
|
264
|
+
* Gets the field information object.
|
|
265
|
+
*/
|
|
84
266
|
getInfo: () => FieldInfo<TParentData, TFormValidator>;
|
|
267
|
+
/**
|
|
268
|
+
* Pushes a new value to the field.
|
|
269
|
+
*/
|
|
85
270
|
pushValue: (value: TData extends any[] ? TData[number] : never, opts?: {
|
|
86
271
|
touch?: boolean;
|
|
87
272
|
}) => void;
|
|
273
|
+
/**
|
|
274
|
+
* Inserts a value at the specified index, shifting the subsequent values to the right.
|
|
275
|
+
*/
|
|
88
276
|
insertValue: (index: number, value: TData extends any[] ? TData[number] : never, opts?: {
|
|
89
277
|
touch?: boolean;
|
|
90
278
|
}) => Promise<void>;
|
|
279
|
+
/**
|
|
280
|
+
* Replaces a value at the specified index.
|
|
281
|
+
*/
|
|
91
282
|
replaceValue: (index: number, value: TData extends any[] ? TData[number] : never, opts?: {
|
|
92
283
|
touch?: boolean;
|
|
93
284
|
}) => Promise<void>;
|
|
285
|
+
/**
|
|
286
|
+
* Removes a value at the specified index.
|
|
287
|
+
*/
|
|
94
288
|
removeValue: (index: number, opts?: {
|
|
95
289
|
touch: boolean;
|
|
96
290
|
}) => Promise<void>;
|
|
291
|
+
/**
|
|
292
|
+
* Swaps the values at the specified indices.
|
|
293
|
+
*/
|
|
97
294
|
swapValues: (aIndex: number, bIndex: number, opts?: {
|
|
98
295
|
touch?: boolean;
|
|
99
296
|
}) => void;
|
|
297
|
+
/**
|
|
298
|
+
* Moves the value at the first specified index to the second specified index.
|
|
299
|
+
*/
|
|
100
300
|
moveValue: (aIndex: number, bIndex: number, opts?: {
|
|
101
301
|
touch?: boolean;
|
|
102
302
|
}) => void;
|
|
303
|
+
/**
|
|
304
|
+
* @private
|
|
305
|
+
*/
|
|
103
306
|
getLinkedFields: (cause: ValidationCause) => FieldApi<any, any, any, any, any>[];
|
|
307
|
+
/**
|
|
308
|
+
* @private
|
|
309
|
+
*/
|
|
104
310
|
validateSync: (cause: ValidationCause) => {
|
|
105
311
|
hasErrored: boolean;
|
|
106
312
|
};
|
|
313
|
+
/**
|
|
314
|
+
* @private
|
|
315
|
+
*/
|
|
107
316
|
validateAsync: (cause: ValidationCause) => Promise<ValidationError[]>;
|
|
317
|
+
/**
|
|
318
|
+
* Validates the field value.
|
|
319
|
+
*/
|
|
108
320
|
validate: (cause: ValidationCause) => ValidationError[] | Promise<ValidationError[]>;
|
|
321
|
+
/**
|
|
322
|
+
* Handles the change event.
|
|
323
|
+
*/
|
|
109
324
|
handleChange: (updater: Updater<TData>) => void;
|
|
325
|
+
/**
|
|
326
|
+
* Handles the blur event.
|
|
327
|
+
*/
|
|
110
328
|
handleBlur: () => void;
|
|
111
329
|
}
|
package/dist/esm/FieldApi.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Store } from "@tanstack/store";
|
|
2
2
|
import { getBy, getSyncValidatorArray, getAsyncValidatorArray } from "./utils.js";
|
|
3
3
|
class FieldApi {
|
|
4
|
+
/**
|
|
5
|
+
* Initializes a new `FieldApi` instance.
|
|
6
|
+
*/
|
|
4
7
|
constructor(opts) {
|
|
5
8
|
this.options = {};
|
|
6
9
|
this.mount = () => {
|
|
@@ -38,11 +41,7 @@ class FieldApi {
|
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
43
|
return () => {
|
|
41
|
-
const preserveValue = this.options.preserveValue;
|
|
42
44
|
unsubscribe();
|
|
43
|
-
if (!preserveValue) {
|
|
44
|
-
this.form.deleteField(this.name);
|
|
45
|
-
}
|
|
46
45
|
};
|
|
47
46
|
};
|
|
48
47
|
this.update = (opts2) => {
|
|
@@ -318,6 +317,9 @@ class FieldApi {
|
|
|
318
317
|
this.prevState = this.state;
|
|
319
318
|
this.options = opts;
|
|
320
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* @private
|
|
322
|
+
*/
|
|
321
323
|
runValidator(props) {
|
|
322
324
|
const adapters = [
|
|
323
325
|
this.form.options.validatorAdapter,
|