@tanstack/form-core 0.3.7 → 0.4.1
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/build/legacy/FieldApi.cjs +46 -26
- package/build/legacy/FieldApi.cjs.map +1 -1
- package/build/legacy/FieldApi.d.cts +1 -0
- package/build/legacy/FieldApi.d.ts +1 -0
- package/build/legacy/FieldApi.js +46 -18
- package/build/legacy/FieldApi.js.map +1 -1
- package/build/legacy/FormApi.cjs +10 -12
- package/build/legacy/FormApi.cjs.map +1 -1
- package/build/legacy/FormApi.d.cts +2 -1
- package/build/legacy/FormApi.d.ts +2 -1
- package/build/legacy/FormApi.js +10 -14
- package/build/legacy/FormApi.js.map +1 -1
- package/build/legacy/index.cjs +3 -1
- package/build/legacy/index.cjs.map +1 -1
- package/build/legacy/index.d.cts +48 -52
- package/build/legacy/index.d.ts +48 -52
- package/build/legacy/index.js +1 -0
- package/build/legacy/index.js.map +1 -1
- package/build/legacy/types.cjs +19 -0
- package/build/legacy/types.cjs.map +1 -0
- package/build/legacy/types.d.cts +7 -0
- package/build/legacy/types.d.ts +7 -0
- package/build/legacy/types.js +1 -0
- package/build/legacy/utils.js +0 -2
- package/build/legacy/utils.js.map +1 -1
- package/build/modern/FieldApi.cjs +44 -9
- package/build/modern/FieldApi.cjs.map +1 -1
- package/build/modern/FieldApi.d.cts +1 -0
- package/build/modern/FieldApi.d.ts +1 -0
- package/build/modern/FieldApi.js +44 -9
- package/build/modern/FieldApi.js.map +1 -1
- package/build/modern/FormApi.cjs +10 -12
- package/build/modern/FormApi.cjs.map +1 -1
- package/build/modern/FormApi.d.cts +2 -1
- package/build/modern/FormApi.d.ts +2 -1
- package/build/modern/FormApi.js +10 -12
- package/build/modern/FormApi.js.map +1 -1
- package/build/modern/index.cjs +3 -1
- package/build/modern/index.cjs.map +1 -1
- package/build/modern/index.d.cts +48 -52
- package/build/modern/index.d.ts +48 -52
- package/build/modern/index.js +1 -0
- package/build/modern/index.js.map +1 -1
- package/build/modern/types.cjs +19 -0
- package/build/modern/types.cjs.map +1 -0
- package/build/modern/types.d.cts +7 -0
- package/build/modern/types.d.ts +7 -0
- package/build/modern/types.js +1 -0
- package/build/modern/types.js.map +1 -0
- package/package.json +1 -1
- package/src/FieldApi.ts +171 -44
- package/src/FormApi.ts +61 -46
- package/src/index.ts +1 -0
- package/src/tests/FieldApi.spec.ts +1 -1
- package/src/tests/FieldApi.test-d.ts +26 -11
- package/src/tests/FormApi.spec.ts +1 -1
- package/src/types.ts +7 -0
- package/build/legacy/chunk-4QZDOMDG.js +0 -19
- /package/build/legacy/{chunk-4QZDOMDG.js.map → types.js.map} +0 -0
|
@@ -16,19 +16,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var __accessCheck = (obj, member, msg) => {
|
|
20
|
-
if (!member.has(obj))
|
|
21
|
-
throw TypeError("Cannot " + msg);
|
|
22
|
-
};
|
|
23
|
-
var __privateGet = (obj, member, getter) => {
|
|
24
|
-
__accessCheck(obj, member, "read from private field");
|
|
25
|
-
return getter ? getter.call(obj) : member.get(obj);
|
|
26
|
-
};
|
|
27
|
-
var __privateAdd = (obj, member, value) => {
|
|
28
|
-
if (member.has(obj))
|
|
29
|
-
throw TypeError("Cannot add the same private member more than once");
|
|
30
|
-
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
31
|
-
};
|
|
32
19
|
|
|
33
20
|
// src/FieldApi.ts
|
|
34
21
|
var FieldApi_exports = {};
|
|
@@ -38,8 +25,7 @@ __export(FieldApi_exports, {
|
|
|
38
25
|
module.exports = __toCommonJS(FieldApi_exports);
|
|
39
26
|
var import_store = require("@tanstack/store");
|
|
40
27
|
var uid = 0;
|
|
41
|
-
var
|
|
42
|
-
var _FieldApi = class _FieldApi {
|
|
28
|
+
var FieldApi = class _FieldApi {
|
|
43
29
|
constructor(opts) {
|
|
44
30
|
this.options = {};
|
|
45
31
|
this.mount = () => {
|
|
@@ -116,7 +102,25 @@ var _FieldApi = class _FieldApi {
|
|
|
116
102
|
return;
|
|
117
103
|
const validationCount = (this.getInfo().validationCount || 0) + 1;
|
|
118
104
|
this.getInfo().validationCount = validationCount;
|
|
119
|
-
const
|
|
105
|
+
const doValidate = () => {
|
|
106
|
+
if (this.options.validator && typeof validate !== "function") {
|
|
107
|
+
return this.options.validator().validate(
|
|
108
|
+
value,
|
|
109
|
+
validate
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
if (this.form.options.validator && typeof validate !== "function") {
|
|
113
|
+
return this.form.options.validator().validate(
|
|
114
|
+
value,
|
|
115
|
+
validate
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return validate(
|
|
119
|
+
value,
|
|
120
|
+
this
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
const error = normalizeError(doValidate());
|
|
120
124
|
const errorMapKey = getErrorMapKey(cause);
|
|
121
125
|
if (this.state.meta.errorMap[errorMapKey] !== error) {
|
|
122
126
|
this.setMeta((prev) => ({
|
|
@@ -131,13 +135,13 @@ var _FieldApi = class _FieldApi {
|
|
|
131
135
|
this.cancelValidateAsync();
|
|
132
136
|
}
|
|
133
137
|
};
|
|
134
|
-
|
|
138
|
+
this.__leaseValidateAsync = () => {
|
|
135
139
|
const count = (this.getInfo().validationAsyncCount || 0) + 1;
|
|
136
140
|
this.getInfo().validationAsyncCount = count;
|
|
137
141
|
return count;
|
|
138
|
-
}
|
|
142
|
+
};
|
|
139
143
|
this.cancelValidateAsync = () => {
|
|
140
|
-
|
|
144
|
+
this.__leaseValidateAsync();
|
|
141
145
|
this.setMeta((prev) => ({
|
|
142
146
|
...prev,
|
|
143
147
|
isValidating: false
|
|
@@ -157,9 +161,10 @@ var _FieldApi = class _FieldApi {
|
|
|
157
161
|
if (!validate)
|
|
158
162
|
return [];
|
|
159
163
|
const debounceMs = cause === "submit" ? 0 : (cause === "change" ? onChangeAsyncDebounceMs : onBlurAsyncDebounceMs) ?? asyncDebounceMs ?? 0;
|
|
160
|
-
if (this.state.meta.isValidating !== true)
|
|
164
|
+
if (this.state.meta.isValidating !== true) {
|
|
161
165
|
this.setMeta((prev) => ({ ...prev, isValidating: true }));
|
|
162
|
-
|
|
166
|
+
}
|
|
167
|
+
const validationAsyncCount = this.__leaseValidateAsync();
|
|
163
168
|
const checkLatest = () => validationAsyncCount === this.getInfo().validationAsyncCount;
|
|
164
169
|
if (!this.getInfo().validationPromise) {
|
|
165
170
|
this.getInfo().validationPromise = new Promise((resolve, reject) => {
|
|
@@ -170,10 +175,25 @@ var _FieldApi = class _FieldApi {
|
|
|
170
175
|
if (debounceMs > 0) {
|
|
171
176
|
await new Promise((r) => setTimeout(r, debounceMs));
|
|
172
177
|
}
|
|
178
|
+
const doValidate = () => {
|
|
179
|
+
if (this.options.validator && typeof validate !== "function") {
|
|
180
|
+
return this.options.validator().validateAsync(
|
|
181
|
+
value,
|
|
182
|
+
validate
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
if (this.form.options.validator && typeof validate !== "function") {
|
|
186
|
+
return this.form.options.validator().validateAsync(value, validate);
|
|
187
|
+
}
|
|
188
|
+
return validate(
|
|
189
|
+
value,
|
|
190
|
+
this
|
|
191
|
+
);
|
|
192
|
+
};
|
|
173
193
|
if (checkLatest()) {
|
|
174
194
|
const prevErrors = this.getMeta().errors;
|
|
175
195
|
try {
|
|
176
|
-
const rawError = await
|
|
196
|
+
const rawError = await doValidate();
|
|
177
197
|
if (checkLatest()) {
|
|
178
198
|
const error = normalizeError(rawError);
|
|
179
199
|
this.setMeta((prev) => ({
|
|
@@ -203,9 +223,11 @@ var _FieldApi = class _FieldApi {
|
|
|
203
223
|
this.validate = (cause, value) => {
|
|
204
224
|
if (!this.state.meta.isTouched)
|
|
205
225
|
return [];
|
|
206
|
-
this.validateSync(value, cause);
|
|
207
226
|
const errorMapKey = getErrorMapKey(cause);
|
|
208
|
-
|
|
227
|
+
const prevError = this.getMeta().errorMap[errorMapKey];
|
|
228
|
+
this.validateSync(value, cause);
|
|
229
|
+
const newError = this.getMeta().errorMap[errorMapKey];
|
|
230
|
+
if (prevError !== newError) {
|
|
209
231
|
if (!this.options.asyncAlways) {
|
|
210
232
|
return this.state.meta.errors;
|
|
211
233
|
}
|
|
@@ -259,8 +281,6 @@ var _FieldApi = class _FieldApi {
|
|
|
259
281
|
this.options = opts;
|
|
260
282
|
}
|
|
261
283
|
};
|
|
262
|
-
_leaseValidateAsync = new WeakMap();
|
|
263
|
-
var FieldApi = _FieldApi;
|
|
264
284
|
function normalizeError(rawError) {
|
|
265
285
|
if (rawError) {
|
|
266
286
|
if (typeof rawError !== "string") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/FieldApi.ts"],"sourcesContent":["import { type DeepKeys, type DeepValue, type Updater } from './utils'\nimport type { FormApi, ValidationError, ValidationErrorMap } from './FormApi'\nimport { Store } from '@tanstack/store'\n\nexport type ValidationCause = 'change' | 'blur' | 'submit' | 'mount'\n\ntype ValidateFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (\n value: TData,\n fieldApi: FieldApi<TParentData, TName>,\n) => ValidationError\n\ntype ValidateAsyncFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData,\n> = (\n value: TData,\n fieldApi: FieldApi<TParentData, TName>,\n) => ValidationError | Promise<ValidationError>\n\nexport interface FieldOptions<\n TParentData,\n /**\n * This allows us to restrict the name to only be a valid field name while\n * also assigning it to a generic\n */\n TName extends DeepKeys<TParentData>,\n /**\n * If TData is unknown, we can use the TName generic to determine the type\n */\n TData = DeepValue<TParentData, TName>,\n> {\n name: DeepKeys<TParentData>\n index?: TData extends any[] ? number : never\n defaultValue?: TData\n asyncDebounceMs?: number\n asyncAlways?: boolean\n onMount?: (formApi: FieldApi<TParentData, TName>) => void\n onChange?: ValidateFn<TParentData, TName, TData>\n onChangeAsync?: ValidateAsyncFn<TParentData, TName, TData>\n onChangeAsyncDebounceMs?: number\n onBlur?: ValidateFn<TParentData, TName, TData>\n onBlurAsync?: ValidateAsyncFn<TParentData, TName, TData>\n onBlurAsyncDebounceMs?: number\n onSubmitAsync?: ValidateAsyncFn<TParentData, TName, TData>\n defaultMeta?: Partial<FieldMeta>\n}\n\nexport interface FieldApiOptions<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n> extends FieldOptions<TParentData, TName, TData> {\n form: FormApi<TParentData>\n}\n\nexport type FieldMeta = {\n isTouched: boolean\n touchedErrors: ValidationError[]\n errors: ValidationError[]\n errorMap: ValidationErrorMap\n isValidating: boolean\n}\n\nlet uid = 0\n\nexport type FieldState<TData> = {\n value: TData\n meta: FieldMeta\n}\n\nexport type ResolveName<TParentData> = unknown extends TParentData\n ? string\n : DeepKeys<TParentData>\n\nexport class FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n> {\n uid: number\n form: FieldApiOptions<TParentData, TName, TData>['form']\n name!: DeepKeys<TParentData>\n options: FieldApiOptions<TParentData, TName> = {} as any\n store!: Store<FieldState<TData>>\n state!: FieldState<TData>\n prevState!: FieldState<TData>\n\n constructor(\n opts: FieldApiOptions<TParentData, TName, TData> & {\n form: FormApi<TParentData>\n },\n ) {\n this.form = opts.form\n this.uid = uid++\n // Support field prefixing from FieldScope\n // let fieldPrefix = ''\n // if (this.form.fieldName) {\n // fieldPrefix = `${this.form.fieldName}.`\n // }\n\n this.name = opts.name as any\n\n if (opts.defaultValue !== undefined) {\n this.form.setFieldValue(this.name, opts.defaultValue as never)\n }\n\n this.store = new Store<FieldState<TData>>(\n {\n value: this.getValue(),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n meta: this._getMeta() ?? {\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...opts.defaultMeta,\n },\n },\n {\n onUpdate: () => {\n const state = this.store.state\n\n state.meta.errors = Object.values(state.meta.errorMap).filter(\n (val: unknown) => val !== undefined,\n )\n\n state.meta.touchedErrors = state.meta.isTouched\n ? state.meta.errors\n : []\n\n this.prevState = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n this.prevState = this.state\n this.options = opts as never\n }\n\n mount = () => {\n const info = this.getInfo()\n info.instances[this.uid] = this as never\n\n const unsubscribe = this.form.store.subscribe(() => {\n this.store.batch(() => {\n const nextValue = this.getValue()\n const nextMeta = this.getMeta()\n\n if (nextValue !== this.state.value) {\n this.store.setState((prev) => ({ ...prev, value: nextValue }))\n }\n\n if (nextMeta !== this.state.meta) {\n this.store.setState((prev) => ({ ...prev, meta: nextMeta }))\n }\n })\n })\n\n this.update(this.options as never)\n this.options.onMount?.(this as never)\n\n return () => {\n unsubscribe()\n delete info.instances[this.uid]\n if (!Object.keys(info.instances).length) {\n delete this.form.fieldInfo[this.name]\n }\n }\n }\n\n update = (opts: FieldApiOptions<TParentData, TName, TData>) => {\n // Default Value\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.state.value === undefined) {\n const formDefault =\n opts.form.options.defaultValues?.[opts.name as keyof TParentData]\n\n if (opts.defaultValue !== undefined) {\n this.setValue(opts.defaultValue as never)\n } else if (formDefault !== undefined) {\n this.setValue(formDefault as never)\n }\n }\n\n // Default Meta\n if (this._getMeta() === undefined) {\n this.setMeta(this.state.meta)\n }\n\n this.options = opts as never\n }\n\n getValue = (): TData => {\n return this.form.getFieldValue(this.name) as any\n }\n\n setValue = (\n updater: Updater<TData>,\n options?: { touch?: boolean; notify?: boolean },\n ) => {\n this.form.setFieldValue(this.name, updater as never, options)\n this.validate('change', this.state.value)\n }\n\n _getMeta = () => this.form.getFieldMeta(this.name)\n getMeta = () =>\n this._getMeta() ??\n ({\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...this.options.defaultMeta,\n } as FieldMeta)\n\n setMeta = (updater: Updater<FieldMeta>) =>\n this.form.setFieldMeta(this.name, updater)\n\n getInfo = () => this.form.getFieldInfo(this.name)\n\n pushValue = (value: TData extends any[] ? TData[number] : never) =>\n this.form.pushFieldValue(this.name, value as any)\n\n insertValue = (\n index: number,\n value: TData extends any[] ? TData[number] : never,\n ) => this.form.insertFieldValue(this.name, index, value as any)\n\n removeValue = (index: number) => this.form.removeFieldValue(this.name, index)\n\n swapValues = (aIndex: number, bIndex: number) =>\n this.form.swapFieldValues(this.name, aIndex, bIndex)\n\n getSubField = <\n TSubName extends DeepKeys<TData>,\n TSubData = DeepValue<TData, TSubName>,\n >(\n name: TSubName,\n ): FieldApi<TData, TSubName, TSubData> =>\n new FieldApi({\n name: `${this.name}.${name}` as never,\n form: this.form,\n }) as any\n\n validateSync = (value = this.state.value, cause: ValidationCause) => {\n const { onChange, onBlur } = this.options\n const validate =\n cause === 'submit' ? undefined : cause === 'change' ? onChange : onBlur\n if (!validate) return\n\n // Use the validationCount for all field instances to\n // track freshness of the validation\n const validationCount = (this.getInfo().validationCount || 0) + 1\n this.getInfo().validationCount = validationCount\n const error = normalizeError(validate(value as never, this as never))\n const errorMapKey = getErrorMapKey(cause)\n if (this.state.meta.errorMap[errorMapKey] !== error) {\n this.setMeta((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n }\n\n // If a sync error is encountered for the errorMapKey (eg. onChange), cancel any async validation\n if (this.state.meta.errorMap[errorMapKey]) {\n this.cancelValidateAsync()\n }\n }\n\n #leaseValidateAsync = () => {\n const count = (this.getInfo().validationAsyncCount || 0) + 1\n this.getInfo().validationAsyncCount = count\n return count\n }\n\n cancelValidateAsync = () => {\n // Lease a new validation count to ignore any pending validations\n this.#leaseValidateAsync()\n // Cancel any pending validation state\n this.setMeta((prev) => ({\n ...prev,\n isValidating: false,\n }))\n }\n\n validateAsync = async (value = this.state.value, cause: ValidationCause) => {\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n asyncDebounceMs,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n } = this.options\n\n const validate =\n cause === 'change'\n ? onChangeAsync\n : cause === 'submit'\n ? onSubmitAsync\n : onBlurAsync\n if (!validate) return []\n const debounceMs =\n cause === 'submit'\n ? 0\n : (cause === 'change'\n ? onChangeAsyncDebounceMs\n : onBlurAsyncDebounceMs) ??\n asyncDebounceMs ??\n 0\n\n if (this.state.meta.isValidating !== true)\n this.setMeta((prev) => ({ ...prev, isValidating: true }))\n\n // Use the validationCount for all field instances to\n // track freshness of the validation\n const validationAsyncCount = this.#leaseValidateAsync()\n\n const checkLatest = () =>\n validationAsyncCount === this.getInfo().validationAsyncCount\n\n if (!this.getInfo().validationPromise) {\n this.getInfo().validationPromise = new Promise((resolve, reject) => {\n this.getInfo().validationResolve = resolve\n this.getInfo().validationReject = reject\n })\n }\n\n if (debounceMs > 0) {\n await new Promise((r) => setTimeout(r, debounceMs))\n }\n\n // Only kick off validation if this validation is the latest attempt\n if (checkLatest()) {\n const prevErrors = this.getMeta().errors\n try {\n const rawError = await validate(value as never, this as never)\n if (checkLatest()) {\n const error = normalizeError(rawError)\n this.setMeta((prev) => ({\n ...prev,\n isValidating: false,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n this.getInfo().validationResolve?.([...prevErrors, error])\n }\n } catch (error) {\n if (checkLatest()) {\n this.getInfo().validationReject?.([...prevErrors, error])\n throw error\n }\n } finally {\n if (checkLatest()) {\n this.setMeta((prev) => ({ ...prev, isValidating: false }))\n delete this.getInfo().validationPromise\n }\n }\n }\n\n // Always return the latest validation promise to the caller\n return this.getInfo().validationPromise ?? []\n }\n\n validate = (\n cause: ValidationCause,\n value?: TData,\n ): ValidationError[] | Promise<ValidationError[]> => {\n // If the field is pristine and validatePristine is false, do not validate\n if (!this.state.meta.isTouched) return []\n // Attempt to sync validate first\n this.validateSync(value, cause)\n\n const errorMapKey = getErrorMapKey(cause)\n // If there is an error mapped to the errorMapKey (eg. onChange, onBlur, onSubmit), return the errors array, do not attempt async validation\n if (this.getMeta().errorMap[errorMapKey]) {\n if (!this.options.asyncAlways) {\n return this.state.meta.errors\n }\n }\n // No error? Attempt async validation\n return this.validateAsync(value, cause)\n }\n\n handleChange = (updater: Updater<TData>) => {\n this.setValue(updater, { touch: true })\n }\n\n handleBlur = () => {\n const prevTouched = this.state.meta.isTouched\n if (!prevTouched) {\n this.setMeta((prev) => ({ ...prev, isTouched: true }))\n this.validate('change')\n }\n this.validate('blur')\n }\n}\n\nfunction normalizeError(rawError?: ValidationError) {\n if (rawError) {\n if (typeof rawError !== 'string') {\n return 'Invalid Form Values'\n }\n\n return rawError\n }\n\n return undefined\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'change':\n return 'onChange'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/FieldApi.ts"],"sourcesContent":["import { type DeepKeys, type DeepValue, type Updater } from './utils'\nimport type { FormApi, ValidationErrorMap } from './FormApi'\nimport { Store } from '@tanstack/store'\nimport type { Validator, ValidationError } from './types'\n\nexport type ValidationCause = 'change' | 'blur' | 'submit' | 'mount'\n\ntype ValidateFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = (\n value: TData,\n fieldApi: FieldApi<TParentData, TName, ValidatorType, TData>,\n) => ValidationError\n\ntype ValidateOrFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = ValidatorType extends Validator<TData>\n ?\n | Parameters<ReturnType<ValidatorType>['validate']>[1]\n | ValidateFn<TParentData, TName, ValidatorType, TData>\n : FormValidator extends Validator<TData>\n ?\n | Parameters<ReturnType<FormValidator>['validate']>[1]\n | ValidateFn<TParentData, TName, ValidatorType, TData>\n : ValidateFn<TParentData, TName, ValidatorType, TData>\n\ntype ValidateAsyncFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = (\n value: TData,\n fieldApi: FieldApi<TParentData, TName, ValidatorType, TData>,\n) => ValidationError | Promise<ValidationError>\n\ntype AsyncValidateOrFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = ValidatorType extends Validator<TData>\n ?\n | Parameters<ReturnType<ValidatorType>['validate']>[1]\n | ValidateAsyncFn<TParentData, TName, ValidatorType, TData>\n : FormValidator extends Validator<TData>\n ?\n | Parameters<ReturnType<FormValidator>['validate']>[1]\n | ValidateAsyncFn<TParentData, TName, ValidatorType, TData>\n : ValidateAsyncFn<TParentData, TName, ValidatorType, TData>\n\nexport interface FieldOptions<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> {\n name: TName\n index?: TData extends any[] ? number : never\n defaultValue?: TData\n asyncDebounceMs?: number\n asyncAlways?: boolean\n validator?: ValidatorType\n onMount?: (\n formApi: FieldApi<TParentData, TName, ValidatorType, TData>,\n ) => void\n onChange?: ValidateOrFn<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >\n onChangeAsync?: AsyncValidateOrFn<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >\n onChangeAsyncDebounceMs?: number\n onBlur?: ValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>\n onBlurAsync?: AsyncValidateOrFn<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >\n onBlurAsyncDebounceMs?: number\n onSubmitAsync?: AsyncValidateOrFn<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >\n defaultMeta?: Partial<FieldMeta>\n}\n\nexport interface FieldApiOptions<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> extends FieldOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n > {\n form: FormApi<TParentData, FormValidator>\n}\n\nexport type FieldMeta = {\n isTouched: boolean\n touchedErrors: ValidationError[]\n errors: ValidationError[]\n errorMap: ValidationErrorMap\n isValidating: boolean\n}\n\nlet uid = 0\n\nexport type FieldState<TData> = {\n value: TData\n meta: FieldMeta\n}\n\nexport type ResolveName<TParentData> = unknown extends TParentData\n ? string\n : DeepKeys<TParentData>\n\nexport class FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> {\n uid: number\n form: FieldApiOptions<TParentData, TName, ValidatorType, TData>['form']\n name!: DeepKeys<TParentData>\n options: FieldApiOptions<TParentData, TName, ValidatorType, TData> = {} as any\n store!: Store<FieldState<TData>>\n state!: FieldState<TData>\n prevState!: FieldState<TData>\n\n constructor(\n opts: FieldApiOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >,\n ) {\n this.form = opts.form as never\n this.uid = uid++\n // Support field prefixing from FieldScope\n // let fieldPrefix = ''\n // if (this.form.fieldName) {\n // fieldPrefix = `${this.form.fieldName}.`\n // }\n\n this.name = opts.name as never\n\n if (opts.defaultValue !== undefined) {\n this.form.setFieldValue(this.name, opts.defaultValue as never)\n }\n\n this.store = new Store<FieldState<TData>>(\n {\n value: this.getValue(),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n meta: this._getMeta() ?? {\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...opts.defaultMeta,\n },\n },\n {\n onUpdate: () => {\n const state = this.store.state\n\n state.meta.errors = Object.values(state.meta.errorMap).filter(\n (val: unknown) => val !== undefined,\n )\n\n state.meta.touchedErrors = state.meta.isTouched\n ? state.meta.errors\n : []\n\n this.prevState = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n this.prevState = this.state\n this.options = opts as never\n }\n\n mount = () => {\n const info = this.getInfo()\n info.instances[this.uid] = this as never\n\n const unsubscribe = this.form.store.subscribe(() => {\n this.store.batch(() => {\n const nextValue = this.getValue()\n const nextMeta = this.getMeta()\n\n if (nextValue !== this.state.value) {\n this.store.setState((prev) => ({ ...prev, value: nextValue }))\n }\n\n if (nextMeta !== this.state.meta) {\n this.store.setState((prev) => ({ ...prev, meta: nextMeta }))\n }\n })\n })\n\n this.update(this.options as never)\n this.options.onMount?.(this as never)\n\n return () => {\n unsubscribe()\n delete info.instances[this.uid]\n if (!Object.keys(info.instances).length) {\n delete this.form.fieldInfo[this.name as never]\n }\n }\n }\n\n update = (\n opts: FieldApiOptions<TParentData, TName, ValidatorType, TData>,\n ) => {\n // Default Value\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.state.value === undefined) {\n const formDefault =\n opts.form.options.defaultValues?.[opts.name as keyof TParentData]\n\n if (opts.defaultValue !== undefined) {\n this.setValue(opts.defaultValue as never)\n } else if (formDefault !== undefined) {\n this.setValue(formDefault as never)\n }\n }\n\n // Default Meta\n if (this._getMeta() === undefined) {\n this.setMeta(this.state.meta)\n }\n\n this.options = opts as never\n }\n\n getValue = (): TData => {\n return this.form.getFieldValue(this.name) as any\n }\n\n setValue = (\n updater: Updater<TData>,\n options?: { touch?: boolean; notify?: boolean },\n ) => {\n this.form.setFieldValue(this.name, updater as never, options)\n this.validate('change', this.state.value)\n }\n\n _getMeta = () => this.form.getFieldMeta(this.name)\n getMeta = () =>\n this._getMeta() ??\n ({\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...this.options.defaultMeta,\n } as FieldMeta)\n\n setMeta = (updater: Updater<FieldMeta>) =>\n this.form.setFieldMeta(this.name, updater)\n\n getInfo = () => this.form.getFieldInfo(this.name)\n\n pushValue = (value: TData extends any[] ? TData[number] : never) =>\n this.form.pushFieldValue(this.name, value as any)\n\n insertValue = (\n index: number,\n value: TData extends any[] ? TData[number] : never,\n ) => this.form.insertFieldValue(this.name, index, value as any)\n\n removeValue = (index: number) => this.form.removeFieldValue(this.name, index)\n\n swapValues = (aIndex: number, bIndex: number) =>\n this.form.swapFieldValues(this.name, aIndex, bIndex)\n\n getSubField = <\n TSubName extends DeepKeys<TData>,\n TSubData extends DeepValue<TData, TSubName> = DeepValue<TData, TSubName>,\n >(\n name: TSubName,\n ): FieldApi<TData, TSubName, ValidatorType, TSubData> =>\n new FieldApi({\n name: `${this.name}.${name}` as never,\n form: this.form,\n }) as any\n\n validateSync = (value = this.state.value, cause: ValidationCause) => {\n const { onChange, onBlur } = this.options\n const validate =\n cause === 'submit' ? undefined : cause === 'change' ? onChange : onBlur\n\n if (!validate) return\n\n // Use the validationCount for all field instances to\n // track freshness of the validation\n const validationCount = (this.getInfo().validationCount || 0) + 1\n this.getInfo().validationCount = validationCount\n\n const doValidate = () => {\n if (this.options.validator && typeof validate !== 'function') {\n return (this.options.validator as Validator<TData>)().validate(\n value,\n validate,\n )\n }\n\n if (this.form.options.validator && typeof validate !== 'function') {\n return (this.form.options.validator as Validator<TData>)().validate(\n value,\n validate,\n )\n }\n\n return (validate as ValidateFn<TParentData, TName, ValidatorType, TData>)(\n value,\n this as never,\n )\n }\n\n const error = normalizeError(doValidate())\n const errorMapKey = getErrorMapKey(cause)\n if (this.state.meta.errorMap[errorMapKey] !== error) {\n this.setMeta((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n }\n\n // If a sync error is encountered for the errorMapKey (eg. onChange), cancel any async validation\n if (this.state.meta.errorMap[errorMapKey]) {\n this.cancelValidateAsync()\n }\n }\n\n __leaseValidateAsync = () => {\n const count = (this.getInfo().validationAsyncCount || 0) + 1\n this.getInfo().validationAsyncCount = count\n return count\n }\n\n cancelValidateAsync = () => {\n // Lease a new validation count to ignore any pending validations\n this.__leaseValidateAsync()\n // Cancel any pending validation state\n this.setMeta((prev) => ({\n ...prev,\n isValidating: false,\n }))\n }\n\n validateAsync = async (value = this.state.value, cause: ValidationCause) => {\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n asyncDebounceMs,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n } = this.options\n\n const validate =\n cause === 'change'\n ? onChangeAsync\n : cause === 'submit'\n ? onSubmitAsync\n : onBlurAsync\n if (!validate) return []\n const debounceMs =\n cause === 'submit'\n ? 0\n : (cause === 'change'\n ? onChangeAsyncDebounceMs\n : onBlurAsyncDebounceMs) ??\n asyncDebounceMs ??\n 0\n\n if (this.state.meta.isValidating !== true) {\n this.setMeta((prev) => ({ ...prev, isValidating: true }))\n }\n\n // Use the validationCount for all field instances to\n // track freshness of the validation\n const validationAsyncCount = this.__leaseValidateAsync()\n\n const checkLatest = () =>\n validationAsyncCount === this.getInfo().validationAsyncCount\n\n if (!this.getInfo().validationPromise) {\n this.getInfo().validationPromise = new Promise((resolve, reject) => {\n this.getInfo().validationResolve = resolve\n this.getInfo().validationReject = reject\n })\n }\n\n if (debounceMs > 0) {\n await new Promise((r) => setTimeout(r, debounceMs))\n }\n\n const doValidate = () => {\n if (this.options.validator && typeof validate !== 'function') {\n return (this.options.validator as Validator<TData>)().validateAsync(\n value,\n validate,\n )\n }\n\n if (this.form.options.validator && typeof validate !== 'function') {\n return (\n this.form.options.validator as Validator<TData>\n )().validateAsync(value, validate)\n }\n\n return (validate as ValidateFn<TParentData, TName, ValidatorType, TData>)(\n value,\n this as never,\n )\n }\n\n // Only kick off validation if this validation is the latest attempt\n if (checkLatest()) {\n const prevErrors = this.getMeta().errors\n try {\n const rawError = await doValidate()\n if (checkLatest()) {\n const error = normalizeError(rawError)\n this.setMeta((prev) => ({\n ...prev,\n isValidating: false,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n this.getInfo().validationResolve?.([...prevErrors, error])\n }\n } catch (error) {\n if (checkLatest()) {\n this.getInfo().validationReject?.([...prevErrors, error])\n throw error\n }\n } finally {\n if (checkLatest()) {\n this.setMeta((prev) => ({ ...prev, isValidating: false }))\n delete this.getInfo().validationPromise\n }\n }\n }\n\n // Always return the latest validation promise to the caller\n return this.getInfo().validationPromise ?? []\n }\n\n validate = (\n cause: ValidationCause,\n value?: TData,\n ): ValidationError[] | Promise<ValidationError[]> => {\n // If the field is pristine and validatePristine is false, do not validate\n if (!this.state.meta.isTouched) return []\n\n // Store the previous error for the errorMapKey (eg. onChange, onBlur, onSubmit)\n const errorMapKey = getErrorMapKey(cause)\n const prevError = this.getMeta().errorMap[errorMapKey]\n\n // Attempt to sync validate first\n this.validateSync(value, cause)\n\n // If there is a new error mapped to the errorMapKey (eg. onChange, onBlur, onSubmit), return the errors array, do not attempt async validation\n const newError = this.getMeta().errorMap[errorMapKey]\n\n if (prevError !== newError) {\n if (!this.options.asyncAlways) {\n return this.state.meta.errors\n }\n }\n // No error? Attempt async validation\n return this.validateAsync(value, cause)\n }\n\n handleChange = (updater: Updater<TData>) => {\n this.setValue(updater, { touch: true })\n }\n\n handleBlur = () => {\n const prevTouched = this.state.meta.isTouched\n if (!prevTouched) {\n this.setMeta((prev) => ({ ...prev, isTouched: true }))\n this.validate('change')\n }\n this.validate('blur')\n }\n}\n\nfunction normalizeError(rawError?: ValidationError) {\n if (rawError) {\n if (typeof rawError !== 'string') {\n return 'Invalid Form Values'\n }\n\n return rawError\n }\n\n return undefined\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'change':\n return 'onChange'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n }\n}\n"],"mappings":"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","names":[]}
|
package/build/legacy/FieldApi.js
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
__privateAdd,
|
|
3
|
-
__privateGet
|
|
4
|
-
} from "./chunk-4QZDOMDG.js";
|
|
5
|
-
|
|
6
1
|
// src/FieldApi.ts
|
|
7
2
|
import { Store } from "@tanstack/store";
|
|
8
3
|
var uid = 0;
|
|
9
|
-
var
|
|
10
|
-
var _FieldApi = class _FieldApi {
|
|
4
|
+
var FieldApi = class _FieldApi {
|
|
11
5
|
constructor(opts) {
|
|
12
6
|
this.options = {};
|
|
13
7
|
this.mount = () => {
|
|
@@ -84,7 +78,25 @@ var _FieldApi = class _FieldApi {
|
|
|
84
78
|
return;
|
|
85
79
|
const validationCount = (this.getInfo().validationCount || 0) + 1;
|
|
86
80
|
this.getInfo().validationCount = validationCount;
|
|
87
|
-
const
|
|
81
|
+
const doValidate = () => {
|
|
82
|
+
if (this.options.validator && typeof validate !== "function") {
|
|
83
|
+
return this.options.validator().validate(
|
|
84
|
+
value,
|
|
85
|
+
validate
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (this.form.options.validator && typeof validate !== "function") {
|
|
89
|
+
return this.form.options.validator().validate(
|
|
90
|
+
value,
|
|
91
|
+
validate
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return validate(
|
|
95
|
+
value,
|
|
96
|
+
this
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
const error = normalizeError(doValidate());
|
|
88
100
|
const errorMapKey = getErrorMapKey(cause);
|
|
89
101
|
if (this.state.meta.errorMap[errorMapKey] !== error) {
|
|
90
102
|
this.setMeta((prev) => ({
|
|
@@ -99,13 +111,13 @@ var _FieldApi = class _FieldApi {
|
|
|
99
111
|
this.cancelValidateAsync();
|
|
100
112
|
}
|
|
101
113
|
};
|
|
102
|
-
|
|
114
|
+
this.__leaseValidateAsync = () => {
|
|
103
115
|
const count = (this.getInfo().validationAsyncCount || 0) + 1;
|
|
104
116
|
this.getInfo().validationAsyncCount = count;
|
|
105
117
|
return count;
|
|
106
|
-
}
|
|
118
|
+
};
|
|
107
119
|
this.cancelValidateAsync = () => {
|
|
108
|
-
|
|
120
|
+
this.__leaseValidateAsync();
|
|
109
121
|
this.setMeta((prev) => ({
|
|
110
122
|
...prev,
|
|
111
123
|
isValidating: false
|
|
@@ -125,9 +137,10 @@ var _FieldApi = class _FieldApi {
|
|
|
125
137
|
if (!validate)
|
|
126
138
|
return [];
|
|
127
139
|
const debounceMs = cause === "submit" ? 0 : (cause === "change" ? onChangeAsyncDebounceMs : onBlurAsyncDebounceMs) ?? asyncDebounceMs ?? 0;
|
|
128
|
-
if (this.state.meta.isValidating !== true)
|
|
140
|
+
if (this.state.meta.isValidating !== true) {
|
|
129
141
|
this.setMeta((prev) => ({ ...prev, isValidating: true }));
|
|
130
|
-
|
|
142
|
+
}
|
|
143
|
+
const validationAsyncCount = this.__leaseValidateAsync();
|
|
131
144
|
const checkLatest = () => validationAsyncCount === this.getInfo().validationAsyncCount;
|
|
132
145
|
if (!this.getInfo().validationPromise) {
|
|
133
146
|
this.getInfo().validationPromise = new Promise((resolve, reject) => {
|
|
@@ -138,10 +151,25 @@ var _FieldApi = class _FieldApi {
|
|
|
138
151
|
if (debounceMs > 0) {
|
|
139
152
|
await new Promise((r) => setTimeout(r, debounceMs));
|
|
140
153
|
}
|
|
154
|
+
const doValidate = () => {
|
|
155
|
+
if (this.options.validator && typeof validate !== "function") {
|
|
156
|
+
return this.options.validator().validateAsync(
|
|
157
|
+
value,
|
|
158
|
+
validate
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
if (this.form.options.validator && typeof validate !== "function") {
|
|
162
|
+
return this.form.options.validator().validateAsync(value, validate);
|
|
163
|
+
}
|
|
164
|
+
return validate(
|
|
165
|
+
value,
|
|
166
|
+
this
|
|
167
|
+
);
|
|
168
|
+
};
|
|
141
169
|
if (checkLatest()) {
|
|
142
170
|
const prevErrors = this.getMeta().errors;
|
|
143
171
|
try {
|
|
144
|
-
const rawError = await
|
|
172
|
+
const rawError = await doValidate();
|
|
145
173
|
if (checkLatest()) {
|
|
146
174
|
const error = normalizeError(rawError);
|
|
147
175
|
this.setMeta((prev) => ({
|
|
@@ -171,9 +199,11 @@ var _FieldApi = class _FieldApi {
|
|
|
171
199
|
this.validate = (cause, value) => {
|
|
172
200
|
if (!this.state.meta.isTouched)
|
|
173
201
|
return [];
|
|
174
|
-
this.validateSync(value, cause);
|
|
175
202
|
const errorMapKey = getErrorMapKey(cause);
|
|
176
|
-
|
|
203
|
+
const prevError = this.getMeta().errorMap[errorMapKey];
|
|
204
|
+
this.validateSync(value, cause);
|
|
205
|
+
const newError = this.getMeta().errorMap[errorMapKey];
|
|
206
|
+
if (prevError !== newError) {
|
|
177
207
|
if (!this.options.asyncAlways) {
|
|
178
208
|
return this.state.meta.errors;
|
|
179
209
|
}
|
|
@@ -227,8 +257,6 @@ var _FieldApi = class _FieldApi {
|
|
|
227
257
|
this.options = opts;
|
|
228
258
|
}
|
|
229
259
|
};
|
|
230
|
-
_leaseValidateAsync = new WeakMap();
|
|
231
|
-
var FieldApi = _FieldApi;
|
|
232
260
|
function normalizeError(rawError) {
|
|
233
261
|
if (rawError) {
|
|
234
262
|
if (typeof rawError !== "string") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/FieldApi.ts"],"sourcesContent":["import { type DeepKeys, type DeepValue, type Updater } from './utils'\nimport type { FormApi, ValidationError, ValidationErrorMap } from './FormApi'\nimport { Store } from '@tanstack/store'\n\nexport type ValidationCause = 'change' | 'blur' | 'submit' | 'mount'\n\ntype ValidateFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (\n value: TData,\n fieldApi: FieldApi<TParentData, TName>,\n) => ValidationError\n\ntype ValidateAsyncFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData,\n> = (\n value: TData,\n fieldApi: FieldApi<TParentData, TName>,\n) => ValidationError | Promise<ValidationError>\n\nexport interface FieldOptions<\n TParentData,\n /**\n * This allows us to restrict the name to only be a valid field name while\n * also assigning it to a generic\n */\n TName extends DeepKeys<TParentData>,\n /**\n * If TData is unknown, we can use the TName generic to determine the type\n */\n TData = DeepValue<TParentData, TName>,\n> {\n name: DeepKeys<TParentData>\n index?: TData extends any[] ? number : never\n defaultValue?: TData\n asyncDebounceMs?: number\n asyncAlways?: boolean\n onMount?: (formApi: FieldApi<TParentData, TName>) => void\n onChange?: ValidateFn<TParentData, TName, TData>\n onChangeAsync?: ValidateAsyncFn<TParentData, TName, TData>\n onChangeAsyncDebounceMs?: number\n onBlur?: ValidateFn<TParentData, TName, TData>\n onBlurAsync?: ValidateAsyncFn<TParentData, TName, TData>\n onBlurAsyncDebounceMs?: number\n onSubmitAsync?: ValidateAsyncFn<TParentData, TName, TData>\n defaultMeta?: Partial<FieldMeta>\n}\n\nexport interface FieldApiOptions<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n> extends FieldOptions<TParentData, TName, TData> {\n form: FormApi<TParentData>\n}\n\nexport type FieldMeta = {\n isTouched: boolean\n touchedErrors: ValidationError[]\n errors: ValidationError[]\n errorMap: ValidationErrorMap\n isValidating: boolean\n}\n\nlet uid = 0\n\nexport type FieldState<TData> = {\n value: TData\n meta: FieldMeta\n}\n\nexport type ResolveName<TParentData> = unknown extends TParentData\n ? string\n : DeepKeys<TParentData>\n\nexport class FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n> {\n uid: number\n form: FieldApiOptions<TParentData, TName, TData>['form']\n name!: DeepKeys<TParentData>\n options: FieldApiOptions<TParentData, TName> = {} as any\n store!: Store<FieldState<TData>>\n state!: FieldState<TData>\n prevState!: FieldState<TData>\n\n constructor(\n opts: FieldApiOptions<TParentData, TName, TData> & {\n form: FormApi<TParentData>\n },\n ) {\n this.form = opts.form\n this.uid = uid++\n // Support field prefixing from FieldScope\n // let fieldPrefix = ''\n // if (this.form.fieldName) {\n // fieldPrefix = `${this.form.fieldName}.`\n // }\n\n this.name = opts.name as any\n\n if (opts.defaultValue !== undefined) {\n this.form.setFieldValue(this.name, opts.defaultValue as never)\n }\n\n this.store = new Store<FieldState<TData>>(\n {\n value: this.getValue(),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n meta: this._getMeta() ?? {\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...opts.defaultMeta,\n },\n },\n {\n onUpdate: () => {\n const state = this.store.state\n\n state.meta.errors = Object.values(state.meta.errorMap).filter(\n (val: unknown) => val !== undefined,\n )\n\n state.meta.touchedErrors = state.meta.isTouched\n ? state.meta.errors\n : []\n\n this.prevState = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n this.prevState = this.state\n this.options = opts as never\n }\n\n mount = () => {\n const info = this.getInfo()\n info.instances[this.uid] = this as never\n\n const unsubscribe = this.form.store.subscribe(() => {\n this.store.batch(() => {\n const nextValue = this.getValue()\n const nextMeta = this.getMeta()\n\n if (nextValue !== this.state.value) {\n this.store.setState((prev) => ({ ...prev, value: nextValue }))\n }\n\n if (nextMeta !== this.state.meta) {\n this.store.setState((prev) => ({ ...prev, meta: nextMeta }))\n }\n })\n })\n\n this.update(this.options as never)\n this.options.onMount?.(this as never)\n\n return () => {\n unsubscribe()\n delete info.instances[this.uid]\n if (!Object.keys(info.instances).length) {\n delete this.form.fieldInfo[this.name]\n }\n }\n }\n\n update = (opts: FieldApiOptions<TParentData, TName, TData>) => {\n // Default Value\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.state.value === undefined) {\n const formDefault =\n opts.form.options.defaultValues?.[opts.name as keyof TParentData]\n\n if (opts.defaultValue !== undefined) {\n this.setValue(opts.defaultValue as never)\n } else if (formDefault !== undefined) {\n this.setValue(formDefault as never)\n }\n }\n\n // Default Meta\n if (this._getMeta() === undefined) {\n this.setMeta(this.state.meta)\n }\n\n this.options = opts as never\n }\n\n getValue = (): TData => {\n return this.form.getFieldValue(this.name) as any\n }\n\n setValue = (\n updater: Updater<TData>,\n options?: { touch?: boolean; notify?: boolean },\n ) => {\n this.form.setFieldValue(this.name, updater as never, options)\n this.validate('change', this.state.value)\n }\n\n _getMeta = () => this.form.getFieldMeta(this.name)\n getMeta = () =>\n this._getMeta() ??\n ({\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...this.options.defaultMeta,\n } as FieldMeta)\n\n setMeta = (updater: Updater<FieldMeta>) =>\n this.form.setFieldMeta(this.name, updater)\n\n getInfo = () => this.form.getFieldInfo(this.name)\n\n pushValue = (value: TData extends any[] ? TData[number] : never) =>\n this.form.pushFieldValue(this.name, value as any)\n\n insertValue = (\n index: number,\n value: TData extends any[] ? TData[number] : never,\n ) => this.form.insertFieldValue(this.name, index, value as any)\n\n removeValue = (index: number) => this.form.removeFieldValue(this.name, index)\n\n swapValues = (aIndex: number, bIndex: number) =>\n this.form.swapFieldValues(this.name, aIndex, bIndex)\n\n getSubField = <\n TSubName extends DeepKeys<TData>,\n TSubData = DeepValue<TData, TSubName>,\n >(\n name: TSubName,\n ): FieldApi<TData, TSubName, TSubData> =>\n new FieldApi({\n name: `${this.name}.${name}` as never,\n form: this.form,\n }) as any\n\n validateSync = (value = this.state.value, cause: ValidationCause) => {\n const { onChange, onBlur } = this.options\n const validate =\n cause === 'submit' ? undefined : cause === 'change' ? onChange : onBlur\n if (!validate) return\n\n // Use the validationCount for all field instances to\n // track freshness of the validation\n const validationCount = (this.getInfo().validationCount || 0) + 1\n this.getInfo().validationCount = validationCount\n const error = normalizeError(validate(value as never, this as never))\n const errorMapKey = getErrorMapKey(cause)\n if (this.state.meta.errorMap[errorMapKey] !== error) {\n this.setMeta((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n }\n\n // If a sync error is encountered for the errorMapKey (eg. onChange), cancel any async validation\n if (this.state.meta.errorMap[errorMapKey]) {\n this.cancelValidateAsync()\n }\n }\n\n #leaseValidateAsync = () => {\n const count = (this.getInfo().validationAsyncCount || 0) + 1\n this.getInfo().validationAsyncCount = count\n return count\n }\n\n cancelValidateAsync = () => {\n // Lease a new validation count to ignore any pending validations\n this.#leaseValidateAsync()\n // Cancel any pending validation state\n this.setMeta((prev) => ({\n ...prev,\n isValidating: false,\n }))\n }\n\n validateAsync = async (value = this.state.value, cause: ValidationCause) => {\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n asyncDebounceMs,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n } = this.options\n\n const validate =\n cause === 'change'\n ? onChangeAsync\n : cause === 'submit'\n ? onSubmitAsync\n : onBlurAsync\n if (!validate) return []\n const debounceMs =\n cause === 'submit'\n ? 0\n : (cause === 'change'\n ? onChangeAsyncDebounceMs\n : onBlurAsyncDebounceMs) ??\n asyncDebounceMs ??\n 0\n\n if (this.state.meta.isValidating !== true)\n this.setMeta((prev) => ({ ...prev, isValidating: true }))\n\n // Use the validationCount for all field instances to\n // track freshness of the validation\n const validationAsyncCount = this.#leaseValidateAsync()\n\n const checkLatest = () =>\n validationAsyncCount === this.getInfo().validationAsyncCount\n\n if (!this.getInfo().validationPromise) {\n this.getInfo().validationPromise = new Promise((resolve, reject) => {\n this.getInfo().validationResolve = resolve\n this.getInfo().validationReject = reject\n })\n }\n\n if (debounceMs > 0) {\n await new Promise((r) => setTimeout(r, debounceMs))\n }\n\n // Only kick off validation if this validation is the latest attempt\n if (checkLatest()) {\n const prevErrors = this.getMeta().errors\n try {\n const rawError = await validate(value as never, this as never)\n if (checkLatest()) {\n const error = normalizeError(rawError)\n this.setMeta((prev) => ({\n ...prev,\n isValidating: false,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n this.getInfo().validationResolve?.([...prevErrors, error])\n }\n } catch (error) {\n if (checkLatest()) {\n this.getInfo().validationReject?.([...prevErrors, error])\n throw error\n }\n } finally {\n if (checkLatest()) {\n this.setMeta((prev) => ({ ...prev, isValidating: false }))\n delete this.getInfo().validationPromise\n }\n }\n }\n\n // Always return the latest validation promise to the caller\n return this.getInfo().validationPromise ?? []\n }\n\n validate = (\n cause: ValidationCause,\n value?: TData,\n ): ValidationError[] | Promise<ValidationError[]> => {\n // If the field is pristine and validatePristine is false, do not validate\n if (!this.state.meta.isTouched) return []\n // Attempt to sync validate first\n this.validateSync(value, cause)\n\n const errorMapKey = getErrorMapKey(cause)\n // If there is an error mapped to the errorMapKey (eg. onChange, onBlur, onSubmit), return the errors array, do not attempt async validation\n if (this.getMeta().errorMap[errorMapKey]) {\n if (!this.options.asyncAlways) {\n return this.state.meta.errors\n }\n }\n // No error? Attempt async validation\n return this.validateAsync(value, cause)\n }\n\n handleChange = (updater: Updater<TData>) => {\n this.setValue(updater, { touch: true })\n }\n\n handleBlur = () => {\n const prevTouched = this.state.meta.isTouched\n if (!prevTouched) {\n this.setMeta((prev) => ({ ...prev, isTouched: true }))\n this.validate('change')\n }\n this.validate('blur')\n }\n}\n\nfunction normalizeError(rawError?: ValidationError) {\n if (rawError) {\n if (typeof rawError !== 'string') {\n return 'Invalid Form Values'\n }\n\n return rawError\n }\n\n return undefined\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'change':\n return 'onChange'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/FieldApi.ts"],"sourcesContent":["import { type DeepKeys, type DeepValue, type Updater } from './utils'\nimport type { FormApi, ValidationErrorMap } from './FormApi'\nimport { Store } from '@tanstack/store'\nimport type { Validator, ValidationError } from './types'\n\nexport type ValidationCause = 'change' | 'blur' | 'submit' | 'mount'\n\ntype ValidateFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = (\n value: TData,\n fieldApi: FieldApi<TParentData, TName, ValidatorType, TData>,\n) => ValidationError\n\ntype ValidateOrFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = ValidatorType extends Validator<TData>\n ?\n | Parameters<ReturnType<ValidatorType>['validate']>[1]\n | ValidateFn<TParentData, TName, ValidatorType, TData>\n : FormValidator extends Validator<TData>\n ?\n | Parameters<ReturnType<FormValidator>['validate']>[1]\n | ValidateFn<TParentData, TName, ValidatorType, TData>\n : ValidateFn<TParentData, TName, ValidatorType, TData>\n\ntype ValidateAsyncFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = (\n value: TData,\n fieldApi: FieldApi<TParentData, TName, ValidatorType, TData>,\n) => ValidationError | Promise<ValidationError>\n\ntype AsyncValidateOrFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = ValidatorType extends Validator<TData>\n ?\n | Parameters<ReturnType<ValidatorType>['validate']>[1]\n | ValidateAsyncFn<TParentData, TName, ValidatorType, TData>\n : FormValidator extends Validator<TData>\n ?\n | Parameters<ReturnType<FormValidator>['validate']>[1]\n | ValidateAsyncFn<TParentData, TName, ValidatorType, TData>\n : ValidateAsyncFn<TParentData, TName, ValidatorType, TData>\n\nexport interface FieldOptions<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> {\n name: TName\n index?: TData extends any[] ? number : never\n defaultValue?: TData\n asyncDebounceMs?: number\n asyncAlways?: boolean\n validator?: ValidatorType\n onMount?: (\n formApi: FieldApi<TParentData, TName, ValidatorType, TData>,\n ) => void\n onChange?: ValidateOrFn<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >\n onChangeAsync?: AsyncValidateOrFn<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >\n onChangeAsyncDebounceMs?: number\n onBlur?: ValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>\n onBlurAsync?: AsyncValidateOrFn<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >\n onBlurAsyncDebounceMs?: number\n onSubmitAsync?: AsyncValidateOrFn<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >\n defaultMeta?: Partial<FieldMeta>\n}\n\nexport interface FieldApiOptions<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> extends FieldOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n > {\n form: FormApi<TParentData, FormValidator>\n}\n\nexport type FieldMeta = {\n isTouched: boolean\n touchedErrors: ValidationError[]\n errors: ValidationError[]\n errorMap: ValidationErrorMap\n isValidating: boolean\n}\n\nlet uid = 0\n\nexport type FieldState<TData> = {\n value: TData\n meta: FieldMeta\n}\n\nexport type ResolveName<TParentData> = unknown extends TParentData\n ? string\n : DeepKeys<TParentData>\n\nexport class FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> {\n uid: number\n form: FieldApiOptions<TParentData, TName, ValidatorType, TData>['form']\n name!: DeepKeys<TParentData>\n options: FieldApiOptions<TParentData, TName, ValidatorType, TData> = {} as any\n store!: Store<FieldState<TData>>\n state!: FieldState<TData>\n prevState!: FieldState<TData>\n\n constructor(\n opts: FieldApiOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >,\n ) {\n this.form = opts.form as never\n this.uid = uid++\n // Support field prefixing from FieldScope\n // let fieldPrefix = ''\n // if (this.form.fieldName) {\n // fieldPrefix = `${this.form.fieldName}.`\n // }\n\n this.name = opts.name as never\n\n if (opts.defaultValue !== undefined) {\n this.form.setFieldValue(this.name, opts.defaultValue as never)\n }\n\n this.store = new Store<FieldState<TData>>(\n {\n value: this.getValue(),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n meta: this._getMeta() ?? {\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...opts.defaultMeta,\n },\n },\n {\n onUpdate: () => {\n const state = this.store.state\n\n state.meta.errors = Object.values(state.meta.errorMap).filter(\n (val: unknown) => val !== undefined,\n )\n\n state.meta.touchedErrors = state.meta.isTouched\n ? state.meta.errors\n : []\n\n this.prevState = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n this.prevState = this.state\n this.options = opts as never\n }\n\n mount = () => {\n const info = this.getInfo()\n info.instances[this.uid] = this as never\n\n const unsubscribe = this.form.store.subscribe(() => {\n this.store.batch(() => {\n const nextValue = this.getValue()\n const nextMeta = this.getMeta()\n\n if (nextValue !== this.state.value) {\n this.store.setState((prev) => ({ ...prev, value: nextValue }))\n }\n\n if (nextMeta !== this.state.meta) {\n this.store.setState((prev) => ({ ...prev, meta: nextMeta }))\n }\n })\n })\n\n this.update(this.options as never)\n this.options.onMount?.(this as never)\n\n return () => {\n unsubscribe()\n delete info.instances[this.uid]\n if (!Object.keys(info.instances).length) {\n delete this.form.fieldInfo[this.name as never]\n }\n }\n }\n\n update = (\n opts: FieldApiOptions<TParentData, TName, ValidatorType, TData>,\n ) => {\n // Default Value\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.state.value === undefined) {\n const formDefault =\n opts.form.options.defaultValues?.[opts.name as keyof TParentData]\n\n if (opts.defaultValue !== undefined) {\n this.setValue(opts.defaultValue as never)\n } else if (formDefault !== undefined) {\n this.setValue(formDefault as never)\n }\n }\n\n // Default Meta\n if (this._getMeta() === undefined) {\n this.setMeta(this.state.meta)\n }\n\n this.options = opts as never\n }\n\n getValue = (): TData => {\n return this.form.getFieldValue(this.name) as any\n }\n\n setValue = (\n updater: Updater<TData>,\n options?: { touch?: boolean; notify?: boolean },\n ) => {\n this.form.setFieldValue(this.name, updater as never, options)\n this.validate('change', this.state.value)\n }\n\n _getMeta = () => this.form.getFieldMeta(this.name)\n getMeta = () =>\n this._getMeta() ??\n ({\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...this.options.defaultMeta,\n } as FieldMeta)\n\n setMeta = (updater: Updater<FieldMeta>) =>\n this.form.setFieldMeta(this.name, updater)\n\n getInfo = () => this.form.getFieldInfo(this.name)\n\n pushValue = (value: TData extends any[] ? TData[number] : never) =>\n this.form.pushFieldValue(this.name, value as any)\n\n insertValue = (\n index: number,\n value: TData extends any[] ? TData[number] : never,\n ) => this.form.insertFieldValue(this.name, index, value as any)\n\n removeValue = (index: number) => this.form.removeFieldValue(this.name, index)\n\n swapValues = (aIndex: number, bIndex: number) =>\n this.form.swapFieldValues(this.name, aIndex, bIndex)\n\n getSubField = <\n TSubName extends DeepKeys<TData>,\n TSubData extends DeepValue<TData, TSubName> = DeepValue<TData, TSubName>,\n >(\n name: TSubName,\n ): FieldApi<TData, TSubName, ValidatorType, TSubData> =>\n new FieldApi({\n name: `${this.name}.${name}` as never,\n form: this.form,\n }) as any\n\n validateSync = (value = this.state.value, cause: ValidationCause) => {\n const { onChange, onBlur } = this.options\n const validate =\n cause === 'submit' ? undefined : cause === 'change' ? onChange : onBlur\n\n if (!validate) return\n\n // Use the validationCount for all field instances to\n // track freshness of the validation\n const validationCount = (this.getInfo().validationCount || 0) + 1\n this.getInfo().validationCount = validationCount\n\n const doValidate = () => {\n if (this.options.validator && typeof validate !== 'function') {\n return (this.options.validator as Validator<TData>)().validate(\n value,\n validate,\n )\n }\n\n if (this.form.options.validator && typeof validate !== 'function') {\n return (this.form.options.validator as Validator<TData>)().validate(\n value,\n validate,\n )\n }\n\n return (validate as ValidateFn<TParentData, TName, ValidatorType, TData>)(\n value,\n this as never,\n )\n }\n\n const error = normalizeError(doValidate())\n const errorMapKey = getErrorMapKey(cause)\n if (this.state.meta.errorMap[errorMapKey] !== error) {\n this.setMeta((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n }\n\n // If a sync error is encountered for the errorMapKey (eg. onChange), cancel any async validation\n if (this.state.meta.errorMap[errorMapKey]) {\n this.cancelValidateAsync()\n }\n }\n\n __leaseValidateAsync = () => {\n const count = (this.getInfo().validationAsyncCount || 0) + 1\n this.getInfo().validationAsyncCount = count\n return count\n }\n\n cancelValidateAsync = () => {\n // Lease a new validation count to ignore any pending validations\n this.__leaseValidateAsync()\n // Cancel any pending validation state\n this.setMeta((prev) => ({\n ...prev,\n isValidating: false,\n }))\n }\n\n validateAsync = async (value = this.state.value, cause: ValidationCause) => {\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n asyncDebounceMs,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n } = this.options\n\n const validate =\n cause === 'change'\n ? onChangeAsync\n : cause === 'submit'\n ? onSubmitAsync\n : onBlurAsync\n if (!validate) return []\n const debounceMs =\n cause === 'submit'\n ? 0\n : (cause === 'change'\n ? onChangeAsyncDebounceMs\n : onBlurAsyncDebounceMs) ??\n asyncDebounceMs ??\n 0\n\n if (this.state.meta.isValidating !== true) {\n this.setMeta((prev) => ({ ...prev, isValidating: true }))\n }\n\n // Use the validationCount for all field instances to\n // track freshness of the validation\n const validationAsyncCount = this.__leaseValidateAsync()\n\n const checkLatest = () =>\n validationAsyncCount === this.getInfo().validationAsyncCount\n\n if (!this.getInfo().validationPromise) {\n this.getInfo().validationPromise = new Promise((resolve, reject) => {\n this.getInfo().validationResolve = resolve\n this.getInfo().validationReject = reject\n })\n }\n\n if (debounceMs > 0) {\n await new Promise((r) => setTimeout(r, debounceMs))\n }\n\n const doValidate = () => {\n if (this.options.validator && typeof validate !== 'function') {\n return (this.options.validator as Validator<TData>)().validateAsync(\n value,\n validate,\n )\n }\n\n if (this.form.options.validator && typeof validate !== 'function') {\n return (\n this.form.options.validator as Validator<TData>\n )().validateAsync(value, validate)\n }\n\n return (validate as ValidateFn<TParentData, TName, ValidatorType, TData>)(\n value,\n this as never,\n )\n }\n\n // Only kick off validation if this validation is the latest attempt\n if (checkLatest()) {\n const prevErrors = this.getMeta().errors\n try {\n const rawError = await doValidate()\n if (checkLatest()) {\n const error = normalizeError(rawError)\n this.setMeta((prev) => ({\n ...prev,\n isValidating: false,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n this.getInfo().validationResolve?.([...prevErrors, error])\n }\n } catch (error) {\n if (checkLatest()) {\n this.getInfo().validationReject?.([...prevErrors, error])\n throw error\n }\n } finally {\n if (checkLatest()) {\n this.setMeta((prev) => ({ ...prev, isValidating: false }))\n delete this.getInfo().validationPromise\n }\n }\n }\n\n // Always return the latest validation promise to the caller\n return this.getInfo().validationPromise ?? []\n }\n\n validate = (\n cause: ValidationCause,\n value?: TData,\n ): ValidationError[] | Promise<ValidationError[]> => {\n // If the field is pristine and validatePristine is false, do not validate\n if (!this.state.meta.isTouched) return []\n\n // Store the previous error for the errorMapKey (eg. onChange, onBlur, onSubmit)\n const errorMapKey = getErrorMapKey(cause)\n const prevError = this.getMeta().errorMap[errorMapKey]\n\n // Attempt to sync validate first\n this.validateSync(value, cause)\n\n // If there is a new error mapped to the errorMapKey (eg. onChange, onBlur, onSubmit), return the errors array, do not attempt async validation\n const newError = this.getMeta().errorMap[errorMapKey]\n\n if (prevError !== newError) {\n if (!this.options.asyncAlways) {\n return this.state.meta.errors\n }\n }\n // No error? Attempt async validation\n return this.validateAsync(value, cause)\n }\n\n handleChange = (updater: Updater<TData>) => {\n this.setValue(updater, { touch: true })\n }\n\n handleBlur = () => {\n const prevTouched = this.state.meta.isTouched\n if (!prevTouched) {\n this.setMeta((prev) => ({ ...prev, isTouched: true }))\n this.validate('change')\n }\n this.validate('blur')\n }\n}\n\nfunction normalizeError(rawError?: ValidationError) {\n if (rawError) {\n if (typeof rawError !== 'string') {\n return 'Invalid Form Values'\n }\n\n return rawError\n }\n\n return undefined\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'change':\n return 'onChange'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n }\n}\n"],"mappings":"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","names":[]}
|
package/build/legacy/FormApi.cjs
CHANGED
|
@@ -84,18 +84,16 @@ var FormApi = class {
|
|
|
84
84
|
this.validateAllFields = async (cause) => {
|
|
85
85
|
const fieldValidationPromises = [];
|
|
86
86
|
this.store.batch(() => {
|
|
87
|
-
void Object.values(this.fieldInfo).forEach(
|
|
88
|
-
(field) => {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
);
|
|
87
|
+
void Object.values(this.fieldInfo).forEach((field) => {
|
|
88
|
+
Object.values(field.instances).forEach((instance) => {
|
|
89
|
+
if (!instance.state.meta.isTouched) {
|
|
90
|
+
instance.setMeta((prev) => ({ ...prev, isTouched: true }));
|
|
91
|
+
fieldValidationPromises.push(
|
|
92
|
+
Promise.resolve().then(() => instance.validate(cause))
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
99
97
|
});
|
|
100
98
|
return Promise.all(fieldValidationPromises);
|
|
101
99
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\n//\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport { functionalUpdate, getBy, isNonEmptyArray, setBy } from './utils'\nimport type { FieldApi, FieldMeta, ValidationCause } from './FieldApi'\n\nexport type FormOptions<TData> = {\n defaultValues?: TData\n defaultState?: Partial<FormState<TData>>\n asyncDebounceMs?: number\n onMount?: (values: TData, formApi: FormApi<TData>) => ValidationError\n onMountAsync?: (\n values: TData,\n formApi: FormApi<TData>,\n ) => ValidationError | Promise<ValidationError>\n onMountAsyncDebounceMs?: number\n onChange?: (values: TData, formApi: FormApi<TData>) => ValidationError\n onChangeAsync?: (\n values: TData,\n formApi: FormApi<TData>,\n ) => ValidationError | Promise<ValidationError>\n onChangeAsyncDebounceMs?: number\n onBlur?: (values: TData, formApi: FormApi<TData>) => ValidationError\n onBlurAsync?: (\n values: TData,\n formApi: FormApi<TData>,\n ) => ValidationError | Promise<ValidationError>\n onBlurAsyncDebounceMs?: number\n onSubmit?: (values: TData, formApi: FormApi<TData>) => any | Promise<any>\n onSubmitInvalid?: (values: TData, formApi: FormApi<TData>) => void\n}\n\nexport type FieldInfo<TFormData> = {\n instances: Record<string, FieldApi<TFormData, any, any>>\n} & ValidationMeta\n\nexport type ValidationMeta = {\n validationCount?: number\n validationAsyncCount?: number\n validationPromise?: Promise<ValidationError[]>\n validationResolve?: (errors: ValidationError[]) => void\n validationReject?: (errors: unknown) => void\n}\n\nexport type ValidationError = undefined | false | null | string\n\nexport type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`\n\nexport type ValidationErrorMap = {\n [K in ValidationErrorMapKeys]?: ValidationError\n}\n\nexport type FormState<TData> = {\n values: TData\n // Form Validation\n isFormValidating: boolean\n formValidationCount: number\n isFormValid: boolean\n formError?: ValidationError\n // Fields\n fieldMeta: Record<DeepKeys<TData>, FieldMeta>\n isFieldsValidating: boolean\n isFieldsValid: boolean\n isSubmitting: boolean\n // General\n isTouched: boolean\n isSubmitted: boolean\n isValidating: boolean\n isValid: boolean\n canSubmit: boolean\n submissionAttempts: number\n}\n\nfunction getDefaultFormState<TData>(\n defaultState: Partial<FormState<TData>>,\n): FormState<TData> {\n return {\n values: defaultState.values ?? ({} as never),\n fieldMeta: defaultState.fieldMeta ?? ({} as never),\n canSubmit: defaultState.canSubmit ?? true,\n isFieldsValid: defaultState.isFieldsValid ?? false,\n isFieldsValidating: defaultState.isFieldsValidating ?? false,\n isFormValid: defaultState.isFormValid ?? false,\n isFormValidating: defaultState.isFormValidating ?? false,\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isTouched: defaultState.isTouched ?? false,\n isValid: defaultState.isValid ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n formValidationCount: defaultState.formValidationCount ?? 0,\n }\n}\n\nexport class FormApi<TFormData> {\n // // This carries the context for nested fields\n options: FormOptions<TFormData> = {}\n store!: Store<FormState<TFormData>>\n // Do not use __state directly, as it is not reactive.\n // Please use form.useStore() utility to subscribe to state\n state!: FormState<TFormData>\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>> = {} as any\n fieldName?: string\n validationMeta: ValidationMeta = {}\n\n constructor(opts?: FormOptions<TFormData>) {\n this.store = new Store<FormState<TFormData>>(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n {\n onUpdate: () => {\n let { state } = this.store\n // Computed state\n const fieldMetaValues = Object.values(state.fieldMeta) as (\n | FieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some((field) =>\n isNonEmptyArray(field?.errors),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n\n const isValidating = isFieldsValidating || state.isFormValidating\n const isFormValid = !state.formError\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (state.submissionAttempts === 0 && !isTouched) ||\n (!isValidating && !state.isSubmitting && isValid)\n\n state = {\n ...state,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n }\n\n this.store.state = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n\n this.update(opts || {})\n }\n\n update = (options?: FormOptions<TFormData>) => {\n if (!options) return\n\n this.store.batch(() => {\n const shouldUpdateValues =\n options.defaultValues &&\n options.defaultValues !== this.options.defaultValues &&\n !this.state.isTouched\n\n const shouldUpdateState =\n options.defaultState !== this.options.defaultState &&\n !this.state.isTouched\n\n this.store.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateState ? options.defaultState : {},\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n ),\n ),\n )\n })\n\n this.options = options\n }\n\n reset = () =>\n this.store.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values: this.options.defaultValues ?? this.options.defaultState?.values,\n }),\n )\n\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n this.store.batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<any>[]).forEach(\n (field) => {\n Object.values(field.instances).forEach((instance) => {\n // If any fields are not touched\n if (!instance.state.meta.isTouched) {\n // Mark them as touched\n instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n // Validate the field\n fieldValidationPromises.push(\n Promise.resolve().then(() => instance.validate(cause)),\n )\n }\n })\n },\n )\n })\n\n return Promise.all(fieldValidationPromises)\n }\n\n handleSubmit = async () => {\n // Check to see that the form and all fields have been touched\n // If they have not, touch them all and run validation\n // Run form validation\n // Submit the form\n\n this.store.setState((old) => ({\n ...old,\n // Submission attempts mark the form as not submitted\n isSubmitted: false,\n // Count submission attempts\n submissionAttempts: old.submissionAttempts + 1,\n }))\n\n // Don't let invalid forms submit\n if (!this.state.canSubmit) return\n\n this.store.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.store.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n // Validate all fields\n await this.validateAllFields('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.(this.state.values, this)\n return\n }\n\n // Run validation for the form\n // await this.validateForm()\n\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.(this.state.values, this)\n return\n }\n\n try {\n // Run the submit code\n await this.options.onSubmit?.(this.state.values, this)\n\n this.store.batch(() => {\n this.store.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n getFieldInfo = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldInfo<TFormData> => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return (this.fieldInfo[field] ||= {\n instances: {},\n })\n }\n\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<FieldMeta>,\n ) => {\n this.store.setState((prev) => {\n return {\n ...prev,\n fieldMeta: {\n ...prev.fieldMeta,\n [field]: functionalUpdate(updater, prev.fieldMeta[field]),\n },\n }\n })\n }\n\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: { touch?: boolean },\n ) => {\n const touch = opts?.touch\n\n this.store.batch(() => {\n if (touch) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n }))\n }\n\n this.store.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n pushFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n value: DeepValue<TFormData, TField>[number],\n opts?: { touch?: boolean },\n ) => {\n return this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n }\n\n insertFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n value: DeepValue<TFormData, TField>[number],\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).map((d, i) =>\n i === index ? value : d,\n ) as any\n },\n opts,\n )\n }\n\n removeFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).filter(\n (_d, i) => i !== index,\n ) as any\n },\n opts,\n )\n }\n\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n ) => {\n this.setFieldValue(field, (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n })\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport { functionalUpdate, getBy, isNonEmptyArray, setBy } from './utils'\nimport type { FieldApi, FieldMeta, ValidationCause } from './FieldApi'\nimport type { ValidationError, Validator } from './types'\n\ntype ValidateFn<TData, ValidatorType> = (\n values: TData,\n formApi: FormApi<TData, ValidatorType>,\n) => ValidationError\n\ntype ValidateOrFn<TData, ValidatorType> = ValidatorType extends Validator<TData>\n ? Parameters<ReturnType<ValidatorType>['validate']>[1]\n : ValidateFn<TData, ValidatorType>\n\ntype ValidateAsyncFn<TData, ValidatorType> = (\n value: TData,\n fieldApi: FormApi<TData, ValidatorType>,\n) => ValidationError | Promise<ValidationError>\n\nexport type FormOptions<TData, ValidatorType> = {\n defaultValues?: TData\n defaultState?: Partial<FormState<TData>>\n asyncDebounceMs?: number\n validator?: ValidatorType\n onMount?: ValidateOrFn<TData, ValidatorType>\n onMountAsync?: ValidateAsyncFn<TData, ValidatorType>\n onMountAsyncDebounceMs?: number\n onChange?: ValidateOrFn<TData, ValidatorType>\n onChangeAsync?: ValidateAsyncFn<TData, ValidatorType>\n onChangeAsyncDebounceMs?: number\n onBlur?: ValidateOrFn<TData, ValidatorType>\n onBlurAsync?: ValidateAsyncFn<TData, ValidatorType>\n onBlurAsyncDebounceMs?: number\n onSubmit?: (\n values: TData,\n formApi: FormApi<TData, ValidatorType>,\n ) => any | Promise<any>\n onSubmitInvalid?: (\n values: TData,\n formApi: FormApi<TData, ValidatorType>,\n ) => void\n}\n\nexport type FieldInfo<TFormData, ValidatorType> = {\n instances: Record<string, FieldApi<TFormData, any, unknown, ValidatorType>>\n} & ValidationMeta\n\nexport type ValidationMeta = {\n validationCount?: number\n validationAsyncCount?: number\n validationPromise?: Promise<ValidationError[]>\n validationResolve?: (errors: ValidationError[]) => void\n validationReject?: (errors: unknown) => void\n}\n\nexport type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`\n\nexport type ValidationErrorMap = {\n [K in ValidationErrorMapKeys]?: ValidationError\n}\n\nexport type FormState<TData> = {\n values: TData\n // Form Validation\n isFormValidating: boolean\n formValidationCount: number\n isFormValid: boolean\n formError?: ValidationError\n // Fields\n fieldMeta: Record<DeepKeys<TData>, FieldMeta>\n isFieldsValidating: boolean\n isFieldsValid: boolean\n isSubmitting: boolean\n // General\n isTouched: boolean\n isSubmitted: boolean\n isValidating: boolean\n isValid: boolean\n canSubmit: boolean\n submissionAttempts: number\n}\n\nfunction getDefaultFormState<TData>(\n defaultState: Partial<FormState<TData>>,\n): FormState<TData> {\n return {\n values: defaultState.values ?? ({} as never),\n fieldMeta: defaultState.fieldMeta ?? ({} as never),\n canSubmit: defaultState.canSubmit ?? true,\n isFieldsValid: defaultState.isFieldsValid ?? false,\n isFieldsValidating: defaultState.isFieldsValidating ?? false,\n isFormValid: defaultState.isFormValid ?? false,\n isFormValidating: defaultState.isFormValidating ?? false,\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isTouched: defaultState.isTouched ?? false,\n isValid: defaultState.isValid ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n formValidationCount: defaultState.formValidationCount ?? 0,\n }\n}\n\nexport class FormApi<TFormData, ValidatorType> {\n // // This carries the context for nested fields\n options: FormOptions<TFormData, ValidatorType> = {}\n store!: Store<FormState<TFormData>>\n // Do not use __state directly, as it is not reactive.\n // Please use form.useStore() utility to subscribe to state\n state!: FormState<TFormData>\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, ValidatorType>> =\n {} as any\n fieldName?: string\n validationMeta: ValidationMeta = {}\n\n constructor(opts?: FormOptions<TFormData, ValidatorType>) {\n this.store = new Store<FormState<TFormData>>(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n {\n onUpdate: () => {\n let { state } = this.store\n // Computed state\n const fieldMetaValues = Object.values(state.fieldMeta) as (\n | FieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some((field) =>\n isNonEmptyArray(field?.errors),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n\n const isValidating = isFieldsValidating || state.isFormValidating\n const isFormValid = !state.formError\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (state.submissionAttempts === 0 && !isTouched) ||\n (!isValidating && !state.isSubmitting && isValid)\n\n state = {\n ...state,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n }\n\n this.store.state = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n\n this.update(opts || {})\n }\n\n update = (options?: FormOptions<TFormData, ValidatorType>) => {\n if (!options) return\n\n this.store.batch(() => {\n const shouldUpdateValues =\n options.defaultValues &&\n options.defaultValues !== this.options.defaultValues &&\n !this.state.isTouched\n\n const shouldUpdateState =\n options.defaultState !== this.options.defaultState &&\n !this.state.isTouched\n\n this.store.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateState ? options.defaultState : {},\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n ),\n ),\n )\n })\n\n this.options = options\n }\n\n reset = () =>\n this.store.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values: this.options.defaultValues ?? this.options.defaultState?.values,\n }),\n )\n\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n this.store.batch(() => {\n void (\n Object.values(this.fieldInfo) as FieldInfo<any, ValidatorType>[]\n ).forEach((field) => {\n Object.values(field.instances).forEach((instance) => {\n // If any fields are not touched\n if (!instance.state.meta.isTouched) {\n // Mark them as touched\n instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n // Validate the field\n fieldValidationPromises.push(\n Promise.resolve().then(() => instance.validate(cause)),\n )\n }\n })\n })\n })\n\n return Promise.all(fieldValidationPromises)\n }\n\n handleSubmit = async () => {\n // Check to see that the form and all fields have been touched\n // If they have not, touch them all and run validation\n // Run form validation\n // Submit the form\n\n this.store.setState((old) => ({\n ...old,\n // Submission attempts mark the form as not submitted\n isSubmitted: false,\n // Count submission attempts\n submissionAttempts: old.submissionAttempts + 1,\n }))\n\n // Don't let invalid forms submit\n if (!this.state.canSubmit) return\n\n this.store.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.store.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n // Validate all fields\n await this.validateAllFields('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.(this.state.values, this)\n return\n }\n\n // Run validation for the form\n // await this.validateForm()\n\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.(this.state.values, this)\n return\n }\n\n try {\n // Run the submit code\n await this.options.onSubmit?.(this.state.values, this)\n\n this.store.batch(() => {\n this.store.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n getFieldInfo = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldInfo<TFormData, ValidatorType> => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return (this.fieldInfo[field] ||= {\n instances: {},\n })\n }\n\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<FieldMeta>,\n ) => {\n this.store.setState((prev) => {\n return {\n ...prev,\n fieldMeta: {\n ...prev.fieldMeta,\n [field]: functionalUpdate(updater, prev.fieldMeta[field]),\n },\n }\n })\n }\n\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: { touch?: boolean },\n ) => {\n const touch = opts?.touch\n\n this.store.batch(() => {\n if (touch) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n }))\n }\n\n this.store.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n pushFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n value: DeepValue<TFormData, TField> extends any[]\n ? DeepValue<TFormData, TField>[number]\n : never,\n opts?: { touch?: boolean },\n ) => {\n return this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n }\n\n insertFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n value: DeepValue<TFormData, TField> extends any[]\n ? DeepValue<TFormData, TField>[number]\n : never,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).map((d, i) =>\n i === index ? value : d,\n ) as any\n },\n opts,\n )\n }\n\n removeFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).filter(\n (_d, i) => i !== index,\n ) as any\n },\n opts,\n )\n }\n\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n ) => {\n this.setFieldValue(field, (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n })\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import '@tanstack/store';
|
|
2
2
|
import './utils.cjs';
|
|
3
|
-
export { FieldInfo, FormApi, FormOptions, FormState,
|
|
3
|
+
export { FieldInfo, FormApi, FormOptions, FormState, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta } from './index.cjs';
|
|
4
|
+
import './types.cjs';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import '@tanstack/store';
|
|
2
2
|
import './utils.js';
|
|
3
|
-
export { FieldInfo, FormApi, FormOptions, FormState,
|
|
3
|
+
export { FieldInfo, FormApi, FormOptions, FormState, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta } from './index.js';
|
|
4
|
+
import './types.js';
|