@tanstack/form-core 0.25.2 → 0.25.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/FieldApi.cjs +10 -7
- package/dist/cjs/FieldApi.cjs.map +1 -1
- package/dist/cjs/FieldApi.d.cts +9 -27
- package/dist/cjs/FormApi.cjs +2 -3
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/FormApi.d.cts +8 -22
- package/dist/cjs/types.d.cts +9 -0
- package/dist/esm/FieldApi.d.ts +9 -27
- package/dist/esm/FieldApi.js +10 -7
- package/dist/esm/FieldApi.js.map +1 -1
- package/dist/esm/FormApi.d.ts +8 -22
- package/dist/esm/FormApi.js +2 -3
- package/dist/esm/FormApi.js.map +1 -1
- package/dist/esm/types.d.ts +9 -0
- package/package.json +1 -1
- package/src/FieldApi.ts +20 -25
- package/src/FormApi.ts +10 -10
- package/src/types.ts +10 -0
package/dist/esm/FormApi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormApi.js","sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport {\n deleteBy,\n functionalUpdate,\n getAsyncValidatorArray,\n getBy,\n getSyncValidatorArray,\n isNonEmptyArray,\n setBy,\n} from './utils'\nimport type { Updater } from './utils'\nimport type { DeepKeys, DeepValue } from './util-types'\nimport type { FieldApi, FieldMeta } from './FieldApi'\nimport type {\n ValidationCause,\n ValidationError,\n ValidationErrorMap,\n ValidationErrorMapKeys,\n Validator,\n} from './types'\n\n/**\n * @private\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\n/**\n * @private\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\n/**\n * @private\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\n/**\n * @private\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 /**\n * Optional function that fires as soon as the component mounts.\n */\n onMount?: FormValidateOrFn<TFormData, TFormValidator>\n /**\n * Optional function that checks the validity of your data whenever a value changes\n */\n onChange?: FormValidateOrFn<TFormData, TFormValidator>\n /**\n * Optional onChange asynchronous counterpart to onChange. Useful for more complex validation logic that might involve server requests.\n */\n onChangeAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\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 ValidationError\n */\n onBlur?: FormValidateOrFn<TFormData, TFormValidator>\n /**\n * Optional onBlur asynchronous validation method for when a field loses focus return a `ValidationError` or a promise of `Promise<ValidationError>`\n */\n onBlurAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\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?: FormValidateOrFn<TFormData, TFormValidator>\n onSubmitAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\n}\n\n/**\n * @private\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\n/**\n * An object representing the options for a form.\n */\nexport interface FormOptions<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\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<FormState<TFormData>>\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 validator adapter to support usage of extra validation types (IE: Zod, Yup, or Valibot usage)\n */\n validatorAdapter?: TFormValidator\n /**\n * A list of validators to pass to the form\n */\n validators?: FormValidators<TFormData, TFormValidator>\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<TFormData, TFormValidator>\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<TFormData, TFormValidator>\n }) => void\n transform?: FormTransform<TFormData, TFormValidator>\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<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n /**\n * An instance of the FieldAPI.\n */\n instance: FieldApi<\n TFormData,\n any,\n Validator<unknown, unknown> | undefined,\n TFormValidator\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 FormState<TFormData> = {\n /**\n * The current values of the form fields.\n */\n values: TFormData\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: ValidationError[]\n /**\n * The error map for the form itself.\n */\n errorMap: ValidationErrorMap\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.\n */\n fieldMeta: Record<DeepKeys<TFormData>, FieldMeta>\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 the form is currently submitting.\n */\n isSubmitting: 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'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 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 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 counter for tracking the number of submission attempts.\n */\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 isPristine: defaultState.isPristine ?? true,\n isDirty: defaultState.isDirty ?? 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\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 TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n /**\n * The options for the form.\n */\n options: FormOptions<TFormData, TFormValidator> = {}\n /**\n * A [TanStack Store instance](https://tanstack.com/store/latest/docs/reference/Store) that keeps track of the form's state.\n */\n store!: Store<FormState<TFormData>>\n /**\n * The current state of the form.\n *\n * **Note:**\n * Do not use `state` directly, as it is not reactive.\n * Please use form.useStore() utility to subscribe to state\n */\n state!: FormState<TFormData>\n /**\n * A record of field information for each field in the form.\n */\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, TFormValidator>> =\n {} as any\n\n /**\n * @private\n */\n prevTransformArray: unknown[] = []\n\n /**\n * Constructs a new `FormApi` instance with the given form options.\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 isDirty = fieldMetaValues.some((field) => field?.isDirty)\n const isPristine = !isDirty\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 isPristine,\n isDirty,\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 /**\n * @private\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 /**\n * Updates the form options and form state.\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\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 */\n reset = () => {\n const { fieldMeta: currentFieldMeta } = this.state\n const fieldMeta = this.resetFieldMeta(currentFieldMeta)\n this.store.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values: this.options.defaultValues ?? this.options.defaultState?.values,\n fieldMeta,\n }),\n )\n }\n\n /**\n * Validates all fields in the form using the correct handlers for a given validation type.\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 if (!field.instance) return\n const fieldInstance = field.instance\n // Validate the field\n fieldValidationPromises.push(\n Promise.resolve().then(() => fieldInstance.validate(cause)),\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 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 this.store.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 ts/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 = (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 /**\n * @private\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 /**\n * @private\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 /**\n * Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks.\n */\n handleSubmit = async () => {\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 /**\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 ): FieldMeta | 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, TFormValidator> => {\n // eslint-disable-next-line ts/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<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 resetFieldMeta = <TField extends DeepKeys<TFormData>>(\n fieldMeta: Record<TField, FieldMeta>,\n ): Record<TField, FieldMeta> => {\n return Object.keys(fieldMeta).reduce(\n (acc: Record<TField, FieldMeta>, key) => {\n const fieldKey = key as TField\n acc[fieldKey] = {\n isValidating: false,\n isTouched: false,\n isDirty: false,\n isPristine: true,\n touchedErrors: [],\n errors: [],\n errorMap: {},\n }\n return acc\n },\n {} as Record<TField, FieldMeta>,\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?: { 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 isDirty: 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 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?: { touch?: boolean },\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 /**\n * Inserts a value into an array field at the specified index, shifting the subsequent values to the right.\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?: { touch?: boolean },\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\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?: { 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 // 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?: { touch?: boolean },\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 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?: { touch?: boolean },\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 // 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?: { touch?: boolean },\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 // 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\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"],"names":["_a","opts"],"mappings":";;AA+QA,SAAS,oBACP,cACsB;AACf,SAAA;AAAA,IACL,QAAQ,aAAa,UAAW,CAAC;AAAA,IACjC,QAAQ,aAAa,UAAU,CAAC;AAAA,IAChC,UAAU,aAAa,YAAY,CAAC;AAAA,IACpC,WAAW,aAAa,aAAc,CAAC;AAAA,IACvC,WAAW,aAAa,aAAa;AAAA,IACrC,eAAe,aAAa,iBAAiB;AAAA,IAC7C,oBAAoB,aAAa,sBAAsB;AAAA,IACvD,aAAa,aAAa,eAAe;AAAA,IACzC,kBAAkB,aAAa,oBAAoB;AAAA,IACnD,aAAa,aAAa,eAAe;AAAA,IACzC,cAAc,aAAa,gBAAgB;AAAA,IAC3C,WAAW,aAAa,aAAa;AAAA,IACrC,YAAY,aAAa,cAAc;AAAA,IACvC,SAAS,aAAa,WAAW;AAAA,IACjC,SAAS,aAAa,WAAW;AAAA,IACjC,cAAc,aAAa,gBAAgB;AAAA,IAC3C,oBAAoB,aAAa,sBAAsB;AAAA,IACvD,mBAAmB,aAAa,qBAAqB;AAAA,MACnD,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AAAA,EAAA;AAEJ;AASO,MAAM,QAGX;AAAA;AAAA;AAAA;AAAA,EA+BA,YAAY,MAA+C;;AA3B3D,SAAA,UAAkD;AAgBlD,SAAA,YACE;AAKF,SAAA,qBAAgC;AAuGhC,SAAA,QAAQ,MAAM;AACZ,YAAM,EAAE,QAAQ,IAAI,KAAK,QAAQ,cAAc,CAAA;AAC/C,UAAI,CAAC;AAAS;AACR,YAAA,QAAQ,KAAK,aAAa;AAAA,QAC9B,UAAU;AAAA,QACV,OAAO;AAAA,UACL,OAAO,KAAK,MAAM;AAAA,UAClB,SAAS;AAAA,QACX;AAAA,QACA,MAAM;AAAA,MAAA,CACP;AACD,UAAI,OAAO;AACJ,aAAA,MAAM,SAAS,CAAC,UAAU;AAAA,UAC7B,GAAG;AAAA,UACH,UAAU,EAAE,GAAG,KAAK,UAAU,SAAS,MAAM;AAAA,QAC7C,EAAA;AAAA,MACJ;AAAA,IAAA;AAMF,SAAA,SAAS,CAAC,YAAqD;AAC7D,UAAI,CAAC;AAAS;AAEd,YAAM,aAAa,KAAK;AAGxB,WAAK,UAAU;AAEV,WAAA,MAAM,MAAM,MAAM;AACf,cAAA,qBACJ,QAAQ,iBACR,QAAQ,kBAAkB,WAAW,iBACrC,CAAC,KAAK,MAAM;AAEd,cAAM,oBACJ,QAAQ,iBAAiB,WAAW,gBACpC,CAAC,KAAK,MAAM;AAEd,aAAK,MAAM;AAAA,UAAS,MAClB;AAAA,YACE,OAAO;AAAA,cACL,CAAC;AAAA,cACD,KAAK;AAAA,cAEL,oBAAoB,QAAQ,eAAe,CAAC;AAAA,cAE5C,qBACI;AAAA,gBACE,QAAQ,QAAQ;AAAA,cAAA,IAElB,CAAC;AAAA,YACP;AAAA,UACF;AAAA,QAAA;AAAA,MACF,CACD;AAAA,IAAA;AAMH,SAAA,QAAQ,MAAM;AACZ,YAAM,EAAE,WAAW,qBAAqB,KAAK;AACvC,YAAA,YAAY,KAAK,eAAe,gBAAgB;AACtD,WAAK,MAAM;AAAA,QAAS,MAAA;;AAClB,qCAAoB;AAAA,YAClB,GAAI,KAAK,QAAQ;AAAA,YACjB,QAAQ,KAAK,QAAQ,mBAAiBA,MAAA,KAAK,QAAQ,iBAAb,gBAAAA,IAA2B;AAAA,YACjE;AAAA,UAAA,CACD;AAAA;AAAA,MAAA;AAAA,IACH;AAMF,SAAA,oBAAoB,OAAO,UAA2B;AACpD,YAAM,0BAAwD,CAAA;AACzD,WAAA,MAAM,MAAM,MAAM;AACrB,aACE,OAAO,OAAO,KAAK,SAAS,EAC5B,QAAQ,CAAC,UAAU;AACnB,cAAI,CAAC,MAAM;AAAU;AACrB,gBAAM,gBAAgB,MAAM;AAEJ,kCAAA;AAAA,YACtB,QAAQ,UAAU,KAAK,MAAM,cAAc,SAAS,KAAK,CAAC;AAAA,UAAA;AAG5D,cAAI,CAAC,MAAM,SAAS,MAAM,KAAK,WAAW;AAElC,kBAAA,SAAS,QAAQ,CAAC,UAAU,EAAE,GAAG,MAAM,WAAW,KAAO,EAAA;AAAA,UACjE;AAAA,QAAA,CACD;AAAA,MAAA,CACF;AAED,YAAM,mBAAmB,MAAM,QAAQ,IAAI,uBAAuB;AAClE,aAAO,iBAAiB;IAAK;AAMG,SAAA,kCAAA,OAChC,OACA,OACA,UACG;AACG,YAAA,eAAe,KAAK,cAAc,KAAK;AAEvC,YAAA,YAAY,MAAM,QAAQ,YAAY,IACxC,KAAK,IAAI,aAAa,SAAS,GAAG,CAAC,IACnC;AAGJ,YAAM,sBAAsB,CAAC,GAAG,KAAK,IAAI,KAAK,GAAG;AACjD,eAAS,IAAI,QAAQ,GAAG,MAAM,aAAa,IAAI,KAAK;AAClD,4BAAoB,KAAK,GAAG,KAAK,IAAI,CAAC,GAAG;AAAA,MAC3C;AAGA,YAAM,mBAAmB,OAAO,KAAK,KAAK,SAAS,EAAE;AAAA,QAAO,CAAC,aAC3D,oBAAoB,KAAK,CAAC,QAAQ,SAAS,WAAW,GAAG,CAAC;AAAA,MAAA;AAI5D,YAAM,0BAAwD,CAAA;AACzD,WAAA,MAAM,MAAM,MAAM;AACJ,yBAAA,QAAQ,CAAC,gBAAgB;AAChB,kCAAA;AAAA,YACtB,QAAQ,QAAU,EAAA,KAAK,MAAM,KAAK,cAAc,aAAa,KAAK,CAAC;AAAA,UAAA;AAAA,QACrE,CACD;AAAA,MAAA,CACF;AAED,YAAM,mBAAmB,MAAM,QAAQ,IAAI,uBAAuB;AAClE,aAAO,iBAAiB;IAAK;AAMf,SAAA,gBAAA,CACd,OACA,UACG;;AAEH,YAAM,iBAAgBA,MAAA,KAAK,UAAU,KAAK,MAApB,gBAAAA,IAAuB;AAC7C,UAAI,CAAC;AAAe,eAAO;AAG3B,UAAI,CAAC,cAAc,MAAM,KAAK,WAAW;AAEzB,sBAAA,QAAQ,CAAC,UAAU,EAAE,GAAG,MAAM,WAAW,KAAO,EAAA;AAAA,MAChE;AAEO,aAAA,cAAc,SAAS,KAAK;AAAA,IAAA;AAOrC,SAAA,eAAe,CAAC,UAA2B;AACzC,YAAM,YAAY,sBAAsB,OAAO,KAAK,OAAO;AAC3D,UAAI,aAAa;AAEZ,WAAA,MAAM,MAAM,MAAM;AACrB,mBAAW,eAAe,WAAW;AACnC,cAAI,CAAC,YAAY;AAAU;AAE3B,gBAAM,QAAQ;AAAA,YACZ,KAAK,aAAa;AAAA,cAChB,UAAU,YAAY;AAAA,cACtB,OAAO;AAAA,gBACL,OAAO,KAAK,MAAM;AAAA,gBAClB,SAAS;AAAA,cACX;AAAA,cACA,MAAM;AAAA,YAAA,CACP;AAAA,UAAA;AAEG,gBAAA,cAAc,eAAe,YAAY,KAAK;AACpD,cAAI,KAAK,MAAM,SAAS,WAAW,MAAM,OAAO;AACzC,iBAAA,MAAM,SAAS,CAAC,UAAU;AAAA,cAC7B,GAAG;AAAA,cACH,UAAU;AAAA,gBACR,GAAG,KAAK;AAAA,gBACR,CAAC,WAAW,GAAG;AAAA,cACjB;AAAA,YACA,EAAA;AAAA,UACJ;AACA,cAAI,OAAO;AACI,yBAAA;AAAA,UACf;AAAA,QACF;AAAA,MAAA,CACD;AAMK,YAAA,eAAe,eAAe,QAAQ;AAE1C,UAAA,KAAK,MAAM,SAAS,YAAY,KAChC,UAAU,YACV,CAAC,YACD;AACK,aAAA,MAAM,SAAS,CAAC,UAAU;AAAA,UAC7B,GAAG;AAAA,UACH,UAAU;AAAA,YACR,GAAG,KAAK;AAAA,YACR,CAAC,YAAY,GAAG;AAAA,UAClB;AAAA,QACA,EAAA;AAAA,MACJ;AAEA,aAAO,EAAE,WAAW;AAAA,IAAA;AAMtB,SAAA,gBAAgB,OACd,UAC+B;AAC/B,YAAM,YAAY,uBAAuB,OAAO,KAAK,OAAO;AAExD,UAAA,CAAC,KAAK,MAAM,kBAAkB;AAC3B,aAAA,MAAM,SAAS,CAAC,UAAU,EAAE,GAAG,MAAM,kBAAkB,KAAO,EAAA;AAAA,MACrE;AAMA,YAAM,WAAmD,CAAA;AAEzD,iBAAW,eAAe,WAAW;AACnC,YAAI,CAAC,YAAY;AAAU;AACrB,cAAA,MAAM,eAAe,YAAY,KAAK;AAC5C,cAAM,qBAAqB,KAAK,MAAM,kBAAkB,GAAG;AAE3D,iEAAoB,oBAAoB;AAClC,cAAA,aAAa,IAAI;AAElB,aAAA,MAAM,kBAAkB,GAAG,IAAI;AAAA,UAClC,qBAAqB;AAAA,QAAA;AAGd,iBAAA;AAAA,UACP,IAAI,QAAqC,OAAO,YAAY;AACtD,gBAAA;AACA,gBAAA;AACF,yBAAW,MAAM,IAAI,QAAQ,CAAC,YAAY,cAAc;AACtD,2BAAW,YAAY;AACrB,sBAAI,WAAW,OAAO;AAAS,2BAAO,WAAW,MAAS;AACtD,sBAAA;AACF;AAAA,sBACE,MAAM,KAAK,aAAa;AAAA,wBACtB,UAAU,YAAY;AAAA,wBACtB,OAAO;AAAA,0BACL,OAAO,KAAK,MAAM;AAAA,0BAClB,SAAS;AAAA,0BACT,QAAQ,WAAW;AAAA,wBACrB;AAAA,wBACA,MAAM;AAAA,sBAAA,CACP;AAAA,oBAAA;AAAA,2BAEI,GAAG;AACV,8BAAU,CAAC;AAAA,kBACb;AAAA,gBAAA,GACC,YAAY,UAAU;AAAA,cAAA,CAC1B;AAAA,qBACM,GAAY;AACR,yBAAA;AAAA,YACb;AACM,kBAAA,QAAQ,eAAe,QAAQ;AAChC,iBAAA,MAAM,SAAS,CAAC,UAAU;AAAA,cAC7B,GAAG;AAAA,cACH,UAAU;AAAA,gBACR,GAAG,KAAK;AAAA,gBACR,CAAC,eAAe,KAAK,CAAC,GAAG;AAAA,cAC3B;AAAA,YACA,EAAA;AAEF,oBAAQ,KAAK;AAAA,UAAA,CACd;AAAA,QAAA;AAAA,MAEL;AAEA,UAAI,UAA6B,CAAA;AACjC,UAAI,SAAS,QAAQ;AACT,kBAAA,MAAM,QAAQ,IAAI,QAAQ;AAAA,MACtC;AAEK,WAAA,MAAM,SAAS,CAAC,UAAU;AAAA,QAC7B,GAAG;AAAA,QACH,kBAAkB;AAAA,MAClB,EAAA;AAEK,aAAA,QAAQ,OAAO,OAAO;AAAA,IAAA;AAM/B,SAAA,WAAW,CACT,UACmD;AAEnD,YAAM,EAAE,WAAe,IAAA,KAAK,aAAa,KAAK;AAE9C,UAAI,cAAc,CAAC,KAAK,QAAQ,aAAa;AAC3C,eAAO,KAAK,MAAM;AAAA,MACpB;AAGO,aAAA,KAAK,cAAc,KAAK;AAAA,IAAA;AAMjC,SAAA,eAAe,YAAY;;AACpB,WAAA,MAAM,SAAS,CAAC,SAAS;AAAA,QAC5B,GAAG;AAAA;AAAA,QAEH,aAAa;AAAA;AAAA,QAEb,oBAAoB,IAAI,qBAAqB;AAAA,MAC7C,EAAA;AAGE,UAAA,CAAC,KAAK,MAAM;AAAW;AAEtB,WAAA,MAAM,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,cAAc,KAAO,EAAA;AAEzD,YAAM,OAAO,MAAM;AACZ,aAAA,MAAM,SAAS,CAAC,UAAU,EAAE,GAAG,MAAM,cAAc,MAAQ,EAAA;AAAA,MAAA;AAI5D,YAAA,KAAK,kBAAkB,QAAQ;AAGjC,UAAA,CAAC,KAAK,MAAM,eAAe;AACxB;AACL,eAAAA,MAAA,KAAK,SAAQ,oBAAb,wBAAAA,KAA+B;AAAA,UAC7B,OAAO,KAAK,MAAM;AAAA,UAClB,SAAS;AAAA,QAAA;AAEX;AAAA,MACF;AAGM,YAAA,KAAK,SAAS,QAAQ;AAExB,UAAA,CAAC,KAAK,MAAM,SAAS;AAClB;AACL,yBAAK,SAAQ,oBAAb,4BAA+B;AAAA,UAC7B,OAAO,KAAK,MAAM;AAAA,UAClB,SAAS;AAAA,QAAA;AAEX;AAAA,MACF;AAEI,UAAA;AAEI,gBAAA,gBAAK,SAAQ,aAAb,4BAAwB,EAAE,OAAO,KAAK,MAAM,QAAQ,SAAS,KAAM;AAEpE,aAAA,MAAM,MAAM,MAAM;AAChB,eAAA,MAAM,SAAS,CAAC,UAAU,EAAE,GAAG,MAAM,aAAa,KAAO,EAAA;AACzD;QAAA,CACN;AAAA,eACM,KAAK;AACP;AACC,cAAA;AAAA,MACR;AAAA,IAAA;AAMF,SAAA,gBAAgB,CACd,UACiC,MAAM,KAAK,MAAM,QAAQ,KAAK;AAKjE,SAAA,eAAe,CACb,UAC0B;AACnB,aAAA,KAAK,MAAM,UAAU,KAAK;AAAA,IAAA;AAMnC,SAAA,eAAe,CACb,UACyC;;AAEjC,cAAAA,MAAA,KAAK,WAAL,WAAAA,IAAA,SAA0B;AAAA,QAChC,UAAU;AAAA,QACV,mBAAmB;AAAA,UACjB,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,SAAS;AAAA,UACT,UAAU;AAAA,QACZ;AAAA,MAAA;AAAA,IACF;AAMa,SAAA,eAAA,CACb,OACA,YACG;AACE,WAAA,MAAM,SAAS,CAAC,SAAS;AACrB,eAAA;AAAA,UACL,GAAG;AAAA,UACH,WAAW;AAAA,YACT,GAAG,KAAK;AAAA,YACR,CAAC,KAAK,GAAG,iBAAiB,SAAS,KAAK,UAAU,KAAK,CAAC;AAAA,UAC1D;AAAA,QAAA;AAAA,MACF,CACD;AAAA,IAAA;AAGH,SAAA,iBAAiB,CACf,cAC8B;AACvB,aAAA,OAAO,KAAK,SAAS,EAAE;AAAA,QAC5B,CAAC,KAAgC,QAAQ;AACvC,gBAAM,WAAW;AACjB,cAAI,QAAQ,IAAI;AAAA,YACd,cAAc;AAAA,YACd,WAAW;AAAA,YACX,SAAS;AAAA,YACT,YAAY;AAAA,YACZ,eAAe,CAAC;AAAA,YAChB,QAAQ,CAAC;AAAA,YACT,UAAU,CAAC;AAAA,UAAA;AAEN,iBAAA;AAAA,QACT;AAAA,QACA,CAAC;AAAA,MAAA;AAAA,IACH;AAMc,SAAA,gBAAA,CACd,OACA,SACAC,UACG;AACH,YAAM,QAAQA,SAAA,gBAAAA,MAAM;AAEf,WAAA,MAAM,MAAM,MAAM;AACrB,YAAI,OAAO;AACJ,eAAA,aAAa,OAAO,CAAC,UAAU;AAAA,YAClC,GAAG;AAAA,YACH,WAAW;AAAA,YACX,SAAS;AAAA,UACT,EAAA;AAAA,QACJ;AAEK,aAAA,MAAM,SAAS,CAAC,SAAS;AACrB,iBAAA;AAAA,YACL,GAAG;AAAA,YACH,QAAQ,MAAM,KAAK,QAAQ,OAAO,OAAO;AAAA,UAAA;AAAA,QAC3C,CACD;AAAA,MAAA,CACF;AAAA,IAAA;AAGH,SAAA,cAAc,CAAqC,UAAkB;AAC9D,WAAA,MAAM,SAAS,CAAC,SAAS;AACtB,cAAA,WAAW,EAAE,GAAG;AACtB,iBAAS,SAAS,SAAS,SAAS,QAAQ,KAAK;AAC1C,eAAA,SAAS,UAAU,KAAK;AAExB,eAAA;AAAA,MAAA,CACR;AACM,aAAA,KAAK,UAAU,KAAK;AAAA,IAAA;AAMZ,SAAA,iBAAA,CACf,OACA,OAGAA,UACG;AACE,WAAA;AAAA,QACH;AAAA,QACA,CAAC,SAAS,CAAC,GAAI,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,GAAI,KAAK;AAAA,QACtDA;AAAA,MAAA;AAEG,WAAA,cAAc,OAAO,QAAQ;AAAA,IAAA;AAMpC,SAAA,mBAAmB,OACjB,OACA,OACA,OAGAA,UACG;AACE,WAAA;AAAA,QACH;AAAA,QACA,CAAC,SAAS;AACD,iBAAA;AAAA,YACL,GAAI,KAAwC,MAAM,GAAG,KAAK;AAAA,YAC1D;AAAA,YACA,GAAI,KAAwC,MAAM,KAAK;AAAA,UAAA;AAAA,QAE3D;AAAA,QACAA;AAAA,MAAA;AAII,YAAA,KAAK,cAAc,OAAO,QAAQ;AAAA,IAAA;AAM1C,SAAA,oBAAoB,OAClB,OACA,OACA,OAGAA,UACG;AACE,WAAA;AAAA,QACH;AAAA,QACA,CAAC,SAAS;AACR,iBAAQ,KAAwC;AAAA,YAAI,CAAC,GAAG,MACtD,MAAM,QAAQ,QAAQ;AAAA,UAAA;AAAA,QAE1B;AAAA,QACAA;AAAA,MAAA;AAII,YAAA,KAAK,cAAc,OAAO,QAAQ;AACxC,YAAM,KAAK,gCAAgC,OAAO,OAAO,QAAQ;AAAA,IAAA;AAMhD,SAAA,mBAAA,OACjB,OACA,OACAA,UACG;AACG,YAAA,aAAa,KAAK,cAAc,KAAK;AAErC,YAAA,YAAY,MAAM,QAAQ,UAAU,IACtC,KAAK,IAAI,WAAW,SAAS,GAAG,CAAC,IACjC;AAEC,WAAA;AAAA,QACH;AAAA,QACA,CAAC,SAAS;AACR,iBAAQ,KAAwC;AAAA,YAC9C,CAAC,IAAI,MAAM,MAAM;AAAA,UAAA;AAAA,QAErB;AAAA,QACAA;AAAA,MAAA;AAGF,UAAI,cAAc,MAAM;AACtB,cAAM,QAAQ,GAAG,KAAK,IAAI,SAAS;AACnC,cAAM,iBAAiB,OAAO,KAAK,KAAK,SAAS,EAAE;AAAA,UAAO,CAAC,MACzD,EAAE,WAAW,KAAK;AAAA,QAAA;AAIpB,uBAAe,QAAQ,CAAC,MAAM,KAAK,YAAY,CAAW,CAAC;AAAA,MAC7D;AAGM,YAAA,KAAK,cAAc,OAAO,QAAQ;AACxC,YAAM,KAAK,gCAAgC,OAAO,OAAO,QAAQ;AAAA,IAAA;AAMnE,SAAA,kBAAkB,CAChB,OACA,QACA,QACAA,UACG;AACE,WAAA;AAAA,QACH;AAAA,QACA,CAAC,SAAc;AACP,gBAAA,QAAQ,KAAK,MAAM;AACnB,gBAAA,QAAQ,KAAK,MAAM;AAClB,iBAAA,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,KAAK,GAAG,GAAG,MAAM,IAAI,KAAK;AAAA,QAClE;AAAA,QACAA;AAAA,MAAA;AAIG,WAAA,cAAc,OAAO,QAAQ;AAElC,WAAK,cAAc,GAAG,KAAK,IAAI,MAAM,KAA4B,QAAQ;AACzE,WAAK,cAAc,GAAG,KAAK,IAAI,MAAM,KAA4B,QAAQ;AAAA,IAAA;AAM3E,SAAA,kBAAkB,CAChB,OACA,QACA,QACAA,UACG;AACE,WAAA;AAAA,QACH;AAAA,QACA,CAAC,SAAc;AACR,eAAA,OAAO,QAAQ,GAAG,KAAK,OAAO,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzC,iBAAA;AAAA,QACT;AAAA,QACAA;AAAA,MAAA;AAIG,WAAA,cAAc,OAAO,QAAQ;AAElC,WAAK,cAAc,GAAG,KAAK,IAAI,MAAM,KAA4B,QAAQ;AACzE,WAAK,cAAc,GAAG,KAAK,IAAI,MAAM,KAA4B,QAAQ;AAAA,IAAA;AA7uBzE,SAAK,QAAQ,IAAI;AAAA,MACf,oBAAoB;AAAA,QAClB,GAAI,6BAAM;AAAA,QACV,SAAQ,6BAAM,oBAAiB,kCAAM,iBAAN,mBAAoB;AAAA,QACnD,aAAa;AAAA,MAAA,CACd;AAAA,MACD;AAAA,QACE,UAAU,MAAM;;AACV,cAAA,EAAE,MAAM,IAAI,KAAK;AAErB,gBAAM,kBAAkB,OAAO,OAAO,MAAM,SAAS;AAKrD,gBAAM,qBAAqB,gBAAgB;AAAA,YACzC,CAAC,UAAU,+BAAO;AAAA,UAAA;AAGd,gBAAA,gBAAgB,CAAC,gBAAgB;AAAA,YACrC,CAAC,WACC,+BAAO,aACP,gBAAgB,OAAO,OAAO,MAAM,QAAQ,EAAE,OAAO,OAAO,CAAC;AAAA,UAAA;AAGjE,gBAAM,YAAY,gBAAgB,KAAK,CAAC,UAAU,+BAAO,SAAS;AAElE,gBAAM,UAAU,gBAAgB,KAAK,CAAC,UAAU,+BAAO,OAAO;AAC9D,gBAAM,aAAa,CAAC;AAEd,gBAAA,eAAe,sBAAsB,MAAM;AACjD,gBAAM,SAAS,OAAO,OAAO,MAAM,QAAQ,EAAE;AAAA,YAC3C,CAAC,QAAiB,QAAQ;AAAA,UAAA;AAEtB,gBAAA,cAAc,MAAM,OAAO,WAAW;AAC5C,gBAAM,UAAU,iBAAiB;AAC3B,gBAAA,YACH,MAAM,uBAAuB,KAAK,CAAC,aACnC,CAAC,gBAAgB,CAAC,MAAM,gBAAgB;AAEnC,kBAAA;AAAA,YACN,GAAG;AAAA,YACH;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UAAA;AAGF,eAAK,QAAQ;AACR,eAAA,MAAM,QAAQ,KAAK;AAGxB,gBAAM,mBAAiBD,MAAA,KAAK,QAAQ,cAAb,gBAAAA,IAAwB,SAAQ,CAAA;AACvD,gBAAM,kBACJ,eAAe,WAAW,KAAK,mBAAmB,UAClD,eAAe,KAAK,CAAC,KAAK,MAAM,QAAQ,KAAK,mBAAmB,CAAC,CAAC;AAEpE,cAAI,iBAAiB;AAEd,uBAAA,QAAQ,cAAR,mBAAmB,GAAG;AACtB,iBAAA,MAAM,QAAQ,KAAK;AACxB,iBAAK,qBAAqB;AAAA,UAC5B;AAAA,QACF;AAAA,MACF;AAAA,IAAA;AAGG,SAAA,QAAQ,KAAK,MAAM;AAEnB,SAAA,OAAO,QAAQ,CAAA,CAAE;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,aAGE,OAMgD;AAC1C,UAAA,UAAU,KAAK,QAAQ;AAC7B,QAAI,WAAW,OAAO,MAAM,aAAa,YAAY;AAC5C,aAAA,QAAA,EAAU,MAAM,IAAI,EAAE,MAAM,OAAO,MAAM,QAAQ;AAAA,IAC1D;AAEQ,WAAA,MAAM,SAAsC,MAAM,KAAK;AAAA,EACjE;AAgpBF;AAEA,SAAS,eAAe,UAA4B;AAClD,MAAI,UAAU;AACR,QAAA,OAAO,aAAa,UAAU;AACzB,aAAA;AAAA,IACT;AAEO,WAAA;AAAA,EACT;AAEO,SAAA;AACT;AAEA,SAAS,eAAe,OAAwB;AAC9C,UAAQ,OAAO;AAAA,IACb,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AACI,aAAA;AAAA,IACT,KAAK;AAAA,IACL;AACS,aAAA;AAAA,EACX;AACF;"}
|
|
1
|
+
{"version":3,"file":"FormApi.js","sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport {\n deleteBy,\n functionalUpdate,\n getAsyncValidatorArray,\n getBy,\n getSyncValidatorArray,\n isNonEmptyArray,\n setBy,\n} from './utils'\nimport type { Updater } from './utils'\nimport type { DeepKeys, DeepValue } from './util-types'\nimport type { FieldApi, FieldMeta } from './FieldApi'\nimport type {\n UpdateMetaOptions,\n ValidationCause,\n ValidationError,\n ValidationErrorMap,\n ValidationErrorMapKeys,\n Validator,\n} from './types'\n\n/**\n * @private\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\n/**\n * @private\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\n/**\n * @private\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\n/**\n * @private\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 /**\n * Optional function that fires as soon as the component mounts.\n */\n onMount?: FormValidateOrFn<TFormData, TFormValidator>\n /**\n * Optional function that checks the validity of your data whenever a value changes\n */\n onChange?: FormValidateOrFn<TFormData, TFormValidator>\n /**\n * Optional onChange asynchronous counterpart to onChange. Useful for more complex validation logic that might involve server requests.\n */\n onChangeAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\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 ValidationError\n */\n onBlur?: FormValidateOrFn<TFormData, TFormValidator>\n /**\n * Optional onBlur asynchronous validation method for when a field loses focus return a `ValidationError` or a promise of `Promise<ValidationError>`\n */\n onBlurAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\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?: FormValidateOrFn<TFormData, TFormValidator>\n onSubmitAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\n}\n\n/**\n * @private\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\n/**\n * An object representing the options for a form.\n */\nexport interface FormOptions<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\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<FormState<TFormData>>\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 validator adapter to support usage of extra validation types (IE: Zod, Yup, or Valibot usage)\n */\n validatorAdapter?: TFormValidator\n /**\n * A list of validators to pass to the form\n */\n validators?: FormValidators<TFormData, TFormValidator>\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<TFormData, TFormValidator>\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<TFormData, TFormValidator>\n }) => void\n transform?: FormTransform<TFormData, TFormValidator>\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<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n /**\n * An instance of the FieldAPI.\n */\n instance: FieldApi<\n TFormData,\n any,\n Validator<unknown, unknown> | undefined,\n TFormValidator\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 FormState<TFormData> = {\n /**\n * The current values of the form fields.\n */\n values: TFormData\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: ValidationError[]\n /**\n * The error map for the form itself.\n */\n errorMap: ValidationErrorMap\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.\n */\n fieldMeta: Record<DeepKeys<TFormData>, FieldMeta>\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 the form is currently submitting.\n */\n isSubmitting: 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'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 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 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 counter for tracking the number of submission attempts.\n */\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 isPristine: defaultState.isPristine ?? true,\n isDirty: defaultState.isDirty ?? 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\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 TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n /**\n * The options for the form.\n */\n options: FormOptions<TFormData, TFormValidator> = {}\n /**\n * A [TanStack Store instance](https://tanstack.com/store/latest/docs/reference/Store) that keeps track of the form's state.\n */\n store!: Store<FormState<TFormData>>\n /**\n * The current state of the form.\n *\n * **Note:**\n * Do not use `state` directly, as it is not reactive.\n * Please use form.useStore() utility to subscribe to state\n */\n state!: FormState<TFormData>\n /**\n * A record of field information for each field in the form.\n */\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, TFormValidator>> =\n {} as any\n\n /**\n * @private\n */\n prevTransformArray: unknown[] = []\n\n /**\n * Constructs a new `FormApi` instance with the given form options.\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 isDirty = fieldMetaValues.some((field) => field?.isDirty)\n const isPristine = !isDirty\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 isPristine,\n isDirty,\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 /**\n * @private\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 /**\n * Updates the form options and form state.\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\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 */\n reset = () => {\n const { fieldMeta: currentFieldMeta } = this.state\n const fieldMeta = this.resetFieldMeta(currentFieldMeta)\n this.store.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values: this.options.defaultValues ?? this.options.defaultState?.values,\n fieldMeta,\n }),\n )\n }\n\n /**\n * Validates all fields in the form using the correct handlers for a given validation type.\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 if (!field.instance) return\n const fieldInstance = field.instance\n // Validate the field\n fieldValidationPromises.push(\n Promise.resolve().then(() => fieldInstance.validate(cause)),\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 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 this.store.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 ts/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 = (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 /**\n * @private\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 /**\n * @private\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 /**\n * Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks.\n */\n handleSubmit = async () => {\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 /**\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 ): FieldMeta | 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, TFormValidator> => {\n // eslint-disable-next-line ts/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<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 resetFieldMeta = <TField extends DeepKeys<TFormData>>(\n fieldMeta: Record<TField, FieldMeta>,\n ): Record<TField, FieldMeta> => {\n return Object.keys(fieldMeta).reduce(\n (acc: Record<TField, FieldMeta>, key) => {\n const fieldKey = key as TField\n acc[fieldKey] = {\n isValidating: false,\n isTouched: false,\n isDirty: false,\n isPristine: true,\n errors: [],\n errorMap: {},\n }\n return acc\n },\n {} as Record<TField, FieldMeta>,\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 this.store.batch(() => {\n if (!dontUpdateMeta) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n isDirty: 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 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 /**\n * Inserts a value into an array field at the specified index, shifting the subsequent values to the right.\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\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 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 // 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 // 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\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"],"names":["_a","opts"],"mappings":"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"}
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -26,3 +26,12 @@ export type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`;
|
|
|
26
26
|
export type ValidationErrorMap = {
|
|
27
27
|
[K in ValidationErrorMapKeys]?: ValidationError;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
export interface UpdateMetaOptions {
|
|
33
|
+
/**
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
dontUpdateMeta?: boolean;
|
|
37
|
+
}
|
package/package.json
CHANGED
package/src/FieldApi.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Store } from '@tanstack/store'
|
|
2
2
|
import { getAsyncValidatorArray, getBy, getSyncValidatorArray } from './utils'
|
|
3
|
-
import type { FieldInfo, FormApi } from './FormApi'
|
|
4
3
|
import type {
|
|
4
|
+
UpdateMetaOptions,
|
|
5
5
|
ValidationCause,
|
|
6
6
|
ValidationError,
|
|
7
7
|
ValidationErrorMap,
|
|
8
8
|
Validator,
|
|
9
9
|
} from './types'
|
|
10
|
+
import type { FieldInfo, FormApi } from './FormApi'
|
|
10
11
|
import type { AsyncValidator, SyncValidator, Updater } from './utils'
|
|
11
12
|
import type { DeepKeys, DeepValue, NoInfer } from './util-types'
|
|
12
13
|
|
|
@@ -340,10 +341,6 @@ export type FieldMeta = {
|
|
|
340
341
|
* A flag that is `true` if the field's value has been modified by the user. Opposite of `isPristine`.
|
|
341
342
|
*/
|
|
342
343
|
isDirty: boolean
|
|
343
|
-
/**
|
|
344
|
-
* An array of errors related to the touched state of the field.
|
|
345
|
-
*/
|
|
346
|
-
touchedErrors: ValidationError[]
|
|
347
344
|
/**
|
|
348
345
|
* An array of errors related to the field value.
|
|
349
346
|
*/
|
|
@@ -445,7 +442,9 @@ export class FieldApi<
|
|
|
445
442
|
this.name = opts.name as never
|
|
446
443
|
|
|
447
444
|
if (opts.defaultValue !== undefined) {
|
|
448
|
-
this.form.setFieldValue(this.name, opts.defaultValue as never
|
|
445
|
+
this.form.setFieldValue(this.name, opts.defaultValue as never, {
|
|
446
|
+
dontUpdateMeta: true,
|
|
447
|
+
})
|
|
449
448
|
}
|
|
450
449
|
|
|
451
450
|
this.store = new Store<FieldState<TData>>(
|
|
@@ -457,7 +456,6 @@ export class FieldApi<
|
|
|
457
456
|
isTouched: false,
|
|
458
457
|
isDirty: false,
|
|
459
458
|
isPristine: true,
|
|
460
|
-
touchedErrors: [],
|
|
461
459
|
errors: [],
|
|
462
460
|
errorMap: {},
|
|
463
461
|
...opts.defaultMeta,
|
|
@@ -471,10 +469,6 @@ export class FieldApi<
|
|
|
471
469
|
(val: unknown) => val !== undefined,
|
|
472
470
|
)
|
|
473
471
|
|
|
474
|
-
state.meta.touchedErrors = state.meta.isTouched
|
|
475
|
-
? state.meta.errors
|
|
476
|
-
: []
|
|
477
|
-
|
|
478
472
|
state.meta.isPristine = !state.meta.isDirty
|
|
479
473
|
|
|
480
474
|
this.prevState = state
|
|
@@ -582,9 +576,13 @@ export class FieldApi<
|
|
|
582
576
|
const formDefault = getBy(opts.form.options.defaultValues, opts.name)
|
|
583
577
|
|
|
584
578
|
if (opts.defaultValue !== undefined) {
|
|
585
|
-
this.setValue(opts.defaultValue as never
|
|
579
|
+
this.setValue(opts.defaultValue as never, {
|
|
580
|
+
dontUpdateMeta: true,
|
|
581
|
+
})
|
|
586
582
|
} else if (formDefault !== undefined) {
|
|
587
|
-
this.setValue(formDefault as never
|
|
583
|
+
this.setValue(formDefault as never, {
|
|
584
|
+
dontUpdateMeta: true,
|
|
585
|
+
})
|
|
588
586
|
}
|
|
589
587
|
}
|
|
590
588
|
|
|
@@ -598,6 +596,7 @@ export class FieldApi<
|
|
|
598
596
|
|
|
599
597
|
/**
|
|
600
598
|
* Gets the current field value.
|
|
599
|
+
* @deprecated Use `field.state.value` instead.
|
|
601
600
|
*/
|
|
602
601
|
getValue = (): TData => {
|
|
603
602
|
return this.form.getFieldValue(this.name) as TData
|
|
@@ -606,10 +605,7 @@ export class FieldApi<
|
|
|
606
605
|
/**
|
|
607
606
|
* Sets the field value and run the `change` validator.
|
|
608
607
|
*/
|
|
609
|
-
setValue = (
|
|
610
|
-
updater: Updater<TData>,
|
|
611
|
-
options?: { touch?: boolean; notify?: boolean },
|
|
612
|
-
) => {
|
|
608
|
+
setValue = (updater: Updater<TData>, options?: UpdateMetaOptions) => {
|
|
613
609
|
this.form.setFieldValue(this.name, updater as never, options)
|
|
614
610
|
this.validate('change')
|
|
615
611
|
}
|
|
@@ -629,7 +625,6 @@ export class FieldApi<
|
|
|
629
625
|
isTouched: false,
|
|
630
626
|
isDirty: false,
|
|
631
627
|
isPristine: true,
|
|
632
|
-
touchedErrors: [],
|
|
633
628
|
errors: [],
|
|
634
629
|
errorMap: {},
|
|
635
630
|
...this.options.defaultMeta,
|
|
@@ -651,7 +646,7 @@ export class FieldApi<
|
|
|
651
646
|
*/
|
|
652
647
|
pushValue = (
|
|
653
648
|
value: TData extends any[] ? TData[number] : never,
|
|
654
|
-
opts?:
|
|
649
|
+
opts?: UpdateMetaOptions,
|
|
655
650
|
) => this.form.pushFieldValue(this.name, value as any, opts)
|
|
656
651
|
|
|
657
652
|
/**
|
|
@@ -660,7 +655,7 @@ export class FieldApi<
|
|
|
660
655
|
insertValue = (
|
|
661
656
|
index: number,
|
|
662
657
|
value: TData extends any[] ? TData[number] : never,
|
|
663
|
-
opts?:
|
|
658
|
+
opts?: UpdateMetaOptions,
|
|
664
659
|
) => this.form.insertFieldValue(this.name, index, value as any, opts)
|
|
665
660
|
|
|
666
661
|
/**
|
|
@@ -669,25 +664,25 @@ export class FieldApi<
|
|
|
669
664
|
replaceValue = (
|
|
670
665
|
index: number,
|
|
671
666
|
value: TData extends any[] ? TData[number] : never,
|
|
672
|
-
opts?:
|
|
667
|
+
opts?: UpdateMetaOptions,
|
|
673
668
|
) => this.form.replaceFieldValue(this.name, index, value as any, opts)
|
|
674
669
|
|
|
675
670
|
/**
|
|
676
671
|
* Removes a value at the specified index.
|
|
677
672
|
*/
|
|
678
|
-
removeValue = (index: number, opts?:
|
|
673
|
+
removeValue = (index: number, opts?: UpdateMetaOptions) =>
|
|
679
674
|
this.form.removeFieldValue(this.name, index, opts)
|
|
680
675
|
|
|
681
676
|
/**
|
|
682
677
|
* Swaps the values at the specified indices.
|
|
683
678
|
*/
|
|
684
|
-
swapValues = (aIndex: number, bIndex: number, opts?:
|
|
679
|
+
swapValues = (aIndex: number, bIndex: number, opts?: UpdateMetaOptions) =>
|
|
685
680
|
this.form.swapFieldValues(this.name, aIndex, bIndex, opts)
|
|
686
681
|
|
|
687
682
|
/**
|
|
688
683
|
* Moves the value at the first specified index to the second specified index.
|
|
689
684
|
*/
|
|
690
|
-
moveValue = (aIndex: number, bIndex: number, opts?:
|
|
685
|
+
moveValue = (aIndex: number, bIndex: number, opts?: UpdateMetaOptions) =>
|
|
691
686
|
this.form.moveFieldValues(this.name, aIndex, bIndex, opts)
|
|
692
687
|
|
|
693
688
|
/**
|
|
@@ -952,7 +947,7 @@ export class FieldApi<
|
|
|
952
947
|
* Handles the change event.
|
|
953
948
|
*/
|
|
954
949
|
handleChange = (updater: Updater<TData>) => {
|
|
955
|
-
this.setValue(updater
|
|
950
|
+
this.setValue(updater)
|
|
956
951
|
}
|
|
957
952
|
|
|
958
953
|
/**
|
package/src/FormApi.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { Updater } from './utils'
|
|
|
12
12
|
import type { DeepKeys, DeepValue } from './util-types'
|
|
13
13
|
import type { FieldApi, FieldMeta } from './FieldApi'
|
|
14
14
|
import type {
|
|
15
|
+
UpdateMetaOptions,
|
|
15
16
|
ValidationCause,
|
|
16
17
|
ValidationError,
|
|
17
18
|
ValidationErrorMap,
|
|
@@ -884,7 +885,6 @@ export class FormApi<
|
|
|
884
885
|
isTouched: false,
|
|
885
886
|
isDirty: false,
|
|
886
887
|
isPristine: true,
|
|
887
|
-
touchedErrors: [],
|
|
888
888
|
errors: [],
|
|
889
889
|
errorMap: {},
|
|
890
890
|
}
|
|
@@ -900,12 +900,12 @@ export class FormApi<
|
|
|
900
900
|
setFieldValue = <TField extends DeepKeys<TFormData>>(
|
|
901
901
|
field: TField,
|
|
902
902
|
updater: Updater<DeepValue<TFormData, TField>>,
|
|
903
|
-
opts?:
|
|
903
|
+
opts?: UpdateMetaOptions,
|
|
904
904
|
) => {
|
|
905
|
-
const
|
|
905
|
+
const dontUpdateMeta = opts?.dontUpdateMeta ?? false
|
|
906
906
|
|
|
907
907
|
this.store.batch(() => {
|
|
908
|
-
if (
|
|
908
|
+
if (!dontUpdateMeta) {
|
|
909
909
|
this.setFieldMeta(field, (prev) => ({
|
|
910
910
|
...prev,
|
|
911
911
|
isTouched: true,
|
|
@@ -941,7 +941,7 @@ export class FormApi<
|
|
|
941
941
|
value: DeepValue<TFormData, TField> extends any[]
|
|
942
942
|
? DeepValue<TFormData, TField>[number]
|
|
943
943
|
: never,
|
|
944
|
-
opts?:
|
|
944
|
+
opts?: UpdateMetaOptions,
|
|
945
945
|
) => {
|
|
946
946
|
this.setFieldValue(
|
|
947
947
|
field,
|
|
@@ -960,7 +960,7 @@ export class FormApi<
|
|
|
960
960
|
value: DeepValue<TFormData, TField> extends any[]
|
|
961
961
|
? DeepValue<TFormData, TField>[number]
|
|
962
962
|
: never,
|
|
963
|
-
opts?:
|
|
963
|
+
opts?: UpdateMetaOptions,
|
|
964
964
|
) => {
|
|
965
965
|
this.setFieldValue(
|
|
966
966
|
field,
|
|
@@ -987,7 +987,7 @@ export class FormApi<
|
|
|
987
987
|
value: DeepValue<TFormData, TField> extends any[]
|
|
988
988
|
? DeepValue<TFormData, TField>[number]
|
|
989
989
|
: never,
|
|
990
|
-
opts?:
|
|
990
|
+
opts?: UpdateMetaOptions,
|
|
991
991
|
) => {
|
|
992
992
|
this.setFieldValue(
|
|
993
993
|
field,
|
|
@@ -1010,7 +1010,7 @@ export class FormApi<
|
|
|
1010
1010
|
removeFieldValue = async <TField extends DeepKeys<TFormData>>(
|
|
1011
1011
|
field: TField,
|
|
1012
1012
|
index: number,
|
|
1013
|
-
opts?:
|
|
1013
|
+
opts?: UpdateMetaOptions,
|
|
1014
1014
|
) => {
|
|
1015
1015
|
const fieldValue = this.getFieldValue(field)
|
|
1016
1016
|
|
|
@@ -1050,7 +1050,7 @@ export class FormApi<
|
|
|
1050
1050
|
field: TField,
|
|
1051
1051
|
index1: number,
|
|
1052
1052
|
index2: number,
|
|
1053
|
-
opts?:
|
|
1053
|
+
opts?: UpdateMetaOptions,
|
|
1054
1054
|
) => {
|
|
1055
1055
|
this.setFieldValue(
|
|
1056
1056
|
field,
|
|
@@ -1076,7 +1076,7 @@ export class FormApi<
|
|
|
1076
1076
|
field: TField,
|
|
1077
1077
|
index1: number,
|
|
1078
1078
|
index2: number,
|
|
1079
|
-
opts?:
|
|
1079
|
+
opts?: UpdateMetaOptions,
|
|
1080
1080
|
) => {
|
|
1081
1081
|
this.setFieldValue(
|
|
1082
1082
|
field,
|
package/src/types.ts
CHANGED
|
@@ -26,3 +26,13 @@ export type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`
|
|
|
26
26
|
export type ValidationErrorMap = {
|
|
27
27
|
[K in ValidationErrorMapKeys]?: ValidationError
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @private
|
|
32
|
+
*/
|
|
33
|
+
export interface UpdateMetaOptions {
|
|
34
|
+
/**
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
dontUpdateMeta?: boolean
|
|
38
|
+
}
|