@tanstack/form-core 0.47.0 → 0.47.2
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/FormApi.cjs +19 -10
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/FormApi.d.cts +8 -2
- package/dist/esm/FormApi.d.ts +8 -2
- package/dist/esm/FormApi.js +19 -10
- package/dist/esm/FormApi.js.map +1 -1
- package/package.json +1 -1
- package/src/FormApi.ts +37 -15
package/dist/cjs/FormApi.cjs
CHANGED
|
@@ -31,7 +31,7 @@ class FormApi {
|
|
|
31
31
|
this.options = {};
|
|
32
32
|
this.fieldInfo = {};
|
|
33
33
|
this.prevTransformArray = [];
|
|
34
|
-
this.
|
|
34
|
+
this.cumulativeFieldsErrorMap = {};
|
|
35
35
|
this.mount = () => {
|
|
36
36
|
const cleanupFieldMetaDerived = this.fieldMetaDerived.mount();
|
|
37
37
|
const cleanupStoreDerived = this.store.mount();
|
|
@@ -45,12 +45,16 @@ class FormApi {
|
|
|
45
45
|
return cleanup;
|
|
46
46
|
};
|
|
47
47
|
this.update = (options) => {
|
|
48
|
+
var _a2, _b;
|
|
48
49
|
if (!options) return;
|
|
49
50
|
const oldOptions = this.options;
|
|
50
51
|
this.options = options;
|
|
52
|
+
const shouldUpdateReeval = !!((_b = (_a2 = options.transform) == null ? void 0 : _a2.deps) == null ? void 0 : _b.some(
|
|
53
|
+
(val, i) => val !== this.prevTransformArray[i]
|
|
54
|
+
));
|
|
51
55
|
const shouldUpdateValues = options.defaultValues && !utils.shallow(options.defaultValues, oldOptions.defaultValues) && !this.state.isTouched;
|
|
52
56
|
const shouldUpdateState = !utils.shallow(options.defaultState, oldOptions.defaultState) && !this.state.isTouched;
|
|
53
|
-
if (!shouldUpdateValues && !shouldUpdateState) return;
|
|
57
|
+
if (!shouldUpdateValues && !shouldUpdateState && !shouldUpdateReeval) return;
|
|
54
58
|
store.batch(() => {
|
|
55
59
|
this.baseStore.setState(
|
|
56
60
|
() => getDefaultFormState(
|
|
@@ -60,7 +64,8 @@ class FormApi {
|
|
|
60
64
|
shouldUpdateState ? options.defaultState : {},
|
|
61
65
|
shouldUpdateValues ? {
|
|
62
66
|
values: options.defaultValues
|
|
63
|
-
} : {}
|
|
67
|
+
} : {},
|
|
68
|
+
shouldUpdateReeval ? { _force_re_eval: !this.state._force_re_eval } : {}
|
|
64
69
|
)
|
|
65
70
|
)
|
|
66
71
|
);
|
|
@@ -141,7 +146,7 @@ class FormApi {
|
|
|
141
146
|
this.validateSync = (cause) => {
|
|
142
147
|
const validates = utils.getSyncValidatorArray(cause, this.options);
|
|
143
148
|
let hasErrored = false;
|
|
144
|
-
const
|
|
149
|
+
const currentValidationErrorMap = {};
|
|
145
150
|
store.batch(() => {
|
|
146
151
|
var _a2;
|
|
147
152
|
for (const validateObj of validates) {
|
|
@@ -159,12 +164,13 @@ class FormApi {
|
|
|
159
164
|
const errorMapKey = getErrorMapKey(validateObj.cause);
|
|
160
165
|
if (fieldErrors) {
|
|
161
166
|
for (const [field, fieldError] of Object.entries(fieldErrors)) {
|
|
162
|
-
const oldErrorMap =
|
|
167
|
+
const oldErrorMap = this.cumulativeFieldsErrorMap[field] || {};
|
|
163
168
|
const newErrorMap = {
|
|
164
169
|
...oldErrorMap,
|
|
165
170
|
[errorMapKey]: fieldError
|
|
166
171
|
};
|
|
167
|
-
|
|
172
|
+
currentValidationErrorMap[field] = newErrorMap;
|
|
173
|
+
this.cumulativeFieldsErrorMap[field] = newErrorMap;
|
|
168
174
|
const fieldMeta = this.getFieldMeta(field);
|
|
169
175
|
if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {
|
|
170
176
|
this.setFieldMeta(field, (prev) => ({
|
|
@@ -177,9 +183,13 @@ class FormApi {
|
|
|
177
183
|
}
|
|
178
184
|
}
|
|
179
185
|
}
|
|
180
|
-
for (const field of Object.keys(this.
|
|
186
|
+
for (const field of Object.keys(this.cumulativeFieldsErrorMap)) {
|
|
181
187
|
const fieldMeta = this.getFieldMeta(field);
|
|
182
|
-
if ((fieldMeta == null ? void 0 : fieldMeta.errorMap[errorMapKey]) && !((_a2 =
|
|
188
|
+
if ((fieldMeta == null ? void 0 : fieldMeta.errorMap[errorMapKey]) && !((_a2 = currentValidationErrorMap[field]) == null ? void 0 : _a2[errorMapKey])) {
|
|
189
|
+
this.cumulativeFieldsErrorMap[field] = {
|
|
190
|
+
...this.cumulativeFieldsErrorMap[field],
|
|
191
|
+
[errorMapKey]: void 0
|
|
192
|
+
};
|
|
183
193
|
this.setFieldMeta(field, (prev) => ({
|
|
184
194
|
...prev,
|
|
185
195
|
errorMap: {
|
|
@@ -213,8 +223,7 @@ class FormApi {
|
|
|
213
223
|
}));
|
|
214
224
|
}
|
|
215
225
|
});
|
|
216
|
-
|
|
217
|
-
return { hasErrored, fieldsErrorMap: newFieldsErrorMap };
|
|
226
|
+
return { hasErrored, fieldsErrorMap: currentValidationErrorMap };
|
|
218
227
|
};
|
|
219
228
|
this.validateAsync = async (cause) => {
|
|
220
229
|
const validates = utils.getAsyncValidatorArray(cause, this.options);
|
package/dist/cjs/FormApi.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormApi.cjs","sources":["../../src/FormApi.ts"],"sourcesContent":["import { Derived, Store, batch } from '@tanstack/store'\nimport {\n deleteBy,\n functionalUpdate,\n getAsyncValidatorArray,\n getBy,\n getSyncValidatorArray,\n isGlobalFormValidationError,\n isNonEmptyArray,\n setBy,\n shallow,\n} from './utils'\nimport {\n isStandardSchemaValidator,\n standardSchemaValidators,\n} from './standardSchemaValidator'\nimport { metaHelper } from './metaHelper'\nimport type {\n StandardSchemaV1,\n StandardSchemaV1Issue,\n TStandardSchemaValidatorValue,\n} from './standardSchemaValidator'\nimport type { AnyFieldMeta, AnyFieldMetaBase, FieldApi } from './FieldApi'\nimport type {\n FormValidationError,\n FormValidationErrorMap,\n UpdateMetaOptions,\n ValidationCause,\n ValidationError,\n ValidationErrorMap,\n ValidationErrorMapKeys,\n} from './types'\nimport type { DeepKeys, DeepValue } from './util-types'\nimport type { Updater } from './utils'\n\n/**\n * @private\n */\n// TODO: Add the `Unwrap` type to the errors\ntype FormErrorMapFromValidator<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = Partial<\n Record<\n DeepKeys<TFormData>,\n ValidationErrorMap<\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n >\n>\n\nexport type FormValidateFn<TFormData> = (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n // This is technically an edge-type; which we try to keep non-`any`, but in this case\n // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n}) => unknown\n\n/**\n * @private\n */\nexport type FormValidateOrFn<TFormData> =\n | FormValidateFn<TFormData>\n | StandardSchemaV1<TFormData, unknown>\n\nexport type UnwrapFormValidateOrFn<\n TValidateOrFn extends undefined | FormValidateOrFn<any>,\n> = [TValidateOrFn] extends [FormValidateFn<any>]\n ? ReturnType<TValidateOrFn>\n : [TValidateOrFn] extends [StandardSchemaV1<any, any>]\n ? Record<string, StandardSchemaV1Issue[]>\n : undefined\n\n/**\n * @private\n */\nexport type FormValidateAsyncFn<TFormData> = (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n // This is technically an edge-type; which we try to keep non-`any`, but in this case\n // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n signal: AbortSignal\n}) => unknown | Promise<unknown>\n\nexport type FormValidator<TFormData, TType, TFn = unknown> = {\n validate(options: { value: TType }, fn: TFn): ValidationError\n validateAsync(\n options: { value: TType },\n fn: TFn,\n ): Promise<FormValidationError<TFormData>>\n}\n\ntype ValidationPromiseResult<TFormData> =\n | {\n fieldErrors: Partial<Record<DeepKeys<TFormData>, ValidationError>>\n errorMapKey: ValidationErrorMapKeys\n }\n | undefined\n\n/**\n * @private\n */\nexport type FormAsyncValidateOrFn<TFormData> =\n | FormValidateAsyncFn<TFormData>\n | StandardSchemaV1<TFormData, unknown>\n\nexport type UnwrapFormAsyncValidateOrFn<\n TValidateOrFn extends undefined | FormAsyncValidateOrFn<any>,\n> = [TValidateOrFn] extends [FormValidateAsyncFn<any>]\n ? Awaited<ReturnType<TValidateOrFn>>\n : [TValidateOrFn] extends [StandardSchemaV1<any, any>]\n ? Record<string, StandardSchemaV1Issue[]>\n : undefined\n\nexport interface FormValidators<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n> {\n /**\n * Optional function that fires as soon as the component mounts.\n */\n onMount?: TOnMount\n /**\n * Optional function that checks the validity of your data whenever a value changes\n */\n onChange?: TOnChange\n /**\n * Optional onChange asynchronous counterpart to onChange. Useful for more complex validation logic that might involve server requests.\n */\n onChangeAsync?: TOnChangeAsync\n /**\n * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds.\n */\n onChangeAsyncDebounceMs?: number\n /**\n * Optional function that validates the form data when a field loses focus, returns a `FormValidationError`\n */\n onBlur?: TOnBlur\n /**\n * Optional onBlur asynchronous validation method for when a field loses focus returns a ` FormValidationError` or a promise of `Promise<FormValidationError>`\n */\n onBlurAsync?: TOnBlurAsync\n /**\n * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds.\n */\n onBlurAsyncDebounceMs?: number\n onSubmit?: TOnSubmit\n onSubmitAsync?: TOnSubmitAsync\n}\n\n/**\n * @private\n */\nexport interface FormTransform<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n fn: (\n formBase: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) => FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n deps: unknown[]\n}\n\n/**\n * An object representing the options for a form.\n */\nexport interface FormOptions<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n /**\n * Set initial values for your form.\n */\n defaultValues?: TFormData\n /**\n * The default state for the form.\n */\n defaultState?: Partial<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n /**\n * If true, always run async validation, even when sync validation has produced an error. Defaults to undefined.\n */\n asyncAlways?: boolean\n /**\n * Optional time in milliseconds if you want to introduce a delay before firing off an async action.\n */\n asyncDebounceMs?: number\n /**\n * A list of validators to pass to the form\n */\n validators?: FormValidators<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n\n /**\n * onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props\n */\n onSubmitMeta?: TSubmitMeta\n\n /**\n * A function to be called when the form is submitted, what should happen once the user submits a valid form returns `any` or a promise `Promise<any>`\n */\n onSubmit?: (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n meta: TSubmitMeta\n }) => any | Promise<any>\n /**\n * Specify an action for scenarios where the user tries to submit an invalid form.\n */\n onSubmitInvalid?: (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n }) => void\n transform?: FormTransform<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n}\n\n/**\n * An object representing the validation metadata for a field. Not intended for public usage.\n */\nexport type ValidationMeta = {\n /**\n * An abort controller stored in memory to cancel previous async validation attempts.\n */\n lastAbortController: AbortController\n}\n\n/**\n * An object representing the field information for a specific field within the form.\n */\nexport type FieldInfo<TFormData> = {\n /**\n * An instance of the FieldAPI.\n */\n instance: FieldApi<\n TFormData,\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 any,\n any,\n any,\n any,\n any,\n any\n > | null\n /**\n * A record of field validation internal handling.\n */\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n}\n\n/**\n * An object representing the current state of the form.\n */\nexport type BaseFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = {\n /**\n * The current values of the form fields.\n */\n values: TFormData\n /**\n * The error map for the form itself.\n */\n errorMap: FormValidationErrorMap<\n UnwrapFormValidateOrFn<TOnMount>,\n UnwrapFormValidateOrFn<TOnChange>,\n UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,\n UnwrapFormValidateOrFn<TOnBlur>,\n UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,\n UnwrapFormValidateOrFn<TOnSubmit>,\n UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,\n UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n /**\n * An internal mechanism used for keeping track of validation logic in a form.\n */\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n /**\n * A record of field metadata for each field in the form, not including the derived properties, like `errors` and such\n */\n fieldMetaBase: Record<DeepKeys<TFormData>, AnyFieldMetaBase>\n /**\n * A boolean indicating if the form is currently in the process of being submitted after `handleSubmit` is called.\n *\n * Goes back to `false` when submission completes for one of the following reasons:\n * - the validation step returned errors.\n * - the `onSubmit` function has completed.\n *\n * Note: if you're running async operations in your `onSubmit` function make sure to await them to ensure `isSubmitting` is set to `false` only when the async operation completes.\n *\n * This is useful for displaying loading indicators or disabling form inputs during submission.\n *\n */\n isSubmitting: boolean\n /**\n * A boolean indicating if the form has been submitted.\n */\n isSubmitted: boolean\n /**\n * A boolean indicating if the form or any of its fields are currently validating.\n */\n isValidating: boolean\n /**\n * A counter for tracking the number of submission attempts.\n */\n submissionAttempts: number\n}\n\nexport type DerivedFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = {\n /**\n * A boolean indicating if the form is currently validating.\n */\n isFormValidating: boolean\n /**\n * A boolean indicating if the form is valid.\n */\n isFormValid: boolean\n /**\n * The error array for the form itself.\n */\n errors: Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n /**\n * A boolean indicating if any of the form fields are currently validating.\n */\n isFieldsValidating: boolean\n /**\n * A boolean indicating if all the form fields are valid.\n */\n isFieldsValid: boolean\n /**\n * A boolean indicating if any of the form fields have been touched.\n */\n isTouched: boolean\n /**\n * A boolean indicating if any of the form fields have been blurred.\n */\n isBlurred: boolean\n /**\n * A boolean indicating if any of the form's fields' values have been modified by the user. `True` if the user have modified at least one of the fields. Opposite of `isPristine`.\n */\n isDirty: boolean\n /**\n * A boolean indicating if none of the form's fields' values have been modified by the user. `True` if the user have not modified any of the fields. Opposite of `isDirty`.\n */\n isPristine: boolean\n /**\n * A boolean indicating if the form and all its fields are valid.\n */\n isValid: boolean\n /**\n * A boolean indicating if the form can be submitted based on its current state.\n */\n canSubmit: boolean\n /**\n * A record of field metadata for each field in the form.\n */\n fieldMeta: Record<DeepKeys<TFormData>, AnyFieldMeta>\n}\n\nexport type FormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n> &\n DerivedFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n\nexport type AnyFormState = FormState<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\nfunction getDefaultFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n>(\n defaultState: Partial<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >,\n): BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n> {\n return {\n values: defaultState.values ?? ({} as never),\n errorMap: defaultState.errorMap ?? {},\n fieldMetaBase: defaultState.fieldMetaBase ?? ({} as never),\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n validationMetaMap: defaultState.validationMetaMap ?? {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n }\n}\n\n/**\n * @public\n *\n * A type representing the Form API with all generics set to `any` for convenience.\n */\nexport type AnyFormApi = FormApi<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\n/**\n * A class representing the Form API. It handles the logic and interactions with the form state.\n *\n * Normally, you will not need to create a new `FormApi` instance directly. Instead, you will use a framework\n * hook/function like `useForm` or `createForm` to create a new instance for you that uses your framework's reactivity model.\n * However, if you need to create a new instance manually, you can do so by calling the `new FormApi` constructor.\n */\nexport class FormApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n /**\n * The options for the form.\n */\n options: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n > = {}\n baseStore!: Store<\n BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n fieldMetaDerived!: Derived<Record<DeepKeys<TFormData>, AnyFieldMeta>>\n store!: Derived<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n /**\n * A record of field information for each field in the form.\n */\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>> = {} as any\n\n get state() {\n return this.store.state\n }\n\n /**\n * @private\n */\n prevTransformArray: unknown[] = []\n\n /**\n * @private map of errors originated from form level validators\n */\n prevFieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n\n /**\n * Constructs a new `FormApi` instance with the given form options.\n */\n constructor(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) {\n this.baseStore = new Store(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n )\n\n this.fieldMetaDerived = new Derived({\n deps: [this.baseStore],\n fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => {\n const prevVal = _prevVal as\n | Record<DeepKeys<TFormData>, AnyFieldMeta>\n | undefined\n const prevBaseStore = prevDepVals?.[0]\n const currBaseStore = currDepVals[0]\n\n let originalMetaCount = 0\n\n const fieldMeta = {} as FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >['fieldMeta']\n\n for (const fieldName of Object.keys(\n currBaseStore.fieldMetaBase,\n ) as Array<keyof typeof currBaseStore.fieldMetaBase>) {\n const currBaseVal = currBaseStore.fieldMetaBase[\n fieldName as never\n ] as AnyFieldMetaBase\n\n const prevBaseVal = prevBaseStore?.fieldMetaBase[\n fieldName as never\n ] as AnyFieldMetaBase | undefined\n\n const prevFieldInfo =\n prevVal?.[fieldName as never as keyof typeof prevVal]\n\n let fieldErrors = prevFieldInfo?.errors\n if (!prevBaseVal || currBaseVal.errorMap !== prevBaseVal.errorMap) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n fieldErrors = Object.values(currBaseVal.errorMap ?? {}).filter(\n (val) => val !== undefined,\n ) as never\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const fieldInstance = this.getFieldInfo(fieldName)?.instance\n\n if (fieldInstance && !fieldInstance.options.disableErrorFlat) {\n fieldErrors = (fieldErrors as undefined | string[])?.flat(\n 1,\n ) as never\n }\n }\n\n // As a primitive, we don't need to aggressively persist the same referential value for performance reasons\n const isFieldPristine = !currBaseVal.isDirty\n\n if (\n prevFieldInfo &&\n prevFieldInfo.isPristine === isFieldPristine &&\n prevFieldInfo.errors === fieldErrors &&\n currBaseVal === prevBaseVal\n ) {\n fieldMeta[fieldName] = prevFieldInfo\n originalMetaCount++\n continue\n }\n\n fieldMeta[fieldName] = {\n ...currBaseVal,\n errors: fieldErrors,\n isPristine: isFieldPristine,\n } as AnyFieldMeta\n }\n\n if (\n prevVal &&\n originalMetaCount === Object.keys(currBaseStore.fieldMetaBase).length\n ) {\n return prevVal\n }\n\n return fieldMeta\n },\n })\n\n this.store = new Derived({\n deps: [this.baseStore, this.fieldMetaDerived],\n fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => {\n const prevVal = _prevVal as\n | FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n | undefined\n const prevBaseStore = prevDepVals?.[0]\n const currBaseStore = currDepVals[0]\n\n // Computed state\n const fieldMetaValues = Object.values(currBaseStore.fieldMetaBase) as (\n | AnyFieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some(\n (field) =>\n field?.errorMap &&\n isNonEmptyArray(Object.values(field.errorMap).filter(Boolean)),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n const isBlurred = fieldMetaValues.some((field) => field?.isBlurred)\n\n const shouldInvalidateOnMount =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n isTouched && currBaseStore?.errorMap?.onMount\n\n const isDirty = fieldMetaValues.some((field) => field?.isDirty)\n const isPristine = !isDirty\n\n const hasOnMountError = Boolean(\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n currBaseStore.errorMap?.onMount ||\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n fieldMetaValues.some((f) => f?.errorMap?.onMount),\n )\n\n const isValidating = !!isFieldsValidating\n\n // As `errors` is not a primitive, we need to aggressively persist the same referencial value for performance reasons\n let errors = prevVal?.errors ?? []\n if (\n !prevBaseStore ||\n currBaseStore.errorMap !== prevBaseStore.errorMap\n ) {\n errors = Object.values(currBaseStore.errorMap).reduce<\n Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n >((prev, curr) => {\n if (curr === undefined) return prev\n\n if (curr && isGlobalFormValidationError(curr)) {\n prev.push(curr.form as never)\n return prev\n }\n prev.push(curr as never)\n return prev\n }, [])\n }\n\n const isFormValid = errors.length === 0\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (currBaseStore.submissionAttempts === 0 &&\n !isTouched &&\n !hasOnMountError) ||\n (!isValidating && !currBaseStore.isSubmitting && isValid)\n\n let errorMap = currBaseStore.errorMap\n if (shouldInvalidateOnMount) {\n errors = errors.filter(\n (err) => err !== currBaseStore.errorMap.onMount,\n )\n errorMap = Object.assign(errorMap, { onMount: undefined })\n }\n\n if (\n prevVal &&\n prevBaseStore &&\n prevVal.errorMap === errorMap &&\n prevVal.fieldMeta === this.fieldMetaDerived.state &&\n prevVal.errors === errors &&\n prevVal.isFieldsValidating === isFieldsValidating &&\n prevVal.isFieldsValid === isFieldsValid &&\n prevVal.isFormValid === isFormValid &&\n prevVal.isValid === isValid &&\n prevVal.canSubmit === canSubmit &&\n prevVal.isTouched === isTouched &&\n prevVal.isBlurred === isBlurred &&\n prevVal.isPristine === isPristine &&\n prevVal.isDirty === isDirty &&\n shallow(prevBaseStore, currBaseStore)\n ) {\n return prevVal\n }\n\n let state = {\n ...currBaseStore,\n errorMap,\n fieldMeta: this.fieldMetaDerived.state,\n errors,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n isBlurred,\n isPristine,\n isDirty,\n } as FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n\n // Only run transform if state has shallowly changed - IE how React.useEffect works\n const transformArray = this.options.transform?.deps ?? []\n const shouldTransform =\n transformArray.length !== this.prevTransformArray.length ||\n transformArray.some((val, i) => val !== this.prevTransformArray[i])\n\n if (shouldTransform) {\n const newObj = Object.assign({}, this, { state })\n // This mutates the state\n this.options.transform?.fn(newObj)\n state = newObj.state\n this.prevTransformArray = transformArray\n }\n\n return state\n },\n })\n\n this.handleSubmit = this.handleSubmit.bind(this)\n\n this.update(opts || {})\n }\n\n /**\n * @private\n */\n runValidator<\n TValue extends TStandardSchemaValidatorValue<TFormData> & {\n formApi: AnyFormApi\n },\n TType extends 'validate' | 'validateAsync',\n >(props: {\n validate: TType extends 'validate'\n ? FormValidateOrFn<TFormData>\n : FormAsyncValidateOrFn<TFormData>\n value: TValue\n type: TType\n }): unknown {\n if (isStandardSchemaValidator(props.validate)) {\n return standardSchemaValidators[props.type](\n props.value,\n props.validate,\n ) as never\n }\n\n return (props.validate as FormValidateFn<any>)(props.value) as never\n }\n\n mount = () => {\n const cleanupFieldMetaDerived = this.fieldMetaDerived.mount()\n const cleanupStoreDerived = this.store.mount()\n const cleanup = () => {\n cleanupFieldMetaDerived()\n cleanupStoreDerived()\n }\n const { onMount } = this.options.validators || {}\n if (!onMount) return cleanup\n this.validateSync('mount')\n\n return cleanup\n }\n\n /**\n * Updates the form options and form state.\n */\n update = (\n options?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) => {\n if (!options) return\n\n const oldOptions = this.options\n\n // Options need to be updated first so that when the store is updated, the state is correct for the derived state\n this.options = options\n\n const shouldUpdateValues =\n options.defaultValues &&\n !shallow(options.defaultValues, oldOptions.defaultValues) &&\n !this.state.isTouched\n\n const shouldUpdateState =\n !shallow(options.defaultState, oldOptions.defaultState) &&\n !this.state.isTouched\n\n if (!shouldUpdateValues && !shouldUpdateState) return\n\n batch(() => {\n this.baseStore.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n\n shouldUpdateState ? options.defaultState : {},\n\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n ),\n ),\n )\n })\n }\n\n /**\n * Resets the form state to the default values.\n * If values are provided, the form will be reset to those values instead and the default values will be updated.\n *\n * @param values - Optional values to reset the form to.\n * @param opts - Optional options to control the reset behavior.\n */\n reset = (values?: TFormData, opts?: { keepDefaultValues?: boolean }) => {\n const { fieldMeta: currentFieldMeta } = this.state\n const fieldMetaBase = this.resetFieldMeta(currentFieldMeta)\n\n if (values && !opts?.keepDefaultValues) {\n this.options = {\n ...this.options,\n defaultValues: values,\n }\n }\n\n this.baseStore.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values:\n values ??\n this.options.defaultValues ??\n this.options.defaultState?.values,\n fieldMetaBase,\n }),\n )\n }\n\n /**\n * Validates all fields using the correct handlers for a given validation cause.\n */\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<any>[]).forEach(\n (field) => {\n if (!field.instance) return\n const fieldInstance = field.instance\n // Validate the field\n fieldValidationPromises.push(\n // Remember, `validate` is either a sync operation or a promise\n Promise.resolve().then(() =>\n fieldInstance.validate(cause, { skipFormValidation: true }),\n ),\n )\n // If any fields are not touched\n if (!field.instance.state.meta.isTouched) {\n // Mark them as touched\n field.instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n },\n )\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\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 <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n cause: ValidationCause,\n ) => {\n const currentValue = this.getFieldValue(field)\n\n const lastIndex = Array.isArray(currentValue)\n ? Math.max(currentValue.length - 1, 0)\n : null\n\n // We have to validate all fields that have shifted (at least the current field)\n const fieldKeysToValidate = [`${field}[${index}]`]\n for (let i = index + 1; i <= (lastIndex ?? 0); i++) {\n fieldKeysToValidate.push(`${field}[${i}]`)\n }\n\n // We also have to include all fields that are nested in the shifted fields\n const fieldsToValidate = Object.keys(this.fieldInfo).filter((fieldKey) =>\n fieldKeysToValidate.some((key) => fieldKey.startsWith(key)),\n ) as DeepKeys<TFormData>[]\n\n // Validate the fields\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n batch(() => {\n fieldsToValidate.forEach((nestedField) => {\n fieldValidationPromises.push(\n Promise.resolve().then(() => this.validateField(nestedField, cause)),\n )\n })\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\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<TFormData>>(\n field: TField,\n cause: ValidationCause,\n ) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const fieldInstance = this.fieldInfo[field]?.instance\n if (!fieldInstance) return []\n\n // If the field is not touched (same logic as in validateAllFields)\n if (!fieldInstance.state.meta.isTouched) {\n // Mark it as touched\n fieldInstance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n\n return fieldInstance.validate(cause)\n }\n\n /**\n * TODO: This code is copied from FieldApi, we should refactor to share\n * @private\n */\n validateSync = (\n cause: ValidationCause,\n ): {\n hasErrored: boolean\n fieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n } => {\n const validates = getSyncValidatorArray(cause, this.options)\n let hasErrored = false as boolean\n\n const newFieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n\n batch(() => {\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n\n const rawError = this.runValidator({\n validate: validateObj.validate,\n value: {\n value: this.state.values,\n formApi: this,\n validationSource: 'form',\n },\n type: 'validate',\n })\n\n const { formError, fieldErrors } = normalizeError<TFormData>(rawError)\n\n const errorMapKey = getErrorMapKey(validateObj.cause)\n\n if (fieldErrors) {\n for (const [field, fieldError] of Object.entries(fieldErrors)) {\n const oldErrorMap =\n newFieldsErrorMap[field as DeepKeys<TFormData>] || {}\n const newErrorMap = {\n ...oldErrorMap,\n [errorMapKey]: fieldError,\n }\n newFieldsErrorMap[field as DeepKeys<TFormData>] = newErrorMap\n\n const fieldMeta = this.getFieldMeta(field as DeepKeys<TFormData>)\n if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {\n this.setFieldMeta(field as DeepKeys<TFormData>, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: fieldError,\n },\n }))\n }\n }\n }\n\n for (const field of Object.keys(this.prevFieldsErrorMap) as Array<\n DeepKeys<TFormData>\n >) {\n const fieldMeta = this.getFieldMeta(field)\n if (\n fieldMeta?.errorMap[errorMapKey] &&\n !newFieldsErrorMap[field]?.[errorMapKey]\n ) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: undefined,\n },\n }))\n }\n }\n\n if (this.state.errorMap[errorMapKey] !== formError) {\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: formError,\n },\n }))\n }\n\n if (formError || fieldErrors) {\n hasErrored = true\n }\n }\n\n /**\n * when we have an error for onSubmit in the state, we want\n * to clear the error as soon as the user enters a valid value in the field\n */\n const submitErrKey = getErrorMapKey('submit')\n if (\n this.state.errorMap[submitErrKey] &&\n cause !== 'submit' &&\n !hasErrored\n ) {\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [submitErrKey]: undefined,\n },\n }))\n }\n })\n\n this.prevFieldsErrorMap = newFieldsErrorMap\n\n return { hasErrored, fieldsErrorMap: newFieldsErrorMap }\n }\n\n /**\n * @private\n */\n validateAsync = async (\n cause: ValidationCause,\n ): Promise<\n FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n > => {\n const validates = getAsyncValidatorArray(cause, this.options)\n\n if (!this.state.isFormValidating) {\n this.baseStore.setState((prev) => ({ ...prev, isFormValidating: true }))\n }\n\n /**\n * We have to use a for loop and generate our promises this way, otherwise it won't be sync\n * when there are no validators needed to be run\n */\n const promises: Promise<ValidationPromiseResult<TFormData>>[] = []\n\n let fieldErrors:\n | Partial<Record<DeepKeys<TFormData>, ValidationError>>\n | undefined\n\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n const key = getErrorMapKey(validateObj.cause)\n const fieldValidatorMeta = this.state.validationMetaMap[key]\n\n fieldValidatorMeta?.lastAbortController.abort()\n const controller = new AbortController()\n\n this.state.validationMetaMap[key] = {\n lastAbortController: controller,\n }\n\n promises.push(\n new Promise<ValidationPromiseResult<TFormData>>(async (resolve) => {\n let rawError!:\n | ValidationError\n | FormValidationError<unknown>\n | undefined\n try {\n rawError = await new Promise((rawResolve, rawReject) => {\n setTimeout(async () => {\n if (controller.signal.aborted) return rawResolve(undefined)\n try {\n rawResolve(\n await this.runValidator({\n validate: validateObj.validate!,\n value: {\n value: this.state.values,\n formApi: this,\n validationSource: 'form',\n signal: controller.signal,\n },\n type: 'validateAsync',\n }),\n )\n } catch (e) {\n rawReject(e)\n }\n }, validateObj.debounceMs)\n })\n } catch (e: unknown) {\n rawError = e as ValidationError\n }\n const { formError, fieldErrors: fieldErrorsFromNormalizeError } =\n normalizeError<TFormData>(rawError)\n\n if (fieldErrorsFromNormalizeError) {\n fieldErrors = fieldErrors\n ? { ...fieldErrors, ...fieldErrorsFromNormalizeError }\n : fieldErrorsFromNormalizeError\n }\n const errorMapKey = getErrorMapKey(validateObj.cause)\n\n if (fieldErrors) {\n for (const [field, fieldError] of Object.entries(fieldErrors)) {\n const fieldMeta = this.getFieldMeta(field as DeepKeys<TFormData>)\n if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {\n this.setFieldMeta(field as DeepKeys<TFormData>, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: fieldError,\n },\n }))\n }\n }\n }\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: formError,\n },\n }))\n\n resolve(fieldErrors ? { fieldErrors, errorMapKey } : undefined)\n }),\n )\n }\n\n let results: ValidationPromiseResult<TFormData>[] = []\n\n const fieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n if (promises.length) {\n results = await Promise.all(promises)\n for (const fieldValidationResult of results) {\n if (fieldValidationResult?.fieldErrors) {\n const { errorMapKey } = fieldValidationResult\n\n for (const [field, fieldError] of Object.entries(\n fieldValidationResult.fieldErrors,\n )) {\n const oldErrorMap =\n fieldsErrorMap[field as DeepKeys<TFormData>] || {}\n const newErrorMap = {\n ...oldErrorMap,\n [errorMapKey]: fieldError,\n }\n fieldsErrorMap[field as DeepKeys<TFormData>] = newErrorMap\n }\n }\n }\n }\n\n this.baseStore.setState((prev) => ({\n ...prev,\n isFormValidating: false,\n }))\n\n return fieldsErrorMap\n }\n\n /**\n * @private\n */\n validate = (\n cause: ValidationCause,\n ):\n | FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n | Promise<\n FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n > => {\n // Attempt to sync validate first\n const { hasErrored, fieldsErrorMap } = this.validateSync(cause)\n\n if (hasErrored && !this.options.asyncAlways) {\n return fieldsErrorMap\n }\n\n // No error? Attempt async validation\n return this.validateAsync(cause)\n }\n\n /**\n * Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks.\n */\n handleSubmit(): Promise<void>\n handleSubmit(submitMeta: TSubmitMeta): Promise<void>\n async handleSubmit(submitMeta?: TSubmitMeta): Promise<void> {\n this.baseStore.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.baseStore.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n await this.validateAllFields('submit')\n\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n await this.validate('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<TFormData>[]).forEach(\n (field) => {\n field.instance?.options.listeners?.onSubmit?.({\n value: field.instance.state.value,\n fieldApi: field.instance,\n })\n },\n )\n })\n\n try {\n // Run the submit code\n await this.options.onSubmit?.({\n value: this.state.values,\n formApi: this,\n meta: submitMeta ?? this.options.onSubmitMeta,\n } as any)\n\n batch(() => {\n this.baseStore.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n /**\n * Gets the value of the specified field.\n */\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n /**\n * Gets the metadata of the specified field.\n */\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): AnyFieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n /**\n * Gets the field info of the specified field.\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 instance: null,\n validationMetaMap: {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n })\n }\n\n /**\n * Updates the metadata of the specified field.\n */\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<AnyFieldMeta>,\n ) => {\n this.baseStore.setState((prev) => {\n return {\n ...prev,\n fieldMetaBase: {\n ...prev.fieldMetaBase,\n [field]: functionalUpdate(\n updater,\n prev.fieldMetaBase[field] as never,\n ),\n },\n }\n })\n }\n\n resetFieldMeta = <TField extends DeepKeys<TFormData>>(\n fieldMeta: Record<TField, AnyFieldMeta>,\n ): Record<TField, AnyFieldMeta> => {\n return Object.keys(fieldMeta).reduce(\n (acc: Record<TField, AnyFieldMeta>, key) => {\n const fieldKey = key as TField\n acc[fieldKey] = {\n isValidating: false,\n isTouched: false,\n isBlurred: false,\n isDirty: false,\n isPristine: true,\n errors: [],\n errorMap: {},\n }\n return acc\n },\n {} as Record<TField, AnyFieldMeta>,\n )\n }\n\n /**\n * Sets the value of the specified field and optionally updates the touched state.\n */\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: UpdateMetaOptions,\n ) => {\n const dontUpdateMeta = opts?.dontUpdateMeta ?? false\n\n batch(() => {\n if (!dontUpdateMeta) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n isDirty: true,\n errorMap: {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n ...prev?.errorMap,\n onMount: undefined,\n },\n }))\n }\n\n this.baseStore.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n deleteField = <TField extends DeepKeys<TFormData>>(field: TField) => {\n this.baseStore.setState((prev) => {\n const newState = { ...prev }\n newState.values = deleteBy(newState.values, field)\n delete newState.fieldMetaBase[field]\n\n return newState\n })\n delete this.fieldInfo[field]\n }\n\n /**\n * Pushes a value into an array field.\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?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n this.validateField(field, 'change')\n }\n\n insertFieldValue = async <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?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return [\n ...(prev as DeepValue<TFormData, TField>[]).slice(0, index),\n value,\n ...(prev as DeepValue<TFormData, TField>[]).slice(index),\n ] as any\n },\n opts,\n )\n\n // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n\n // Shift down all meta after validating to make sure the new field has been mounted\n metaHelper(this).handleArrayFieldMetaShift(field, index, 'insert')\n\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Replaces a value into an array field at the specified index.\n */\n replaceFieldValue = async <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?: UpdateMetaOptions,\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 // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Removes a value from an array field at the specified index.\n */\n removeFieldValue = async <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: UpdateMetaOptions,\n ) => {\n const fieldValue = this.getFieldValue(field)\n\n const lastIndex = Array.isArray(fieldValue)\n ? Math.max(fieldValue.length - 1, 0)\n : null\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 // Shift up all meta\n metaHelper(this).handleArrayFieldMetaShift(field, index, 'remove')\n\n if (lastIndex !== null) {\n const start = `${field}[${lastIndex}]`\n const fieldsToDelete = Object.keys(this.fieldInfo).filter((f) =>\n f.startsWith(start),\n )\n\n // Cleanup the last fields\n fieldsToDelete.forEach((f) => this.deleteField(f as TField))\n }\n\n // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Swaps the values at the specified indices within an array field.\n */\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n },\n opts,\n )\n\n // Swap meta\n metaHelper(this).handleArrayFieldMetaShift(field, index1, 'swap', index2)\n\n // Validate the whole array\n this.validateField(field, 'change')\n // Validate the swapped fields\n this.validateField(`${field}[${index1}]` as DeepKeys<TFormData>, 'change')\n this.validateField(`${field}[${index2}]` as DeepKeys<TFormData>, 'change')\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 DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev: any) => {\n prev.splice(index2, 0, prev.splice(index1, 1)[0])\n return prev\n },\n opts,\n )\n\n // Move meta between index1 and index2\n metaHelper(this).handleArrayFieldMetaShift(field, index1, 'move', index2)\n\n // Validate the whole array\n this.validateField(field, 'change')\n // Validate the moved fields\n this.validateField(`${field}[${index1}]` as DeepKeys<TFormData>, 'change')\n this.validateField(`${field}[${index2}]` as DeepKeys<TFormData>, 'change')\n }\n /**\n * Updates the form's errorMap\n */\n setErrorMap(\n errorMap: ValidationErrorMap<\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >,\n ) {\n this.baseStore.setState(\n (prev) =>\n ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n ...errorMap,\n },\n }) as never,\n )\n }\n\n /**\n * Returns form and field level errors\n */\n getAllErrors = (): {\n form: {\n errors: Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n errorMap: FormValidationErrorMap<\n UnwrapFormValidateOrFn<TOnMount>,\n UnwrapFormValidateOrFn<TOnChange>,\n UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,\n UnwrapFormValidateOrFn<TOnBlur>,\n UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,\n UnwrapFormValidateOrFn<TOnSubmit>,\n UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,\n UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n }\n fields: Record<\n DeepKeys<TFormData>,\n { errors: ValidationError[]; errorMap: ValidationErrorMap }\n >\n } => {\n return {\n form: {\n errors: this.state.errors,\n errorMap: this.state.errorMap,\n },\n fields: Object.entries(this.state.fieldMeta).reduce(\n (acc, [fieldName, fieldMeta]) => {\n if (\n Object.keys(fieldMeta as AnyFieldMeta).length &&\n (fieldMeta as AnyFieldMeta).errors.length\n ) {\n acc[fieldName as DeepKeys<TFormData>] = {\n errors: (fieldMeta as AnyFieldMeta).errors,\n errorMap: (fieldMeta as AnyFieldMeta).errorMap,\n }\n }\n\n return acc\n },\n {} as Record<\n DeepKeys<TFormData>,\n { errors: ValidationError[]; errorMap: ValidationErrorMap }\n >,\n ),\n }\n }\n}\n\nfunction normalizeError<TFormData>(rawError?: FormValidationError<unknown>): {\n formError: ValidationError\n fieldErrors?: Partial<Record<DeepKeys<TFormData>, ValidationError>>\n} {\n if (rawError) {\n if (isGlobalFormValidationError(rawError)) {\n const formError = normalizeError(rawError.form).formError\n const fieldErrors = rawError.fields\n return { formError, fieldErrors } as never\n }\n\n return { formError: rawError }\n }\n\n return { formError: undefined }\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n case 'server':\n return 'onServer'\n case 'change':\n default:\n return 'onChange'\n }\n}\n"],"names":["shallow","batch","opts","_a","getSyncValidatorArray","getAsyncValidatorArray","getBy","functionalUpdate","setBy","deleteBy","metaHelper","Store","Derived","isNonEmptyArray","isGlobalFormValidationError","isStandardSchemaValidator","standardSchemaValidators","_c","_b"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormApi.cjs","sources":["../../src/FormApi.ts"],"sourcesContent":["import { Derived, Store, batch } from '@tanstack/store'\nimport {\n deleteBy,\n functionalUpdate,\n getAsyncValidatorArray,\n getBy,\n getSyncValidatorArray,\n isGlobalFormValidationError,\n isNonEmptyArray,\n setBy,\n shallow,\n} from './utils'\nimport {\n isStandardSchemaValidator,\n standardSchemaValidators,\n} from './standardSchemaValidator'\nimport { metaHelper } from './metaHelper'\nimport type {\n StandardSchemaV1,\n StandardSchemaV1Issue,\n TStandardSchemaValidatorValue,\n} from './standardSchemaValidator'\nimport type { AnyFieldMeta, AnyFieldMetaBase, FieldApi } from './FieldApi'\nimport type {\n FormValidationError,\n FormValidationErrorMap,\n UpdateMetaOptions,\n ValidationCause,\n ValidationError,\n ValidationErrorMap,\n ValidationErrorMapKeys,\n} from './types'\nimport type { DeepKeys, DeepValue } from './util-types'\nimport type { Updater } from './utils'\n\n/**\n * @private\n */\n// TODO: Add the `Unwrap` type to the errors\ntype FormErrorMapFromValidator<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = Partial<\n Record<\n DeepKeys<TFormData>,\n ValidationErrorMap<\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n >\n>\n\nexport type FormValidateFn<TFormData> = (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n // This is technically an edge-type; which we try to keep non-`any`, but in this case\n // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n}) => unknown\n\n/**\n * @private\n */\nexport type FormValidateOrFn<TFormData> =\n | FormValidateFn<TFormData>\n | StandardSchemaV1<TFormData, unknown>\n\nexport type UnwrapFormValidateOrFn<\n TValidateOrFn extends undefined | FormValidateOrFn<any>,\n> = [TValidateOrFn] extends [FormValidateFn<any>]\n ? ReturnType<TValidateOrFn>\n : [TValidateOrFn] extends [StandardSchemaV1<any, any>]\n ? Record<string, StandardSchemaV1Issue[]>\n : undefined\n\n/**\n * @private\n */\nexport type FormValidateAsyncFn<TFormData> = (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n // This is technically an edge-type; which we try to keep non-`any`, but in this case\n // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n signal: AbortSignal\n}) => unknown | Promise<unknown>\n\nexport type FormValidator<TFormData, TType, TFn = unknown> = {\n validate(options: { value: TType }, fn: TFn): ValidationError\n validateAsync(\n options: { value: TType },\n fn: TFn,\n ): Promise<FormValidationError<TFormData>>\n}\n\ntype ValidationPromiseResult<TFormData> =\n | {\n fieldErrors: Partial<Record<DeepKeys<TFormData>, ValidationError>>\n errorMapKey: ValidationErrorMapKeys\n }\n | undefined\n\n/**\n * @private\n */\nexport type FormAsyncValidateOrFn<TFormData> =\n | FormValidateAsyncFn<TFormData>\n | StandardSchemaV1<TFormData, unknown>\n\nexport type UnwrapFormAsyncValidateOrFn<\n TValidateOrFn extends undefined | FormAsyncValidateOrFn<any>,\n> = [TValidateOrFn] extends [FormValidateAsyncFn<any>]\n ? Awaited<ReturnType<TValidateOrFn>>\n : [TValidateOrFn] extends [StandardSchemaV1<any, any>]\n ? Record<string, StandardSchemaV1Issue[]>\n : undefined\n\nexport interface FormValidators<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n> {\n /**\n * Optional function that fires as soon as the component mounts.\n */\n onMount?: TOnMount\n /**\n * Optional function that checks the validity of your data whenever a value changes\n */\n onChange?: TOnChange\n /**\n * Optional onChange asynchronous counterpart to onChange. Useful for more complex validation logic that might involve server requests.\n */\n onChangeAsync?: TOnChangeAsync\n /**\n * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds.\n */\n onChangeAsyncDebounceMs?: number\n /**\n * Optional function that validates the form data when a field loses focus, returns a `FormValidationError`\n */\n onBlur?: TOnBlur\n /**\n * Optional onBlur asynchronous validation method for when a field loses focus returns a ` FormValidationError` or a promise of `Promise<FormValidationError>`\n */\n onBlurAsync?: TOnBlurAsync\n /**\n * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds.\n */\n onBlurAsyncDebounceMs?: number\n onSubmit?: TOnSubmit\n onSubmitAsync?: TOnSubmitAsync\n}\n\n/**\n * @private\n */\nexport interface FormTransform<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n fn: (\n formBase: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) => FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n deps: unknown[]\n}\n\n/**\n * An object representing the options for a form.\n */\nexport interface FormOptions<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n /**\n * Set initial values for your form.\n */\n defaultValues?: TFormData\n /**\n * The default state for the form.\n */\n defaultState?: Partial<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n /**\n * If true, always run async validation, even when sync validation has produced an error. Defaults to undefined.\n */\n asyncAlways?: boolean\n /**\n * Optional time in milliseconds if you want to introduce a delay before firing off an async action.\n */\n asyncDebounceMs?: number\n /**\n * A list of validators to pass to the form\n */\n validators?: FormValidators<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n\n /**\n * onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props\n */\n onSubmitMeta?: TSubmitMeta\n\n /**\n * A function to be called when the form is submitted, what should happen once the user submits a valid form returns `any` or a promise `Promise<any>`\n */\n onSubmit?: (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n meta: TSubmitMeta\n }) => any | Promise<any>\n /**\n * Specify an action for scenarios where the user tries to submit an invalid form.\n */\n onSubmitInvalid?: (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n }) => void\n transform?: FormTransform<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n}\n\n/**\n * An object representing the validation metadata for a field. Not intended for public usage.\n */\nexport type ValidationMeta = {\n /**\n * An abort controller stored in memory to cancel previous async validation attempts.\n */\n lastAbortController: AbortController\n}\n\n/**\n * An object representing the field information for a specific field within the form.\n */\nexport type FieldInfo<TFormData> = {\n /**\n * An instance of the FieldAPI.\n */\n instance: FieldApi<\n TFormData,\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 any,\n any,\n any,\n any,\n any,\n any\n > | null\n /**\n * A record of field validation internal handling.\n */\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n}\n\n/**\n * An object representing the current state of the form.\n */\nexport type BaseFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = {\n /**\n * The current values of the form fields.\n */\n values: TFormData\n /**\n * The error map for the form itself.\n */\n errorMap: FormValidationErrorMap<\n UnwrapFormValidateOrFn<TOnMount>,\n UnwrapFormValidateOrFn<TOnChange>,\n UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,\n UnwrapFormValidateOrFn<TOnBlur>,\n UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,\n UnwrapFormValidateOrFn<TOnSubmit>,\n UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,\n UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n /**\n * An internal mechanism used for keeping track of validation logic in a form.\n */\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n /**\n * A record of field metadata for each field in the form, not including the derived properties, like `errors` and such\n */\n fieldMetaBase: Record<DeepKeys<TFormData>, AnyFieldMetaBase>\n /**\n * A boolean indicating if the form is currently in the process of being submitted after `handleSubmit` is called.\n *\n * Goes back to `false` when submission completes for one of the following reasons:\n * - the validation step returned errors.\n * - the `onSubmit` function has completed.\n *\n * Note: if you're running async operations in your `onSubmit` function make sure to await them to ensure `isSubmitting` is set to `false` only when the async operation completes.\n *\n * This is useful for displaying loading indicators or disabling form inputs during submission.\n *\n */\n isSubmitting: boolean\n /**\n * A boolean indicating if the form has been submitted.\n */\n isSubmitted: boolean\n /**\n * A boolean indicating if the form or any of its fields are currently validating.\n */\n isValidating: boolean\n /**\n * A counter for tracking the number of submission attempts.\n */\n submissionAttempts: number\n /**\n * @private, used to force a re-evaluation of the form state when options change\n */\n _force_re_eval?: boolean\n}\n\nexport type DerivedFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = {\n /**\n * A boolean indicating if the form is currently validating.\n */\n isFormValidating: boolean\n /**\n * A boolean indicating if the form is valid.\n */\n isFormValid: boolean\n /**\n * The error array for the form itself.\n */\n errors: Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n /**\n * A boolean indicating if any of the form fields are currently validating.\n */\n isFieldsValidating: boolean\n /**\n * A boolean indicating if all the form fields are valid.\n */\n isFieldsValid: boolean\n /**\n * A boolean indicating if any of the form fields have been touched.\n */\n isTouched: boolean\n /**\n * A boolean indicating if any of the form fields have been blurred.\n */\n isBlurred: boolean\n /**\n * A boolean indicating if any of the form's fields' values have been modified by the user. `True` if the user have modified at least one of the fields. Opposite of `isPristine`.\n */\n isDirty: boolean\n /**\n * A boolean indicating if none of the form's fields' values have been modified by the user. `True` if the user have not modified any of the fields. Opposite of `isDirty`.\n */\n isPristine: boolean\n /**\n * A boolean indicating if the form and all its fields are valid.\n */\n isValid: boolean\n /**\n * A boolean indicating if the form can be submitted based on its current state.\n */\n canSubmit: boolean\n /**\n * A record of field metadata for each field in the form.\n */\n fieldMeta: Record<DeepKeys<TFormData>, AnyFieldMeta>\n}\n\nexport type FormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n> &\n DerivedFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n\nexport type AnyFormState = FormState<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\nfunction getDefaultFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n>(\n defaultState: Partial<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >,\n): BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n> {\n return {\n values: defaultState.values ?? ({} as never),\n errorMap: defaultState.errorMap ?? {},\n fieldMetaBase: defaultState.fieldMetaBase ?? ({} as never),\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n validationMetaMap: defaultState.validationMetaMap ?? {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n }\n}\n\n/**\n * @public\n *\n * A type representing the Form API with all generics set to `any` for convenience.\n */\nexport type AnyFormApi = FormApi<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\n/**\n * A class representing the Form API. It handles the logic and interactions with the form state.\n *\n * Normally, you will not need to create a new `FormApi` instance directly. Instead, you will use a framework\n * hook/function like `useForm` or `createForm` to create a new instance for you that uses your framework's reactivity model.\n * However, if you need to create a new instance manually, you can do so by calling the `new FormApi` constructor.\n */\nexport class FormApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n /**\n * The options for the form.\n */\n options: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n > = {}\n baseStore!: Store<\n BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n fieldMetaDerived!: Derived<Record<DeepKeys<TFormData>, AnyFieldMeta>>\n store!: Derived<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n /**\n * A record of field information for each field in the form.\n */\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>> = {} as any\n\n get state() {\n return this.store.state\n }\n\n /**\n * @private\n */\n prevTransformArray: unknown[] = []\n\n /**\n * @private Persistent store of all field validation errors originating from form-level validators.\n * Maintains the cumulative state across validation cycles, including cleared errors (undefined values).\n * This map preserves the complete validation state for all fields.\n */\n cumulativeFieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n\n /**\n * Constructs a new `FormApi` instance with the given form options.\n */\n constructor(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) {\n this.baseStore = new Store(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n )\n\n this.fieldMetaDerived = new Derived({\n deps: [this.baseStore],\n fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => {\n const prevVal = _prevVal as\n | Record<DeepKeys<TFormData>, AnyFieldMeta>\n | undefined\n const prevBaseStore = prevDepVals?.[0]\n const currBaseStore = currDepVals[0]\n\n let originalMetaCount = 0\n\n const fieldMeta = {} as FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >['fieldMeta']\n\n for (const fieldName of Object.keys(\n currBaseStore.fieldMetaBase,\n ) as Array<keyof typeof currBaseStore.fieldMetaBase>) {\n const currBaseVal = currBaseStore.fieldMetaBase[\n fieldName as never\n ] as AnyFieldMetaBase\n\n const prevBaseVal = prevBaseStore?.fieldMetaBase[\n fieldName as never\n ] as AnyFieldMetaBase | undefined\n\n const prevFieldInfo =\n prevVal?.[fieldName as never as keyof typeof prevVal]\n\n let fieldErrors = prevFieldInfo?.errors\n if (!prevBaseVal || currBaseVal.errorMap !== prevBaseVal.errorMap) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n fieldErrors = Object.values(currBaseVal.errorMap ?? {}).filter(\n (val) => val !== undefined,\n ) as never\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const fieldInstance = this.getFieldInfo(fieldName)?.instance\n\n if (fieldInstance && !fieldInstance.options.disableErrorFlat) {\n fieldErrors = (fieldErrors as undefined | string[])?.flat(\n 1,\n ) as never\n }\n }\n\n // As a primitive, we don't need to aggressively persist the same referential value for performance reasons\n const isFieldPristine = !currBaseVal.isDirty\n\n if (\n prevFieldInfo &&\n prevFieldInfo.isPristine === isFieldPristine &&\n prevFieldInfo.errors === fieldErrors &&\n currBaseVal === prevBaseVal\n ) {\n fieldMeta[fieldName] = prevFieldInfo\n originalMetaCount++\n continue\n }\n\n fieldMeta[fieldName] = {\n ...currBaseVal,\n errors: fieldErrors,\n isPristine: isFieldPristine,\n } as AnyFieldMeta\n }\n\n if (\n prevVal &&\n originalMetaCount === Object.keys(currBaseStore.fieldMetaBase).length\n ) {\n return prevVal\n }\n\n return fieldMeta\n },\n })\n\n this.store = new Derived({\n deps: [this.baseStore, this.fieldMetaDerived],\n fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => {\n const prevVal = _prevVal as\n | FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n | undefined\n const prevBaseStore = prevDepVals?.[0]\n const currBaseStore = currDepVals[0]\n\n // Computed state\n const fieldMetaValues = Object.values(currBaseStore.fieldMetaBase) as (\n | AnyFieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some(\n (field) =>\n field?.errorMap &&\n isNonEmptyArray(Object.values(field.errorMap).filter(Boolean)),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n const isBlurred = fieldMetaValues.some((field) => field?.isBlurred)\n\n const shouldInvalidateOnMount =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n isTouched && currBaseStore?.errorMap?.onMount\n\n const isDirty = fieldMetaValues.some((field) => field?.isDirty)\n const isPristine = !isDirty\n\n const hasOnMountError = Boolean(\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n currBaseStore.errorMap?.onMount ||\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n fieldMetaValues.some((f) => f?.errorMap?.onMount),\n )\n\n const isValidating = !!isFieldsValidating\n\n // As `errors` is not a primitive, we need to aggressively persist the same referencial value for performance reasons\n let errors = prevVal?.errors ?? []\n if (\n !prevBaseStore ||\n currBaseStore.errorMap !== prevBaseStore.errorMap\n ) {\n errors = Object.values(currBaseStore.errorMap).reduce<\n Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n >((prev, curr) => {\n if (curr === undefined) return prev\n\n if (curr && isGlobalFormValidationError(curr)) {\n prev.push(curr.form as never)\n return prev\n }\n prev.push(curr as never)\n return prev\n }, [])\n }\n\n const isFormValid = errors.length === 0\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (currBaseStore.submissionAttempts === 0 &&\n !isTouched &&\n !hasOnMountError) ||\n (!isValidating && !currBaseStore.isSubmitting && isValid)\n\n let errorMap = currBaseStore.errorMap\n if (shouldInvalidateOnMount) {\n errors = errors.filter(\n (err) => err !== currBaseStore.errorMap.onMount,\n )\n errorMap = Object.assign(errorMap, { onMount: undefined })\n }\n\n if (\n prevVal &&\n prevBaseStore &&\n prevVal.errorMap === errorMap &&\n prevVal.fieldMeta === this.fieldMetaDerived.state &&\n prevVal.errors === errors &&\n prevVal.isFieldsValidating === isFieldsValidating &&\n prevVal.isFieldsValid === isFieldsValid &&\n prevVal.isFormValid === isFormValid &&\n prevVal.isValid === isValid &&\n prevVal.canSubmit === canSubmit &&\n prevVal.isTouched === isTouched &&\n prevVal.isBlurred === isBlurred &&\n prevVal.isPristine === isPristine &&\n prevVal.isDirty === isDirty &&\n shallow(prevBaseStore, currBaseStore)\n ) {\n return prevVal\n }\n\n let state = {\n ...currBaseStore,\n errorMap,\n fieldMeta: this.fieldMetaDerived.state,\n errors,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n isBlurred,\n isPristine,\n isDirty,\n } as FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n\n // Only run transform if state has shallowly changed - IE how React.useEffect works\n const transformArray = this.options.transform?.deps ?? []\n const shouldTransform =\n transformArray.length !== this.prevTransformArray.length ||\n transformArray.some((val, i) => val !== this.prevTransformArray[i])\n\n if (shouldTransform) {\n const newObj = Object.assign({}, this, { state })\n // This mutates the state\n this.options.transform?.fn(newObj)\n state = newObj.state\n this.prevTransformArray = transformArray\n }\n\n return state\n },\n })\n\n this.handleSubmit = this.handleSubmit.bind(this)\n\n this.update(opts || {})\n }\n\n /**\n * @private\n */\n runValidator<\n TValue extends TStandardSchemaValidatorValue<TFormData> & {\n formApi: AnyFormApi\n },\n TType extends 'validate' | 'validateAsync',\n >(props: {\n validate: TType extends 'validate'\n ? FormValidateOrFn<TFormData>\n : FormAsyncValidateOrFn<TFormData>\n value: TValue\n type: TType\n }): unknown {\n if (isStandardSchemaValidator(props.validate)) {\n return standardSchemaValidators[props.type](\n props.value,\n props.validate,\n ) as never\n }\n\n return (props.validate as FormValidateFn<any>)(props.value) as never\n }\n\n mount = () => {\n const cleanupFieldMetaDerived = this.fieldMetaDerived.mount()\n const cleanupStoreDerived = this.store.mount()\n const cleanup = () => {\n cleanupFieldMetaDerived()\n cleanupStoreDerived()\n }\n const { onMount } = this.options.validators || {}\n if (!onMount) return cleanup\n this.validateSync('mount')\n\n return cleanup\n }\n\n /**\n * Updates the form options and form state.\n */\n update = (\n options?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) => {\n if (!options) return\n\n const oldOptions = this.options\n\n // Options need to be updated first so that when the store is updated, the state is correct for the derived state\n this.options = options\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const shouldUpdateReeval = !!options.transform?.deps?.some(\n (val, i) => val !== this.prevTransformArray[i],\n )\n\n const shouldUpdateValues =\n options.defaultValues &&\n !shallow(options.defaultValues, oldOptions.defaultValues) &&\n !this.state.isTouched\n\n const shouldUpdateState =\n !shallow(options.defaultState, oldOptions.defaultState) &&\n !this.state.isTouched\n\n if (!shouldUpdateValues && !shouldUpdateState && !shouldUpdateReeval) return\n\n batch(() => {\n this.baseStore.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n\n shouldUpdateState ? options.defaultState : {},\n\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n\n shouldUpdateReeval\n ? { _force_re_eval: !this.state._force_re_eval }\n : {},\n ),\n ),\n )\n })\n }\n\n /**\n * Resets the form state to the default values.\n * If values are provided, the form will be reset to those values instead and the default values will be updated.\n *\n * @param values - Optional values to reset the form to.\n * @param opts - Optional options to control the reset behavior.\n */\n reset = (values?: TFormData, opts?: { keepDefaultValues?: boolean }) => {\n const { fieldMeta: currentFieldMeta } = this.state\n const fieldMetaBase = this.resetFieldMeta(currentFieldMeta)\n\n if (values && !opts?.keepDefaultValues) {\n this.options = {\n ...this.options,\n defaultValues: values,\n }\n }\n\n this.baseStore.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values:\n values ??\n this.options.defaultValues ??\n this.options.defaultState?.values,\n fieldMetaBase,\n }),\n )\n }\n\n /**\n * Validates all fields using the correct handlers for a given validation cause.\n */\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<any>[]).forEach(\n (field) => {\n if (!field.instance) return\n const fieldInstance = field.instance\n // Validate the field\n fieldValidationPromises.push(\n // Remember, `validate` is either a sync operation or a promise\n Promise.resolve().then(() =>\n fieldInstance.validate(cause, { skipFormValidation: true }),\n ),\n )\n // If any fields are not touched\n if (!field.instance.state.meta.isTouched) {\n // Mark them as touched\n field.instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n },\n )\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\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 <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n cause: ValidationCause,\n ) => {\n const currentValue = this.getFieldValue(field)\n\n const lastIndex = Array.isArray(currentValue)\n ? Math.max(currentValue.length - 1, 0)\n : null\n\n // We have to validate all fields that have shifted (at least the current field)\n const fieldKeysToValidate = [`${field}[${index}]`]\n for (let i = index + 1; i <= (lastIndex ?? 0); i++) {\n fieldKeysToValidate.push(`${field}[${i}]`)\n }\n\n // We also have to include all fields that are nested in the shifted fields\n const fieldsToValidate = Object.keys(this.fieldInfo).filter((fieldKey) =>\n fieldKeysToValidate.some((key) => fieldKey.startsWith(key)),\n ) as DeepKeys<TFormData>[]\n\n // Validate the fields\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n batch(() => {\n fieldsToValidate.forEach((nestedField) => {\n fieldValidationPromises.push(\n Promise.resolve().then(() => this.validateField(nestedField, cause)),\n )\n })\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\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<TFormData>>(\n field: TField,\n cause: ValidationCause,\n ) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const fieldInstance = this.fieldInfo[field]?.instance\n if (!fieldInstance) return []\n\n // If the field is not touched (same logic as in validateAllFields)\n if (!fieldInstance.state.meta.isTouched) {\n // Mark it as touched\n fieldInstance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n\n return fieldInstance.validate(cause)\n }\n\n /**\n * TODO: This code is copied from FieldApi, we should refactor to share\n * @private\n */\n validateSync = (\n cause: ValidationCause,\n ): {\n hasErrored: boolean\n fieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n } => {\n const validates = getSyncValidatorArray(cause, this.options)\n let hasErrored = false as boolean\n\n // This map will only include fields that have errors in the current validation cycle\n const currentValidationErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n\n batch(() => {\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n\n const rawError = this.runValidator({\n validate: validateObj.validate,\n value: {\n value: this.state.values,\n formApi: this,\n validationSource: 'form',\n },\n type: 'validate',\n })\n\n const { formError, fieldErrors } = normalizeError<TFormData>(rawError)\n\n const errorMapKey = getErrorMapKey(validateObj.cause)\n\n if (fieldErrors) {\n for (const [field, fieldError] of Object.entries(fieldErrors) as [\n DeepKeys<TFormData>,\n ValidationError,\n ][]) {\n const oldErrorMap = this.cumulativeFieldsErrorMap[field] || {}\n const newErrorMap = {\n ...oldErrorMap,\n [errorMapKey]: fieldError,\n }\n currentValidationErrorMap[field] = newErrorMap\n this.cumulativeFieldsErrorMap[field] = newErrorMap\n\n const fieldMeta = this.getFieldMeta(field)\n if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: fieldError,\n },\n }))\n }\n }\n }\n\n for (const field of Object.keys(this.cumulativeFieldsErrorMap) as Array<\n DeepKeys<TFormData>\n >) {\n const fieldMeta = this.getFieldMeta(field)\n if (\n fieldMeta?.errorMap[errorMapKey] &&\n !currentValidationErrorMap[field]?.[errorMapKey]\n ) {\n this.cumulativeFieldsErrorMap[field] = {\n ...this.cumulativeFieldsErrorMap[field],\n [errorMapKey]: undefined,\n }\n\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: undefined,\n },\n }))\n }\n }\n\n if (this.state.errorMap[errorMapKey] !== formError) {\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: formError,\n },\n }))\n }\n\n if (formError || fieldErrors) {\n hasErrored = true\n }\n }\n\n /**\n * when we have an error for onSubmit in the state, we want\n * to clear the error as soon as the user enters a valid value in the field\n */\n const submitErrKey = getErrorMapKey('submit')\n if (\n this.state.errorMap[submitErrKey] &&\n cause !== 'submit' &&\n !hasErrored\n ) {\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [submitErrKey]: undefined,\n },\n }))\n }\n })\n\n return { hasErrored, fieldsErrorMap: currentValidationErrorMap }\n }\n\n /**\n * @private\n */\n validateAsync = async (\n cause: ValidationCause,\n ): Promise<\n FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n > => {\n const validates = getAsyncValidatorArray(cause, this.options)\n\n if (!this.state.isFormValidating) {\n this.baseStore.setState((prev) => ({ ...prev, isFormValidating: true }))\n }\n\n /**\n * We have to use a for loop and generate our promises this way, otherwise it won't be sync\n * when there are no validators needed to be run\n */\n const promises: Promise<ValidationPromiseResult<TFormData>>[] = []\n\n let fieldErrors:\n | Partial<Record<DeepKeys<TFormData>, ValidationError>>\n | undefined\n\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n const key = getErrorMapKey(validateObj.cause)\n const fieldValidatorMeta = this.state.validationMetaMap[key]\n\n fieldValidatorMeta?.lastAbortController.abort()\n const controller = new AbortController()\n\n this.state.validationMetaMap[key] = {\n lastAbortController: controller,\n }\n\n promises.push(\n new Promise<ValidationPromiseResult<TFormData>>(async (resolve) => {\n let rawError!:\n | ValidationError\n | FormValidationError<unknown>\n | undefined\n try {\n rawError = await new Promise((rawResolve, rawReject) => {\n setTimeout(async () => {\n if (controller.signal.aborted) return rawResolve(undefined)\n try {\n rawResolve(\n await this.runValidator({\n validate: validateObj.validate!,\n value: {\n value: this.state.values,\n formApi: this,\n validationSource: 'form',\n signal: controller.signal,\n },\n type: 'validateAsync',\n }),\n )\n } catch (e) {\n rawReject(e)\n }\n }, validateObj.debounceMs)\n })\n } catch (e: unknown) {\n rawError = e as ValidationError\n }\n const { formError, fieldErrors: fieldErrorsFromNormalizeError } =\n normalizeError<TFormData>(rawError)\n\n if (fieldErrorsFromNormalizeError) {\n fieldErrors = fieldErrors\n ? { ...fieldErrors, ...fieldErrorsFromNormalizeError }\n : fieldErrorsFromNormalizeError\n }\n const errorMapKey = getErrorMapKey(validateObj.cause)\n\n if (fieldErrors) {\n for (const [field, fieldError] of Object.entries(fieldErrors)) {\n const fieldMeta = this.getFieldMeta(field as DeepKeys<TFormData>)\n if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {\n this.setFieldMeta(field as DeepKeys<TFormData>, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: fieldError,\n },\n }))\n }\n }\n }\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: formError,\n },\n }))\n\n resolve(fieldErrors ? { fieldErrors, errorMapKey } : undefined)\n }),\n )\n }\n\n let results: ValidationPromiseResult<TFormData>[] = []\n\n const fieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n if (promises.length) {\n results = await Promise.all(promises)\n for (const fieldValidationResult of results) {\n if (fieldValidationResult?.fieldErrors) {\n const { errorMapKey } = fieldValidationResult\n\n for (const [field, fieldError] of Object.entries(\n fieldValidationResult.fieldErrors,\n )) {\n const oldErrorMap =\n fieldsErrorMap[field as DeepKeys<TFormData>] || {}\n const newErrorMap = {\n ...oldErrorMap,\n [errorMapKey]: fieldError,\n }\n fieldsErrorMap[field as DeepKeys<TFormData>] = newErrorMap\n }\n }\n }\n }\n\n this.baseStore.setState((prev) => ({\n ...prev,\n isFormValidating: false,\n }))\n\n return fieldsErrorMap\n }\n\n /**\n * @private\n */\n validate = (\n cause: ValidationCause,\n ):\n | FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n | Promise<\n FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n > => {\n // Attempt to sync validate first\n const { hasErrored, fieldsErrorMap } = this.validateSync(cause)\n\n if (hasErrored && !this.options.asyncAlways) {\n return fieldsErrorMap\n }\n\n // No error? Attempt async validation\n return this.validateAsync(cause)\n }\n\n /**\n * Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks.\n */\n handleSubmit(): Promise<void>\n handleSubmit(submitMeta: TSubmitMeta): Promise<void>\n async handleSubmit(submitMeta?: TSubmitMeta): Promise<void> {\n this.baseStore.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.baseStore.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n await this.validateAllFields('submit')\n\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n await this.validate('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<TFormData>[]).forEach(\n (field) => {\n field.instance?.options.listeners?.onSubmit?.({\n value: field.instance.state.value,\n fieldApi: field.instance,\n })\n },\n )\n })\n\n try {\n // Run the submit code\n await this.options.onSubmit?.({\n value: this.state.values,\n formApi: this,\n meta: submitMeta ?? this.options.onSubmitMeta,\n } as any)\n\n batch(() => {\n this.baseStore.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n /**\n * Gets the value of the specified field.\n */\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n /**\n * Gets the metadata of the specified field.\n */\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): AnyFieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n /**\n * Gets the field info of the specified field.\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 instance: null,\n validationMetaMap: {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n })\n }\n\n /**\n * Updates the metadata of the specified field.\n */\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<AnyFieldMeta>,\n ) => {\n this.baseStore.setState((prev) => {\n return {\n ...prev,\n fieldMetaBase: {\n ...prev.fieldMetaBase,\n [field]: functionalUpdate(\n updater,\n prev.fieldMetaBase[field] as never,\n ),\n },\n }\n })\n }\n\n resetFieldMeta = <TField extends DeepKeys<TFormData>>(\n fieldMeta: Record<TField, AnyFieldMeta>,\n ): Record<TField, AnyFieldMeta> => {\n return Object.keys(fieldMeta).reduce(\n (acc: Record<TField, AnyFieldMeta>, key) => {\n const fieldKey = key as TField\n acc[fieldKey] = {\n isValidating: false,\n isTouched: false,\n isBlurred: false,\n isDirty: false,\n isPristine: true,\n errors: [],\n errorMap: {},\n }\n return acc\n },\n {} as Record<TField, AnyFieldMeta>,\n )\n }\n\n /**\n * Sets the value of the specified field and optionally updates the touched state.\n */\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: UpdateMetaOptions,\n ) => {\n const dontUpdateMeta = opts?.dontUpdateMeta ?? false\n\n batch(() => {\n if (!dontUpdateMeta) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n isDirty: true,\n errorMap: {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n ...prev?.errorMap,\n onMount: undefined,\n },\n }))\n }\n\n this.baseStore.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n deleteField = <TField extends DeepKeys<TFormData>>(field: TField) => {\n this.baseStore.setState((prev) => {\n const newState = { ...prev }\n newState.values = deleteBy(newState.values, field)\n delete newState.fieldMetaBase[field]\n\n return newState\n })\n delete this.fieldInfo[field]\n }\n\n /**\n * Pushes a value into an array field.\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?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n this.validateField(field, 'change')\n }\n\n insertFieldValue = async <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?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return [\n ...(prev as DeepValue<TFormData, TField>[]).slice(0, index),\n value,\n ...(prev as DeepValue<TFormData, TField>[]).slice(index),\n ] as any\n },\n opts,\n )\n\n // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n\n // Shift down all meta after validating to make sure the new field has been mounted\n metaHelper(this).handleArrayFieldMetaShift(field, index, 'insert')\n\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Replaces a value into an array field at the specified index.\n */\n replaceFieldValue = async <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?: UpdateMetaOptions,\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 // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Removes a value from an array field at the specified index.\n */\n removeFieldValue = async <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: UpdateMetaOptions,\n ) => {\n const fieldValue = this.getFieldValue(field)\n\n const lastIndex = Array.isArray(fieldValue)\n ? Math.max(fieldValue.length - 1, 0)\n : null\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 // Shift up all meta\n metaHelper(this).handleArrayFieldMetaShift(field, index, 'remove')\n\n if (lastIndex !== null) {\n const start = `${field}[${lastIndex}]`\n const fieldsToDelete = Object.keys(this.fieldInfo).filter((f) =>\n f.startsWith(start),\n )\n\n // Cleanup the last fields\n fieldsToDelete.forEach((f) => this.deleteField(f as TField))\n }\n\n // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Swaps the values at the specified indices within an array field.\n */\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n },\n opts,\n )\n\n // Swap meta\n metaHelper(this).handleArrayFieldMetaShift(field, index1, 'swap', index2)\n\n // Validate the whole array\n this.validateField(field, 'change')\n // Validate the swapped fields\n this.validateField(`${field}[${index1}]` as DeepKeys<TFormData>, 'change')\n this.validateField(`${field}[${index2}]` as DeepKeys<TFormData>, 'change')\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 DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev: any) => {\n prev.splice(index2, 0, prev.splice(index1, 1)[0])\n return prev\n },\n opts,\n )\n\n // Move meta between index1 and index2\n metaHelper(this).handleArrayFieldMetaShift(field, index1, 'move', index2)\n\n // Validate the whole array\n this.validateField(field, 'change')\n // Validate the moved fields\n this.validateField(`${field}[${index1}]` as DeepKeys<TFormData>, 'change')\n this.validateField(`${field}[${index2}]` as DeepKeys<TFormData>, 'change')\n }\n /**\n * Updates the form's errorMap\n */\n setErrorMap(\n errorMap: ValidationErrorMap<\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >,\n ) {\n this.baseStore.setState(\n (prev) =>\n ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n ...errorMap,\n },\n }) as never,\n )\n }\n\n /**\n * Returns form and field level errors\n */\n getAllErrors = (): {\n form: {\n errors: Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n errorMap: FormValidationErrorMap<\n UnwrapFormValidateOrFn<TOnMount>,\n UnwrapFormValidateOrFn<TOnChange>,\n UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,\n UnwrapFormValidateOrFn<TOnBlur>,\n UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,\n UnwrapFormValidateOrFn<TOnSubmit>,\n UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,\n UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n }\n fields: Record<\n DeepKeys<TFormData>,\n { errors: ValidationError[]; errorMap: ValidationErrorMap }\n >\n } => {\n return {\n form: {\n errors: this.state.errors,\n errorMap: this.state.errorMap,\n },\n fields: Object.entries(this.state.fieldMeta).reduce(\n (acc, [fieldName, fieldMeta]) => {\n if (\n Object.keys(fieldMeta as AnyFieldMeta).length &&\n (fieldMeta as AnyFieldMeta).errors.length\n ) {\n acc[fieldName as DeepKeys<TFormData>] = {\n errors: (fieldMeta as AnyFieldMeta).errors,\n errorMap: (fieldMeta as AnyFieldMeta).errorMap,\n }\n }\n\n return acc\n },\n {} as Record<\n DeepKeys<TFormData>,\n { errors: ValidationError[]; errorMap: ValidationErrorMap }\n >,\n ),\n }\n }\n}\n\nfunction normalizeError<TFormData>(rawError?: FormValidationError<unknown>): {\n formError: ValidationError\n fieldErrors?: Partial<Record<DeepKeys<TFormData>, ValidationError>>\n} {\n if (rawError) {\n if (isGlobalFormValidationError(rawError)) {\n const formError = normalizeError(rawError.form).formError\n const fieldErrors = rawError.fields\n return { formError, fieldErrors } as never\n }\n\n return { formError: rawError }\n }\n\n return { formError: undefined }\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n case 'server':\n return 'onServer'\n case 'change':\n default:\n return 'onChange'\n }\n}\n"],"names":["_a","shallow","batch","opts","getSyncValidatorArray","getAsyncValidatorArray","getBy","functionalUpdate","setBy","deleteBy","metaHelper","Store","Derived","isNonEmptyArray","isGlobalFormValidationError","isStandardSchemaValidator","standardSchemaValidators","_c","_b"],"mappings":"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"}
|
package/dist/cjs/FormApi.d.cts
CHANGED
|
@@ -189,6 +189,10 @@ export type BaseFormState<TFormData, TOnMount extends undefined | FormValidateOr
|
|
|
189
189
|
* A counter for tracking the number of submission attempts.
|
|
190
190
|
*/
|
|
191
191
|
submissionAttempts: number;
|
|
192
|
+
/**
|
|
193
|
+
* @private, used to force a re-evaluation of the form state when options change
|
|
194
|
+
*/
|
|
195
|
+
_force_re_eval?: boolean;
|
|
192
196
|
};
|
|
193
197
|
export type DerivedFormState<TFormData, TOnMount extends undefined | FormValidateOrFn<TFormData>, TOnChange extends undefined | FormValidateOrFn<TFormData>, TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnBlur extends undefined | FormValidateOrFn<TFormData>, TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnSubmit extends undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>> = {
|
|
194
198
|
/**
|
|
@@ -273,9 +277,11 @@ export declare class FormApi<TFormData, TOnMount extends undefined | FormValidat
|
|
|
273
277
|
*/
|
|
274
278
|
prevTransformArray: unknown[];
|
|
275
279
|
/**
|
|
276
|
-
* @private
|
|
280
|
+
* @private Persistent store of all field validation errors originating from form-level validators.
|
|
281
|
+
* Maintains the cumulative state across validation cycles, including cleared errors (undefined values).
|
|
282
|
+
* This map preserves the complete validation state for all fields.
|
|
277
283
|
*/
|
|
278
|
-
|
|
284
|
+
cumulativeFieldsErrorMap: FormErrorMapFromValidator<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync>;
|
|
279
285
|
/**
|
|
280
286
|
* Constructs a new `FormApi` instance with the given form options.
|
|
281
287
|
*/
|
package/dist/esm/FormApi.d.ts
CHANGED
|
@@ -189,6 +189,10 @@ export type BaseFormState<TFormData, TOnMount extends undefined | FormValidateOr
|
|
|
189
189
|
* A counter for tracking the number of submission attempts.
|
|
190
190
|
*/
|
|
191
191
|
submissionAttempts: number;
|
|
192
|
+
/**
|
|
193
|
+
* @private, used to force a re-evaluation of the form state when options change
|
|
194
|
+
*/
|
|
195
|
+
_force_re_eval?: boolean;
|
|
192
196
|
};
|
|
193
197
|
export type DerivedFormState<TFormData, TOnMount extends undefined | FormValidateOrFn<TFormData>, TOnChange extends undefined | FormValidateOrFn<TFormData>, TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnBlur extends undefined | FormValidateOrFn<TFormData>, TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnSubmit extends undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>> = {
|
|
194
198
|
/**
|
|
@@ -273,9 +277,11 @@ export declare class FormApi<TFormData, TOnMount extends undefined | FormValidat
|
|
|
273
277
|
*/
|
|
274
278
|
prevTransformArray: unknown[];
|
|
275
279
|
/**
|
|
276
|
-
* @private
|
|
280
|
+
* @private Persistent store of all field validation errors originating from form-level validators.
|
|
281
|
+
* Maintains the cumulative state across validation cycles, including cleared errors (undefined values).
|
|
282
|
+
* This map preserves the complete validation state for all fields.
|
|
277
283
|
*/
|
|
278
|
-
|
|
284
|
+
cumulativeFieldsErrorMap: FormErrorMapFromValidator<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync>;
|
|
279
285
|
/**
|
|
280
286
|
* Constructs a new `FormApi` instance with the given form options.
|
|
281
287
|
*/
|
package/dist/esm/FormApi.js
CHANGED
|
@@ -29,7 +29,7 @@ class FormApi {
|
|
|
29
29
|
this.options = {};
|
|
30
30
|
this.fieldInfo = {};
|
|
31
31
|
this.prevTransformArray = [];
|
|
32
|
-
this.
|
|
32
|
+
this.cumulativeFieldsErrorMap = {};
|
|
33
33
|
this.mount = () => {
|
|
34
34
|
const cleanupFieldMetaDerived = this.fieldMetaDerived.mount();
|
|
35
35
|
const cleanupStoreDerived = this.store.mount();
|
|
@@ -43,12 +43,16 @@ class FormApi {
|
|
|
43
43
|
return cleanup;
|
|
44
44
|
};
|
|
45
45
|
this.update = (options) => {
|
|
46
|
+
var _a2, _b;
|
|
46
47
|
if (!options) return;
|
|
47
48
|
const oldOptions = this.options;
|
|
48
49
|
this.options = options;
|
|
50
|
+
const shouldUpdateReeval = !!((_b = (_a2 = options.transform) == null ? void 0 : _a2.deps) == null ? void 0 : _b.some(
|
|
51
|
+
(val, i) => val !== this.prevTransformArray[i]
|
|
52
|
+
));
|
|
49
53
|
const shouldUpdateValues = options.defaultValues && !shallow(options.defaultValues, oldOptions.defaultValues) && !this.state.isTouched;
|
|
50
54
|
const shouldUpdateState = !shallow(options.defaultState, oldOptions.defaultState) && !this.state.isTouched;
|
|
51
|
-
if (!shouldUpdateValues && !shouldUpdateState) return;
|
|
55
|
+
if (!shouldUpdateValues && !shouldUpdateState && !shouldUpdateReeval) return;
|
|
52
56
|
batch(() => {
|
|
53
57
|
this.baseStore.setState(
|
|
54
58
|
() => getDefaultFormState(
|
|
@@ -58,7 +62,8 @@ class FormApi {
|
|
|
58
62
|
shouldUpdateState ? options.defaultState : {},
|
|
59
63
|
shouldUpdateValues ? {
|
|
60
64
|
values: options.defaultValues
|
|
61
|
-
} : {}
|
|
65
|
+
} : {},
|
|
66
|
+
shouldUpdateReeval ? { _force_re_eval: !this.state._force_re_eval } : {}
|
|
62
67
|
)
|
|
63
68
|
)
|
|
64
69
|
);
|
|
@@ -139,7 +144,7 @@ class FormApi {
|
|
|
139
144
|
this.validateSync = (cause) => {
|
|
140
145
|
const validates = getSyncValidatorArray(cause, this.options);
|
|
141
146
|
let hasErrored = false;
|
|
142
|
-
const
|
|
147
|
+
const currentValidationErrorMap = {};
|
|
143
148
|
batch(() => {
|
|
144
149
|
var _a2;
|
|
145
150
|
for (const validateObj of validates) {
|
|
@@ -157,12 +162,13 @@ class FormApi {
|
|
|
157
162
|
const errorMapKey = getErrorMapKey(validateObj.cause);
|
|
158
163
|
if (fieldErrors) {
|
|
159
164
|
for (const [field, fieldError] of Object.entries(fieldErrors)) {
|
|
160
|
-
const oldErrorMap =
|
|
165
|
+
const oldErrorMap = this.cumulativeFieldsErrorMap[field] || {};
|
|
161
166
|
const newErrorMap = {
|
|
162
167
|
...oldErrorMap,
|
|
163
168
|
[errorMapKey]: fieldError
|
|
164
169
|
};
|
|
165
|
-
|
|
170
|
+
currentValidationErrorMap[field] = newErrorMap;
|
|
171
|
+
this.cumulativeFieldsErrorMap[field] = newErrorMap;
|
|
166
172
|
const fieldMeta = this.getFieldMeta(field);
|
|
167
173
|
if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {
|
|
168
174
|
this.setFieldMeta(field, (prev) => ({
|
|
@@ -175,9 +181,13 @@ class FormApi {
|
|
|
175
181
|
}
|
|
176
182
|
}
|
|
177
183
|
}
|
|
178
|
-
for (const field of Object.keys(this.
|
|
184
|
+
for (const field of Object.keys(this.cumulativeFieldsErrorMap)) {
|
|
179
185
|
const fieldMeta = this.getFieldMeta(field);
|
|
180
|
-
if ((fieldMeta == null ? void 0 : fieldMeta.errorMap[errorMapKey]) && !((_a2 =
|
|
186
|
+
if ((fieldMeta == null ? void 0 : fieldMeta.errorMap[errorMapKey]) && !((_a2 = currentValidationErrorMap[field]) == null ? void 0 : _a2[errorMapKey])) {
|
|
187
|
+
this.cumulativeFieldsErrorMap[field] = {
|
|
188
|
+
...this.cumulativeFieldsErrorMap[field],
|
|
189
|
+
[errorMapKey]: void 0
|
|
190
|
+
};
|
|
181
191
|
this.setFieldMeta(field, (prev) => ({
|
|
182
192
|
...prev,
|
|
183
193
|
errorMap: {
|
|
@@ -211,8 +221,7 @@ class FormApi {
|
|
|
211
221
|
}));
|
|
212
222
|
}
|
|
213
223
|
});
|
|
214
|
-
|
|
215
|
-
return { hasErrored, fieldsErrorMap: newFieldsErrorMap };
|
|
224
|
+
return { hasErrored, fieldsErrorMap: currentValidationErrorMap };
|
|
216
225
|
};
|
|
217
226
|
this.validateAsync = async (cause) => {
|
|
218
227
|
const validates = getAsyncValidatorArray(cause, this.options);
|
package/dist/esm/FormApi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormApi.js","sources":["../../src/FormApi.ts"],"sourcesContent":["import { Derived, Store, batch } from '@tanstack/store'\nimport {\n deleteBy,\n functionalUpdate,\n getAsyncValidatorArray,\n getBy,\n getSyncValidatorArray,\n isGlobalFormValidationError,\n isNonEmptyArray,\n setBy,\n shallow,\n} from './utils'\nimport {\n isStandardSchemaValidator,\n standardSchemaValidators,\n} from './standardSchemaValidator'\nimport { metaHelper } from './metaHelper'\nimport type {\n StandardSchemaV1,\n StandardSchemaV1Issue,\n TStandardSchemaValidatorValue,\n} from './standardSchemaValidator'\nimport type { AnyFieldMeta, AnyFieldMetaBase, FieldApi } from './FieldApi'\nimport type {\n FormValidationError,\n FormValidationErrorMap,\n UpdateMetaOptions,\n ValidationCause,\n ValidationError,\n ValidationErrorMap,\n ValidationErrorMapKeys,\n} from './types'\nimport type { DeepKeys, DeepValue } from './util-types'\nimport type { Updater } from './utils'\n\n/**\n * @private\n */\n// TODO: Add the `Unwrap` type to the errors\ntype FormErrorMapFromValidator<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = Partial<\n Record<\n DeepKeys<TFormData>,\n ValidationErrorMap<\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n >\n>\n\nexport type FormValidateFn<TFormData> = (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n // This is technically an edge-type; which we try to keep non-`any`, but in this case\n // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n}) => unknown\n\n/**\n * @private\n */\nexport type FormValidateOrFn<TFormData> =\n | FormValidateFn<TFormData>\n | StandardSchemaV1<TFormData, unknown>\n\nexport type UnwrapFormValidateOrFn<\n TValidateOrFn extends undefined | FormValidateOrFn<any>,\n> = [TValidateOrFn] extends [FormValidateFn<any>]\n ? ReturnType<TValidateOrFn>\n : [TValidateOrFn] extends [StandardSchemaV1<any, any>]\n ? Record<string, StandardSchemaV1Issue[]>\n : undefined\n\n/**\n * @private\n */\nexport type FormValidateAsyncFn<TFormData> = (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n // This is technically an edge-type; which we try to keep non-`any`, but in this case\n // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n signal: AbortSignal\n}) => unknown | Promise<unknown>\n\nexport type FormValidator<TFormData, TType, TFn = unknown> = {\n validate(options: { value: TType }, fn: TFn): ValidationError\n validateAsync(\n options: { value: TType },\n fn: TFn,\n ): Promise<FormValidationError<TFormData>>\n}\n\ntype ValidationPromiseResult<TFormData> =\n | {\n fieldErrors: Partial<Record<DeepKeys<TFormData>, ValidationError>>\n errorMapKey: ValidationErrorMapKeys\n }\n | undefined\n\n/**\n * @private\n */\nexport type FormAsyncValidateOrFn<TFormData> =\n | FormValidateAsyncFn<TFormData>\n | StandardSchemaV1<TFormData, unknown>\n\nexport type UnwrapFormAsyncValidateOrFn<\n TValidateOrFn extends undefined | FormAsyncValidateOrFn<any>,\n> = [TValidateOrFn] extends [FormValidateAsyncFn<any>]\n ? Awaited<ReturnType<TValidateOrFn>>\n : [TValidateOrFn] extends [StandardSchemaV1<any, any>]\n ? Record<string, StandardSchemaV1Issue[]>\n : undefined\n\nexport interface FormValidators<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n> {\n /**\n * Optional function that fires as soon as the component mounts.\n */\n onMount?: TOnMount\n /**\n * Optional function that checks the validity of your data whenever a value changes\n */\n onChange?: TOnChange\n /**\n * Optional onChange asynchronous counterpart to onChange. Useful for more complex validation logic that might involve server requests.\n */\n onChangeAsync?: TOnChangeAsync\n /**\n * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds.\n */\n onChangeAsyncDebounceMs?: number\n /**\n * Optional function that validates the form data when a field loses focus, returns a `FormValidationError`\n */\n onBlur?: TOnBlur\n /**\n * Optional onBlur asynchronous validation method for when a field loses focus returns a ` FormValidationError` or a promise of `Promise<FormValidationError>`\n */\n onBlurAsync?: TOnBlurAsync\n /**\n * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds.\n */\n onBlurAsyncDebounceMs?: number\n onSubmit?: TOnSubmit\n onSubmitAsync?: TOnSubmitAsync\n}\n\n/**\n * @private\n */\nexport interface FormTransform<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n fn: (\n formBase: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) => FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n deps: unknown[]\n}\n\n/**\n * An object representing the options for a form.\n */\nexport interface FormOptions<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n /**\n * Set initial values for your form.\n */\n defaultValues?: TFormData\n /**\n * The default state for the form.\n */\n defaultState?: Partial<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n /**\n * If true, always run async validation, even when sync validation has produced an error. Defaults to undefined.\n */\n asyncAlways?: boolean\n /**\n * Optional time in milliseconds if you want to introduce a delay before firing off an async action.\n */\n asyncDebounceMs?: number\n /**\n * A list of validators to pass to the form\n */\n validators?: FormValidators<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n\n /**\n * onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props\n */\n onSubmitMeta?: TSubmitMeta\n\n /**\n * A function to be called when the form is submitted, what should happen once the user submits a valid form returns `any` or a promise `Promise<any>`\n */\n onSubmit?: (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n meta: TSubmitMeta\n }) => any | Promise<any>\n /**\n * Specify an action for scenarios where the user tries to submit an invalid form.\n */\n onSubmitInvalid?: (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n }) => void\n transform?: FormTransform<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n}\n\n/**\n * An object representing the validation metadata for a field. Not intended for public usage.\n */\nexport type ValidationMeta = {\n /**\n * An abort controller stored in memory to cancel previous async validation attempts.\n */\n lastAbortController: AbortController\n}\n\n/**\n * An object representing the field information for a specific field within the form.\n */\nexport type FieldInfo<TFormData> = {\n /**\n * An instance of the FieldAPI.\n */\n instance: FieldApi<\n TFormData,\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 any,\n any,\n any,\n any,\n any,\n any\n > | null\n /**\n * A record of field validation internal handling.\n */\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n}\n\n/**\n * An object representing the current state of the form.\n */\nexport type BaseFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = {\n /**\n * The current values of the form fields.\n */\n values: TFormData\n /**\n * The error map for the form itself.\n */\n errorMap: FormValidationErrorMap<\n UnwrapFormValidateOrFn<TOnMount>,\n UnwrapFormValidateOrFn<TOnChange>,\n UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,\n UnwrapFormValidateOrFn<TOnBlur>,\n UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,\n UnwrapFormValidateOrFn<TOnSubmit>,\n UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,\n UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n /**\n * An internal mechanism used for keeping track of validation logic in a form.\n */\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n /**\n * A record of field metadata for each field in the form, not including the derived properties, like `errors` and such\n */\n fieldMetaBase: Record<DeepKeys<TFormData>, AnyFieldMetaBase>\n /**\n * A boolean indicating if the form is currently in the process of being submitted after `handleSubmit` is called.\n *\n * Goes back to `false` when submission completes for one of the following reasons:\n * - the validation step returned errors.\n * - the `onSubmit` function has completed.\n *\n * Note: if you're running async operations in your `onSubmit` function make sure to await them to ensure `isSubmitting` is set to `false` only when the async operation completes.\n *\n * This is useful for displaying loading indicators or disabling form inputs during submission.\n *\n */\n isSubmitting: boolean\n /**\n * A boolean indicating if the form has been submitted.\n */\n isSubmitted: boolean\n /**\n * A boolean indicating if the form or any of its fields are currently validating.\n */\n isValidating: boolean\n /**\n * A counter for tracking the number of submission attempts.\n */\n submissionAttempts: number\n}\n\nexport type DerivedFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = {\n /**\n * A boolean indicating if the form is currently validating.\n */\n isFormValidating: boolean\n /**\n * A boolean indicating if the form is valid.\n */\n isFormValid: boolean\n /**\n * The error array for the form itself.\n */\n errors: Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n /**\n * A boolean indicating if any of the form fields are currently validating.\n */\n isFieldsValidating: boolean\n /**\n * A boolean indicating if all the form fields are valid.\n */\n isFieldsValid: boolean\n /**\n * A boolean indicating if any of the form fields have been touched.\n */\n isTouched: boolean\n /**\n * A boolean indicating if any of the form fields have been blurred.\n */\n isBlurred: boolean\n /**\n * A boolean indicating if any of the form's fields' values have been modified by the user. `True` if the user have modified at least one of the fields. Opposite of `isPristine`.\n */\n isDirty: boolean\n /**\n * A boolean indicating if none of the form's fields' values have been modified by the user. `True` if the user have not modified any of the fields. Opposite of `isDirty`.\n */\n isPristine: boolean\n /**\n * A boolean indicating if the form and all its fields are valid.\n */\n isValid: boolean\n /**\n * A boolean indicating if the form can be submitted based on its current state.\n */\n canSubmit: boolean\n /**\n * A record of field metadata for each field in the form.\n */\n fieldMeta: Record<DeepKeys<TFormData>, AnyFieldMeta>\n}\n\nexport type FormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n> &\n DerivedFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n\nexport type AnyFormState = FormState<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\nfunction getDefaultFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n>(\n defaultState: Partial<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >,\n): BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n> {\n return {\n values: defaultState.values ?? ({} as never),\n errorMap: defaultState.errorMap ?? {},\n fieldMetaBase: defaultState.fieldMetaBase ?? ({} as never),\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n validationMetaMap: defaultState.validationMetaMap ?? {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n }\n}\n\n/**\n * @public\n *\n * A type representing the Form API with all generics set to `any` for convenience.\n */\nexport type AnyFormApi = FormApi<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\n/**\n * A class representing the Form API. It handles the logic and interactions with the form state.\n *\n * Normally, you will not need to create a new `FormApi` instance directly. Instead, you will use a framework\n * hook/function like `useForm` or `createForm` to create a new instance for you that uses your framework's reactivity model.\n * However, if you need to create a new instance manually, you can do so by calling the `new FormApi` constructor.\n */\nexport class FormApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n /**\n * The options for the form.\n */\n options: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n > = {}\n baseStore!: Store<\n BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n fieldMetaDerived!: Derived<Record<DeepKeys<TFormData>, AnyFieldMeta>>\n store!: Derived<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n /**\n * A record of field information for each field in the form.\n */\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>> = {} as any\n\n get state() {\n return this.store.state\n }\n\n /**\n * @private\n */\n prevTransformArray: unknown[] = []\n\n /**\n * @private map of errors originated from form level validators\n */\n prevFieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n\n /**\n * Constructs a new `FormApi` instance with the given form options.\n */\n constructor(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) {\n this.baseStore = new Store(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n )\n\n this.fieldMetaDerived = new Derived({\n deps: [this.baseStore],\n fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => {\n const prevVal = _prevVal as\n | Record<DeepKeys<TFormData>, AnyFieldMeta>\n | undefined\n const prevBaseStore = prevDepVals?.[0]\n const currBaseStore = currDepVals[0]\n\n let originalMetaCount = 0\n\n const fieldMeta = {} as FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >['fieldMeta']\n\n for (const fieldName of Object.keys(\n currBaseStore.fieldMetaBase,\n ) as Array<keyof typeof currBaseStore.fieldMetaBase>) {\n const currBaseVal = currBaseStore.fieldMetaBase[\n fieldName as never\n ] as AnyFieldMetaBase\n\n const prevBaseVal = prevBaseStore?.fieldMetaBase[\n fieldName as never\n ] as AnyFieldMetaBase | undefined\n\n const prevFieldInfo =\n prevVal?.[fieldName as never as keyof typeof prevVal]\n\n let fieldErrors = prevFieldInfo?.errors\n if (!prevBaseVal || currBaseVal.errorMap !== prevBaseVal.errorMap) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n fieldErrors = Object.values(currBaseVal.errorMap ?? {}).filter(\n (val) => val !== undefined,\n ) as never\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const fieldInstance = this.getFieldInfo(fieldName)?.instance\n\n if (fieldInstance && !fieldInstance.options.disableErrorFlat) {\n fieldErrors = (fieldErrors as undefined | string[])?.flat(\n 1,\n ) as never\n }\n }\n\n // As a primitive, we don't need to aggressively persist the same referential value for performance reasons\n const isFieldPristine = !currBaseVal.isDirty\n\n if (\n prevFieldInfo &&\n prevFieldInfo.isPristine === isFieldPristine &&\n prevFieldInfo.errors === fieldErrors &&\n currBaseVal === prevBaseVal\n ) {\n fieldMeta[fieldName] = prevFieldInfo\n originalMetaCount++\n continue\n }\n\n fieldMeta[fieldName] = {\n ...currBaseVal,\n errors: fieldErrors,\n isPristine: isFieldPristine,\n } as AnyFieldMeta\n }\n\n if (\n prevVal &&\n originalMetaCount === Object.keys(currBaseStore.fieldMetaBase).length\n ) {\n return prevVal\n }\n\n return fieldMeta\n },\n })\n\n this.store = new Derived({\n deps: [this.baseStore, this.fieldMetaDerived],\n fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => {\n const prevVal = _prevVal as\n | FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n | undefined\n const prevBaseStore = prevDepVals?.[0]\n const currBaseStore = currDepVals[0]\n\n // Computed state\n const fieldMetaValues = Object.values(currBaseStore.fieldMetaBase) as (\n | AnyFieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some(\n (field) =>\n field?.errorMap &&\n isNonEmptyArray(Object.values(field.errorMap).filter(Boolean)),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n const isBlurred = fieldMetaValues.some((field) => field?.isBlurred)\n\n const shouldInvalidateOnMount =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n isTouched && currBaseStore?.errorMap?.onMount\n\n const isDirty = fieldMetaValues.some((field) => field?.isDirty)\n const isPristine = !isDirty\n\n const hasOnMountError = Boolean(\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n currBaseStore.errorMap?.onMount ||\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n fieldMetaValues.some((f) => f?.errorMap?.onMount),\n )\n\n const isValidating = !!isFieldsValidating\n\n // As `errors` is not a primitive, we need to aggressively persist the same referencial value for performance reasons\n let errors = prevVal?.errors ?? []\n if (\n !prevBaseStore ||\n currBaseStore.errorMap !== prevBaseStore.errorMap\n ) {\n errors = Object.values(currBaseStore.errorMap).reduce<\n Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n >((prev, curr) => {\n if (curr === undefined) return prev\n\n if (curr && isGlobalFormValidationError(curr)) {\n prev.push(curr.form as never)\n return prev\n }\n prev.push(curr as never)\n return prev\n }, [])\n }\n\n const isFormValid = errors.length === 0\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (currBaseStore.submissionAttempts === 0 &&\n !isTouched &&\n !hasOnMountError) ||\n (!isValidating && !currBaseStore.isSubmitting && isValid)\n\n let errorMap = currBaseStore.errorMap\n if (shouldInvalidateOnMount) {\n errors = errors.filter(\n (err) => err !== currBaseStore.errorMap.onMount,\n )\n errorMap = Object.assign(errorMap, { onMount: undefined })\n }\n\n if (\n prevVal &&\n prevBaseStore &&\n prevVal.errorMap === errorMap &&\n prevVal.fieldMeta === this.fieldMetaDerived.state &&\n prevVal.errors === errors &&\n prevVal.isFieldsValidating === isFieldsValidating &&\n prevVal.isFieldsValid === isFieldsValid &&\n prevVal.isFormValid === isFormValid &&\n prevVal.isValid === isValid &&\n prevVal.canSubmit === canSubmit &&\n prevVal.isTouched === isTouched &&\n prevVal.isBlurred === isBlurred &&\n prevVal.isPristine === isPristine &&\n prevVal.isDirty === isDirty &&\n shallow(prevBaseStore, currBaseStore)\n ) {\n return prevVal\n }\n\n let state = {\n ...currBaseStore,\n errorMap,\n fieldMeta: this.fieldMetaDerived.state,\n errors,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n isBlurred,\n isPristine,\n isDirty,\n } as FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n\n // Only run transform if state has shallowly changed - IE how React.useEffect works\n const transformArray = this.options.transform?.deps ?? []\n const shouldTransform =\n transformArray.length !== this.prevTransformArray.length ||\n transformArray.some((val, i) => val !== this.prevTransformArray[i])\n\n if (shouldTransform) {\n const newObj = Object.assign({}, this, { state })\n // This mutates the state\n this.options.transform?.fn(newObj)\n state = newObj.state\n this.prevTransformArray = transformArray\n }\n\n return state\n },\n })\n\n this.handleSubmit = this.handleSubmit.bind(this)\n\n this.update(opts || {})\n }\n\n /**\n * @private\n */\n runValidator<\n TValue extends TStandardSchemaValidatorValue<TFormData> & {\n formApi: AnyFormApi\n },\n TType extends 'validate' | 'validateAsync',\n >(props: {\n validate: TType extends 'validate'\n ? FormValidateOrFn<TFormData>\n : FormAsyncValidateOrFn<TFormData>\n value: TValue\n type: TType\n }): unknown {\n if (isStandardSchemaValidator(props.validate)) {\n return standardSchemaValidators[props.type](\n props.value,\n props.validate,\n ) as never\n }\n\n return (props.validate as FormValidateFn<any>)(props.value) as never\n }\n\n mount = () => {\n const cleanupFieldMetaDerived = this.fieldMetaDerived.mount()\n const cleanupStoreDerived = this.store.mount()\n const cleanup = () => {\n cleanupFieldMetaDerived()\n cleanupStoreDerived()\n }\n const { onMount } = this.options.validators || {}\n if (!onMount) return cleanup\n this.validateSync('mount')\n\n return cleanup\n }\n\n /**\n * Updates the form options and form state.\n */\n update = (\n options?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) => {\n if (!options) return\n\n const oldOptions = this.options\n\n // Options need to be updated first so that when the store is updated, the state is correct for the derived state\n this.options = options\n\n const shouldUpdateValues =\n options.defaultValues &&\n !shallow(options.defaultValues, oldOptions.defaultValues) &&\n !this.state.isTouched\n\n const shouldUpdateState =\n !shallow(options.defaultState, oldOptions.defaultState) &&\n !this.state.isTouched\n\n if (!shouldUpdateValues && !shouldUpdateState) return\n\n batch(() => {\n this.baseStore.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n\n shouldUpdateState ? options.defaultState : {},\n\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n ),\n ),\n )\n })\n }\n\n /**\n * Resets the form state to the default values.\n * If values are provided, the form will be reset to those values instead and the default values will be updated.\n *\n * @param values - Optional values to reset the form to.\n * @param opts - Optional options to control the reset behavior.\n */\n reset = (values?: TFormData, opts?: { keepDefaultValues?: boolean }) => {\n const { fieldMeta: currentFieldMeta } = this.state\n const fieldMetaBase = this.resetFieldMeta(currentFieldMeta)\n\n if (values && !opts?.keepDefaultValues) {\n this.options = {\n ...this.options,\n defaultValues: values,\n }\n }\n\n this.baseStore.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values:\n values ??\n this.options.defaultValues ??\n this.options.defaultState?.values,\n fieldMetaBase,\n }),\n )\n }\n\n /**\n * Validates all fields using the correct handlers for a given validation cause.\n */\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<any>[]).forEach(\n (field) => {\n if (!field.instance) return\n const fieldInstance = field.instance\n // Validate the field\n fieldValidationPromises.push(\n // Remember, `validate` is either a sync operation or a promise\n Promise.resolve().then(() =>\n fieldInstance.validate(cause, { skipFormValidation: true }),\n ),\n )\n // If any fields are not touched\n if (!field.instance.state.meta.isTouched) {\n // Mark them as touched\n field.instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n },\n )\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\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 <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n cause: ValidationCause,\n ) => {\n const currentValue = this.getFieldValue(field)\n\n const lastIndex = Array.isArray(currentValue)\n ? Math.max(currentValue.length - 1, 0)\n : null\n\n // We have to validate all fields that have shifted (at least the current field)\n const fieldKeysToValidate = [`${field}[${index}]`]\n for (let i = index + 1; i <= (lastIndex ?? 0); i++) {\n fieldKeysToValidate.push(`${field}[${i}]`)\n }\n\n // We also have to include all fields that are nested in the shifted fields\n const fieldsToValidate = Object.keys(this.fieldInfo).filter((fieldKey) =>\n fieldKeysToValidate.some((key) => fieldKey.startsWith(key)),\n ) as DeepKeys<TFormData>[]\n\n // Validate the fields\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n batch(() => {\n fieldsToValidate.forEach((nestedField) => {\n fieldValidationPromises.push(\n Promise.resolve().then(() => this.validateField(nestedField, cause)),\n )\n })\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\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<TFormData>>(\n field: TField,\n cause: ValidationCause,\n ) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const fieldInstance = this.fieldInfo[field]?.instance\n if (!fieldInstance) return []\n\n // If the field is not touched (same logic as in validateAllFields)\n if (!fieldInstance.state.meta.isTouched) {\n // Mark it as touched\n fieldInstance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n\n return fieldInstance.validate(cause)\n }\n\n /**\n * TODO: This code is copied from FieldApi, we should refactor to share\n * @private\n */\n validateSync = (\n cause: ValidationCause,\n ): {\n hasErrored: boolean\n fieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n } => {\n const validates = getSyncValidatorArray(cause, this.options)\n let hasErrored = false as boolean\n\n const newFieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n\n batch(() => {\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n\n const rawError = this.runValidator({\n validate: validateObj.validate,\n value: {\n value: this.state.values,\n formApi: this,\n validationSource: 'form',\n },\n type: 'validate',\n })\n\n const { formError, fieldErrors } = normalizeError<TFormData>(rawError)\n\n const errorMapKey = getErrorMapKey(validateObj.cause)\n\n if (fieldErrors) {\n for (const [field, fieldError] of Object.entries(fieldErrors)) {\n const oldErrorMap =\n newFieldsErrorMap[field as DeepKeys<TFormData>] || {}\n const newErrorMap = {\n ...oldErrorMap,\n [errorMapKey]: fieldError,\n }\n newFieldsErrorMap[field as DeepKeys<TFormData>] = newErrorMap\n\n const fieldMeta = this.getFieldMeta(field as DeepKeys<TFormData>)\n if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {\n this.setFieldMeta(field as DeepKeys<TFormData>, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: fieldError,\n },\n }))\n }\n }\n }\n\n for (const field of Object.keys(this.prevFieldsErrorMap) as Array<\n DeepKeys<TFormData>\n >) {\n const fieldMeta = this.getFieldMeta(field)\n if (\n fieldMeta?.errorMap[errorMapKey] &&\n !newFieldsErrorMap[field]?.[errorMapKey]\n ) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: undefined,\n },\n }))\n }\n }\n\n if (this.state.errorMap[errorMapKey] !== formError) {\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: formError,\n },\n }))\n }\n\n if (formError || fieldErrors) {\n hasErrored = true\n }\n }\n\n /**\n * when we have an error for onSubmit in the state, we want\n * to clear the error as soon as the user enters a valid value in the field\n */\n const submitErrKey = getErrorMapKey('submit')\n if (\n this.state.errorMap[submitErrKey] &&\n cause !== 'submit' &&\n !hasErrored\n ) {\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [submitErrKey]: undefined,\n },\n }))\n }\n })\n\n this.prevFieldsErrorMap = newFieldsErrorMap\n\n return { hasErrored, fieldsErrorMap: newFieldsErrorMap }\n }\n\n /**\n * @private\n */\n validateAsync = async (\n cause: ValidationCause,\n ): Promise<\n FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n > => {\n const validates = getAsyncValidatorArray(cause, this.options)\n\n if (!this.state.isFormValidating) {\n this.baseStore.setState((prev) => ({ ...prev, isFormValidating: true }))\n }\n\n /**\n * We have to use a for loop and generate our promises this way, otherwise it won't be sync\n * when there are no validators needed to be run\n */\n const promises: Promise<ValidationPromiseResult<TFormData>>[] = []\n\n let fieldErrors:\n | Partial<Record<DeepKeys<TFormData>, ValidationError>>\n | undefined\n\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n const key = getErrorMapKey(validateObj.cause)\n const fieldValidatorMeta = this.state.validationMetaMap[key]\n\n fieldValidatorMeta?.lastAbortController.abort()\n const controller = new AbortController()\n\n this.state.validationMetaMap[key] = {\n lastAbortController: controller,\n }\n\n promises.push(\n new Promise<ValidationPromiseResult<TFormData>>(async (resolve) => {\n let rawError!:\n | ValidationError\n | FormValidationError<unknown>\n | undefined\n try {\n rawError = await new Promise((rawResolve, rawReject) => {\n setTimeout(async () => {\n if (controller.signal.aborted) return rawResolve(undefined)\n try {\n rawResolve(\n await this.runValidator({\n validate: validateObj.validate!,\n value: {\n value: this.state.values,\n formApi: this,\n validationSource: 'form',\n signal: controller.signal,\n },\n type: 'validateAsync',\n }),\n )\n } catch (e) {\n rawReject(e)\n }\n }, validateObj.debounceMs)\n })\n } catch (e: unknown) {\n rawError = e as ValidationError\n }\n const { formError, fieldErrors: fieldErrorsFromNormalizeError } =\n normalizeError<TFormData>(rawError)\n\n if (fieldErrorsFromNormalizeError) {\n fieldErrors = fieldErrors\n ? { ...fieldErrors, ...fieldErrorsFromNormalizeError }\n : fieldErrorsFromNormalizeError\n }\n const errorMapKey = getErrorMapKey(validateObj.cause)\n\n if (fieldErrors) {\n for (const [field, fieldError] of Object.entries(fieldErrors)) {\n const fieldMeta = this.getFieldMeta(field as DeepKeys<TFormData>)\n if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {\n this.setFieldMeta(field as DeepKeys<TFormData>, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: fieldError,\n },\n }))\n }\n }\n }\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: formError,\n },\n }))\n\n resolve(fieldErrors ? { fieldErrors, errorMapKey } : undefined)\n }),\n )\n }\n\n let results: ValidationPromiseResult<TFormData>[] = []\n\n const fieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n if (promises.length) {\n results = await Promise.all(promises)\n for (const fieldValidationResult of results) {\n if (fieldValidationResult?.fieldErrors) {\n const { errorMapKey } = fieldValidationResult\n\n for (const [field, fieldError] of Object.entries(\n fieldValidationResult.fieldErrors,\n )) {\n const oldErrorMap =\n fieldsErrorMap[field as DeepKeys<TFormData>] || {}\n const newErrorMap = {\n ...oldErrorMap,\n [errorMapKey]: fieldError,\n }\n fieldsErrorMap[field as DeepKeys<TFormData>] = newErrorMap\n }\n }\n }\n }\n\n this.baseStore.setState((prev) => ({\n ...prev,\n isFormValidating: false,\n }))\n\n return fieldsErrorMap\n }\n\n /**\n * @private\n */\n validate = (\n cause: ValidationCause,\n ):\n | FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n | Promise<\n FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n > => {\n // Attempt to sync validate first\n const { hasErrored, fieldsErrorMap } = this.validateSync(cause)\n\n if (hasErrored && !this.options.asyncAlways) {\n return fieldsErrorMap\n }\n\n // No error? Attempt async validation\n return this.validateAsync(cause)\n }\n\n /**\n * Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks.\n */\n handleSubmit(): Promise<void>\n handleSubmit(submitMeta: TSubmitMeta): Promise<void>\n async handleSubmit(submitMeta?: TSubmitMeta): Promise<void> {\n this.baseStore.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.baseStore.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n await this.validateAllFields('submit')\n\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n await this.validate('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<TFormData>[]).forEach(\n (field) => {\n field.instance?.options.listeners?.onSubmit?.({\n value: field.instance.state.value,\n fieldApi: field.instance,\n })\n },\n )\n })\n\n try {\n // Run the submit code\n await this.options.onSubmit?.({\n value: this.state.values,\n formApi: this,\n meta: submitMeta ?? this.options.onSubmitMeta,\n } as any)\n\n batch(() => {\n this.baseStore.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n /**\n * Gets the value of the specified field.\n */\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n /**\n * Gets the metadata of the specified field.\n */\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): AnyFieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n /**\n * Gets the field info of the specified field.\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 instance: null,\n validationMetaMap: {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n })\n }\n\n /**\n * Updates the metadata of the specified field.\n */\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<AnyFieldMeta>,\n ) => {\n this.baseStore.setState((prev) => {\n return {\n ...prev,\n fieldMetaBase: {\n ...prev.fieldMetaBase,\n [field]: functionalUpdate(\n updater,\n prev.fieldMetaBase[field] as never,\n ),\n },\n }\n })\n }\n\n resetFieldMeta = <TField extends DeepKeys<TFormData>>(\n fieldMeta: Record<TField, AnyFieldMeta>,\n ): Record<TField, AnyFieldMeta> => {\n return Object.keys(fieldMeta).reduce(\n (acc: Record<TField, AnyFieldMeta>, key) => {\n const fieldKey = key as TField\n acc[fieldKey] = {\n isValidating: false,\n isTouched: false,\n isBlurred: false,\n isDirty: false,\n isPristine: true,\n errors: [],\n errorMap: {},\n }\n return acc\n },\n {} as Record<TField, AnyFieldMeta>,\n )\n }\n\n /**\n * Sets the value of the specified field and optionally updates the touched state.\n */\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: UpdateMetaOptions,\n ) => {\n const dontUpdateMeta = opts?.dontUpdateMeta ?? false\n\n batch(() => {\n if (!dontUpdateMeta) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n isDirty: true,\n errorMap: {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n ...prev?.errorMap,\n onMount: undefined,\n },\n }))\n }\n\n this.baseStore.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n deleteField = <TField extends DeepKeys<TFormData>>(field: TField) => {\n this.baseStore.setState((prev) => {\n const newState = { ...prev }\n newState.values = deleteBy(newState.values, field)\n delete newState.fieldMetaBase[field]\n\n return newState\n })\n delete this.fieldInfo[field]\n }\n\n /**\n * Pushes a value into an array field.\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?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n this.validateField(field, 'change')\n }\n\n insertFieldValue = async <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?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return [\n ...(prev as DeepValue<TFormData, TField>[]).slice(0, index),\n value,\n ...(prev as DeepValue<TFormData, TField>[]).slice(index),\n ] as any\n },\n opts,\n )\n\n // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n\n // Shift down all meta after validating to make sure the new field has been mounted\n metaHelper(this).handleArrayFieldMetaShift(field, index, 'insert')\n\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Replaces a value into an array field at the specified index.\n */\n replaceFieldValue = async <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?: UpdateMetaOptions,\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 // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Removes a value from an array field at the specified index.\n */\n removeFieldValue = async <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: UpdateMetaOptions,\n ) => {\n const fieldValue = this.getFieldValue(field)\n\n const lastIndex = Array.isArray(fieldValue)\n ? Math.max(fieldValue.length - 1, 0)\n : null\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 // Shift up all meta\n metaHelper(this).handleArrayFieldMetaShift(field, index, 'remove')\n\n if (lastIndex !== null) {\n const start = `${field}[${lastIndex}]`\n const fieldsToDelete = Object.keys(this.fieldInfo).filter((f) =>\n f.startsWith(start),\n )\n\n // Cleanup the last fields\n fieldsToDelete.forEach((f) => this.deleteField(f as TField))\n }\n\n // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Swaps the values at the specified indices within an array field.\n */\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n },\n opts,\n )\n\n // Swap meta\n metaHelper(this).handleArrayFieldMetaShift(field, index1, 'swap', index2)\n\n // Validate the whole array\n this.validateField(field, 'change')\n // Validate the swapped fields\n this.validateField(`${field}[${index1}]` as DeepKeys<TFormData>, 'change')\n this.validateField(`${field}[${index2}]` as DeepKeys<TFormData>, 'change')\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 DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev: any) => {\n prev.splice(index2, 0, prev.splice(index1, 1)[0])\n return prev\n },\n opts,\n )\n\n // Move meta between index1 and index2\n metaHelper(this).handleArrayFieldMetaShift(field, index1, 'move', index2)\n\n // Validate the whole array\n this.validateField(field, 'change')\n // Validate the moved fields\n this.validateField(`${field}[${index1}]` as DeepKeys<TFormData>, 'change')\n this.validateField(`${field}[${index2}]` as DeepKeys<TFormData>, 'change')\n }\n /**\n * Updates the form's errorMap\n */\n setErrorMap(\n errorMap: ValidationErrorMap<\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >,\n ) {\n this.baseStore.setState(\n (prev) =>\n ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n ...errorMap,\n },\n }) as never,\n )\n }\n\n /**\n * Returns form and field level errors\n */\n getAllErrors = (): {\n form: {\n errors: Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n errorMap: FormValidationErrorMap<\n UnwrapFormValidateOrFn<TOnMount>,\n UnwrapFormValidateOrFn<TOnChange>,\n UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,\n UnwrapFormValidateOrFn<TOnBlur>,\n UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,\n UnwrapFormValidateOrFn<TOnSubmit>,\n UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,\n UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n }\n fields: Record<\n DeepKeys<TFormData>,\n { errors: ValidationError[]; errorMap: ValidationErrorMap }\n >\n } => {\n return {\n form: {\n errors: this.state.errors,\n errorMap: this.state.errorMap,\n },\n fields: Object.entries(this.state.fieldMeta).reduce(\n (acc, [fieldName, fieldMeta]) => {\n if (\n Object.keys(fieldMeta as AnyFieldMeta).length &&\n (fieldMeta as AnyFieldMeta).errors.length\n ) {\n acc[fieldName as DeepKeys<TFormData>] = {\n errors: (fieldMeta as AnyFieldMeta).errors,\n errorMap: (fieldMeta as AnyFieldMeta).errorMap,\n }\n }\n\n return acc\n },\n {} as Record<\n DeepKeys<TFormData>,\n { errors: ValidationError[]; errorMap: ValidationErrorMap }\n >,\n ),\n }\n }\n}\n\nfunction normalizeError<TFormData>(rawError?: FormValidationError<unknown>): {\n formError: ValidationError\n fieldErrors?: Partial<Record<DeepKeys<TFormData>, ValidationError>>\n} {\n if (rawError) {\n if (isGlobalFormValidationError(rawError)) {\n const formError = normalizeError(rawError.form).formError\n const fieldErrors = rawError.fields\n return { formError, fieldErrors } as never\n }\n\n return { formError: rawError }\n }\n\n return { formError: undefined }\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n case 'server':\n return 'onServer'\n case 'change':\n default:\n return 'onChange'\n }\n}\n"],"names":["opts","_a","_c","_b"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormApi.js","sources":["../../src/FormApi.ts"],"sourcesContent":["import { Derived, Store, batch } from '@tanstack/store'\nimport {\n deleteBy,\n functionalUpdate,\n getAsyncValidatorArray,\n getBy,\n getSyncValidatorArray,\n isGlobalFormValidationError,\n isNonEmptyArray,\n setBy,\n shallow,\n} from './utils'\nimport {\n isStandardSchemaValidator,\n standardSchemaValidators,\n} from './standardSchemaValidator'\nimport { metaHelper } from './metaHelper'\nimport type {\n StandardSchemaV1,\n StandardSchemaV1Issue,\n TStandardSchemaValidatorValue,\n} from './standardSchemaValidator'\nimport type { AnyFieldMeta, AnyFieldMetaBase, FieldApi } from './FieldApi'\nimport type {\n FormValidationError,\n FormValidationErrorMap,\n UpdateMetaOptions,\n ValidationCause,\n ValidationError,\n ValidationErrorMap,\n ValidationErrorMapKeys,\n} from './types'\nimport type { DeepKeys, DeepValue } from './util-types'\nimport type { Updater } from './utils'\n\n/**\n * @private\n */\n// TODO: Add the `Unwrap` type to the errors\ntype FormErrorMapFromValidator<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = Partial<\n Record<\n DeepKeys<TFormData>,\n ValidationErrorMap<\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n >\n>\n\nexport type FormValidateFn<TFormData> = (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n // This is technically an edge-type; which we try to keep non-`any`, but in this case\n // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n}) => unknown\n\n/**\n * @private\n */\nexport type FormValidateOrFn<TFormData> =\n | FormValidateFn<TFormData>\n | StandardSchemaV1<TFormData, unknown>\n\nexport type UnwrapFormValidateOrFn<\n TValidateOrFn extends undefined | FormValidateOrFn<any>,\n> = [TValidateOrFn] extends [FormValidateFn<any>]\n ? ReturnType<TValidateOrFn>\n : [TValidateOrFn] extends [StandardSchemaV1<any, any>]\n ? Record<string, StandardSchemaV1Issue[]>\n : undefined\n\n/**\n * @private\n */\nexport type FormValidateAsyncFn<TFormData> = (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n // This is technically an edge-type; which we try to keep non-`any`, but in this case\n // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n signal: AbortSignal\n}) => unknown | Promise<unknown>\n\nexport type FormValidator<TFormData, TType, TFn = unknown> = {\n validate(options: { value: TType }, fn: TFn): ValidationError\n validateAsync(\n options: { value: TType },\n fn: TFn,\n ): Promise<FormValidationError<TFormData>>\n}\n\ntype ValidationPromiseResult<TFormData> =\n | {\n fieldErrors: Partial<Record<DeepKeys<TFormData>, ValidationError>>\n errorMapKey: ValidationErrorMapKeys\n }\n | undefined\n\n/**\n * @private\n */\nexport type FormAsyncValidateOrFn<TFormData> =\n | FormValidateAsyncFn<TFormData>\n | StandardSchemaV1<TFormData, unknown>\n\nexport type UnwrapFormAsyncValidateOrFn<\n TValidateOrFn extends undefined | FormAsyncValidateOrFn<any>,\n> = [TValidateOrFn] extends [FormValidateAsyncFn<any>]\n ? Awaited<ReturnType<TValidateOrFn>>\n : [TValidateOrFn] extends [StandardSchemaV1<any, any>]\n ? Record<string, StandardSchemaV1Issue[]>\n : undefined\n\nexport interface FormValidators<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n> {\n /**\n * Optional function that fires as soon as the component mounts.\n */\n onMount?: TOnMount\n /**\n * Optional function that checks the validity of your data whenever a value changes\n */\n onChange?: TOnChange\n /**\n * Optional onChange asynchronous counterpart to onChange. Useful for more complex validation logic that might involve server requests.\n */\n onChangeAsync?: TOnChangeAsync\n /**\n * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds.\n */\n onChangeAsyncDebounceMs?: number\n /**\n * Optional function that validates the form data when a field loses focus, returns a `FormValidationError`\n */\n onBlur?: TOnBlur\n /**\n * Optional onBlur asynchronous validation method for when a field loses focus returns a ` FormValidationError` or a promise of `Promise<FormValidationError>`\n */\n onBlurAsync?: TOnBlurAsync\n /**\n * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds.\n */\n onBlurAsyncDebounceMs?: number\n onSubmit?: TOnSubmit\n onSubmitAsync?: TOnSubmitAsync\n}\n\n/**\n * @private\n */\nexport interface FormTransform<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n fn: (\n formBase: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) => FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n deps: unknown[]\n}\n\n/**\n * An object representing the options for a form.\n */\nexport interface FormOptions<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n /**\n * Set initial values for your form.\n */\n defaultValues?: TFormData\n /**\n * The default state for the form.\n */\n defaultState?: Partial<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n /**\n * If true, always run async validation, even when sync validation has produced an error. Defaults to undefined.\n */\n asyncAlways?: boolean\n /**\n * Optional time in milliseconds if you want to introduce a delay before firing off an async action.\n */\n asyncDebounceMs?: number\n /**\n * A list of validators to pass to the form\n */\n validators?: FormValidators<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n\n /**\n * onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props\n */\n onSubmitMeta?: TSubmitMeta\n\n /**\n * A function to be called when the form is submitted, what should happen once the user submits a valid form returns `any` or a promise `Promise<any>`\n */\n onSubmit?: (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n meta: TSubmitMeta\n }) => any | Promise<any>\n /**\n * Specify an action for scenarios where the user tries to submit an invalid form.\n */\n onSubmitInvalid?: (props: {\n value: TFormData\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n }) => void\n transform?: FormTransform<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n}\n\n/**\n * An object representing the validation metadata for a field. Not intended for public usage.\n */\nexport type ValidationMeta = {\n /**\n * An abort controller stored in memory to cancel previous async validation attempts.\n */\n lastAbortController: AbortController\n}\n\n/**\n * An object representing the field information for a specific field within the form.\n */\nexport type FieldInfo<TFormData> = {\n /**\n * An instance of the FieldAPI.\n */\n instance: FieldApi<\n TFormData,\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 any,\n any,\n any,\n any,\n any,\n any\n > | null\n /**\n * A record of field validation internal handling.\n */\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n}\n\n/**\n * An object representing the current state of the form.\n */\nexport type BaseFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = {\n /**\n * The current values of the form fields.\n */\n values: TFormData\n /**\n * The error map for the form itself.\n */\n errorMap: FormValidationErrorMap<\n UnwrapFormValidateOrFn<TOnMount>,\n UnwrapFormValidateOrFn<TOnChange>,\n UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,\n UnwrapFormValidateOrFn<TOnBlur>,\n UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,\n UnwrapFormValidateOrFn<TOnSubmit>,\n UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,\n UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n /**\n * An internal mechanism used for keeping track of validation logic in a form.\n */\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n /**\n * A record of field metadata for each field in the form, not including the derived properties, like `errors` and such\n */\n fieldMetaBase: Record<DeepKeys<TFormData>, AnyFieldMetaBase>\n /**\n * A boolean indicating if the form is currently in the process of being submitted after `handleSubmit` is called.\n *\n * Goes back to `false` when submission completes for one of the following reasons:\n * - the validation step returned errors.\n * - the `onSubmit` function has completed.\n *\n * Note: if you're running async operations in your `onSubmit` function make sure to await them to ensure `isSubmitting` is set to `false` only when the async operation completes.\n *\n * This is useful for displaying loading indicators or disabling form inputs during submission.\n *\n */\n isSubmitting: boolean\n /**\n * A boolean indicating if the form has been submitted.\n */\n isSubmitted: boolean\n /**\n * A boolean indicating if the form or any of its fields are currently validating.\n */\n isValidating: boolean\n /**\n * A counter for tracking the number of submission attempts.\n */\n submissionAttempts: number\n /**\n * @private, used to force a re-evaluation of the form state when options change\n */\n _force_re_eval?: boolean\n}\n\nexport type DerivedFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = {\n /**\n * A boolean indicating if the form is currently validating.\n */\n isFormValidating: boolean\n /**\n * A boolean indicating if the form is valid.\n */\n isFormValid: boolean\n /**\n * The error array for the form itself.\n */\n errors: Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n /**\n * A boolean indicating if any of the form fields are currently validating.\n */\n isFieldsValidating: boolean\n /**\n * A boolean indicating if all the form fields are valid.\n */\n isFieldsValid: boolean\n /**\n * A boolean indicating if any of the form fields have been touched.\n */\n isTouched: boolean\n /**\n * A boolean indicating if any of the form fields have been blurred.\n */\n isBlurred: boolean\n /**\n * A boolean indicating if any of the form's fields' values have been modified by the user. `True` if the user have modified at least one of the fields. Opposite of `isPristine`.\n */\n isDirty: boolean\n /**\n * A boolean indicating if none of the form's fields' values have been modified by the user. `True` if the user have not modified any of the fields. Opposite of `isDirty`.\n */\n isPristine: boolean\n /**\n * A boolean indicating if the form and all its fields are valid.\n */\n isValid: boolean\n /**\n * A boolean indicating if the form can be submitted based on its current state.\n */\n canSubmit: boolean\n /**\n * A record of field metadata for each field in the form.\n */\n fieldMeta: Record<DeepKeys<TFormData>, AnyFieldMeta>\n}\n\nexport type FormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n> = BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n> &\n DerivedFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n\nexport type AnyFormState = FormState<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\nfunction getDefaultFormState<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n>(\n defaultState: Partial<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >,\n): BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n> {\n return {\n values: defaultState.values ?? ({} as never),\n errorMap: defaultState.errorMap ?? {},\n fieldMetaBase: defaultState.fieldMetaBase ?? ({} as never),\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n validationMetaMap: defaultState.validationMetaMap ?? {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n }\n}\n\n/**\n * @public\n *\n * A type representing the Form API with all generics set to `any` for convenience.\n */\nexport type AnyFormApi = FormApi<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\n/**\n * A class representing the Form API. It handles the logic and interactions with the form state.\n *\n * Normally, you will not need to create a new `FormApi` instance directly. Instead, you will use a framework\n * hook/function like `useForm` or `createForm` to create a new instance for you that uses your framework's reactivity model.\n * However, if you need to create a new instance manually, you can do so by calling the `new FormApi` constructor.\n */\nexport class FormApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n> {\n /**\n * The options for the form.\n */\n options: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n > = {}\n baseStore!: Store<\n BaseFormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n fieldMetaDerived!: Derived<Record<DeepKeys<TFormData>, AnyFieldMeta>>\n store!: Derived<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >\n /**\n * A record of field information for each field in the form.\n */\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>> = {} as any\n\n get state() {\n return this.store.state\n }\n\n /**\n * @private\n */\n prevTransformArray: unknown[] = []\n\n /**\n * @private Persistent store of all field validation errors originating from form-level validators.\n * Maintains the cumulative state across validation cycles, including cleared errors (undefined values).\n * This map preserves the complete validation state for all fields.\n */\n cumulativeFieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n\n /**\n * Constructs a new `FormApi` instance with the given form options.\n */\n constructor(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) {\n this.baseStore = new Store(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n )\n\n this.fieldMetaDerived = new Derived({\n deps: [this.baseStore],\n fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => {\n const prevVal = _prevVal as\n | Record<DeepKeys<TFormData>, AnyFieldMeta>\n | undefined\n const prevBaseStore = prevDepVals?.[0]\n const currBaseStore = currDepVals[0]\n\n let originalMetaCount = 0\n\n const fieldMeta = {} as FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >['fieldMeta']\n\n for (const fieldName of Object.keys(\n currBaseStore.fieldMetaBase,\n ) as Array<keyof typeof currBaseStore.fieldMetaBase>) {\n const currBaseVal = currBaseStore.fieldMetaBase[\n fieldName as never\n ] as AnyFieldMetaBase\n\n const prevBaseVal = prevBaseStore?.fieldMetaBase[\n fieldName as never\n ] as AnyFieldMetaBase | undefined\n\n const prevFieldInfo =\n prevVal?.[fieldName as never as keyof typeof prevVal]\n\n let fieldErrors = prevFieldInfo?.errors\n if (!prevBaseVal || currBaseVal.errorMap !== prevBaseVal.errorMap) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n fieldErrors = Object.values(currBaseVal.errorMap ?? {}).filter(\n (val) => val !== undefined,\n ) as never\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const fieldInstance = this.getFieldInfo(fieldName)?.instance\n\n if (fieldInstance && !fieldInstance.options.disableErrorFlat) {\n fieldErrors = (fieldErrors as undefined | string[])?.flat(\n 1,\n ) as never\n }\n }\n\n // As a primitive, we don't need to aggressively persist the same referential value for performance reasons\n const isFieldPristine = !currBaseVal.isDirty\n\n if (\n prevFieldInfo &&\n prevFieldInfo.isPristine === isFieldPristine &&\n prevFieldInfo.errors === fieldErrors &&\n currBaseVal === prevBaseVal\n ) {\n fieldMeta[fieldName] = prevFieldInfo\n originalMetaCount++\n continue\n }\n\n fieldMeta[fieldName] = {\n ...currBaseVal,\n errors: fieldErrors,\n isPristine: isFieldPristine,\n } as AnyFieldMeta\n }\n\n if (\n prevVal &&\n originalMetaCount === Object.keys(currBaseStore.fieldMetaBase).length\n ) {\n return prevVal\n }\n\n return fieldMeta\n },\n })\n\n this.store = new Derived({\n deps: [this.baseStore, this.fieldMetaDerived],\n fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => {\n const prevVal = _prevVal as\n | FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n | undefined\n const prevBaseStore = prevDepVals?.[0]\n const currBaseStore = currDepVals[0]\n\n // Computed state\n const fieldMetaValues = Object.values(currBaseStore.fieldMetaBase) as (\n | AnyFieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some(\n (field) =>\n field?.errorMap &&\n isNonEmptyArray(Object.values(field.errorMap).filter(Boolean)),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n const isBlurred = fieldMetaValues.some((field) => field?.isBlurred)\n\n const shouldInvalidateOnMount =\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n isTouched && currBaseStore?.errorMap?.onMount\n\n const isDirty = fieldMetaValues.some((field) => field?.isDirty)\n const isPristine = !isDirty\n\n const hasOnMountError = Boolean(\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n currBaseStore.errorMap?.onMount ||\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n fieldMetaValues.some((f) => f?.errorMap?.onMount),\n )\n\n const isValidating = !!isFieldsValidating\n\n // As `errors` is not a primitive, we need to aggressively persist the same referencial value for performance reasons\n let errors = prevVal?.errors ?? []\n if (\n !prevBaseStore ||\n currBaseStore.errorMap !== prevBaseStore.errorMap\n ) {\n errors = Object.values(currBaseStore.errorMap).reduce<\n Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n >((prev, curr) => {\n if (curr === undefined) return prev\n\n if (curr && isGlobalFormValidationError(curr)) {\n prev.push(curr.form as never)\n return prev\n }\n prev.push(curr as never)\n return prev\n }, [])\n }\n\n const isFormValid = errors.length === 0\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (currBaseStore.submissionAttempts === 0 &&\n !isTouched &&\n !hasOnMountError) ||\n (!isValidating && !currBaseStore.isSubmitting && isValid)\n\n let errorMap = currBaseStore.errorMap\n if (shouldInvalidateOnMount) {\n errors = errors.filter(\n (err) => err !== currBaseStore.errorMap.onMount,\n )\n errorMap = Object.assign(errorMap, { onMount: undefined })\n }\n\n if (\n prevVal &&\n prevBaseStore &&\n prevVal.errorMap === errorMap &&\n prevVal.fieldMeta === this.fieldMetaDerived.state &&\n prevVal.errors === errors &&\n prevVal.isFieldsValidating === isFieldsValidating &&\n prevVal.isFieldsValid === isFieldsValid &&\n prevVal.isFormValid === isFormValid &&\n prevVal.isValid === isValid &&\n prevVal.canSubmit === canSubmit &&\n prevVal.isTouched === isTouched &&\n prevVal.isBlurred === isBlurred &&\n prevVal.isPristine === isPristine &&\n prevVal.isDirty === isDirty &&\n shallow(prevBaseStore, currBaseStore)\n ) {\n return prevVal\n }\n\n let state = {\n ...currBaseStore,\n errorMap,\n fieldMeta: this.fieldMetaDerived.state,\n errors,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n isBlurred,\n isPristine,\n isDirty,\n } as FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n\n // Only run transform if state has shallowly changed - IE how React.useEffect works\n const transformArray = this.options.transform?.deps ?? []\n const shouldTransform =\n transformArray.length !== this.prevTransformArray.length ||\n transformArray.some((val, i) => val !== this.prevTransformArray[i])\n\n if (shouldTransform) {\n const newObj = Object.assign({}, this, { state })\n // This mutates the state\n this.options.transform?.fn(newObj)\n state = newObj.state\n this.prevTransformArray = transformArray\n }\n\n return state\n },\n })\n\n this.handleSubmit = this.handleSubmit.bind(this)\n\n this.update(opts || {})\n }\n\n /**\n * @private\n */\n runValidator<\n TValue extends TStandardSchemaValidatorValue<TFormData> & {\n formApi: AnyFormApi\n },\n TType extends 'validate' | 'validateAsync',\n >(props: {\n validate: TType extends 'validate'\n ? FormValidateOrFn<TFormData>\n : FormAsyncValidateOrFn<TFormData>\n value: TValue\n type: TType\n }): unknown {\n if (isStandardSchemaValidator(props.validate)) {\n return standardSchemaValidators[props.type](\n props.value,\n props.validate,\n ) as never\n }\n\n return (props.validate as FormValidateFn<any>)(props.value) as never\n }\n\n mount = () => {\n const cleanupFieldMetaDerived = this.fieldMetaDerived.mount()\n const cleanupStoreDerived = this.store.mount()\n const cleanup = () => {\n cleanupFieldMetaDerived()\n cleanupStoreDerived()\n }\n const { onMount } = this.options.validators || {}\n if (!onMount) return cleanup\n this.validateSync('mount')\n\n return cleanup\n }\n\n /**\n * Updates the form options and form state.\n */\n update = (\n options?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n ) => {\n if (!options) return\n\n const oldOptions = this.options\n\n // Options need to be updated first so that when the store is updated, the state is correct for the derived state\n this.options = options\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const shouldUpdateReeval = !!options.transform?.deps?.some(\n (val, i) => val !== this.prevTransformArray[i],\n )\n\n const shouldUpdateValues =\n options.defaultValues &&\n !shallow(options.defaultValues, oldOptions.defaultValues) &&\n !this.state.isTouched\n\n const shouldUpdateState =\n !shallow(options.defaultState, oldOptions.defaultState) &&\n !this.state.isTouched\n\n if (!shouldUpdateValues && !shouldUpdateState && !shouldUpdateReeval) return\n\n batch(() => {\n this.baseStore.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n\n shouldUpdateState ? options.defaultState : {},\n\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n\n shouldUpdateReeval\n ? { _force_re_eval: !this.state._force_re_eval }\n : {},\n ),\n ),\n )\n })\n }\n\n /**\n * Resets the form state to the default values.\n * If values are provided, the form will be reset to those values instead and the default values will be updated.\n *\n * @param values - Optional values to reset the form to.\n * @param opts - Optional options to control the reset behavior.\n */\n reset = (values?: TFormData, opts?: { keepDefaultValues?: boolean }) => {\n const { fieldMeta: currentFieldMeta } = this.state\n const fieldMetaBase = this.resetFieldMeta(currentFieldMeta)\n\n if (values && !opts?.keepDefaultValues) {\n this.options = {\n ...this.options,\n defaultValues: values,\n }\n }\n\n this.baseStore.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values:\n values ??\n this.options.defaultValues ??\n this.options.defaultState?.values,\n fieldMetaBase,\n }),\n )\n }\n\n /**\n * Validates all fields using the correct handlers for a given validation cause.\n */\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<any>[]).forEach(\n (field) => {\n if (!field.instance) return\n const fieldInstance = field.instance\n // Validate the field\n fieldValidationPromises.push(\n // Remember, `validate` is either a sync operation or a promise\n Promise.resolve().then(() =>\n fieldInstance.validate(cause, { skipFormValidation: true }),\n ),\n )\n // If any fields are not touched\n if (!field.instance.state.meta.isTouched) {\n // Mark them as touched\n field.instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n },\n )\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\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 <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n cause: ValidationCause,\n ) => {\n const currentValue = this.getFieldValue(field)\n\n const lastIndex = Array.isArray(currentValue)\n ? Math.max(currentValue.length - 1, 0)\n : null\n\n // We have to validate all fields that have shifted (at least the current field)\n const fieldKeysToValidate = [`${field}[${index}]`]\n for (let i = index + 1; i <= (lastIndex ?? 0); i++) {\n fieldKeysToValidate.push(`${field}[${i}]`)\n }\n\n // We also have to include all fields that are nested in the shifted fields\n const fieldsToValidate = Object.keys(this.fieldInfo).filter((fieldKey) =>\n fieldKeysToValidate.some((key) => fieldKey.startsWith(key)),\n ) as DeepKeys<TFormData>[]\n\n // Validate the fields\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n batch(() => {\n fieldsToValidate.forEach((nestedField) => {\n fieldValidationPromises.push(\n Promise.resolve().then(() => this.validateField(nestedField, cause)),\n )\n })\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\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<TFormData>>(\n field: TField,\n cause: ValidationCause,\n ) => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const fieldInstance = this.fieldInfo[field]?.instance\n if (!fieldInstance) return []\n\n // If the field is not touched (same logic as in validateAllFields)\n if (!fieldInstance.state.meta.isTouched) {\n // Mark it as touched\n fieldInstance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n\n return fieldInstance.validate(cause)\n }\n\n /**\n * TODO: This code is copied from FieldApi, we should refactor to share\n * @private\n */\n validateSync = (\n cause: ValidationCause,\n ): {\n hasErrored: boolean\n fieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n } => {\n const validates = getSyncValidatorArray(cause, this.options)\n let hasErrored = false as boolean\n\n // This map will only include fields that have errors in the current validation cycle\n const currentValidationErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n\n batch(() => {\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n\n const rawError = this.runValidator({\n validate: validateObj.validate,\n value: {\n value: this.state.values,\n formApi: this,\n validationSource: 'form',\n },\n type: 'validate',\n })\n\n const { formError, fieldErrors } = normalizeError<TFormData>(rawError)\n\n const errorMapKey = getErrorMapKey(validateObj.cause)\n\n if (fieldErrors) {\n for (const [field, fieldError] of Object.entries(fieldErrors) as [\n DeepKeys<TFormData>,\n ValidationError,\n ][]) {\n const oldErrorMap = this.cumulativeFieldsErrorMap[field] || {}\n const newErrorMap = {\n ...oldErrorMap,\n [errorMapKey]: fieldError,\n }\n currentValidationErrorMap[field] = newErrorMap\n this.cumulativeFieldsErrorMap[field] = newErrorMap\n\n const fieldMeta = this.getFieldMeta(field)\n if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: fieldError,\n },\n }))\n }\n }\n }\n\n for (const field of Object.keys(this.cumulativeFieldsErrorMap) as Array<\n DeepKeys<TFormData>\n >) {\n const fieldMeta = this.getFieldMeta(field)\n if (\n fieldMeta?.errorMap[errorMapKey] &&\n !currentValidationErrorMap[field]?.[errorMapKey]\n ) {\n this.cumulativeFieldsErrorMap[field] = {\n ...this.cumulativeFieldsErrorMap[field],\n [errorMapKey]: undefined,\n }\n\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: undefined,\n },\n }))\n }\n }\n\n if (this.state.errorMap[errorMapKey] !== formError) {\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: formError,\n },\n }))\n }\n\n if (formError || fieldErrors) {\n hasErrored = true\n }\n }\n\n /**\n * when we have an error for onSubmit in the state, we want\n * to clear the error as soon as the user enters a valid value in the field\n */\n const submitErrKey = getErrorMapKey('submit')\n if (\n this.state.errorMap[submitErrKey] &&\n cause !== 'submit' &&\n !hasErrored\n ) {\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [submitErrKey]: undefined,\n },\n }))\n }\n })\n\n return { hasErrored, fieldsErrorMap: currentValidationErrorMap }\n }\n\n /**\n * @private\n */\n validateAsync = async (\n cause: ValidationCause,\n ): Promise<\n FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n > => {\n const validates = getAsyncValidatorArray(cause, this.options)\n\n if (!this.state.isFormValidating) {\n this.baseStore.setState((prev) => ({ ...prev, isFormValidating: true }))\n }\n\n /**\n * We have to use a for loop and generate our promises this way, otherwise it won't be sync\n * when there are no validators needed to be run\n */\n const promises: Promise<ValidationPromiseResult<TFormData>>[] = []\n\n let fieldErrors:\n | Partial<Record<DeepKeys<TFormData>, ValidationError>>\n | undefined\n\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n const key = getErrorMapKey(validateObj.cause)\n const fieldValidatorMeta = this.state.validationMetaMap[key]\n\n fieldValidatorMeta?.lastAbortController.abort()\n const controller = new AbortController()\n\n this.state.validationMetaMap[key] = {\n lastAbortController: controller,\n }\n\n promises.push(\n new Promise<ValidationPromiseResult<TFormData>>(async (resolve) => {\n let rawError!:\n | ValidationError\n | FormValidationError<unknown>\n | undefined\n try {\n rawError = await new Promise((rawResolve, rawReject) => {\n setTimeout(async () => {\n if (controller.signal.aborted) return rawResolve(undefined)\n try {\n rawResolve(\n await this.runValidator({\n validate: validateObj.validate!,\n value: {\n value: this.state.values,\n formApi: this,\n validationSource: 'form',\n signal: controller.signal,\n },\n type: 'validateAsync',\n }),\n )\n } catch (e) {\n rawReject(e)\n }\n }, validateObj.debounceMs)\n })\n } catch (e: unknown) {\n rawError = e as ValidationError\n }\n const { formError, fieldErrors: fieldErrorsFromNormalizeError } =\n normalizeError<TFormData>(rawError)\n\n if (fieldErrorsFromNormalizeError) {\n fieldErrors = fieldErrors\n ? { ...fieldErrors, ...fieldErrorsFromNormalizeError }\n : fieldErrorsFromNormalizeError\n }\n const errorMapKey = getErrorMapKey(validateObj.cause)\n\n if (fieldErrors) {\n for (const [field, fieldError] of Object.entries(fieldErrors)) {\n const fieldMeta = this.getFieldMeta(field as DeepKeys<TFormData>)\n if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {\n this.setFieldMeta(field as DeepKeys<TFormData>, (prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: fieldError,\n },\n }))\n }\n }\n }\n this.baseStore.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: formError,\n },\n }))\n\n resolve(fieldErrors ? { fieldErrors, errorMapKey } : undefined)\n }),\n )\n }\n\n let results: ValidationPromiseResult<TFormData>[] = []\n\n const fieldsErrorMap: FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > = {}\n if (promises.length) {\n results = await Promise.all(promises)\n for (const fieldValidationResult of results) {\n if (fieldValidationResult?.fieldErrors) {\n const { errorMapKey } = fieldValidationResult\n\n for (const [field, fieldError] of Object.entries(\n fieldValidationResult.fieldErrors,\n )) {\n const oldErrorMap =\n fieldsErrorMap[field as DeepKeys<TFormData>] || {}\n const newErrorMap = {\n ...oldErrorMap,\n [errorMapKey]: fieldError,\n }\n fieldsErrorMap[field as DeepKeys<TFormData>] = newErrorMap\n }\n }\n }\n }\n\n this.baseStore.setState((prev) => ({\n ...prev,\n isFormValidating: false,\n }))\n\n return fieldsErrorMap\n }\n\n /**\n * @private\n */\n validate = (\n cause: ValidationCause,\n ):\n | FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n | Promise<\n FormErrorMapFromValidator<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >\n > => {\n // Attempt to sync validate first\n const { hasErrored, fieldsErrorMap } = this.validateSync(cause)\n\n if (hasErrored && !this.options.asyncAlways) {\n return fieldsErrorMap\n }\n\n // No error? Attempt async validation\n return this.validateAsync(cause)\n }\n\n /**\n * Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks.\n */\n handleSubmit(): Promise<void>\n handleSubmit(submitMeta: TSubmitMeta): Promise<void>\n async handleSubmit(submitMeta?: TSubmitMeta): Promise<void> {\n this.baseStore.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.baseStore.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.baseStore.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n await this.validateAllFields('submit')\n\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n await this.validate('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<TFormData>[]).forEach(\n (field) => {\n field.instance?.options.listeners?.onSubmit?.({\n value: field.instance.state.value,\n fieldApi: field.instance,\n })\n },\n )\n })\n\n try {\n // Run the submit code\n await this.options.onSubmit?.({\n value: this.state.values,\n formApi: this,\n meta: submitMeta ?? this.options.onSubmitMeta,\n } as any)\n\n batch(() => {\n this.baseStore.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n /**\n * Gets the value of the specified field.\n */\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n /**\n * Gets the metadata of the specified field.\n */\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): AnyFieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n /**\n * Gets the field info of the specified field.\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 instance: null,\n validationMetaMap: {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n })\n }\n\n /**\n * Updates the metadata of the specified field.\n */\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<AnyFieldMeta>,\n ) => {\n this.baseStore.setState((prev) => {\n return {\n ...prev,\n fieldMetaBase: {\n ...prev.fieldMetaBase,\n [field]: functionalUpdate(\n updater,\n prev.fieldMetaBase[field] as never,\n ),\n },\n }\n })\n }\n\n resetFieldMeta = <TField extends DeepKeys<TFormData>>(\n fieldMeta: Record<TField, AnyFieldMeta>,\n ): Record<TField, AnyFieldMeta> => {\n return Object.keys(fieldMeta).reduce(\n (acc: Record<TField, AnyFieldMeta>, key) => {\n const fieldKey = key as TField\n acc[fieldKey] = {\n isValidating: false,\n isTouched: false,\n isBlurred: false,\n isDirty: false,\n isPristine: true,\n errors: [],\n errorMap: {},\n }\n return acc\n },\n {} as Record<TField, AnyFieldMeta>,\n )\n }\n\n /**\n * Sets the value of the specified field and optionally updates the touched state.\n */\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: UpdateMetaOptions,\n ) => {\n const dontUpdateMeta = opts?.dontUpdateMeta ?? false\n\n batch(() => {\n if (!dontUpdateMeta) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n isDirty: true,\n errorMap: {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n ...prev?.errorMap,\n onMount: undefined,\n },\n }))\n }\n\n this.baseStore.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n deleteField = <TField extends DeepKeys<TFormData>>(field: TField) => {\n this.baseStore.setState((prev) => {\n const newState = { ...prev }\n newState.values = deleteBy(newState.values, field)\n delete newState.fieldMetaBase[field]\n\n return newState\n })\n delete this.fieldInfo[field]\n }\n\n /**\n * Pushes a value into an array field.\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?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n this.validateField(field, 'change')\n }\n\n insertFieldValue = async <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?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return [\n ...(prev as DeepValue<TFormData, TField>[]).slice(0, index),\n value,\n ...(prev as DeepValue<TFormData, TField>[]).slice(index),\n ] as any\n },\n opts,\n )\n\n // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n\n // Shift down all meta after validating to make sure the new field has been mounted\n metaHelper(this).handleArrayFieldMetaShift(field, index, 'insert')\n\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Replaces a value into an array field at the specified index.\n */\n replaceFieldValue = async <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?: UpdateMetaOptions,\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 // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Removes a value from an array field at the specified index.\n */\n removeFieldValue = async <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: UpdateMetaOptions,\n ) => {\n const fieldValue = this.getFieldValue(field)\n\n const lastIndex = Array.isArray(fieldValue)\n ? Math.max(fieldValue.length - 1, 0)\n : null\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 // Shift up all meta\n metaHelper(this).handleArrayFieldMetaShift(field, index, 'remove')\n\n if (lastIndex !== null) {\n const start = `${field}[${lastIndex}]`\n const fieldsToDelete = Object.keys(this.fieldInfo).filter((f) =>\n f.startsWith(start),\n )\n\n // Cleanup the last fields\n fieldsToDelete.forEach((f) => this.deleteField(f as TField))\n }\n\n // Validate the whole array + all fields that have shifted\n await this.validateField(field, 'change')\n await this.validateArrayFieldsStartingFrom(field, index, 'change')\n }\n\n /**\n * Swaps the values at the specified indices within an array field.\n */\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n },\n opts,\n )\n\n // Swap meta\n metaHelper(this).handleArrayFieldMetaShift(field, index1, 'swap', index2)\n\n // Validate the whole array\n this.validateField(field, 'change')\n // Validate the swapped fields\n this.validateField(`${field}[${index1}]` as DeepKeys<TFormData>, 'change')\n this.validateField(`${field}[${index2}]` as DeepKeys<TFormData>, 'change')\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 DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n opts?: UpdateMetaOptions,\n ) => {\n this.setFieldValue(\n field,\n (prev: any) => {\n prev.splice(index2, 0, prev.splice(index1, 1)[0])\n return prev\n },\n opts,\n )\n\n // Move meta between index1 and index2\n metaHelper(this).handleArrayFieldMetaShift(field, index1, 'move', index2)\n\n // Validate the whole array\n this.validateField(field, 'change')\n // Validate the moved fields\n this.validateField(`${field}[${index1}]` as DeepKeys<TFormData>, 'change')\n this.validateField(`${field}[${index2}]` as DeepKeys<TFormData>, 'change')\n }\n /**\n * Updates the form's errorMap\n */\n setErrorMap(\n errorMap: ValidationErrorMap<\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >,\n ) {\n this.baseStore.setState(\n (prev) =>\n ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n ...errorMap,\n },\n }) as never,\n )\n }\n\n /**\n * Returns form and field level errors\n */\n getAllErrors = (): {\n form: {\n errors: Array<\n | UnwrapFormValidateOrFn<TOnMount>\n | UnwrapFormValidateOrFn<TOnChange>\n | UnwrapFormAsyncValidateOrFn<TOnChangeAsync>\n | UnwrapFormValidateOrFn<TOnBlur>\n | UnwrapFormAsyncValidateOrFn<TOnBlurAsync>\n | UnwrapFormValidateOrFn<TOnSubmit>\n | UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>\n | UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n errorMap: FormValidationErrorMap<\n UnwrapFormValidateOrFn<TOnMount>,\n UnwrapFormValidateOrFn<TOnChange>,\n UnwrapFormAsyncValidateOrFn<TOnChangeAsync>,\n UnwrapFormValidateOrFn<TOnBlur>,\n UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,\n UnwrapFormValidateOrFn<TOnSubmit>,\n UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,\n UnwrapFormAsyncValidateOrFn<TOnServer>\n >\n }\n fields: Record<\n DeepKeys<TFormData>,\n { errors: ValidationError[]; errorMap: ValidationErrorMap }\n >\n } => {\n return {\n form: {\n errors: this.state.errors,\n errorMap: this.state.errorMap,\n },\n fields: Object.entries(this.state.fieldMeta).reduce(\n (acc, [fieldName, fieldMeta]) => {\n if (\n Object.keys(fieldMeta as AnyFieldMeta).length &&\n (fieldMeta as AnyFieldMeta).errors.length\n ) {\n acc[fieldName as DeepKeys<TFormData>] = {\n errors: (fieldMeta as AnyFieldMeta).errors,\n errorMap: (fieldMeta as AnyFieldMeta).errorMap,\n }\n }\n\n return acc\n },\n {} as Record<\n DeepKeys<TFormData>,\n { errors: ValidationError[]; errorMap: ValidationErrorMap }\n >,\n ),\n }\n }\n}\n\nfunction normalizeError<TFormData>(rawError?: FormValidationError<unknown>): {\n formError: ValidationError\n fieldErrors?: Partial<Record<DeepKeys<TFormData>, ValidationError>>\n} {\n if (rawError) {\n if (isGlobalFormValidationError(rawError)) {\n const formError = normalizeError(rawError.form).formError\n const fieldErrors = rawError.fields\n return { formError, fieldErrors } as never\n }\n\n return { formError: rawError }\n }\n\n return { formError: undefined }\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n case 'server':\n return 'onServer'\n case 'change':\n default:\n return 'onChange'\n }\n}\n"],"names":["_a","opts","_c","_b"],"mappings":"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"}
|
package/package.json
CHANGED
package/src/FormApi.ts
CHANGED
|
@@ -452,6 +452,10 @@ export type BaseFormState<
|
|
|
452
452
|
* A counter for tracking the number of submission attempts.
|
|
453
453
|
*/
|
|
454
454
|
submissionAttempts: number
|
|
455
|
+
/**
|
|
456
|
+
* @private, used to force a re-evaluation of the form state when options change
|
|
457
|
+
*/
|
|
458
|
+
_force_re_eval?: boolean
|
|
455
459
|
}
|
|
456
460
|
|
|
457
461
|
export type DerivedFormState<
|
|
@@ -716,9 +720,11 @@ export class FormApi<
|
|
|
716
720
|
prevTransformArray: unknown[] = []
|
|
717
721
|
|
|
718
722
|
/**
|
|
719
|
-
* @private
|
|
723
|
+
* @private Persistent store of all field validation errors originating from form-level validators.
|
|
724
|
+
* Maintains the cumulative state across validation cycles, including cleared errors (undefined values).
|
|
725
|
+
* This map preserves the complete validation state for all fields.
|
|
720
726
|
*/
|
|
721
|
-
|
|
727
|
+
cumulativeFieldsErrorMap: FormErrorMapFromValidator<
|
|
722
728
|
TFormData,
|
|
723
729
|
TOnMount,
|
|
724
730
|
TOnChange,
|
|
@@ -1071,6 +1077,11 @@ export class FormApi<
|
|
|
1071
1077
|
// Options need to be updated first so that when the store is updated, the state is correct for the derived state
|
|
1072
1078
|
this.options = options
|
|
1073
1079
|
|
|
1080
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1081
|
+
const shouldUpdateReeval = !!options.transform?.deps?.some(
|
|
1082
|
+
(val, i) => val !== this.prevTransformArray[i],
|
|
1083
|
+
)
|
|
1084
|
+
|
|
1074
1085
|
const shouldUpdateValues =
|
|
1075
1086
|
options.defaultValues &&
|
|
1076
1087
|
!shallow(options.defaultValues, oldOptions.defaultValues) &&
|
|
@@ -1080,7 +1091,7 @@ export class FormApi<
|
|
|
1080
1091
|
!shallow(options.defaultState, oldOptions.defaultState) &&
|
|
1081
1092
|
!this.state.isTouched
|
|
1082
1093
|
|
|
1083
|
-
if (!shouldUpdateValues && !shouldUpdateState) return
|
|
1094
|
+
if (!shouldUpdateValues && !shouldUpdateState && !shouldUpdateReeval) return
|
|
1084
1095
|
|
|
1085
1096
|
batch(() => {
|
|
1086
1097
|
this.baseStore.setState(() =>
|
|
@@ -1096,6 +1107,10 @@ export class FormApi<
|
|
|
1096
1107
|
values: options.defaultValues,
|
|
1097
1108
|
}
|
|
1098
1109
|
: {},
|
|
1110
|
+
|
|
1111
|
+
shouldUpdateReeval
|
|
1112
|
+
? { _force_re_eval: !this.state._force_re_eval }
|
|
1113
|
+
: {},
|
|
1099
1114
|
),
|
|
1100
1115
|
),
|
|
1101
1116
|
)
|
|
@@ -1243,7 +1258,8 @@ export class FormApi<
|
|
|
1243
1258
|
const validates = getSyncValidatorArray(cause, this.options)
|
|
1244
1259
|
let hasErrored = false as boolean
|
|
1245
1260
|
|
|
1246
|
-
|
|
1261
|
+
// This map will only include fields that have errors in the current validation cycle
|
|
1262
|
+
const currentValidationErrorMap: FormErrorMapFromValidator<
|
|
1247
1263
|
TFormData,
|
|
1248
1264
|
TOnMount,
|
|
1249
1265
|
TOnChange,
|
|
@@ -1273,18 +1289,21 @@ export class FormApi<
|
|
|
1273
1289
|
const errorMapKey = getErrorMapKey(validateObj.cause)
|
|
1274
1290
|
|
|
1275
1291
|
if (fieldErrors) {
|
|
1276
|
-
for (const [field, fieldError] of Object.entries(fieldErrors)
|
|
1277
|
-
|
|
1278
|
-
|
|
1292
|
+
for (const [field, fieldError] of Object.entries(fieldErrors) as [
|
|
1293
|
+
DeepKeys<TFormData>,
|
|
1294
|
+
ValidationError,
|
|
1295
|
+
][]) {
|
|
1296
|
+
const oldErrorMap = this.cumulativeFieldsErrorMap[field] || {}
|
|
1279
1297
|
const newErrorMap = {
|
|
1280
1298
|
...oldErrorMap,
|
|
1281
1299
|
[errorMapKey]: fieldError,
|
|
1282
1300
|
}
|
|
1283
|
-
|
|
1301
|
+
currentValidationErrorMap[field] = newErrorMap
|
|
1302
|
+
this.cumulativeFieldsErrorMap[field] = newErrorMap
|
|
1284
1303
|
|
|
1285
|
-
const fieldMeta = this.getFieldMeta(field
|
|
1304
|
+
const fieldMeta = this.getFieldMeta(field)
|
|
1286
1305
|
if (fieldMeta && fieldMeta.errorMap[errorMapKey] !== fieldError) {
|
|
1287
|
-
this.setFieldMeta(field
|
|
1306
|
+
this.setFieldMeta(field, (prev) => ({
|
|
1288
1307
|
...prev,
|
|
1289
1308
|
errorMap: {
|
|
1290
1309
|
...prev.errorMap,
|
|
@@ -1295,14 +1314,19 @@ export class FormApi<
|
|
|
1295
1314
|
}
|
|
1296
1315
|
}
|
|
1297
1316
|
|
|
1298
|
-
for (const field of Object.keys(this.
|
|
1317
|
+
for (const field of Object.keys(this.cumulativeFieldsErrorMap) as Array<
|
|
1299
1318
|
DeepKeys<TFormData>
|
|
1300
1319
|
>) {
|
|
1301
1320
|
const fieldMeta = this.getFieldMeta(field)
|
|
1302
1321
|
if (
|
|
1303
1322
|
fieldMeta?.errorMap[errorMapKey] &&
|
|
1304
|
-
!
|
|
1323
|
+
!currentValidationErrorMap[field]?.[errorMapKey]
|
|
1305
1324
|
) {
|
|
1325
|
+
this.cumulativeFieldsErrorMap[field] = {
|
|
1326
|
+
...this.cumulativeFieldsErrorMap[field],
|
|
1327
|
+
[errorMapKey]: undefined,
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1306
1330
|
this.setFieldMeta(field, (prev) => ({
|
|
1307
1331
|
...prev,
|
|
1308
1332
|
errorMap: {
|
|
@@ -1348,9 +1372,7 @@ export class FormApi<
|
|
|
1348
1372
|
}
|
|
1349
1373
|
})
|
|
1350
1374
|
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
return { hasErrored, fieldsErrorMap: newFieldsErrorMap }
|
|
1375
|
+
return { hasErrored, fieldsErrorMap: currentValidationErrorMap }
|
|
1354
1376
|
}
|
|
1355
1377
|
|
|
1356
1378
|
/**
|