@tanstack/form-core 1.14.0 → 1.15.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/FieldGroupApi.cjs +156 -0
- package/dist/cjs/FieldGroupApi.cjs.map +1 -0
- package/dist/cjs/FieldGroupApi.d.cts +116 -0
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/FormApi.d.cts +13 -8
- package/dist/cjs/index.cjs +4 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/types.d.cts +78 -1
- package/dist/cjs/util-types.d.cts +7 -0
- package/dist/cjs/utils.cjs +24 -2
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +7 -0
- package/dist/esm/FieldGroupApi.d.ts +116 -0
- package/dist/esm/FieldGroupApi.js +156 -0
- package/dist/esm/FieldGroupApi.js.map +1 -0
- package/dist/esm/FormApi.d.ts +13 -8
- package/dist/esm/FormApi.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +5 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types.d.ts +78 -1
- package/dist/esm/util-types.d.ts +7 -0
- package/dist/esm/utils.d.ts +7 -0
- package/dist/esm/utils.js +24 -2
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/FieldGroupApi.ts +461 -0
- package/src/FormApi.ts +18 -11
- package/src/index.ts +1 -0
- package/src/types.ts +152 -1
- package/src/util-types.ts +16 -0
- package/src/utils.ts +32 -2
package/dist/cjs/types.d.cts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AnyFieldMeta, AnyFieldMetaBase } from './FieldApi.cjs';
|
|
2
|
+
import { DeepKeys, DeepKeysOfType, DeepValue } from './util-types.cjs';
|
|
3
|
+
import { Updater } from './utils.cjs';
|
|
2
4
|
export type ValidationError = unknown;
|
|
3
5
|
export type ValidationSource = 'form' | 'field';
|
|
4
6
|
/**
|
|
@@ -72,3 +74,78 @@ export interface UpdateMetaOptions {
|
|
|
72
74
|
*/
|
|
73
75
|
dontUpdateMeta?: boolean;
|
|
74
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* @private
|
|
79
|
+
* A list of field manipulation methods that a form-like API must implement.
|
|
80
|
+
*/
|
|
81
|
+
export interface FieldManipulator<TFormData, TSubmitMeta> {
|
|
82
|
+
/**
|
|
83
|
+
* Validates all fields using the correct handlers for a given validation cause.
|
|
84
|
+
*/
|
|
85
|
+
validateAllFields: (cause: ValidationCause) => Promise<unknown[]>;
|
|
86
|
+
/**
|
|
87
|
+
* Validates the children of a specified array in the form starting from a given index until the end using the correct handlers for a given validation type.
|
|
88
|
+
*/
|
|
89
|
+
validateArrayFieldsStartingFrom: <TField extends DeepKeysOfType<TFormData, any[]>>(field: TField, index: number, cause: ValidationCause) => Promise<unknown[]>;
|
|
90
|
+
/**
|
|
91
|
+
* Validates a specified field in the form using the correct handlers for a given validation type.
|
|
92
|
+
*/
|
|
93
|
+
validateField: <TField extends DeepKeys<TFormData>>(field: TField, cause: ValidationCause) => unknown[] | Promise<unknown[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Handles the form submission, performs validation, and calls the appropriate onSubmit or onSubmitInvalid callbacks.
|
|
96
|
+
*/
|
|
97
|
+
handleSubmit(): Promise<void>;
|
|
98
|
+
handleSubmit(submitMeta: TSubmitMeta): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Gets the value of the specified field.
|
|
101
|
+
*/
|
|
102
|
+
getFieldValue: <TField extends DeepKeys<TFormData>>(field: TField) => DeepValue<TFormData, TField>;
|
|
103
|
+
/**
|
|
104
|
+
* Gets the metadata of the specified field.
|
|
105
|
+
*/
|
|
106
|
+
getFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField) => AnyFieldMeta | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* Updates the metadata of the specified field.
|
|
109
|
+
*/
|
|
110
|
+
setFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<AnyFieldMetaBase>) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Sets the value of the specified field and optionally updates the touched state.
|
|
113
|
+
*/
|
|
114
|
+
setFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<DeepValue<TFormData, TField>>, opts?: UpdateMetaOptions) => void;
|
|
115
|
+
/**
|
|
116
|
+
* Delete the specified field. Also deletes all subfields if there are any.
|
|
117
|
+
*/
|
|
118
|
+
deleteField: <TField extends DeepKeys<TFormData>>(field: TField) => void;
|
|
119
|
+
/**
|
|
120
|
+
* Pushes a value into an array field.
|
|
121
|
+
*/
|
|
122
|
+
pushFieldValue: <TField extends DeepKeysOfType<TFormData, any[]>>(field: TField, value: DeepValue<TFormData, TField> extends any[] ? DeepValue<TFormData, TField>[number] : never, opts?: UpdateMetaOptions) => void;
|
|
123
|
+
/**
|
|
124
|
+
* Insert a value into an array field at the specified index.
|
|
125
|
+
*/
|
|
126
|
+
insertFieldValue: <TField extends DeepKeysOfType<TFormData, any[]>>(field: TField, index: number, value: DeepValue<TFormData, TField> extends any[] ? DeepValue<TFormData, TField>[number] : never, opts?: UpdateMetaOptions) => Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Replaces a value into an array field at the specified index.
|
|
129
|
+
*/
|
|
130
|
+
replaceFieldValue: <TField extends DeepKeysOfType<TFormData, any[]>>(field: TField, index: number, value: DeepValue<TFormData, TField> extends any[] ? DeepValue<TFormData, TField>[number] : never, opts?: UpdateMetaOptions) => Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Removes a value from an array field at the specified index.
|
|
133
|
+
*/
|
|
134
|
+
removeFieldValue: <TField extends DeepKeysOfType<TFormData, any[]>>(field: TField, index: number, opts?: UpdateMetaOptions) => Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Swaps the values at the specified indices within an array field.
|
|
137
|
+
*/
|
|
138
|
+
swapFieldValues: <TField extends DeepKeysOfType<TFormData, any[]>>(field: TField, index1: number, index2: number, opts?: UpdateMetaOptions) => void;
|
|
139
|
+
/**
|
|
140
|
+
* Moves the value at the first specified index to the second specified index within an array field.
|
|
141
|
+
*/
|
|
142
|
+
moveFieldValues: <TField extends DeepKeysOfType<TFormData, any[]>>(field: TField, index1: number, index2: number, opts?: UpdateMetaOptions) => void;
|
|
143
|
+
/**
|
|
144
|
+
* Clear all values within an array field.
|
|
145
|
+
*/
|
|
146
|
+
clearFieldValues: <TField extends DeepKeysOfType<TFormData, any[]>>(field: TField, opts?: UpdateMetaOptions) => void;
|
|
147
|
+
/**
|
|
148
|
+
* Resets the field value and meta to default state
|
|
149
|
+
*/
|
|
150
|
+
resetField: <TField extends DeepKeys<TFormData>>(field: TField) => void;
|
|
151
|
+
}
|
|
@@ -59,4 +59,11 @@ export type DeepValue<TValue, TAccessor> = unknown extends TValue ? TValue : TAc
|
|
|
59
59
|
* The keys of an object or array, deeply nested and only with a value of TValue
|
|
60
60
|
*/
|
|
61
61
|
export type DeepKeysOfType<TData, TValue> = Extract<DeepKeysAndValues<TData>, AnyDeepKeyAndValue<string, TValue>>['key'];
|
|
62
|
+
/**
|
|
63
|
+
* Maps the deep keys of TFormData to the shallow keys of TFieldGroupData.
|
|
64
|
+
* Since using template strings as keys is impractical, it relies on shallow keys only.
|
|
65
|
+
*/
|
|
66
|
+
export type FieldsMap<TFormData, TFieldGroupData> = TFieldGroupData extends any[] ? never : string extends keyof TFieldGroupData ? never : {
|
|
67
|
+
[K in keyof TFieldGroupData]: DeepKeysOfType<TFormData, TFieldGroupData[K]>;
|
|
68
|
+
};
|
|
62
69
|
export {};
|
package/dist/cjs/utils.cjs
CHANGED
|
@@ -99,12 +99,25 @@ function makePathArray(str) {
|
|
|
99
99
|
throw new Error("Path must be a string.");
|
|
100
100
|
}
|
|
101
101
|
return str.replace(/(^\[)|]/gm, "").replace(/\[/g, ".").replace(reLineOfOnlyDigits, intReplace).replace(reDigitsBetweenDots, `.${intReplace}.`).replace(reStartWithDigitThenDot, `${intReplace}.`).replace(reDotWithDigitsToEnd, `.${intReplace}`).replace(reMultipleDots, ".").split(".").map((d) => {
|
|
102
|
-
if (d.
|
|
103
|
-
|
|
102
|
+
if (d.startsWith(intPrefix)) {
|
|
103
|
+
const numStr = d.substring(intPrefix.length);
|
|
104
|
+
const num = parseInt(numStr, 10);
|
|
105
|
+
if (String(num) === numStr) {
|
|
106
|
+
return num;
|
|
107
|
+
}
|
|
108
|
+
return numStr;
|
|
104
109
|
}
|
|
105
110
|
return d;
|
|
106
111
|
});
|
|
107
112
|
}
|
|
113
|
+
function concatenatePaths(path1, path2) {
|
|
114
|
+
if (path1.length === 0) return path2;
|
|
115
|
+
if (path2.length === 0) return path1;
|
|
116
|
+
if (path2.startsWith("[")) {
|
|
117
|
+
return path1 + path2;
|
|
118
|
+
}
|
|
119
|
+
return `${path1}.${path2}`;
|
|
120
|
+
}
|
|
108
121
|
function isNonEmptyArray(obj) {
|
|
109
122
|
return !(Array.isArray(obj) && obj.length === 0);
|
|
110
123
|
}
|
|
@@ -243,6 +256,15 @@ const determineFieldLevelErrorSourceAndValue = ({
|
|
|
243
256
|
}
|
|
244
257
|
return { newErrorValue: void 0, newSource: void 0 };
|
|
245
258
|
};
|
|
259
|
+
function createFieldMap(values) {
|
|
260
|
+
const output = {};
|
|
261
|
+
for (const key in values) {
|
|
262
|
+
output[key] = key;
|
|
263
|
+
}
|
|
264
|
+
return output;
|
|
265
|
+
}
|
|
266
|
+
exports.concatenatePaths = concatenatePaths;
|
|
267
|
+
exports.createFieldMap = createFieldMap;
|
|
246
268
|
exports.deleteBy = deleteBy;
|
|
247
269
|
exports.determineFieldLevelErrorSourceAndValue = determineFieldLevelErrorSourceAndValue;
|
|
248
270
|
exports.determineFormLevelErrorSourceAndValue = determineFormLevelErrorSourceAndValue;
|
package/dist/cjs/utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import 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: 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 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.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\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 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 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"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.cjs","sources":["../../src/utils.ts"],"sourcesContent":["import 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: 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 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 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\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 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 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"],"names":[],"mappings":"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"}
|
package/dist/cjs/utils.d.cts
CHANGED
|
@@ -26,6 +26,10 @@ export declare function deleteBy(obj: any, _path: any): any;
|
|
|
26
26
|
* @private
|
|
27
27
|
*/
|
|
28
28
|
export declare function makePathArray(str: string | Array<string | number>): (string | number)[];
|
|
29
|
+
/**
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
export declare function concatenatePaths(path1: string, path2: string): string;
|
|
29
33
|
/**
|
|
30
34
|
* @private
|
|
31
35
|
*/
|
|
@@ -85,4 +89,7 @@ export declare const determineFieldLevelErrorSourceAndValue: ({ formLevelError,
|
|
|
85
89
|
newErrorValue: ValidationError;
|
|
86
90
|
newSource: ValidationSource | undefined;
|
|
87
91
|
};
|
|
92
|
+
export declare function createFieldMap<T>(values: Readonly<T>): {
|
|
93
|
+
[K in keyof T]: K;
|
|
94
|
+
};
|
|
88
95
|
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Derived } from '@tanstack/store';
|
|
2
|
+
import { Updater } from './utils.js';
|
|
3
|
+
import { FormApi, FormAsyncValidateOrFn, FormValidateOrFn } from './FormApi.js';
|
|
4
|
+
import { AnyFieldMeta, AnyFieldMetaBase } from './FieldApi.js';
|
|
5
|
+
import { DeepKeys, DeepKeysOfType, DeepValue, FieldsMap } from './util-types.js';
|
|
6
|
+
import { FieldManipulator, UpdateMetaOptions, ValidationCause } from './types.js';
|
|
7
|
+
export type AnyFieldGroupApi = FieldGroupApi<any, any, any, any, any, any, any, any, any, any, any, any>;
|
|
8
|
+
export interface FieldGroupState<in out TFieldGroupData> {
|
|
9
|
+
/**
|
|
10
|
+
* The current values of the field group
|
|
11
|
+
*/
|
|
12
|
+
values: TFieldGroupData;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* An object representing the options for a field group.
|
|
16
|
+
*/
|
|
17
|
+
export interface FieldGroupOptions<in out TFormData, in out TFieldGroupData, in out TFields extends DeepKeysOfType<TFormData, TFieldGroupData | null | undefined> | FieldsMap<TFormData, TFieldGroupData>, in out TOnMount extends undefined | FormValidateOrFn<TFormData>, in out TOnChange extends undefined | FormValidateOrFn<TFormData>, in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnBlur extends undefined | FormValidateOrFn<TFormData>, in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>, in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>, in out TSubmitMeta = never> {
|
|
18
|
+
form: FormApi<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta> | FieldGroupApi<any, TFormData, any, any, any, any, any, any, any, any, any, TSubmitMeta>;
|
|
19
|
+
/**
|
|
20
|
+
* The path to the field group data.
|
|
21
|
+
*/
|
|
22
|
+
fields: TFields;
|
|
23
|
+
/**
|
|
24
|
+
* The expected subsetValues that the form must provide.
|
|
25
|
+
*/
|
|
26
|
+
defaultValues?: TFieldGroupData;
|
|
27
|
+
/**
|
|
28
|
+
* onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props
|
|
29
|
+
*/
|
|
30
|
+
onSubmitMeta?: TSubmitMeta;
|
|
31
|
+
}
|
|
32
|
+
export declare class FieldGroupApi<in out TFormData, in out TFieldGroupData, in out TFields extends DeepKeysOfType<TFormData, TFieldGroupData | null | undefined> | FieldsMap<TFormData, TFieldGroupData>, in out TOnMount extends undefined | FormValidateOrFn<TFormData>, in out TOnChange extends undefined | FormValidateOrFn<TFormData>, in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnBlur extends undefined | FormValidateOrFn<TFormData>, in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>, in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>, in out TSubmitMeta = never> implements FieldManipulator<TFieldGroupData, TSubmitMeta> {
|
|
33
|
+
/**
|
|
34
|
+
* The form that called this field group.
|
|
35
|
+
*/
|
|
36
|
+
readonly form: FormApi<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta>;
|
|
37
|
+
readonly fieldsMap: TFields;
|
|
38
|
+
/**
|
|
39
|
+
* Get the true name of the field. Not required within `Field` or `AppField`.
|
|
40
|
+
* @private
|
|
41
|
+
*/
|
|
42
|
+
getFormFieldName: <TField extends DeepKeys<TFieldGroupData>>(subfield: TField) => DeepKeys<TFormData>;
|
|
43
|
+
store: Derived<FieldGroupState<TFieldGroupData>>;
|
|
44
|
+
get state(): FieldGroupState<TFieldGroupData>;
|
|
45
|
+
/**
|
|
46
|
+
* Constructs a new `FieldGroupApi` instance with the given form options.
|
|
47
|
+
*/
|
|
48
|
+
constructor(opts: FieldGroupOptions<TFormData, TFieldGroupData, TFields, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta>);
|
|
49
|
+
/**
|
|
50
|
+
* Mounts the field group instance to listen to value changes.
|
|
51
|
+
*/
|
|
52
|
+
mount: () => () => void;
|
|
53
|
+
/**
|
|
54
|
+
* Validates the children of a specified array in the form starting from a given index until the end using the correct handlers for a given validation type.
|
|
55
|
+
*/
|
|
56
|
+
validateArrayFieldsStartingFrom: <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(field: TField, index: number, cause: ValidationCause) => Promise<unknown[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Validates a specified field in the form using the correct handlers for a given validation type.
|
|
59
|
+
*/
|
|
60
|
+
validateField: <TField extends DeepKeys<TFieldGroupData>>(field: TField, cause: ValidationCause) => unknown[] | Promise<unknown[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Handles the form submission, performs validation, and calls the appropriate onSubmit or onSubmitInvalid callbacks.
|
|
63
|
+
*/
|
|
64
|
+
handleSubmit(): Promise<void>;
|
|
65
|
+
handleSubmit(submitMeta: TSubmitMeta): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Gets the value of the specified field.
|
|
68
|
+
*/
|
|
69
|
+
getFieldValue: <TField extends DeepKeys<TFieldGroupData>>(field: TField) => DeepValue<TFieldGroupData, TField>;
|
|
70
|
+
/**
|
|
71
|
+
* Gets the metadata of the specified field.
|
|
72
|
+
*/
|
|
73
|
+
getFieldMeta: <TField extends DeepKeys<TFieldGroupData>>(field: TField) => AnyFieldMeta | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Updates the metadata of the specified field.
|
|
76
|
+
*/
|
|
77
|
+
setFieldMeta: <TField extends DeepKeys<TFieldGroupData>>(field: TField, updater: Updater<AnyFieldMetaBase>) => void;
|
|
78
|
+
/**
|
|
79
|
+
* Sets the value of the specified field and optionally updates the touched state.
|
|
80
|
+
*/
|
|
81
|
+
setFieldValue: <TField extends DeepKeys<TFieldGroupData>>(field: TField, updater: Updater<DeepValue<TFieldGroupData, TField>>, opts?: UpdateMetaOptions) => void;
|
|
82
|
+
/**
|
|
83
|
+
* Delete a field and its subfields.
|
|
84
|
+
*/
|
|
85
|
+
deleteField: <TField extends DeepKeys<TFieldGroupData>>(field: TField) => void;
|
|
86
|
+
/**
|
|
87
|
+
* Pushes a value into an array field.
|
|
88
|
+
*/
|
|
89
|
+
pushFieldValue: <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(field: TField, value: DeepValue<TFieldGroupData, TField> extends any[] ? DeepValue<TFieldGroupData, TField>[number] : never, opts?: UpdateMetaOptions) => void;
|
|
90
|
+
/**
|
|
91
|
+
* Insert a value into an array field at the specified index.
|
|
92
|
+
*/
|
|
93
|
+
insertFieldValue: <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(field: TField, index: number, value: DeepValue<TFieldGroupData, TField> extends any[] ? DeepValue<TFieldGroupData, TField>[number] : never, opts?: UpdateMetaOptions) => Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Replaces a value into an array field at the specified index.
|
|
96
|
+
*/
|
|
97
|
+
replaceFieldValue: <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(field: TField, index: number, value: DeepValue<TFieldGroupData, TField> extends any[] ? DeepValue<TFieldGroupData, TField>[number] : never, opts?: UpdateMetaOptions) => Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Removes a value from an array field at the specified index.
|
|
100
|
+
*/
|
|
101
|
+
removeFieldValue: <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(field: TField, index: number, opts?: UpdateMetaOptions) => Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Swaps the values at the specified indices within an array field.
|
|
104
|
+
*/
|
|
105
|
+
swapFieldValues: <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(field: TField, index1: number, index2: number, opts?: UpdateMetaOptions) => void;
|
|
106
|
+
/**
|
|
107
|
+
* Moves the value at the first specified index to the second specified index within an array field.
|
|
108
|
+
*/
|
|
109
|
+
moveFieldValues: <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(field: TField, index1: number, index2: number, opts?: UpdateMetaOptions) => void;
|
|
110
|
+
clearFieldValues: <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(field: TField, opts?: UpdateMetaOptions) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Resets the field value and meta to default state
|
|
113
|
+
*/
|
|
114
|
+
resetField: <TField extends DeepKeys<TFieldGroupData>>(field: TField) => void;
|
|
115
|
+
validateAllFields: (cause: ValidationCause) => Promise<unknown[]>;
|
|
116
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { Derived } from "@tanstack/store";
|
|
2
|
+
import { concatenatePaths, makePathArray, getBy } from "./utils.js";
|
|
3
|
+
class FieldGroupApi {
|
|
4
|
+
/**
|
|
5
|
+
* Constructs a new `FieldGroupApi` instance with the given form options.
|
|
6
|
+
*/
|
|
7
|
+
constructor(opts) {
|
|
8
|
+
this.getFormFieldName = (subfield) => {
|
|
9
|
+
if (typeof this.fieldsMap === "string") {
|
|
10
|
+
return concatenatePaths(this.fieldsMap, subfield);
|
|
11
|
+
}
|
|
12
|
+
const firstAccessor = makePathArray(subfield)[0];
|
|
13
|
+
if (typeof firstAccessor !== "string") {
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
const restOfPath = subfield.slice(firstAccessor.length);
|
|
17
|
+
const formMappedPath = (
|
|
18
|
+
// TFields is either a string or this. See guard above.
|
|
19
|
+
this.fieldsMap[firstAccessor]
|
|
20
|
+
);
|
|
21
|
+
return concatenatePaths(formMappedPath, restOfPath);
|
|
22
|
+
};
|
|
23
|
+
this.mount = () => {
|
|
24
|
+
const cleanup = this.store.mount();
|
|
25
|
+
return cleanup;
|
|
26
|
+
};
|
|
27
|
+
this.validateArrayFieldsStartingFrom = async (field, index, cause) => {
|
|
28
|
+
return this.form.validateArrayFieldsStartingFrom(
|
|
29
|
+
this.getFormFieldName(field),
|
|
30
|
+
index,
|
|
31
|
+
cause
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
this.validateField = (field, cause) => {
|
|
35
|
+
return this.form.validateField(this.getFormFieldName(field), cause);
|
|
36
|
+
};
|
|
37
|
+
this.getFieldValue = (field) => {
|
|
38
|
+
return this.form.getFieldValue(this.getFormFieldName(field));
|
|
39
|
+
};
|
|
40
|
+
this.getFieldMeta = (field) => {
|
|
41
|
+
return this.form.getFieldMeta(this.getFormFieldName(field));
|
|
42
|
+
};
|
|
43
|
+
this.setFieldMeta = (field, updater) => {
|
|
44
|
+
return this.form.setFieldMeta(this.getFormFieldName(field), updater);
|
|
45
|
+
};
|
|
46
|
+
this.setFieldValue = (field, updater, opts2) => {
|
|
47
|
+
return this.form.setFieldValue(
|
|
48
|
+
this.getFormFieldName(field),
|
|
49
|
+
updater,
|
|
50
|
+
opts2
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
this.deleteField = (field) => {
|
|
54
|
+
return this.form.deleteField(this.getFormFieldName(field));
|
|
55
|
+
};
|
|
56
|
+
this.pushFieldValue = (field, value, opts2) => {
|
|
57
|
+
return this.form.pushFieldValue(
|
|
58
|
+
this.getFormFieldName(field),
|
|
59
|
+
// since unknown doesn't extend an array, it types `value` as never.
|
|
60
|
+
value,
|
|
61
|
+
opts2
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
this.insertFieldValue = async (field, index, value, opts2) => {
|
|
65
|
+
return this.form.insertFieldValue(
|
|
66
|
+
this.getFormFieldName(field),
|
|
67
|
+
index,
|
|
68
|
+
// since unknown doesn't extend an array, it types `value` as never.
|
|
69
|
+
value,
|
|
70
|
+
opts2
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
this.replaceFieldValue = async (field, index, value, opts2) => {
|
|
74
|
+
return this.form.replaceFieldValue(
|
|
75
|
+
this.getFormFieldName(field),
|
|
76
|
+
index,
|
|
77
|
+
// since unknown doesn't extend an array, it types `value` as never.
|
|
78
|
+
value,
|
|
79
|
+
opts2
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
this.removeFieldValue = async (field, index, opts2) => {
|
|
83
|
+
return this.form.removeFieldValue(this.getFormFieldName(field), index, opts2);
|
|
84
|
+
};
|
|
85
|
+
this.swapFieldValues = (field, index1, index2, opts2) => {
|
|
86
|
+
return this.form.swapFieldValues(
|
|
87
|
+
this.getFormFieldName(field),
|
|
88
|
+
index1,
|
|
89
|
+
index2,
|
|
90
|
+
opts2
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
this.moveFieldValues = (field, index1, index2, opts2) => {
|
|
94
|
+
return this.form.moveFieldValues(
|
|
95
|
+
this.getFormFieldName(field),
|
|
96
|
+
index1,
|
|
97
|
+
index2,
|
|
98
|
+
opts2
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
this.clearFieldValues = (field, opts2) => {
|
|
102
|
+
return this.form.clearFieldValues(this.getFormFieldName(field), opts2);
|
|
103
|
+
};
|
|
104
|
+
this.resetField = (field) => {
|
|
105
|
+
return this.form.resetField(this.getFormFieldName(field));
|
|
106
|
+
};
|
|
107
|
+
this.validateAllFields = (cause) => this.form.validateAllFields(cause);
|
|
108
|
+
if (opts.form instanceof FieldGroupApi) {
|
|
109
|
+
const group = opts.form;
|
|
110
|
+
this.form = group.form;
|
|
111
|
+
if (typeof opts.fields === "string") {
|
|
112
|
+
this.fieldsMap = group.getFormFieldName(opts.fields);
|
|
113
|
+
} else {
|
|
114
|
+
const fields = {
|
|
115
|
+
...opts.fields
|
|
116
|
+
};
|
|
117
|
+
for (const key in fields) {
|
|
118
|
+
fields[key] = group.getFormFieldName(fields[key]);
|
|
119
|
+
}
|
|
120
|
+
this.fieldsMap = fields;
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
this.form = opts.form;
|
|
124
|
+
this.fieldsMap = opts.fields;
|
|
125
|
+
}
|
|
126
|
+
this.store = new Derived({
|
|
127
|
+
deps: [this.form.store],
|
|
128
|
+
fn: ({ currDepVals }) => {
|
|
129
|
+
const currFormStore = currDepVals[0];
|
|
130
|
+
let values;
|
|
131
|
+
if (typeof this.fieldsMap === "string") {
|
|
132
|
+
values = getBy(currFormStore.values, this.fieldsMap);
|
|
133
|
+
} else {
|
|
134
|
+
values = {};
|
|
135
|
+
const fields = this.fieldsMap;
|
|
136
|
+
for (const key in fields) {
|
|
137
|
+
values[key] = getBy(currFormStore.values, fields[key]);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
values
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
get state() {
|
|
147
|
+
return this.store.state;
|
|
148
|
+
}
|
|
149
|
+
async handleSubmit(submitMeta) {
|
|
150
|
+
return this.form.handleSubmit(submitMeta);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
export {
|
|
154
|
+
FieldGroupApi
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=FieldGroupApi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldGroupApi.js","sources":["../../src/FieldGroupApi.ts"],"sourcesContent":["import { Derived } from '@tanstack/store'\nimport { concatenatePaths, getBy, makePathArray } from './utils'\nimport type { Updater } from './utils'\nimport type {\n FormApi,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from './FormApi'\nimport type { AnyFieldMeta, AnyFieldMetaBase } from './FieldApi'\nimport type {\n DeepKeys,\n DeepKeysOfType,\n DeepValue,\n FieldsMap,\n} from './util-types'\nimport type {\n FieldManipulator,\n UpdateMetaOptions,\n ValidationCause,\n} from './types'\n\nexport type AnyFieldGroupApi = FieldGroupApi<\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\nexport interface FieldGroupState<in out TFieldGroupData> {\n /**\n * The current values of the field group\n */\n values: TFieldGroupData\n}\n\n/**\n * An object representing the options for a field group.\n */\nexport interface FieldGroupOptions<\n in out TFormData,\n in out TFieldGroupData,\n in out TFields extends\n | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>\n | FieldsMap<TFormData, TFieldGroupData>,\n in out TOnMount extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChange extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TSubmitMeta = never,\n> {\n form:\n | FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n | FieldGroupApi<\n any,\n TFormData,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n TSubmitMeta\n >\n /**\n * The path to the field group data.\n */\n fields: TFields\n /**\n * The expected subsetValues that the form must provide.\n */\n defaultValues?: TFieldGroupData\n /**\n * onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props\n */\n onSubmitMeta?: TSubmitMeta\n}\n\nexport class FieldGroupApi<\n in out TFormData,\n in out TFieldGroupData,\n in out TFields extends\n | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>\n | FieldsMap<TFormData, TFieldGroupData>,\n in out TOnMount extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChange extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TSubmitMeta = never,\n> implements FieldManipulator<TFieldGroupData, TSubmitMeta>\n{\n /**\n * The form that called this field group.\n */\n readonly form: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n\n readonly fieldsMap: TFields\n\n /**\n * Get the true name of the field. Not required within `Field` or `AppField`.\n * @private\n */\n getFormFieldName = <TField extends DeepKeys<TFieldGroupData>>(\n subfield: TField,\n ): DeepKeys<TFormData> => {\n if (typeof this.fieldsMap === 'string') {\n return concatenatePaths(this.fieldsMap, subfield)\n }\n\n const firstAccessor = makePathArray(subfield)[0]\n if (typeof firstAccessor !== 'string') {\n // top-level arrays cannot be mapped\n return ''\n }\n\n const restOfPath = subfield.slice(firstAccessor.length)\n const formMappedPath =\n // TFields is either a string or this. See guard above.\n (this.fieldsMap as FieldsMap<TFormData, TFieldGroupData>)[\n firstAccessor as keyof TFieldGroupData\n ]\n\n return concatenatePaths(formMappedPath, restOfPath)\n }\n\n store: Derived<FieldGroupState<TFieldGroupData>>\n\n get state() {\n return this.store.state\n }\n\n /**\n * Constructs a new `FieldGroupApi` instance with the given form options.\n */\n constructor(\n opts: FieldGroupOptions<\n TFormData,\n TFieldGroupData,\n TFields,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) {\n if (opts.form instanceof FieldGroupApi) {\n const group = opts.form\n this.form = group.form as never\n\n // the DeepKey is already namespaced, so we need to ensure that we reference\n // the form and not the group\n if (typeof opts.fields === 'string') {\n this.fieldsMap = group.getFormFieldName(opts.fields) as TFields\n } else {\n // TypeScript has a tough time with generics being a union for some reason\n const fields = {\n ...(opts.fields as FieldsMap<TFormData, TFieldGroupData>),\n }\n for (const key in fields) {\n fields[key] = group.getFormFieldName(fields[key]) as never\n }\n this.fieldsMap = fields as never\n }\n } else {\n this.form = opts.form\n this.fieldsMap = opts.fields\n }\n\n this.store = new Derived({\n deps: [this.form.store],\n fn: ({ currDepVals }) => {\n const currFormStore = currDepVals[0]\n let values: TFieldGroupData\n if (typeof this.fieldsMap === 'string') {\n // all values live at that name, so we can directly fetch it\n values = getBy(currFormStore.values, this.fieldsMap)\n } else {\n // we need to fetch the values from all places where they were mapped from\n values = {} as never\n const fields: Record<keyof TFieldGroupData, string> = this\n .fieldsMap as never\n for (const key in fields) {\n values[key] = getBy(currFormStore.values, fields[key])\n }\n }\n\n return {\n values,\n }\n },\n })\n }\n\n /**\n * Mounts the field group instance to listen to value changes.\n */\n mount = () => {\n const cleanup = this.store.mount()\n\n return cleanup\n }\n\n /**\n * Validates the children of a specified array in the form starting from a given index until the end using the correct handlers for a given validation type.\n */\n validateArrayFieldsStartingFrom = async <\n TField extends DeepKeysOfType<TFieldGroupData, any[]>,\n >(\n field: TField,\n index: number,\n cause: ValidationCause,\n ) => {\n return this.form.validateArrayFieldsStartingFrom(\n this.getFormFieldName(field),\n index,\n cause,\n )\n }\n\n /**\n * Validates a specified field in the form using the correct handlers for a given validation type.\n */\n validateField = <TField extends DeepKeys<TFieldGroupData>>(\n field: TField,\n cause: ValidationCause,\n ) => {\n return this.form.validateField(this.getFormFieldName(field), cause)\n }\n\n /**\n * Handles the form submission, performs validation, and calls the appropriate onSubmit or onSubmitInvalid callbacks.\n */\n handleSubmit(): Promise<void>\n handleSubmit(submitMeta: TSubmitMeta): Promise<void>\n async handleSubmit(submitMeta?: TSubmitMeta): Promise<void> {\n // cast is required since the implementation isn't one of the two overloads\n return this.form.handleSubmit(submitMeta as any)\n }\n\n /**\n * Gets the value of the specified field.\n */\n getFieldValue = <TField extends DeepKeys<TFieldGroupData>>(\n field: TField,\n ): DeepValue<TFieldGroupData, TField> => {\n return this.form.getFieldValue(this.getFormFieldName(field)) as DeepValue<\n TFieldGroupData,\n TField\n >\n }\n\n /**\n * Gets the metadata of the specified field.\n */\n getFieldMeta = <TField extends DeepKeys<TFieldGroupData>>(field: TField) => {\n return this.form.getFieldMeta(this.getFormFieldName(field))\n }\n\n /**\n * Updates the metadata of the specified field.\n */\n setFieldMeta = <TField extends DeepKeys<TFieldGroupData>>(\n field: TField,\n updater: Updater<AnyFieldMetaBase>,\n ) => {\n return this.form.setFieldMeta(this.getFormFieldName(field), updater)\n }\n\n /**\n * Sets the value of the specified field and optionally updates the touched state.\n */\n setFieldValue = <TField extends DeepKeys<TFieldGroupData>>(\n field: TField,\n updater: Updater<DeepValue<TFieldGroupData, TField>>,\n opts?: UpdateMetaOptions,\n ) => {\n return this.form.setFieldValue(\n this.getFormFieldName(field) as never,\n updater as never,\n opts,\n )\n }\n\n /**\n * Delete a field and its subfields.\n */\n deleteField = <TField extends DeepKeys<TFieldGroupData>>(field: TField) => {\n return this.form.deleteField(this.getFormFieldName(field))\n }\n\n /**\n * Pushes a value into an array field.\n */\n pushFieldValue = <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(\n field: TField,\n value: DeepValue<TFieldGroupData, TField> extends any[]\n ? DeepValue<TFieldGroupData, TField>[number]\n : never,\n opts?: UpdateMetaOptions,\n ) => {\n return this.form.pushFieldValue(\n this.getFormFieldName(field),\n // since unknown doesn't extend an array, it types `value` as never.\n value as never,\n opts,\n )\n }\n\n /**\n * Insert a value into an array field at the specified index.\n */\n insertFieldValue = async <\n TField extends DeepKeysOfType<TFieldGroupData, any[]>,\n >(\n field: TField,\n index: number,\n value: DeepValue<TFieldGroupData, TField> extends any[]\n ? DeepValue<TFieldGroupData, TField>[number]\n : never,\n opts?: UpdateMetaOptions,\n ) => {\n return this.form.insertFieldValue(\n this.getFormFieldName(field),\n index,\n // since unknown doesn't extend an array, it types `value` as never.\n value as never,\n opts,\n )\n }\n\n /**\n * Replaces a value into an array field at the specified index.\n */\n replaceFieldValue = async <\n TField extends DeepKeysOfType<TFieldGroupData, any[]>,\n >(\n field: TField,\n index: number,\n value: DeepValue<TFieldGroupData, TField> extends any[]\n ? DeepValue<TFieldGroupData, TField>[number]\n : never,\n opts?: UpdateMetaOptions,\n ) => {\n return this.form.replaceFieldValue(\n this.getFormFieldName(field),\n index,\n // since unknown doesn't extend an array, it types `value` as never.\n value as never,\n opts,\n )\n }\n\n /**\n * Removes a value from an array field at the specified index.\n */\n removeFieldValue = async <\n TField extends DeepKeysOfType<TFieldGroupData, any[]>,\n >(\n field: TField,\n index: number,\n opts?: UpdateMetaOptions,\n ) => {\n return this.form.removeFieldValue(this.getFormFieldName(field), index, opts)\n }\n\n /**\n * Swaps the values at the specified indices within an array field.\n */\n swapFieldValues = <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n return this.form.swapFieldValues(\n this.getFormFieldName(field),\n index1,\n index2,\n opts,\n )\n }\n\n /**\n * Moves the value at the first specified index to the second specified index within an array field.\n */\n moveFieldValues = <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n return this.form.moveFieldValues(\n this.getFormFieldName(field),\n index1,\n index2,\n opts,\n )\n }\n\n clearFieldValues = <TField extends DeepKeysOfType<TFieldGroupData, any[]>>(\n field: TField,\n opts?: UpdateMetaOptions,\n ) => {\n return this.form.clearFieldValues(this.getFormFieldName(field), opts)\n }\n\n /**\n * Resets the field value and meta to default state\n */\n resetField = <TField extends DeepKeys<TFieldGroupData>>(field: TField) => {\n return this.form.resetField(this.getFormFieldName(field))\n }\n\n validateAllFields = (cause: ValidationCause) =>\n this.form.validateAllFields(cause)\n}\n"],"names":["opts"],"mappings":"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"}
|
package/dist/esm/FormApi.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Derived, Store } from '@tanstack/store';
|
|
2
2
|
import { StandardSchemaV1, StandardSchemaV1Issue, TStandardSchemaValidatorValue } from './standardSchemaValidator.js';
|
|
3
3
|
import { AnyFieldApi, AnyFieldMeta, AnyFieldMetaBase, FieldApi } from './FieldApi.js';
|
|
4
|
-
import { ExtractGlobalFormError, FormValidationError, FormValidationErrorMap, UpdateMetaOptions, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys } from './types.js';
|
|
4
|
+
import { ExtractGlobalFormError, FieldManipulator, FormValidationError, FormValidationErrorMap, UpdateMetaOptions, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys } from './types.js';
|
|
5
5
|
import { DeepKeys, DeepKeysOfType, DeepValue } from './util-types.js';
|
|
6
6
|
import { Updater } from './utils.js';
|
|
7
7
|
/**
|
|
@@ -96,13 +96,22 @@ export interface FormListeners<TFormData, TOnMount extends undefined | FormValid
|
|
|
96
96
|
}) => void;
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
|
-
* An object representing the
|
|
99
|
+
* An object representing the base properties of a form, unrelated to any validators
|
|
100
100
|
*/
|
|
101
|
-
export interface
|
|
101
|
+
export interface BaseFormOptions<in out TFormData, in out TSubmitMeta = never> {
|
|
102
102
|
/**
|
|
103
103
|
* Set initial values for your form.
|
|
104
104
|
*/
|
|
105
105
|
defaultValues?: TFormData;
|
|
106
|
+
/**
|
|
107
|
+
* onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props
|
|
108
|
+
*/
|
|
109
|
+
onSubmitMeta?: TSubmitMeta;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* An object representing the options for a form.
|
|
113
|
+
*/
|
|
114
|
+
export interface FormOptions<in out TFormData, in out TOnMount extends undefined | FormValidateOrFn<TFormData>, in out TOnChange extends undefined | FormValidateOrFn<TFormData>, in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnBlur extends undefined | FormValidateOrFn<TFormData>, in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>, in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>, in out TSubmitMeta = never> extends BaseFormOptions<TFormData, TSubmitMeta> {
|
|
106
115
|
/**
|
|
107
116
|
* The default state for the form.
|
|
108
117
|
*/
|
|
@@ -123,10 +132,6 @@ export interface FormOptions<in out TFormData, in out TOnMount extends undefined
|
|
|
123
132
|
* A list of validators to pass to the form
|
|
124
133
|
*/
|
|
125
134
|
validators?: FormValidators<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync>;
|
|
126
|
-
/**
|
|
127
|
-
* onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props
|
|
128
|
-
*/
|
|
129
|
-
onSubmitMeta?: TSubmitMeta;
|
|
130
135
|
/**
|
|
131
136
|
* form level listeners
|
|
132
137
|
*/
|
|
@@ -298,7 +303,7 @@ export type AnyFormApi = FormApi<any, any, any, any, any, any, any, any, any, an
|
|
|
298
303
|
* hook/function like `useForm` or `createForm` to create a new instance for you that uses your framework's reactivity model.
|
|
299
304
|
* However, if you need to create a new instance manually, you can do so by calling the `new FormApi` constructor.
|
|
300
305
|
*/
|
|
301
|
-
export declare class FormApi<in out TFormData, in out TOnMount extends undefined | FormValidateOrFn<TFormData>, in out TOnChange extends undefined | FormValidateOrFn<TFormData>, in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnBlur extends undefined | FormValidateOrFn<TFormData>, in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>, in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>, in out TSubmitMeta = never> {
|
|
306
|
+
export declare class FormApi<in out TFormData, in out TOnMount extends undefined | FormValidateOrFn<TFormData>, in out TOnChange extends undefined | FormValidateOrFn<TFormData>, in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnBlur extends undefined | FormValidateOrFn<TFormData>, in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>, in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>, in out TSubmitMeta = never> implements FieldManipulator<TFormData, TSubmitMeta> {
|
|
302
307
|
/**
|
|
303
308
|
* The options for the form.
|
|
304
309
|
*/
|