@tanstack/form-core 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/cjs/FieldApi.d.ts +94 -0
  2. package/dist/cjs/FormApi.d.ts +118 -0
  3. package/dist/cjs/index.cjs +926 -0
  4. package/dist/cjs/index.cjs.map +1 -0
  5. package/dist/cjs/index.d.cts +5 -0
  6. package/dist/cjs/index.d.ts +5 -0
  7. package/dist/cjs/index.js +926 -0
  8. package/dist/cjs/mergeForm.d.ts +4 -0
  9. package/dist/cjs/tests/FieldApi.spec.d.ts +1 -0
  10. package/dist/cjs/tests/FieldApi.test-d.d.ts +1 -0
  11. package/dist/cjs/tests/FormApi.spec.d.ts +1 -0
  12. package/dist/cjs/tests/mutateMergeDeep.spec.d.ts +1 -0
  13. package/dist/cjs/tests/utils.d.ts +1 -0
  14. package/dist/cjs/tests/utils.spec.d.ts +1 -0
  15. package/dist/cjs/types.d.ts +14 -0
  16. package/dist/cjs/utils.d.ts +57 -0
  17. package/dist/mjs/FieldApi.d.ts +94 -0
  18. package/dist/mjs/FormApi.d.ts +118 -0
  19. package/dist/mjs/index.d.mts +5 -0
  20. package/dist/mjs/index.d.ts +5 -0
  21. package/dist/mjs/index.js +926 -0
  22. package/dist/mjs/index.mjs +926 -0
  23. package/dist/mjs/index.mjs.map +1 -0
  24. package/dist/mjs/mergeForm.d.ts +4 -0
  25. package/dist/mjs/tests/FieldApi.spec.d.ts +1 -0
  26. package/dist/mjs/tests/FieldApi.test-d.d.ts +1 -0
  27. package/dist/mjs/tests/FormApi.spec.d.ts +1 -0
  28. package/dist/mjs/tests/mutateMergeDeep.spec.d.ts +1 -0
  29. package/dist/mjs/tests/utils.d.ts +1 -0
  30. package/dist/mjs/tests/utils.spec.d.ts +1 -0
  31. package/dist/mjs/types.d.ts +14 -0
  32. package/dist/mjs/utils.d.ts +57 -0
  33. package/package.json +16 -21
  34. package/src/FieldApi.ts +53 -38
  35. package/src/FormApi.ts +59 -23
  36. package/src/index.ts +1 -0
  37. package/src/mergeForm.ts +42 -0
  38. package/src/tests/FormApi.spec.ts +1 -0
  39. package/src/tests/mutateMergeDeep.spec.ts +32 -0
  40. package/src/types.ts +2 -1
  41. package/src/utils.ts +40 -23
  42. package/build/legacy/FieldApi.cjs +0 -313
  43. package/build/legacy/FieldApi.cjs.map +0 -1
  44. package/build/legacy/FieldApi.d.cts +0 -3
  45. package/build/legacy/FieldApi.d.ts +0 -3
  46. package/build/legacy/FieldApi.js +0 -288
  47. package/build/legacy/FieldApi.js.map +0 -1
  48. package/build/legacy/FormApi.cjs +0 -445
  49. package/build/legacy/FormApi.cjs.map +0 -1
  50. package/build/legacy/FormApi.d.cts +0 -3
  51. package/build/legacy/FormApi.d.ts +0 -3
  52. package/build/legacy/FormApi.js +0 -428
  53. package/build/legacy/FormApi.js.map +0 -1
  54. package/build/legacy/index.cjs +0 -31
  55. package/build/legacy/index.cjs.map +0 -1
  56. package/build/legacy/index.d.cts +0 -257
  57. package/build/legacy/index.d.ts +0 -257
  58. package/build/legacy/index.js +0 -6
  59. package/build/legacy/index.js.map +0 -1
  60. package/build/legacy/types.cjs +0 -19
  61. package/build/legacy/types.cjs.map +0 -1
  62. package/build/legacy/types.d.cts +0 -16
  63. package/build/legacy/types.d.ts +0 -16
  64. package/build/legacy/types.js +0 -1
  65. package/build/legacy/types.js.map +0 -1
  66. package/build/legacy/utils.cjs +0 -187
  67. package/build/legacy/utils.cjs.map +0 -1
  68. package/build/legacy/utils.d.cts +0 -3
  69. package/build/legacy/utils.d.ts +0 -3
  70. package/build/legacy/utils.js +0 -156
  71. package/build/legacy/utils.js.map +0 -1
  72. package/build/modern/FieldApi.cjs +0 -312
  73. package/build/modern/FieldApi.cjs.map +0 -1
  74. package/build/modern/FieldApi.d.cts +0 -3
  75. package/build/modern/FieldApi.d.ts +0 -3
  76. package/build/modern/FieldApi.js +0 -287
  77. package/build/modern/FieldApi.js.map +0 -1
  78. package/build/modern/FormApi.cjs +0 -439
  79. package/build/modern/FormApi.cjs.map +0 -1
  80. package/build/modern/FormApi.d.cts +0 -3
  81. package/build/modern/FormApi.d.ts +0 -3
  82. package/build/modern/FormApi.js +0 -422
  83. package/build/modern/FormApi.js.map +0 -1
  84. package/build/modern/index.cjs +0 -31
  85. package/build/modern/index.cjs.map +0 -1
  86. package/build/modern/index.d.cts +0 -257
  87. package/build/modern/index.d.ts +0 -257
  88. package/build/modern/index.js +0 -6
  89. package/build/modern/index.js.map +0 -1
  90. package/build/modern/types.cjs +0 -19
  91. package/build/modern/types.cjs.map +0 -1
  92. package/build/modern/types.d.cts +0 -16
  93. package/build/modern/types.d.ts +0 -16
  94. package/build/modern/types.js +0 -1
  95. package/build/modern/types.js.map +0 -1
  96. package/build/modern/utils.cjs +0 -187
  97. package/build/modern/utils.cjs.map +0 -1
  98. package/build/modern/utils.d.cts +0 -3
  99. package/build/modern/utils.d.ts +0 -3
  100. package/build/modern/utils.js +0 -156
  101. package/build/modern/utils.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/utils.ts","../../src/FormApi.ts","../../src/FieldApi.ts","../../src/mergeForm.ts"],"sourcesContent":["import type { ValidationCause, Validator } from './types'\nimport type { FormValidators } from './FormApi'\nimport type { FieldValidators } from './FieldApi'\n\nexport type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n */\nexport function getBy(obj: any, path: any) {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart: any) => {\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (Array.isArray(parent) && key !== undefined) {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n return doSet(obj)\n}\n\n/**\n * Delete a field on an object using a path, including dot notation.\n */\nexport function deleteBy(obj: any, _path: any) {\n const path = makePathArray(_path)\n\n function doDelete(parent: any): any {\n if (path.length === 1) {\n const finalPath = path[0]!\n const { [finalPath]: remove, ...rest } = parent\n return rest\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doDelete(parent[key]),\n }\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doDelete(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n }\n\n throw new Error('It seems we have created an infinite loop in deleteBy. ')\n }\n\n return doDelete(obj)\n}\n\nconst reFindNumbers0 = /^(\\d*)$/gm\nconst reFindNumbers1 = /\\.(\\d*)\\./gm\nconst reFindNumbers2 = /^(\\d*)\\./gm\nconst reFindNumbers3 = /\\.(\\d*$)/gm\nconst reFindMultiplePeriods = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\nfunction makePathArray(str: string) {\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return str\n .replace('[', '.')\n .replace(']', '')\n .replace(reFindNumbers0, intReplace)\n .replace(reFindNumbers1, `.${intReplace}.`)\n .replace(reFindNumbers2, `${intReplace}.`)\n .replace(reFindNumbers3, `.${intReplace}`)\n .replace(reFindMultiplePeriods, '.')\n .split('.')\n .map((d) => {\n if (d.indexOf(intPrefix) === 0) {\n return parseInt(d.substring(intPrefix.length), 10)\n }\n return d\n })\n}\n\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\ninterface AsyncValidatorArrayPartialOptions<T> {\n validators?: T\n asyncDebounceMs?: number\n}\n\ninterface AsyncValidator<T> {\n cause: ValidationCause\n validate: T\n debounceMs: number\n}\n\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any>\n ? Array<\n AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>\n >\n : T extends FormValidators<any, any>\n ? Array<\n AsyncValidator<\n T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onChangeAsync,\n onBlurAsync,\n onSubmitAsync,\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n onSubmitAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<any, any>\n | FormValidators<any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const changeValidator = {\n cause: 'change',\n validate: onChangeAsync,\n debounceMs: onChangeAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const blurValidator = {\n cause: 'blur',\n validate: onBlurAsync,\n debounceMs: onBlurAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n const submitValidator = {\n cause: 'submit',\n validate: onSubmitAsync,\n debounceMs: onSubmitAsyncDebounceMs ?? defaultDebounceMs,\n } as const\n\n switch (cause) {\n case 'submit':\n return [changeValidator, blurValidator, submitValidator] as never\n case 'server':\n return [] as never\n case 'blur':\n return [blurValidator] as never\n case 'change':\n default:\n return [changeValidator] as never\n }\n}\n\ninterface SyncValidatorArrayPartialOptions<T> {\n validators?: T\n}\n\ninterface SyncValidator<T> {\n cause: ValidationCause\n validate: T\n}\n\nexport function getSyncValidatorArray<T>(\n cause: ValidationCause,\n options: SyncValidatorArrayPartialOptions<T>,\n): T extends FieldValidators<any, any>\n ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>>\n : T extends FormValidators<any, any>\n ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>>\n : never {\n const { onChange, onBlur, onSubmit } = (options.validators || {}) as\n | FieldValidators<any, any>\n | FormValidators<any, any>\n\n const changeValidator = { cause: 'change', validate: onChange } as const\n const blurValidator = { cause: 'blur', validate: onBlur } as const\n const submitValidator = { cause: 'submit', validate: onSubmit } as const\n\n // Allows us to clear onServer errors\n const serverValidator = {\n cause: 'server',\n validate: () => undefined,\n } as const\n\n switch (cause) {\n case 'submit':\n return [\n changeValidator,\n blurValidator,\n submitValidator,\n serverValidator,\n ] as never\n case 'server':\n return [serverValidator] as never\n case 'blur':\n return [blurValidator, serverValidator] as never\n case 'change':\n default:\n return [changeValidator, serverValidator] as never\n }\n}\n\nexport type RequiredByKey<T, K extends keyof T> = Omit<T, K> &\n Required<Pick<T, K>>\n\ntype ComputeRange<\n N extends number,\n Result extends Array<unknown> = [],\n> = Result['length'] extends N\n ? Result\n : ComputeRange<N, [...Result, Result['length']]>\ntype Index40 = ComputeRange<40>[number]\n\n// Is this type a tuple?\ntype IsTuple<T> = T extends readonly any[] & { length: infer Length }\n ? Length extends Index40\n ? T\n : never\n : never\n\n// If this type is a tuple, what indices are allowed?\ntype AllowedIndexes<\n Tuple extends ReadonlyArray<any>,\n Keys extends number = never,\n> = Tuple extends readonly []\n ? Keys\n : Tuple extends readonly [infer _, ...infer Tail]\n ? AllowedIndexes<Tail, Keys | Tail['length']>\n : Keys\n\nexport type DeepKeys<T, TDepth extends any[] = []> = TDepth['length'] extends 5\n ? never\n : unknown extends T\n ? string\n : object extends T\n ? string\n : T extends readonly any[] & IsTuple<T>\n ? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T>, TDepth>\n : T extends any[]\n ? DeepKeys<T[number], [...TDepth, any]>\n : T extends Date\n ? never\n : T extends object\n ? (keyof T & string) | DeepKeysPrefix<T, keyof T, TDepth>\n : never\n\ntype DeepKeysPrefix<\n T,\n TPrefix,\n TDepth extends any[],\n> = TPrefix extends keyof T & (number | string)\n ? `${TPrefix}.${DeepKeys<T[TPrefix], [...TDepth, any]> & string}`\n : never\n\nexport type DeepValue<T, TProp> = T extends Record<string | number, any>\n ? TProp extends `${infer TBranch}.${infer TDeepProp}`\n ? DeepValue<T[TBranch], TDeepProp>\n : T[TProp & string]\n : never\n\ntype Narrowable = string | number | bigint | boolean\n\ntype NarrowRaw<A> =\n | (A extends [] ? [] : never)\n | (A extends Narrowable ? A : never)\n | {\n [K in keyof A]: A[K] extends Function ? A[K] : NarrowRaw<A[K]>\n }\n\nexport type Narrow<A> = Try<A, [], NarrowRaw<A>>\n\ntype Try<A1, A2, Catch = never> = A1 extends A2 ? A1 : Catch\n\n// Hack to get TypeScript to show simplified types in error messages\nexport type Pretty<T> = { [K in keyof T]: T[K] } & {}\n","import { Store } from '@tanstack/store'\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport {\n getAsyncValidatorArray,\n getSyncValidatorArray,\n deleteBy,\n functionalUpdate,\n getBy,\n isNonEmptyArray,\n setBy,\n} from './utils'\nimport type { FieldApi, FieldMeta } from './FieldApi'\nimport type {\n ValidationError,\n ValidationErrorMap,\n Validator,\n ValidationCause,\n ValidationErrorMapKeys,\n} from './types'\n\nexport type FormValidateFn<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = (props: {\n value: TFormData\n formApi: FormApi<TFormData, TFormValidator>\n}) => ValidationError\n\nexport type FormValidateOrFn<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = TFormValidator extends Validator<TFormData, infer TFN>\n ? TFN\n : FormValidateFn<TFormData, TFormValidator>\n\nexport type FormValidateAsyncFn<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = (props: {\n value: TFormData\n formApi: FormApi<TFormData, TFormValidator>\n signal: AbortSignal\n}) => ValidationError | Promise<ValidationError>\n\nexport type FormAsyncValidateOrFn<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = TFormValidator extends Validator<TFormData, infer FFN>\n ? FFN | FormValidateAsyncFn<TFormData, TFormValidator>\n : FormValidateAsyncFn<TFormData, TFormValidator>\n\nexport interface FormValidators<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n onMount?: FormValidateOrFn<TFormData, TFormValidator>\n onChange?: FormValidateOrFn<TFormData, TFormValidator>\n onChangeAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\n onChangeAsyncDebounceMs?: number\n onBlur?: FormValidateOrFn<TFormData, TFormValidator>\n onBlurAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\n onBlurAsyncDebounceMs?: number\n onSubmit?: FormValidateOrFn<TFormData, TFormValidator>\n onSubmitAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\n onSubmitAsyncDebounceMs?: number\n}\n\nexport interface FormTransform<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n fn: (\n formBase: FormApi<TFormData, TFormValidator>,\n ) => FormApi<TFormData, TFormValidator>\n deps: unknown[]\n}\n\nexport interface FormOptions<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n defaultValues?: TFormData\n defaultState?: Partial<FormState<TFormData>>\n asyncAlways?: boolean\n asyncDebounceMs?: number\n validatorAdapter?: TFormValidator\n validators?: FormValidators<TFormData, TFormValidator>\n onSubmit?: (props: {\n value: TFormData\n formApi: FormApi<TFormData, TFormValidator>\n }) => any | Promise<any>\n onSubmitInvalid?: (props: {\n value: TFormData\n formApi: FormApi<TFormData, TFormValidator>\n }) => void\n transform?: FormTransform<TFormData, TFormValidator>\n}\n\nexport type ValidationMeta = {\n lastAbortController: AbortController\n}\n\nexport type FieldInfo<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n instances: Record<\n string,\n FieldApi<\n TFormData,\n any,\n Validator<unknown, unknown> | undefined,\n TFormValidator\n >\n >\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n}\n\nexport type FormState<TFormData> = {\n values: TFormData\n // Form Validation\n isFormValidating: boolean\n isFormValid: boolean\n errors: ValidationError[]\n errorMap: ValidationErrorMap\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n // Fields\n fieldMeta: Record<DeepKeys<TFormData>, FieldMeta>\n isFieldsValidating: boolean\n isFieldsValid: boolean\n isSubmitting: boolean\n // General\n isTouched: boolean\n isSubmitted: boolean\n isValidating: boolean\n isValid: boolean\n canSubmit: boolean\n submissionAttempts: number\n}\n\nfunction getDefaultFormState<TFormData>(\n defaultState: Partial<FormState<TFormData>>,\n): FormState<TFormData> {\n return {\n values: defaultState.values ?? ({} as never),\n errors: defaultState.errors ?? [],\n errorMap: defaultState.errorMap ?? {},\n fieldMeta: defaultState.fieldMeta ?? ({} as never),\n canSubmit: defaultState.canSubmit ?? true,\n isFieldsValid: defaultState.isFieldsValid ?? false,\n isFieldsValidating: defaultState.isFieldsValidating ?? false,\n isFormValid: defaultState.isFormValid ?? false,\n isFormValidating: defaultState.isFormValidating ?? false,\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isTouched: defaultState.isTouched ?? false,\n isValid: defaultState.isValid ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n validationMetaMap: defaultState.validationMetaMap ?? {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n }\n}\n\nexport class FormApi<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n options: FormOptions<TFormData, TFormValidator> = {}\n store!: Store<FormState<TFormData>>\n // Do not use __state directly, as it is not reactive.\n // Please use form.useStore() utility to subscribe to state\n state!: FormState<TFormData>\n // // This carries the context for nested fields\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, TFormValidator>> =\n {} as any\n\n prevTransformArray: unknown[] = []\n\n constructor(opts?: FormOptions<TFormData, TFormValidator>) {\n this.store = new Store<FormState<TFormData>>(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n {\n onUpdate: () => {\n let { state } = this.store\n // Computed state\n const fieldMetaValues = Object.values(state.fieldMeta) as (\n | FieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some(\n (field) =>\n field?.errorMap &&\n isNonEmptyArray(Object.values(field.errorMap).filter(Boolean)),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n\n const isValidating = isFieldsValidating || state.isFormValidating\n state.errors = Object.values(state.errorMap).filter(\n (val: unknown) => val !== undefined,\n )\n const isFormValid = state.errors.length === 0\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (state.submissionAttempts === 0 && !isTouched) ||\n (!isValidating && !state.isSubmitting && isValid)\n\n state = {\n ...state,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n }\n\n this.state = state\n this.store.state = this.state\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 // This mutates the state\n this.options.transform?.fn(this)\n this.store.state = this.state\n this.prevTransformArray = transformArray\n }\n },\n },\n )\n\n this.state = this.store.state\n\n this.update(opts || {})\n }\n\n runValidator<\n TValue extends { value: TFormData; formApi: FormApi<any, any> },\n TType extends 'validate' | 'validateAsync',\n >(props: {\n validate: TType extends 'validate'\n ? FormValidateOrFn<TFormData, TFormValidator>\n : FormAsyncValidateOrFn<TFormData, TFormValidator>\n value: TValue\n type: TType\n }): ReturnType<ReturnType<Validator<any>>[TType]> {\n const adapter = this.options.validatorAdapter\n if (adapter && typeof props.validate !== 'function') {\n return adapter()[props.type](props.value, props.validate) as never\n }\n\n return (props.validate as FormValidateFn<any, any>)(props.value) as never\n }\n\n mount = () => {\n const { onMount } = this.options.validators || {}\n if (!onMount) return\n const error = this.runValidator({\n validate: onMount,\n value: {\n value: this.state.values,\n formApi: this,\n },\n type: 'validate',\n })\n if (error) {\n this.store.setState((prev) => ({\n ...prev,\n errorMap: { ...prev.errorMap, onMount: error },\n }))\n }\n }\n\n update = (options?: FormOptions<TFormData, TFormValidator>) => {\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 this.store.batch(() => {\n const shouldUpdateValues =\n options.defaultValues &&\n options.defaultValues !== oldOptions.defaultValues &&\n !this.state.isTouched\n\n const shouldUpdateState =\n options.defaultState !== oldOptions.defaultState &&\n !this.state.isTouched\n\n this.store.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateState ? options.defaultState : {},\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n ),\n ),\n )\n })\n }\n\n reset = () =>\n this.store.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values: this.options.defaultValues ?? this.options.defaultState?.values,\n }),\n )\n\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n this.store.batch(() => {\n void (\n Object.values(this.fieldInfo) as FieldInfo<any, TFormValidator>[]\n ).forEach((field) => {\n Object.values(field.instances).forEach((instance) => {\n // Validate the field\n fieldValidationPromises.push(\n Promise.resolve().then(() => instance.validate(cause)),\n )\n // If any fields are not touched\n if (!instance.state.meta.isTouched) {\n // Mark them as touched\n instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n })\n })\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\n }\n\n // TODO: This code is copied from FieldApi, we should refactor to share\n validateSync = (cause: ValidationCause) => {\n const validates = getSyncValidatorArray(cause, this.options)\n let hasErrored = false as boolean\n\n this.store.batch(() => {\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n\n const error = normalizeError(\n this.runValidator({\n validate: validateObj.validate,\n value: {\n value: this.state.values,\n formApi: this,\n },\n type: 'validate',\n }),\n )\n const errorMapKey = getErrorMapKey(validateObj.cause)\n if (this.state.errorMap[errorMapKey] !== error) {\n this.store.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: error,\n },\n }))\n }\n if (error) {\n hasErrored = true\n }\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.store.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [submitErrKey]: undefined,\n },\n }))\n }\n\n return { hasErrored }\n }\n\n validateAsync = async (\n cause: ValidationCause,\n ): Promise<ValidationError[]> => {\n const validates = getAsyncValidatorArray(cause, this.options)\n\n if (!this.state.isFormValidating) {\n this.store.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<ValidationError | 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<ValidationError | undefined>(async (resolve) => {\n let rawError!: ValidationError | 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 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 error = normalizeError(rawError)\n this.store.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n\n resolve(error)\n }),\n )\n }\n\n let results: ValidationError[] = []\n if (promises.length) {\n results = await Promise.all(promises)\n }\n\n this.store.setState((prev) => ({\n ...prev,\n isFormValidating: false,\n }))\n\n return results.filter(Boolean)\n }\n\n validate = (\n cause: ValidationCause,\n ): ValidationError[] | Promise<ValidationError[]> => {\n // Attempt to sync validate first\n const { hasErrored } = this.validateSync(cause)\n\n if (hasErrored && !this.options.asyncAlways) {\n return this.state.errors\n }\n\n // No error? Attempt async validation\n return this.validateAsync(cause)\n }\n\n handleSubmit = async () => {\n // Check to see that the form and all fields have been touched\n // If they have not, touch them all and run validation\n // Run form validation\n // Submit the form\n\n this.store.setState((old) => ({\n ...old,\n // Submission attempts mark the form as not submitted\n isSubmitted: false,\n // Count submission attempts\n submissionAttempts: old.submissionAttempts + 1,\n }))\n\n // Don't let invalid forms submit\n if (!this.state.canSubmit) return\n\n this.store.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.store.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n // Validate all fields\n await this.validateAllFields('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n // Run validation for the form\n await this.validate('submit')\n\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 try {\n // Run the submit code\n await this.options.onSubmit?.({ value: this.state.values, formApi: this })\n\n this.store.batch(() => {\n this.store.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n getFieldInfo = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldInfo<TFormData, TFormValidator> => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return (this.fieldInfo[field] ||= {\n instances: {},\n validationMetaMap: {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n })\n }\n\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<FieldMeta>,\n ) => {\n this.store.setState((prev) => {\n return {\n ...prev,\n fieldMeta: {\n ...prev.fieldMeta,\n [field]: functionalUpdate(updater, prev.fieldMeta[field]),\n },\n }\n })\n }\n\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: { touch?: boolean },\n ) => {\n const touch = opts?.touch\n\n this.store.batch(() => {\n if (touch) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n }))\n }\n\n this.store.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n deleteField = <TField extends DeepKeys<TFormData>>(field: TField) => {\n this.store.setState((prev) => {\n const newState = { ...prev }\n newState.values = deleteBy(newState.values, field)\n delete newState.fieldMeta[field]\n\n return newState\n })\n }\n\n pushFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n value: DeepValue<TFormData, TField> extends any[]\n ? DeepValue<TFormData, TField>[number]\n : never,\n opts?: { touch?: boolean },\n ) => {\n return this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n }\n\n insertFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n value: DeepValue<TFormData, TField> extends any[]\n ? DeepValue<TFormData, TField>[number]\n : never,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).map((d, i) =>\n i === index ? value : d,\n ) as any\n },\n opts,\n )\n }\n\n removeFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).filter(\n (_d, i) => i !== index,\n ) as any\n },\n opts,\n )\n }\n\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n ) => {\n this.setFieldValue(field, (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n })\n }\n}\n\nfunction normalizeError(rawError?: ValidationError) {\n if (rawError) {\n if (typeof rawError !== 'string') {\n return 'Invalid Form Values'\n }\n\n return rawError\n }\n\n return undefined\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case '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","import { Store } from '@tanstack/store'\nimport type { FormApi } from './FormApi'\nimport type {\n ValidationCause,\n ValidationError,\n ValidationErrorMap,\n Validator,\n} from './types'\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport { getAsyncValidatorArray, getSyncValidatorArray } from './utils'\n\nexport type FieldValidateFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = (props: {\n value: TData\n fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>\n}) => ValidationError\n\nexport type FieldValidateOrFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = TFieldValidator extends Validator<TData, infer TFN>\n ?\n | TFN\n | FieldValidateFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n : TFormValidator extends Validator<TParentData, infer FFN>\n ?\n | FFN\n | FieldValidateFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n : FieldValidateFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n\nexport type FieldValidateAsyncFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = (options: {\n value: TData\n fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>\n signal: AbortSignal\n}) => ValidationError | Promise<ValidationError>\n\nexport type FieldAsyncValidateOrFn<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = TFieldValidator extends Validator<TData, infer TFN>\n ?\n | TFN\n | FieldValidateAsyncFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n : TFormValidator extends Validator<TParentData, infer FFN>\n ?\n | FFN\n | FieldValidateAsyncFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n : FieldValidateAsyncFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n\nexport interface FieldValidators<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> {\n onMount?: FieldValidateOrFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n onChange?: FieldValidateOrFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n onChangeAsync?: FieldAsyncValidateOrFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n onChangeAsyncDebounceMs?: number\n onBlur?: FieldValidateOrFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n onBlurAsync?: FieldAsyncValidateOrFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n onBlurAsyncDebounceMs?: number\n onSubmit?: FieldValidateOrFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n onSubmitAsync?: FieldAsyncValidateOrFn<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n onSubmitAsyncDebounceMs?: number\n}\n\nexport interface FieldOptions<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> {\n name: TName\n index?: TData extends any[] ? number : never\n defaultValue?: TData\n asyncDebounceMs?: number\n asyncAlways?: boolean\n preserveValue?: boolean\n validatorAdapter?: TFieldValidator\n validators?: FieldValidators<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n defaultMeta?: Partial<FieldMeta>\n}\n\nexport interface FieldApiOptions<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> extends FieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n > {\n form: FormApi<TParentData, TFormValidator>\n}\n\nexport type FieldMeta = {\n isTouched: boolean\n touchedErrors: ValidationError[]\n errors: ValidationError[]\n errorMap: ValidationErrorMap\n isValidating: boolean\n}\n\nlet uid = 0\n\nexport type FieldState<TData> = {\n value: TData\n meta: FieldMeta\n}\n\nexport type ResolveName<TParentData> = unknown extends TParentData\n ? string\n : DeepKeys<TParentData>\n\nexport class FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> {\n uid: number\n form: FieldApiOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >['form']\n name!: DeepKeys<TParentData>\n options: FieldApiOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n > = {} as any\n store!: Store<FieldState<TData>>\n state!: FieldState<TData>\n prevState!: FieldState<TData>\n\n constructor(\n opts: FieldApiOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) {\n this.form = opts.form as never\n this.uid = uid++\n // Support field prefixing from FieldScope\n // let fieldPrefix = ''\n // if (this.form.fieldName) {\n // fieldPrefix = `${this.form.fieldName}.`\n // }\n\n this.name = opts.name as never\n\n if (opts.defaultValue !== undefined) {\n this.form.setFieldValue(this.name, opts.defaultValue as never)\n }\n\n this.store = new Store<FieldState<TData>>(\n {\n value: this.getValue(),\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n meta: this._getMeta() ?? {\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...opts.defaultMeta,\n },\n },\n {\n onUpdate: () => {\n const state = this.store.state\n\n state.meta.errors = Object.values(state.meta.errorMap).filter(\n (val: unknown) => val !== undefined,\n )\n\n state.meta.touchedErrors = state.meta.isTouched\n ? state.meta.errors\n : []\n\n this.prevState = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n this.prevState = this.state\n this.options = opts as never\n }\n\n runValidator<\n TValue extends { value: TData; fieldApi: FieldApi<any, any, any, any> },\n TType extends 'validate' | 'validateAsync',\n >(props: {\n validate: TType extends 'validate'\n ? FieldValidateOrFn<any, any, any, any>\n : FieldAsyncValidateOrFn<any, any, any, any>\n value: TValue\n type: TType\n }): ReturnType<ReturnType<Validator<any>>[TType]> {\n const adapters = [\n this.form.options.validatorAdapter,\n this.options.validatorAdapter,\n ] as const\n for (const adapter of adapters) {\n if (adapter && typeof props.validate !== 'function') {\n return adapter()[props.type](props.value, props.validate) as never\n }\n }\n\n return (props.validate as FieldValidateFn<any, any>)(props.value) as never\n }\n\n mount = () => {\n const info = this.getInfo()\n info.instances[this.uid] = this as never\n const unsubscribe = this.form.store.subscribe(() => {\n this.store.batch(() => {\n const nextValue = this.getValue()\n const nextMeta = this.getMeta()\n\n if (nextValue !== this.state.value) {\n this.store.setState((prev) => ({ ...prev, value: nextValue }))\n }\n\n if (nextMeta !== this.state.meta) {\n this.store.setState((prev) => ({ ...prev, meta: nextMeta }))\n }\n })\n })\n\n this.update(this.options as never)\n const { onMount } = this.options.validators || {}\n\n if (onMount) {\n const error = this.runValidator({\n validate: onMount,\n value: {\n value: this.state.value,\n fieldApi: this,\n },\n type: 'validate',\n })\n if (error) {\n this.setMeta((prev) => ({\n ...prev,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n errorMap: { ...prev?.errorMap, onMount: error },\n }))\n }\n }\n\n return () => {\n const preserveValue = this.options.preserveValue\n unsubscribe()\n if (!preserveValue) {\n delete info.instances[this.uid]\n this.form.deleteField(this.name)\n }\n\n if (!Object.keys(info.instances).length && !preserveValue) {\n delete this.form.fieldInfo[this.name]\n }\n }\n }\n\n update = (\n opts: FieldApiOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => {\n // Default Value\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (this.state.value === undefined) {\n const formDefault =\n opts.form.options.defaultValues?.[opts.name as keyof TParentData]\n\n if (opts.defaultValue !== undefined) {\n this.setValue(opts.defaultValue as never)\n } else if (formDefault !== undefined) {\n this.setValue(formDefault as never)\n }\n }\n\n // Default Meta\n if (this._getMeta() === undefined) {\n this.setMeta(this.state.meta)\n }\n\n this.options = opts as never\n }\n\n getValue = (): TData => {\n return this.form.getFieldValue(this.name) as any\n }\n\n setValue = (\n updater: Updater<TData>,\n options?: { touch?: boolean; notify?: boolean },\n ) => {\n this.form.setFieldValue(this.name, updater as never, options)\n this.validate('change', this.state.value)\n }\n\n _getMeta = () => this.form.getFieldMeta(this.name)\n getMeta = () =>\n this._getMeta() ??\n ({\n isValidating: false,\n isTouched: false,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n ...this.options.defaultMeta,\n } as FieldMeta)\n\n setMeta = (updater: Updater<FieldMeta>) =>\n this.form.setFieldMeta(this.name, updater)\n\n getInfo = () => this.form.getFieldInfo(this.name)\n\n pushValue = (value: TData extends any[] ? TData[number] : never) =>\n this.form.pushFieldValue(this.name, value as any)\n\n insertValue = (\n index: number,\n value: TData extends any[] ? TData[number] : never,\n ) => this.form.insertFieldValue(this.name, index, value as any)\n\n removeValue = (index: number) => this.form.removeFieldValue(this.name, index)\n\n swapValues = (aIndex: number, bIndex: number) =>\n this.form.swapFieldValues(this.name, aIndex, bIndex)\n\n getSubField = <\n TSubName extends DeepKeys<TData>,\n TSubData extends DeepValue<TData, TSubName> = DeepValue<TData, TSubName>,\n >(\n name: TSubName,\n ): FieldApi<\n TData,\n TSubName,\n Validator<TSubData, unknown> | undefined,\n Validator<TData, unknown> | undefined,\n TSubData\n > =>\n new FieldApi({\n name: `${this.name}.${name}` as never,\n form: this.form,\n }) as any\n\n validateSync = (value = this.state.value, cause: ValidationCause) => {\n const validates = getSyncValidatorArray(cause, this.options)\n\n // Needs type cast as eslint errantly believes this is always falsy\n let hasErrored = false as boolean\n\n this.form.store.batch(() => {\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n const error = normalizeError(\n this.runValidator({\n validate: validateObj.validate,\n value: { value, fieldApi: this },\n type: 'validate',\n }),\n )\n const errorMapKey = getErrorMapKey(validateObj.cause)\n if (this.state.meta.errorMap[errorMapKey] !== error) {\n this.setMeta((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(validateObj.cause)]: error,\n },\n }))\n }\n if (error) {\n hasErrored = true\n }\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.meta.errorMap[submitErrKey] &&\n cause !== 'submit' &&\n !hasErrored\n ) {\n this.setMeta((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [submitErrKey]: undefined,\n },\n }))\n }\n\n return { hasErrored }\n }\n\n validateAsync = async (value = this.state.value, cause: ValidationCause) => {\n const validates = getAsyncValidatorArray(cause, this.options)\n\n if (!this.state.meta.isValidating) {\n this.setMeta((prev) => ({ ...prev, isValidating: 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<ValidationError | undefined>[] = []\n\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n const key = getErrorMapKey(validateObj.cause)\n const fieldValidatorMeta = this.getInfo().validationMetaMap[key]\n\n fieldValidatorMeta?.lastAbortController.abort()\n const controller = new AbortController()\n\n this.getInfo().validationMetaMap[key] = {\n lastAbortController: controller,\n }\n\n promises.push(\n new Promise<ValidationError | undefined>(async (resolve) => {\n let rawError!: ValidationError | 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,\n fieldApi: this,\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 error = normalizeError(rawError)\n this.setMeta((prev) => {\n return {\n ...prev,\n errorMap: {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n ...prev?.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }\n })\n\n resolve(error)\n }),\n )\n }\n\n let results: ValidationError[] = []\n if (promises.length) {\n results = await Promise.all(promises)\n }\n\n this.setMeta((prev) => ({ ...prev, isValidating: false }))\n\n return results.filter(Boolean)\n }\n\n validate = (\n cause: ValidationCause,\n value?: TData,\n ): ValidationError[] | Promise<ValidationError[]> => {\n // If the field is pristine and validatePristine is false, do not validate\n if (!this.state.meta.isTouched) return []\n\n try {\n this.form.validate(cause)\n } catch (_) {}\n\n // Attempt to sync validate first\n const { hasErrored } = this.validateSync(value, cause)\n\n if (hasErrored && !this.options.asyncAlways) {\n return this.state.meta.errors\n }\n // No error? Attempt async validation\n return this.validateAsync(value, cause)\n }\n\n handleChange = (updater: Updater<TData>) => {\n this.setValue(updater, { touch: true })\n }\n\n handleBlur = () => {\n const prevTouched = this.state.meta.isTouched\n if (!prevTouched) {\n this.setMeta((prev) => ({ ...prev, isTouched: true }))\n this.validate('change')\n }\n this.validate('blur')\n }\n}\n\nfunction normalizeError(rawError?: ValidationError) {\n if (rawError) {\n if (typeof rawError !== 'string') {\n return 'Invalid Form Values'\n }\n\n return rawError\n }\n\n return undefined\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case '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","import type { FormApi } from './FormApi'\nimport type { Validator } from './types'\n\nexport function mutateMergeDeep(target: object, source: object): object {\n const targetKeys = Object.keys(target)\n const sourceKeys = Object.keys(source)\n const keySet = new Set([...targetKeys, ...sourceKeys])\n for (const key of keySet) {\n const targetKey = key as never as keyof typeof target\n const sourceKey = key as never as keyof typeof source\n if (Array.isArray(target[targetKey]) && Array.isArray(source[sourceKey])) {\n target[targetKey] = [\n ...(target[targetKey] as []),\n ...(source[sourceKey] as []),\n ] as never\n } else if (\n typeof target[targetKey] === 'object' &&\n typeof source[sourceKey] === 'object'\n ) {\n mutateMergeDeep(target[targetKey] as {}, source[sourceKey] as {})\n } else {\n // Prevent assigning undefined to target, only if undefined is not explicitly set on source\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!(sourceKey in source) && source[sourceKey] === undefined) {\n continue\n }\n target[targetKey] = source[sourceKey] as never\n }\n }\n return target\n}\n\nexport function mergeForm<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n baseForm: FormApi<TFormData, TFormValidator>,\n state: Partial<FormApi<TFormData, TFormValidator>['state']>,\n) {\n mutateMergeDeep(baseForm.state, state)\n return baseForm\n}\n"],"names":["_a","normalizeError","getErrorMapKey","opts"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { FormApi } from './FormApi';
2
+ import type { Validator } from './types';
3
+ export declare function mutateMergeDeep(target: object, source: object): object;
4
+ export declare function mergeForm<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined>(baseForm: FormApi<TFormData, TFormValidator>, state: Partial<FormApi<TFormData, TFormValidator>['state']>): FormApi<TFormData, TFormValidator>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare function sleep(timeout: number): Promise<void>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ export type ValidationError = undefined | false | null | string;
2
+ export type Validator<Type, Fn = unknown> = () => {
3
+ validate(options: {
4
+ value: Type;
5
+ }, fn: Fn): ValidationError;
6
+ validateAsync(options: {
7
+ value: Type;
8
+ }, fn: Fn): Promise<ValidationError>;
9
+ };
10
+ export type ValidationCause = 'change' | 'blur' | 'submit' | 'mount' | 'server';
11
+ export type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`;
12
+ export type ValidationErrorMap = {
13
+ [K in ValidationErrorMapKeys]?: ValidationError;
14
+ };
@@ -0,0 +1,57 @@
1
+ import type { ValidationCause } from './types';
2
+ import type { FormValidators } from './FormApi';
3
+ import type { FieldValidators } from './FieldApi';
4
+ export type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput;
5
+ export type Updater<TInput, TOutput = TInput> = TOutput | UpdaterFn<TInput, TOutput>;
6
+ export declare function functionalUpdate<TInput, TOutput = TInput>(updater: Updater<TInput, TOutput>, input: TInput): TOutput;
7
+ /**
8
+ * Get a value from an object using a path, including dot notation.
9
+ */
10
+ export declare function getBy(obj: any, path: any): any;
11
+ /**
12
+ * Set a value on an object using a path, including dot notation.
13
+ */
14
+ export declare function setBy(obj: any, _path: any, updater: Updater<any>): any;
15
+ /**
16
+ * Delete a field on an object using a path, including dot notation.
17
+ */
18
+ export declare function deleteBy(obj: any, _path: any): any;
19
+ export declare function isNonEmptyArray(obj: any): boolean;
20
+ interface AsyncValidatorArrayPartialOptions<T> {
21
+ validators?: T;
22
+ asyncDebounceMs?: number;
23
+ }
24
+ interface AsyncValidator<T> {
25
+ cause: ValidationCause;
26
+ validate: T;
27
+ debounceMs: number;
28
+ }
29
+ export declare function getAsyncValidatorArray<T>(cause: ValidationCause, options: AsyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any> ? Array<AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>> : T extends FormValidators<any, any> ? Array<AsyncValidator<T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync']>> : never;
30
+ interface SyncValidatorArrayPartialOptions<T> {
31
+ validators?: T;
32
+ }
33
+ interface SyncValidator<T> {
34
+ cause: ValidationCause;
35
+ validate: T;
36
+ }
37
+ export declare function getSyncValidatorArray<T>(cause: ValidationCause, options: SyncValidatorArrayPartialOptions<T>): T extends FieldValidators<any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>> : T extends FormValidators<any, any> ? Array<SyncValidator<T['onChange'] | T['onBlur'] | T['onSubmit']>> : never;
38
+ export type RequiredByKey<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
39
+ type ComputeRange<N extends number, Result extends Array<unknown> = []> = Result['length'] extends N ? Result : ComputeRange<N, [...Result, Result['length']]>;
40
+ type Index40 = ComputeRange<40>[number];
41
+ type IsTuple<T> = T extends readonly any[] & {
42
+ length: infer Length;
43
+ } ? Length extends Index40 ? T : never : never;
44
+ type AllowedIndexes<Tuple extends ReadonlyArray<any>, Keys extends number = never> = Tuple extends readonly [] ? Keys : Tuple extends readonly [infer _, ...infer Tail] ? AllowedIndexes<Tail, Keys | Tail['length']> : Keys;
45
+ export type DeepKeys<T, TDepth extends any[] = []> = TDepth['length'] extends 5 ? never : unknown extends T ? string : object extends T ? string : T extends readonly any[] & IsTuple<T> ? AllowedIndexes<T> | DeepKeysPrefix<T, AllowedIndexes<T>, TDepth> : T extends any[] ? DeepKeys<T[number], [...TDepth, any]> : T extends Date ? never : T extends object ? (keyof T & string) | DeepKeysPrefix<T, keyof T, TDepth> : never;
46
+ type DeepKeysPrefix<T, TPrefix, TDepth extends any[]> = TPrefix extends keyof T & (number | string) ? `${TPrefix}.${DeepKeys<T[TPrefix], [...TDepth, any]> & string}` : never;
47
+ export type DeepValue<T, TProp> = T extends Record<string | number, any> ? TProp extends `${infer TBranch}.${infer TDeepProp}` ? DeepValue<T[TBranch], TDeepProp> : T[TProp & string] : never;
48
+ type Narrowable = string | number | bigint | boolean;
49
+ type NarrowRaw<A> = (A extends [] ? [] : never) | (A extends Narrowable ? A : never) | {
50
+ [K in keyof A]: A[K] extends Function ? A[K] : NarrowRaw<A[K]>;
51
+ };
52
+ export type Narrow<A> = Try<A, [], NarrowRaw<A>>;
53
+ type Try<A1, A2, Catch = never> = A1 extends A2 ? A1 : Catch;
54
+ export type Pretty<T> = {
55
+ [K in keyof T]: T[K];
56
+ } & {};
57
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/form-core",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "Powerful, type-safe, framework agnostic forms.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -11,46 +11,41 @@
11
11
  "url": "https://github.com/sponsors/tannerlinsley"
12
12
  },
13
13
  "type": "module",
14
- "types": "build/legacy/index.d.ts",
15
- "main": "build/legacy/index.cjs",
16
- "module": "build/legacy/index.js",
14
+ "types": "dist/mjs/index.d.mts",
15
+ "main": "dist/cjs/index.cjs",
16
+ "module": "dist/mjs/index.mjs",
17
17
  "exports": {
18
18
  ".": {
19
19
  "import": {
20
- "types": "./build/modern/index.d.ts",
21
- "default": "./build/modern/index.js"
20
+ "types": "./dist/mjs/index.d.mts",
21
+ "default": "./dist/mjs/index.mjs"
22
22
  },
23
23
  "require": {
24
- "types": "./build/modern/index.d.cts",
25
- "default": "./build/modern/index.cjs"
24
+ "types": "./dist/cjs/index.d.cts",
25
+ "default": "./dist/cjs/index.cjs"
26
26
  }
27
27
  },
28
28
  "./package.json": "./package.json"
29
29
  },
30
30
  "sideEffects": false,
31
31
  "files": [
32
- "build",
32
+ "dist",
33
33
  "src"
34
34
  ],
35
- "nx": {
36
- "targets": {
37
- "test:build": {
38
- "dependsOn": [
39
- "build"
40
- ]
41
- }
42
- }
43
- },
44
35
  "dependencies": {
45
36
  "@tanstack/store": "0.1.3"
46
37
  },
47
38
  "scripts": {
48
- "clean": "rimraf ./build && rimraf ./coverage",
39
+ "clean": "rimraf ./dist && rimraf ./coverage",
49
40
  "test:eslint": "eslint --ext .ts,.tsx ./src",
50
- "test:types": "tsc --noEmit && vitest typecheck",
41
+ "test:types:versions49": "../../node_modules/typescript49/bin/tsc --noEmit",
42
+ "test:types:versions50": "../../node_modules/typescript50/bin/tsc --noEmit",
43
+ "test:types:versions51": "../../node_modules/typescript51/bin/tsc --noEmit",
44
+ "test:types:versions52": "tsc --noEmit",
45
+ "test:types": "pnpm run \"/^test:types:versions.*/\" && vitest --typecheck",
51
46
  "test:lib": "vitest run --coverage",
52
47
  "test:lib:dev": "pnpm run test:lib --watch",
53
48
  "test:build": "publint --strict",
54
- "build": "tsup"
49
+ "build": "vite build"
55
50
  }
56
51
  }
package/src/FieldApi.ts CHANGED
@@ -45,16 +45,22 @@ export type FieldValidateOrFn<
45
45
  TData
46
46
  >
47
47
  : TFormValidator extends Validator<TParentData, infer FFN>
48
- ?
49
- | FFN
50
- | FieldValidateFn<
51
- TParentData,
52
- TName,
53
- TFieldValidator,
54
- TFormValidator,
55
- TData
56
- >
57
- : FieldValidateFn<TParentData, TName, TFieldValidator, TFormValidator, TData>
48
+ ?
49
+ | FFN
50
+ | FieldValidateFn<
51
+ TParentData,
52
+ TName,
53
+ TFieldValidator,
54
+ TFormValidator,
55
+ TData
56
+ >
57
+ : FieldValidateFn<
58
+ TParentData,
59
+ TName,
60
+ TFieldValidator,
61
+ TFormValidator,
62
+ TData
63
+ >
58
64
 
59
65
  export type FieldValidateAsyncFn<
60
66
  TParentData,
@@ -93,22 +99,22 @@ export type FieldAsyncValidateOrFn<
93
99
  TData
94
100
  >
95
101
  : TFormValidator extends Validator<TParentData, infer FFN>
96
- ?
97
- | FFN
98
- | FieldValidateAsyncFn<
99
- TParentData,
100
- TName,
101
- TFieldValidator,
102
- TFormValidator,
103
- TData
104
- >
105
- : FieldValidateAsyncFn<
106
- TParentData,
107
- TName,
108
- TFieldValidator,
109
- TFormValidator,
110
- TData
111
- >
102
+ ?
103
+ | FFN
104
+ | FieldValidateAsyncFn<
105
+ TParentData,
106
+ TName,
107
+ TFieldValidator,
108
+ TFormValidator,
109
+ TData
110
+ >
111
+ : FieldValidateAsyncFn<
112
+ TParentData,
113
+ TName,
114
+ TFieldValidator,
115
+ TFormValidator,
116
+ TData
117
+ >
112
118
 
113
119
  export interface FieldValidators<
114
120
  TParentData,
@@ -570,8 +576,6 @@ export class FieldApi<
570
576
  const fieldValidatorMeta = this.getInfo().validationMetaMap[key]
571
577
 
572
578
  fieldValidatorMeta?.lastAbortController.abort()
573
- // Sorry Safari 12
574
- // eslint-disable-next-line compat/compat
575
579
  const controller = new AbortController()
576
580
 
577
581
  this.getInfo().validationMetaMap[key] = {
@@ -583,15 +587,23 @@ export class FieldApi<
583
587
  let rawError!: ValidationError | undefined
584
588
  try {
585
589
  rawError = await new Promise((rawResolve, rawReject) => {
586
- setTimeout(() => {
590
+ setTimeout(async () => {
587
591
  if (controller.signal.aborted) return rawResolve(undefined)
588
- this.runValidator({
589
- validate: validateObj.validate,
590
- value: { value, fieldApi: this, signal: controller.signal },
591
- type: 'validateAsync',
592
- })
593
- .then(rawResolve)
594
- .catch(rawReject)
592
+ try {
593
+ rawResolve(
594
+ await this.runValidator({
595
+ validate: validateObj.validate,
596
+ value: {
597
+ value,
598
+ fieldApi: this,
599
+ signal: controller.signal,
600
+ },
601
+ type: 'validateAsync',
602
+ }),
603
+ )
604
+ } catch (e) {
605
+ rawReject(e)
606
+ }
595
607
  }, validateObj.debounceMs)
596
608
  })
597
609
  } catch (e: unknown) {
@@ -675,11 +687,14 @@ function getErrorMapKey(cause: ValidationCause) {
675
687
  switch (cause) {
676
688
  case 'submit':
677
689
  return 'onSubmit'
678
- case 'change':
679
- return 'onChange'
680
690
  case 'blur':
681
691
  return 'onBlur'
682
692
  case 'mount':
683
693
  return 'onMount'
694
+ case 'server':
695
+ return 'onServer'
696
+ case 'change':
697
+ default:
698
+ return 'onChange'
684
699
  }
685
700
  }
package/src/FormApi.ts CHANGED
@@ -65,10 +65,20 @@ export interface FormValidators<
65
65
  onSubmitAsyncDebounceMs?: number
66
66
  }
67
67
 
68
- export type FormOptions<
68
+ export interface FormTransform<
69
69
  TFormData,
70
70
  TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
71
- > = {
71
+ > {
72
+ fn: (
73
+ formBase: FormApi<TFormData, TFormValidator>,
74
+ ) => FormApi<TFormData, TFormValidator>
75
+ deps: unknown[]
76
+ }
77
+
78
+ export interface FormOptions<
79
+ TFormData,
80
+ TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
81
+ > {
72
82
  defaultValues?: TFormData
73
83
  defaultState?: Partial<FormState<TFormData>>
74
84
  asyncAlways?: boolean
@@ -83,6 +93,7 @@ export type FormOptions<
83
93
  value: TFormData
84
94
  formApi: FormApi<TFormData, TFormValidator>
85
95
  }) => void
96
+ transform?: FormTransform<TFormData, TFormValidator>
86
97
  }
87
98
 
88
99
  export type ValidationMeta = {
@@ -151,6 +162,7 @@ function getDefaultFormState<TFormData>(
151
162
  onBlur: undefined,
152
163
  onSubmit: undefined,
153
164
  onMount: undefined,
165
+ onServer: undefined,
154
166
  },
155
167
  }
156
168
  }
@@ -168,6 +180,8 @@ export class FormApi<
168
180
  fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, TFormValidator>> =
169
181
  {} as any
170
182
 
183
+ prevTransformArray: unknown[] = []
184
+
171
185
  constructor(opts?: FormOptions<TFormData, TFormValidator>) {
172
186
  this.store = new Store<FormState<TFormData>>(
173
187
  getDefaultFormState({
@@ -216,8 +230,21 @@ export class FormApi<
216
230
  isTouched,
217
231
  }
218
232
 
219
- this.store.state = state
220
233
  this.state = state
234
+ this.store.state = this.state
235
+
236
+ // Only run transform if state has shallowly changed - IE how React.useEffect works
237
+ const transformArray = this.options.transform?.deps ?? []
238
+ const shouldTransform =
239
+ transformArray.length !== this.prevTransformArray.length ||
240
+ transformArray.some((val, i) => val !== this.prevTransformArray[i])
241
+
242
+ if (shouldTransform) {
243
+ // This mutates the state
244
+ this.options.transform?.fn(this)
245
+ this.store.state = this.state
246
+ this.prevTransformArray = transformArray
247
+ }
221
248
  },
222
249
  },
223
250
  )
@@ -267,14 +294,19 @@ export class FormApi<
267
294
  update = (options?: FormOptions<TFormData, TFormValidator>) => {
268
295
  if (!options) return
269
296
 
297
+ const oldOptions = this.options
298
+
299
+ // Options need to be updated first so that when the store is updated, the state is correct for the derived state
300
+ this.options = options
301
+
270
302
  this.store.batch(() => {
271
303
  const shouldUpdateValues =
272
304
  options.defaultValues &&
273
- options.defaultValues !== this.options.defaultValues &&
305
+ options.defaultValues !== oldOptions.defaultValues &&
274
306
  !this.state.isTouched
275
307
 
276
308
  const shouldUpdateState =
277
- options.defaultState !== this.options.defaultState &&
309
+ options.defaultState !== oldOptions.defaultState &&
278
310
  !this.state.isTouched
279
311
 
280
312
  this.store.setState(() =>
@@ -294,8 +326,6 @@ export class FormApi<
294
326
  ),
295
327
  )
296
328
  })
297
-
298
- this.options = options
299
329
  }
300
330
 
301
331
  reset = () =>
@@ -408,8 +438,6 @@ export class FormApi<
408
438
  const fieldValidatorMeta = this.state.validationMetaMap[key]
409
439
 
410
440
  fieldValidatorMeta?.lastAbortController.abort()
411
- // Sorry Safari 12
412
- // eslint-disable-next-line compat/compat
413
441
  const controller = new AbortController()
414
442
 
415
443
  this.state.validationMetaMap[key] = {
@@ -421,19 +449,23 @@ export class FormApi<
421
449
  let rawError!: ValidationError | undefined
422
450
  try {
423
451
  rawError = await new Promise((rawResolve, rawReject) => {
424
- setTimeout(() => {
452
+ setTimeout(async () => {
425
453
  if (controller.signal.aborted) return rawResolve(undefined)
426
- this.runValidator({
427
- validate: validateObj.validate!,
428
- value: {
429
- value: this.state.values,
430
- formApi: this,
431
- signal: controller.signal,
432
- },
433
- type: 'validateAsync',
434
- })
435
- .then(rawResolve)
436
- .catch(rawReject)
454
+ try {
455
+ rawResolve(
456
+ await this.runValidator({
457
+ validate: validateObj.validate!,
458
+ value: {
459
+ value: this.state.values,
460
+ formApi: this,
461
+ signal: controller.signal,
462
+ },
463
+ type: 'validateAsync',
464
+ }),
465
+ )
466
+ } catch (e) {
467
+ rawReject(e)
468
+ }
437
469
  }, validateObj.debounceMs)
438
470
  })
439
471
  } catch (e: unknown) {
@@ -563,6 +595,7 @@ export class FormApi<
563
595
  onBlur: undefined,
564
596
  onSubmit: undefined,
565
597
  onMount: undefined,
598
+ onServer: undefined,
566
599
  },
567
600
  })
568
601
  }
@@ -694,11 +727,14 @@ function getErrorMapKey(cause: ValidationCause) {
694
727
  switch (cause) {
695
728
  case 'submit':
696
729
  return 'onSubmit'
697
- case 'change':
698
- return 'onChange'
699
730
  case 'blur':
700
731
  return 'onBlur'
701
732
  case 'mount':
702
733
  return 'onMount'
734
+ case 'server':
735
+ return 'onServer'
736
+ case 'change':
737
+ default:
738
+ return 'onChange'
703
739
  }
704
740
  }
package/src/index.ts CHANGED
@@ -2,3 +2,4 @@ export * from './FormApi'
2
2
  export * from './FieldApi'
3
3
  export * from './utils'
4
4
  export * from './types'
5
+ export * from './mergeForm'