@tanstack/form-core 1.19.1 → 1.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ValidationLogic.js","sources":["../../src/ValidationLogic.ts"],"sourcesContent":["import type { AnyFormApi, FormValidators } from './FormApi'\n\ninterface ValidationLogicValidatorsFn {\n // TODO: Type this properly\n fn: FormValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >[keyof FormValidators<any, any, any, any, any, any, any, any, any, any>]\n cause: 'change' | 'blur' | 'submit' | 'mount' | 'server' | 'dynamic'\n}\n\nexport interface ValidationLogicProps {\n // TODO: Type this properly\n form: AnyFormApi\n // TODO: Type this properly\n validators:\n | FormValidators<any, any, any, any, any, any, any, any, any, any>\n | undefined\n | null\n event: {\n type: 'blur' | 'change' | 'submit' | 'mount' | 'server'\n fieldName?: string\n async: boolean\n }\n runValidation: (props: {\n validators: Array<ValidationLogicValidatorsFn | undefined>\n form: AnyFormApi\n }) => void\n}\n\ninterface RevalidateLogicProps {\n /**\n * @default 'submit'\n *\n * This is the mode that will be used before the form has been submitted.\n * It will run the validation logic on `submit` by default, but can be set to `change` or `blur`.\n */\n mode?: 'change' | 'blur' | 'submit'\n /**\n * @default 'change'\n *\n * This is the mode that will be used after the form has been submitted.\n * It will run the validation logic on `change` by default, but can be set to `blur` or `submit`.\n */\n modeAfterSubmission?: 'change' | 'blur' | 'submit'\n}\n\nexport type ValidationLogicFn = (props: ValidationLogicProps) => void\n\n/**\n * This forces a form's validation logic to be ran as if it were a React Hook Form validation logic.\n *\n * This means that it will only run the `onDynamic` validator, and it will not run any other validators and changes the validation\n * type based on the state of the form itself.\n *\n * When the form is not yet submitted, it will not run the validation logic.\n * When the form is submitted, it will run the validation logic on `change`\n */\nexport const revalidateLogic =\n ({\n mode = 'submit',\n modeAfterSubmission = 'change',\n }: RevalidateLogicProps = {}): ValidationLogicFn =>\n (props) => {\n const validatorNames = Object.keys(props.validators ?? {})\n if (validatorNames.length === 0) {\n // No validators is a valid case, just return\n return props.runValidation({\n validators: [],\n form: props.form,\n })\n }\n\n const dynamicValidator = {\n fn: props.event.async\n ? props.validators!['onDynamicAsync']\n : props.validators!['onDynamic'],\n cause: 'dynamic',\n } as const\n\n const validatorsToAdd = [] as ValidationLogicValidatorsFn[]\n\n const modeToWatch =\n props.form.state.submissionAttempts === 0 ? mode : modeAfterSubmission\n\n if ([modeToWatch, 'submit'].includes(props.event.type)) {\n validatorsToAdd.push(dynamicValidator)\n }\n\n let defaultValidators = [] as ValidationLogicValidatorsFn[]\n\n defaultValidationLogic({\n ...props,\n runValidation: (vProps) => {\n defaultValidators = vProps.validators as ValidationLogicValidatorsFn[]\n },\n })\n\n if (validatorsToAdd.length === 0) {\n return props.runValidation({\n validators: defaultValidators,\n form: props.form,\n })\n }\n\n return props.runValidation({\n validators: [...defaultValidators, ...validatorsToAdd],\n form: props.form,\n })\n }\n\nexport const defaultValidationLogic: ValidationLogicFn = (props) => {\n // Handle case where no validators are provided\n if (!props.validators) {\n return props.runValidation({\n validators: [],\n form: props.form,\n })\n }\n\n const isAsync = props.event.async\n\n const onMountValidator = isAsync\n ? undefined\n : ({ fn: props.validators.onMount, cause: 'mount' } as const)\n\n const onChangeValidator = {\n fn: isAsync ? props.validators.onChangeAsync : props.validators.onChange,\n cause: 'change',\n } as const\n\n const onBlurValidator = {\n fn: isAsync ? props.validators.onBlurAsync : props.validators.onBlur,\n cause: 'blur',\n } as const\n\n const onSubmitValidator = {\n fn: isAsync ? props.validators.onSubmitAsync : props.validators.onSubmit,\n cause: 'submit',\n } as const\n\n // Allows us to clear onServer errors\n const onServerValidator = isAsync\n ? undefined\n : ({ fn: () => undefined, cause: 'server' } as const)\n\n switch (props.event.type) {\n case 'mount': {\n // Run mount validation\n return props.runValidation({\n validators: [onMountValidator],\n form: props.form,\n })\n }\n case 'submit': {\n // Run change, blur, submit, server validation\n return props.runValidation({\n validators: [\n onChangeValidator,\n onBlurValidator,\n onSubmitValidator,\n onServerValidator,\n ],\n form: props.form,\n })\n }\n case 'server': {\n // Run server validation\n return props.runValidation({\n validators: [],\n form: props.form,\n })\n }\n case 'blur': {\n // Run blur, server validation\n return props.runValidation({\n validators: [onBlurValidator, onServerValidator],\n form: props.form,\n })\n }\n case 'change': {\n // Run change, server validation\n return props.runValidation({\n validators: [onChangeValidator, onServerValidator],\n form: props.form,\n })\n }\n default: {\n throw new Error(`Unknown validation event type: ${props.event.type}`)\n }\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ValidationLogic.js","sources":["../../src/ValidationLogic.ts"],"sourcesContent":["import type { AnyFormApi, FormValidators } from './FormApi'\n\ninterface ValidationLogicValidatorsFn {\n // TODO: Type this properly\n fn: FormValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >[keyof FormValidators<any, any, any, any, any, any, any, any, any, any>]\n cause: 'change' | 'blur' | 'submit' | 'mount' | 'server' | 'dynamic'\n}\n\nexport interface ValidationLogicProps {\n // TODO: Type this properly\n form: AnyFormApi\n // TODO: Type this properly\n validators:\n | FormValidators<any, any, any, any, any, any, any, any, any, any>\n | undefined\n | null\n event: {\n type: 'blur' | 'change' | 'submit' | 'mount' | 'server'\n fieldName?: string\n async: boolean\n }\n runValidation: (props: {\n validators: Array<ValidationLogicValidatorsFn | undefined>\n form: AnyFormApi\n }) => void\n}\n\ninterface RevalidateLogicProps {\n /**\n * @default 'submit'\n *\n * This is the mode that will be used before the form has been submitted.\n * It will run the validation logic on `submit` by default, but can be set to `change` or `blur`.\n */\n mode?: 'change' | 'blur' | 'submit'\n /**\n * @default 'change'\n *\n * This is the mode that will be used after the form has been submitted.\n * It will run the validation logic on `change` by default, but can be set to `blur` or `submit`.\n */\n modeAfterSubmission?: 'change' | 'blur' | 'submit'\n}\n\nexport type ValidationLogicFn = (props: ValidationLogicProps) => void\n\n/**\n * This forces a form's validation logic to be ran as if it were a React Hook Form validation logic.\n *\n * This means that it will only run the `onDynamic` validator, and it will not run any other validators and changes the validation\n * type based on the state of the form itself.\n *\n * When the form is not yet submitted, it will not run the validation logic.\n * When the form is submitted, it will run the validation logic on `change`\n */\nexport const revalidateLogic =\n ({\n mode = 'submit',\n modeAfterSubmission = 'change',\n }: RevalidateLogicProps = {}): ValidationLogicFn =>\n (props) => {\n const validatorNames = Object.keys(props.validators ?? {})\n if (validatorNames.length === 0) {\n // No validators is a valid case, just return\n return props.runValidation({\n validators: [],\n form: props.form,\n })\n }\n\n const dynamicValidator = {\n fn: props.event.async\n ? props.validators!['onDynamicAsync']\n : props.validators!['onDynamic'],\n cause: 'dynamic',\n } as const\n\n const validatorsToAdd = [] as ValidationLogicValidatorsFn[]\n\n const modeToWatch =\n props.form.state.submissionAttempts === 0 ? mode : modeAfterSubmission\n\n if ([modeToWatch, 'submit'].includes(props.event.type)) {\n validatorsToAdd.push(dynamicValidator)\n }\n\n let defaultValidators = [] as ValidationLogicValidatorsFn[]\n\n defaultValidationLogic({\n ...props,\n runValidation: (vProps) => {\n defaultValidators = vProps.validators as ValidationLogicValidatorsFn[]\n },\n })\n\n if (validatorsToAdd.length === 0) {\n return props.runValidation({\n validators: defaultValidators,\n form: props.form,\n })\n }\n\n return props.runValidation({\n validators: [...defaultValidators, ...validatorsToAdd],\n form: props.form,\n })\n }\n\nexport const defaultValidationLogic: ValidationLogicFn = (props) => {\n // Handle case where no validators are provided\n if (!props.validators) {\n return props.runValidation({\n validators: [],\n form: props.form,\n })\n }\n\n const isAsync = props.event.async\n\n const onMountValidator = isAsync\n ? undefined\n : ({ fn: props.validators.onMount, cause: 'mount' } as const)\n\n const onChangeValidator = {\n fn: isAsync ? props.validators.onChangeAsync : props.validators.onChange,\n cause: 'change',\n } as const\n\n const onBlurValidator = {\n fn: isAsync ? props.validators.onBlurAsync : props.validators.onBlur,\n cause: 'blur',\n } as const\n\n const onSubmitValidator = {\n fn: isAsync ? props.validators.onSubmitAsync : props.validators.onSubmit,\n cause: 'submit',\n } as const\n\n // Allows us to clear onServer errors\n const onServerValidator = isAsync\n ? undefined\n : ({ fn: () => undefined, cause: 'server' } as const)\n\n switch (props.event.type) {\n case 'mount': {\n // Run mount validation\n return props.runValidation({\n validators: [onMountValidator],\n form: props.form,\n })\n }\n case 'submit': {\n // Run change, blur, submit, server validation\n return props.runValidation({\n validators: [\n onChangeValidator,\n onBlurValidator,\n onSubmitValidator,\n onServerValidator,\n ],\n form: props.form,\n })\n }\n case 'server': {\n // Run server validation\n return props.runValidation({\n validators: [],\n form: props.form,\n })\n }\n case 'blur': {\n // Run blur, server validation\n return props.runValidation({\n validators: [onBlurValidator, onServerValidator],\n form: props.form,\n })\n }\n case 'change': {\n // Run change, server validation\n return props.runValidation({\n validators: [onChangeValidator, onServerValidator],\n form: props.form,\n })\n }\n default: {\n throw new Error(`Unknown validation event type: ${props.event.type}`)\n }\n }\n}\n"],"names":[],"mappings":"AAkEO,MAAM,kBACX,CAAC;AAAA,EACC,OAAO;AAAA,EACP,sBAAsB;AACxB,IAA0B,CAAA,MAC1B,CAAC,UAAU;AACT,QAAM,iBAAiB,OAAO,KAAK,MAAM,cAAc,CAAA,CAAE;AACzD,MAAI,eAAe,WAAW,GAAG;AAE/B,WAAO,MAAM,cAAc;AAAA,MACzB,YAAY,CAAA;AAAA,MACZ,MAAM,MAAM;AAAA,IAAA,CACb;AAAA,EACH;AAEA,QAAM,mBAAmB;AAAA,IACvB,IAAI,MAAM,MAAM,QACZ,MAAM,WAAY,gBAAgB,IAClC,MAAM,WAAY,WAAW;AAAA,IACjC,OAAO;AAAA,EAAA;AAGT,QAAM,kBAAkB,CAAA;AAExB,QAAM,cACJ,MAAM,KAAK,MAAM,uBAAuB,IAAI,OAAO;AAErD,MAAI,CAAC,aAAa,QAAQ,EAAE,SAAS,MAAM,MAAM,IAAI,GAAG;AACtD,oBAAgB,KAAK,gBAAgB;AAAA,EACvC;AAEA,MAAI,oBAAoB,CAAA;AAExB,yBAAuB;AAAA,IACrB,GAAG;AAAA,IACH,eAAe,CAAC,WAAW;AACzB,0BAAoB,OAAO;AAAA,IAC7B;AAAA,EAAA,CACD;AAED,MAAI,gBAAgB,WAAW,GAAG;AAChC,WAAO,MAAM,cAAc;AAAA,MACzB,YAAY;AAAA,MACZ,MAAM,MAAM;AAAA,IAAA,CACb;AAAA,EACH;AAEA,SAAO,MAAM,cAAc;AAAA,IACzB,YAAY,CAAC,GAAG,mBAAmB,GAAG,eAAe;AAAA,IACrD,MAAM,MAAM;AAAA,EAAA,CACb;AACH;AAEK,MAAM,yBAA4C,CAAC,UAAU;AAElE,MAAI,CAAC,MAAM,YAAY;AACrB,WAAO,MAAM,cAAc;AAAA,MACzB,YAAY,CAAA;AAAA,MACZ,MAAM,MAAM;AAAA,IAAA,CACb;AAAA,EACH;AAEA,QAAM,UAAU,MAAM,MAAM;AAE5B,QAAM,mBAAmB,UACrB,SACC,EAAE,IAAI,MAAM,WAAW,SAAS,OAAO,QAAA;AAE5C,QAAM,oBAAoB;AAAA,IACxB,IAAI,UAAU,MAAM,WAAW,gBAAgB,MAAM,WAAW;AAAA,IAChE,OAAO;AAAA,EAAA;AAGT,QAAM,kBAAkB;AAAA,IACtB,IAAI,UAAU,MAAM,WAAW,cAAc,MAAM,WAAW;AAAA,IAC9D,OAAO;AAAA,EAAA;AAGT,QAAM,oBAAoB;AAAA,IACxB,IAAI,UAAU,MAAM,WAAW,gBAAgB,MAAM,WAAW;AAAA,IAChE,OAAO;AAAA,EAAA;AAIT,QAAM,oBAAoB,UACtB,SACC,EAAE,IAAI,MAAM,QAAW,OAAO,SAAA;AAEnC,UAAQ,MAAM,MAAM,MAAA;AAAA,IAClB,KAAK,SAAS;AAEZ,aAAO,MAAM,cAAc;AAAA,QACzB,YAAY,CAAC,gBAAgB;AAAA,QAC7B,MAAM,MAAM;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,KAAK,UAAU;AAEb,aAAO,MAAM,cAAc;AAAA,QACzB,YAAY;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAEF,MAAM,MAAM;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,KAAK,UAAU;AAEb,aAAO,MAAM,cAAc;AAAA,QACzB,YAAY,CAAA;AAAA,QACZ,MAAM,MAAM;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,KAAK,QAAQ;AAEX,aAAO,MAAM,cAAc;AAAA,QACzB,YAAY,CAAC,iBAAiB,iBAAiB;AAAA,QAC/C,MAAM,MAAM;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,KAAK,UAAU;AAEb,aAAO,MAAM,cAAc;AAAA,QACzB,YAAY,CAAC,mBAAmB,iBAAiB;AAAA,QACjD,MAAM,MAAM;AAAA,MAAA,CACb;AAAA,IACH;AAAA,IACA,SAAS;AACP,YAAM,IAAI,MAAM,kCAAkC,MAAM,MAAM,IAAI,EAAE;AAAA,IACtE;AAAA,EAAA;AAEJ;"}
@@ -1,2 +1,2 @@
1
1
  import { FormAsyncValidateOrFn, FormOptions, FormValidateOrFn } from './FormApi.js';
2
- export declare function formOptions<TOptions extends Partial<FormOptions<TFormData, undefined | FormValidateOrFn<TFormData>, undefined | FormValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, undefined | FormValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, undefined | FormValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, undefined | FormValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, TSubmitMeta>>, TFormData = TOptions['defaultValues'], TSubmitMeta = TOptions['onSubmitMeta']>(defaultOpts: Partial<FormOptions<TFormData, undefined | FormValidateOrFn<TFormData>, undefined | FormValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, undefined | FormValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, undefined | FormValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, undefined | FormValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, undefined | FormAsyncValidateOrFn<TFormData>, TSubmitMeta>> & TOptions): TOptions;
2
+ export declare function formOptions<TOptions extends Partial<FormOptions<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnDynamic, TOnDynamicAsync, TOnServer, TSubmitMeta>>, TFormData, TOnMount extends undefined | FormValidateOrFn<TFormData>, TOnChange extends undefined | FormValidateOrFn<TFormData>, TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnBlur extends undefined | FormValidateOrFn<TFormData>, TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnSubmit extends undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnDynamic extends undefined | FormValidateOrFn<TFormData>, TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>, TSubmitMeta = never>(defaultOpts: Partial<FormOptions<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnDynamic, TOnDynamicAsync, TOnServer, TSubmitMeta>> & TOptions): TOptions;
@@ -1 +1 @@
1
- {"version":3,"file":"formOptions.js","sources":["../../src/formOptions.ts"],"sourcesContent":["import type {\n FormAsyncValidateOrFn,\n FormOptions,\n FormValidateOrFn,\n} from './FormApi'\n\n/*\n\nThese types need to do two things:\n\n1. Validator generics need to depend on the TFormData generic\n2. The resulting needs to allow overriding values\n\nThe generics from formOptions almost work, except that it loses information\nabout how to infer TFormData.\nIf you pass a validator function, it tries to resolve the `formApi` or `value`\ninside of it, meaning that TFormData changes to `unknown`.\n\nTo bypass this, the intersection for defaultOpts gives TypeScript that information again,\nwithout losing the benefits from the TOptions generic.\n*/\n\nexport function formOptions<\n TOptions extends Partial<\n FormOptions<\n TFormData,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta\n >\n >,\n TFormData = TOptions['defaultValues'],\n TSubmitMeta = TOptions['onSubmitMeta'],\n>(\n defaultOpts: Partial<\n FormOptions<\n TFormData,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n undefined | FormValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta\n >\n > &\n TOptions,\n): TOptions {\n return defaultOpts\n}\n"],"names":[],"mappings":"AAsBO,SAAS,YAoBd,aAiBU;AACH,SAAA;AACT;"}
1
+ {"version":3,"file":"formOptions.js","sources":["../../src/formOptions.ts"],"sourcesContent":["import type {\n FormAsyncValidateOrFn,\n FormOptions,\n FormValidateOrFn,\n} from './FormApi'\n\n/*\n\nThese types need to do two things:\n\n1. Validator generics need to depend on the TFormData generic\n2. The resulting needs to allow overriding values\n\nThe generics from formOptions almost work, except that it loses information\nabout how to infer TFormData.\nIf you pass a validator function, it tries to resolve the `formApi` or `value`\ninside of it, meaning that TFormData changes to `unknown`.\n\nTo bypass this, the intersection for defaultOpts gives TypeScript that information again,\nwithout losing the benefits from the TOptions generic.\n*/\n\nexport function formOptions<\n TOptions extends Partial<\n FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n >,\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta = never,\n>(\n defaultOpts: Partial<\n FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n > &\n TOptions,\n): TOptions {\n return defaultOpts\n}\n"],"names":[],"mappings":"AAsBO,SAAS,YA8Bd,aAiBU;AACV,SAAO;AACT;"}
@@ -1 +1 @@
1
- {"version":3,"file":"mergeForm.js","sources":["../../src/mergeForm.ts"],"sourcesContent":["import type { FormApi } from './FormApi'\n\nfunction isValidKey(key: string | number | symbol): boolean {\n const dangerousProps = ['__proto__', 'constructor', 'prototype']\n return !dangerousProps.includes(String(key))\n}\n\n/**\n * @private\n */\nexport function mutateMergeDeep(\n target: object | null | undefined,\n source: object | null | undefined,\n): object {\n // Early return if either is not an object\n if (target === null || target === undefined || typeof target !== 'object')\n return {} as object\n if (source === null || source === undefined || typeof source !== 'object')\n return target\n\n const targetKeys = Object.keys(target)\n const sourceKeys = Object.keys(source)\n const keySet = new Set([...targetKeys, ...sourceKeys])\n\n for (const key of keySet) {\n if (!isValidKey(key)) continue\n\n const targetKey = key as keyof typeof target\n const sourceKey = key as keyof typeof source\n\n if (!Object.hasOwn(source, sourceKey)) continue\n\n const sourceValue = source[sourceKey] as unknown\n const targetValue = target[targetKey] as unknown\n\n // Handle arrays\n if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {\n Object.defineProperty(target, key, {\n value: [...sourceValue],\n enumerable: true,\n writable: true,\n configurable: true,\n })\n continue\n }\n\n // Handle nested objects (type assertion to satisfy ESLint)\n const isTargetObj = typeof targetValue === 'object' && targetValue !== null\n const isSourceObj = typeof sourceValue === 'object' && sourceValue !== null\n const areObjects =\n isTargetObj &&\n isSourceObj &&\n !Array.isArray(targetValue) &&\n !Array.isArray(sourceValue)\n\n if (areObjects) {\n mutateMergeDeep(targetValue as object, sourceValue as object)\n continue\n }\n\n // Handle all other cases\n Object.defineProperty(target, key, {\n value: sourceValue,\n enumerable: true,\n writable: true,\n configurable: true,\n })\n }\n\n return target\n}\n\nexport function mergeForm<TFormData>(\n baseForm: FormApi<\n NoInfer<TFormData>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n state: Partial<\n FormApi<\n TFormData,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >['state']\n >,\n) {\n mutateMergeDeep(baseForm.state, state)\n return baseForm\n}\n"],"names":[],"mappings":"AAEA,SAAS,WAAW,KAAwC;AAC1D,QAAM,iBAAiB,CAAC,aAAa,eAAe,WAAW;AAC/D,SAAO,CAAC,eAAe,SAAS,OAAO,GAAG,CAAC;AAC7C;AAKgB,SAAA,gBACd,QACA,QACQ;AAER,MAAI,WAAW,QAAQ,WAAW,UAAa,OAAO,WAAW;AAC/D,WAAO,CAAC;AACV,MAAI,WAAW,QAAQ,WAAW,UAAa,OAAO,WAAW;AACxD,WAAA;AAEH,QAAA,aAAa,OAAO,KAAK,MAAM;AAC/B,QAAA,aAAa,OAAO,KAAK,MAAM;AAC/B,QAAA,6BAAa,IAAI,CAAC,GAAG,YAAY,GAAG,UAAU,CAAC;AAErD,aAAW,OAAO,QAAQ;AACpB,QAAA,CAAC,WAAW,GAAG,EAAG;AAEtB,UAAM,YAAY;AAClB,UAAM,YAAY;AAElB,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAS,EAAG;AAEjC,UAAA,cAAc,OAAO,SAAS;AAC9B,UAAA,cAAc,OAAO,SAAS;AAGpC,QAAI,MAAM,QAAQ,WAAW,KAAK,MAAM,QAAQ,WAAW,GAAG;AACrD,aAAA,eAAe,QAAQ,KAAK;AAAA,QACjC,OAAO,CAAC,GAAG,WAAW;AAAA,QACtB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,cAAc;AAAA,MAAA,CACf;AACD;AAAA,IAAA;AAIF,UAAM,cAAc,OAAO,gBAAgB,YAAY,gBAAgB;AACvE,UAAM,cAAc,OAAO,gBAAgB,YAAY,gBAAgB;AACjE,UAAA,aACJ,eACA,eACA,CAAC,MAAM,QAAQ,WAAW,KAC1B,CAAC,MAAM,QAAQ,WAAW;AAE5B,QAAI,YAAY;AACd,sBAAgB,aAAuB,WAAqB;AAC5D;AAAA,IAAA;AAIK,WAAA,eAAe,QAAQ,KAAK;AAAA,MACjC,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,cAAc;AAAA,IAAA,CACf;AAAA,EAAA;AAGI,SAAA;AACT;AAEgB,SAAA,UACd,UAcA,OAgBA;AACgB,kBAAA,SAAS,OAAO,KAAK;AAC9B,SAAA;AACT;"}
1
+ {"version":3,"file":"mergeForm.js","sources":["../../src/mergeForm.ts"],"sourcesContent":["import type { FormApi } from './FormApi'\n\nfunction isValidKey(key: string | number | symbol): boolean {\n const dangerousProps = ['__proto__', 'constructor', 'prototype']\n return !dangerousProps.includes(String(key))\n}\n\n/**\n * @private\n */\nexport function mutateMergeDeep(\n target: object | null | undefined,\n source: object | null | undefined,\n): object {\n // Early return if either is not an object\n if (target === null || target === undefined || typeof target !== 'object')\n return {} as object\n if (source === null || source === undefined || typeof source !== 'object')\n return target\n\n const targetKeys = Object.keys(target)\n const sourceKeys = Object.keys(source)\n const keySet = new Set([...targetKeys, ...sourceKeys])\n\n for (const key of keySet) {\n if (!isValidKey(key)) continue\n\n const targetKey = key as keyof typeof target\n const sourceKey = key as keyof typeof source\n\n if (!Object.hasOwn(source, sourceKey)) continue\n\n const sourceValue = source[sourceKey] as unknown\n const targetValue = target[targetKey] as unknown\n\n // Handle arrays\n if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {\n Object.defineProperty(target, key, {\n value: [...sourceValue],\n enumerable: true,\n writable: true,\n configurable: true,\n })\n continue\n }\n\n // Handle nested objects (type assertion to satisfy ESLint)\n const isTargetObj = typeof targetValue === 'object' && targetValue !== null\n const isSourceObj = typeof sourceValue === 'object' && sourceValue !== null\n const areObjects =\n isTargetObj &&\n isSourceObj &&\n !Array.isArray(targetValue) &&\n !Array.isArray(sourceValue)\n\n if (areObjects) {\n mutateMergeDeep(targetValue as object, sourceValue as object)\n continue\n }\n\n // Handle all other cases\n Object.defineProperty(target, key, {\n value: sourceValue,\n enumerable: true,\n writable: true,\n configurable: true,\n })\n }\n\n return target\n}\n\nexport function mergeForm<TFormData>(\n baseForm: FormApi<\n NoInfer<TFormData>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >,\n state: Partial<\n FormApi<\n TFormData,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >['state']\n >,\n) {\n mutateMergeDeep(baseForm.state, state)\n return baseForm\n}\n"],"names":[],"mappings":"AAEA,SAAS,WAAW,KAAwC;AAC1D,QAAM,iBAAiB,CAAC,aAAa,eAAe,WAAW;AAC/D,SAAO,CAAC,eAAe,SAAS,OAAO,GAAG,CAAC;AAC7C;AAKO,SAAS,gBACd,QACA,QACQ;AAER,MAAI,WAAW,QAAQ,WAAW,UAAa,OAAO,WAAW;AAC/D,WAAO,CAAA;AACT,MAAI,WAAW,QAAQ,WAAW,UAAa,OAAO,WAAW;AAC/D,WAAO;AAET,QAAM,aAAa,OAAO,KAAK,MAAM;AACrC,QAAM,aAAa,OAAO,KAAK,MAAM;AACrC,QAAM,6BAAa,IAAI,CAAC,GAAG,YAAY,GAAG,UAAU,CAAC;AAErD,aAAW,OAAO,QAAQ;AACxB,QAAI,CAAC,WAAW,GAAG,EAAG;AAEtB,UAAM,YAAY;AAClB,UAAM,YAAY;AAElB,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAS,EAAG;AAEvC,UAAM,cAAc,OAAO,SAAS;AACpC,UAAM,cAAc,OAAO,SAAS;AAGpC,QAAI,MAAM,QAAQ,WAAW,KAAK,MAAM,QAAQ,WAAW,GAAG;AAC5D,aAAO,eAAe,QAAQ,KAAK;AAAA,QACjC,OAAO,CAAC,GAAG,WAAW;AAAA,QACtB,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,cAAc;AAAA,MAAA,CACf;AACD;AAAA,IACF;AAGA,UAAM,cAAc,OAAO,gBAAgB,YAAY,gBAAgB;AACvE,UAAM,cAAc,OAAO,gBAAgB,YAAY,gBAAgB;AACvE,UAAM,aACJ,eACA,eACA,CAAC,MAAM,QAAQ,WAAW,KAC1B,CAAC,MAAM,QAAQ,WAAW;AAE5B,QAAI,YAAY;AACd,sBAAgB,aAAuB,WAAqB;AAC5D;AAAA,IACF;AAGA,WAAO,eAAe,QAAQ,KAAK;AAAA,MACjC,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,cAAc;AAAA,IAAA,CACf;AAAA,EACH;AAEA,SAAO;AACT;AAEO,SAAS,UACd,UAcA,OAgBA;AACA,kBAAgB,SAAS,OAAO,KAAK;AACrC,SAAO;AACT;"}
@@ -1 +1 @@
1
- {"version":3,"file":"metaHelper.js","sources":["../../src/metaHelper.ts"],"sourcesContent":["import type {\n FormApi,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from './FormApi'\nimport type { AnyFieldMeta } from './FieldApi'\nimport type { DeepKeys } from './util-types'\n\ntype ArrayFieldMode = 'insert' | 'remove' | 'swap' | 'move'\n\nexport const defaultFieldMeta: AnyFieldMeta = {\n isValidating: false,\n isTouched: false,\n isBlurred: false,\n isDirty: false,\n isPristine: true,\n isValid: true,\n isDefaultValue: true,\n errors: [],\n errorMap: {},\n errorSourceMap: {},\n}\n\nexport function metaHelper<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n>(\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >,\n) {\n function handleArrayFieldMetaShift(\n field: DeepKeys<TFormData>,\n index: number,\n mode: ArrayFieldMode,\n secondIndex?: number,\n ) {\n const affectedFields = getAffectedFields(field, index, mode, secondIndex)\n\n const handlers = {\n insert: () => handleInsertMode(affectedFields, field, index),\n remove: () => handleRemoveMode(affectedFields),\n swap: () =>\n secondIndex !== undefined &&\n handleSwapMode(affectedFields, field, index, secondIndex),\n move: () =>\n secondIndex !== undefined &&\n handleMoveMode(affectedFields, field, index, secondIndex),\n }\n\n handlers[mode]()\n }\n\n function getFieldPath(field: DeepKeys<TFormData>, index: number): string {\n return `${field}[${index}]`\n }\n\n function getAffectedFields(\n field: DeepKeys<TFormData>,\n index: number,\n mode: ArrayFieldMode,\n secondIndex?: number,\n ): DeepKeys<TFormData>[] {\n const affectedFieldKeys = [getFieldPath(field, index)]\n\n if (mode === 'swap') {\n affectedFieldKeys.push(getFieldPath(field, secondIndex!))\n } else if (mode === 'move') {\n const [startIndex, endIndex] = [\n Math.min(index, secondIndex!),\n Math.max(index, secondIndex!),\n ]\n for (let i = startIndex; i <= endIndex; i++) {\n affectedFieldKeys.push(getFieldPath(field, i))\n }\n } else {\n const currentValue = formApi.getFieldValue(field)\n const fieldItems = Array.isArray(currentValue)\n ? (currentValue as Array<unknown>).length\n : 0\n for (let i = index + 1; i < fieldItems; i++) {\n affectedFieldKeys.push(getFieldPath(field, i))\n }\n }\n\n return Object.keys(formApi.fieldInfo).filter((fieldKey) =>\n affectedFieldKeys.some((key) => fieldKey.startsWith(key)),\n ) as DeepKeys<TFormData>[]\n }\n\n function updateIndex(\n fieldKey: string,\n direction: 'up' | 'down',\n ): DeepKeys<TFormData> {\n return fieldKey.replace(/\\[(\\d+)\\]/, (_, num) => {\n const currIndex = parseInt(num, 10)\n const newIndex =\n direction === 'up' ? currIndex + 1 : Math.max(0, currIndex - 1)\n return `[${newIndex}]`\n }) as DeepKeys<TFormData>\n }\n\n function shiftMeta(fields: DeepKeys<TFormData>[], direction: 'up' | 'down') {\n const sortedFields = direction === 'up' ? fields : [...fields].reverse()\n\n sortedFields.forEach((fieldKey) => {\n const nextFieldKey = updateIndex(fieldKey.toString(), direction)\n const nextFieldMeta = formApi.getFieldMeta(nextFieldKey)\n if (nextFieldMeta) {\n formApi.setFieldMeta(fieldKey, nextFieldMeta)\n } else {\n formApi.setFieldMeta(fieldKey, getEmptyFieldMeta())\n }\n })\n }\n\n const getEmptyFieldMeta = (): AnyFieldMeta => defaultFieldMeta\n\n const handleInsertMode = (\n fields: DeepKeys<TFormData>[],\n field: DeepKeys<TFormData>,\n insertIndex: number,\n ) => {\n shiftMeta(fields, 'down')\n\n fields.forEach((fieldKey) => {\n if (fieldKey.toString().startsWith(getFieldPath(field, insertIndex))) {\n formApi.setFieldMeta(fieldKey, getEmptyFieldMeta())\n }\n })\n }\n\n const handleRemoveMode = (fields: DeepKeys<TFormData>[]) => {\n shiftMeta(fields, 'up')\n }\n\n const handleMoveMode = (\n fields: DeepKeys<TFormData>[],\n field: DeepKeys<TFormData>,\n fromIndex: number,\n toIndex: number,\n ) => {\n // Store the original field meta that will be reapplied at the destination index\n const fromFields = new Map(\n Object.keys(formApi.fieldInfo)\n .filter((fieldKey) =>\n fieldKey.startsWith(getFieldPath(field, fromIndex)),\n )\n .map((fieldKey) => [\n fieldKey as DeepKeys<TFormData>,\n formApi.getFieldMeta(fieldKey as DeepKeys<TFormData>),\n ]),\n )\n\n shiftMeta(fields, fromIndex < toIndex ? 'up' : 'down')\n\n // Reapply the stored field meta at the destination index\n Object.keys(formApi.fieldInfo)\n .filter((fieldKey) => fieldKey.startsWith(getFieldPath(field, toIndex)))\n .forEach((fieldKey) => {\n const fromKey = fieldKey.replace(\n getFieldPath(field, toIndex),\n getFieldPath(field, fromIndex),\n ) as DeepKeys<TFormData>\n\n const fromMeta = fromFields.get(fromKey)\n if (fromMeta) {\n formApi.setFieldMeta(fieldKey as DeepKeys<TFormData>, fromMeta)\n }\n })\n }\n\n const handleSwapMode = (\n fields: DeepKeys<TFormData>[],\n field: DeepKeys<TFormData>,\n index: number,\n secondIndex: number,\n ) => {\n fields.forEach((fieldKey) => {\n if (!fieldKey.toString().startsWith(getFieldPath(field, index))) return\n\n const swappedKey = fieldKey\n .toString()\n .replace(\n getFieldPath(field, index),\n getFieldPath(field, secondIndex),\n ) as DeepKeys<TFormData>\n\n const [meta1, meta2] = [\n formApi.getFieldMeta(fieldKey),\n formApi.getFieldMeta(swappedKey),\n ]\n\n if (meta1) formApi.setFieldMeta(swappedKey, meta1)\n if (meta2) formApi.setFieldMeta(fieldKey, meta2)\n })\n }\n\n return { handleArrayFieldMetaShift }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"metaHelper.js","sources":["../../src/metaHelper.ts"],"sourcesContent":["import type {\n FormApi,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from './FormApi'\nimport type { AnyFieldMeta } from './FieldApi'\nimport type { DeepKeys } from './util-types'\n\ntype ArrayFieldMode = 'insert' | 'remove' | 'swap' | 'move'\n\nexport const defaultFieldMeta: AnyFieldMeta = {\n isValidating: false,\n isTouched: false,\n isBlurred: false,\n isDirty: false,\n isPristine: true,\n isValid: true,\n isDefaultValue: true,\n errors: [],\n errorMap: {},\n errorSourceMap: {},\n}\n\nexport function metaHelper<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n>(\n formApi: FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >,\n) {\n function handleArrayFieldMetaShift(\n field: DeepKeys<TFormData>,\n index: number,\n mode: ArrayFieldMode,\n secondIndex?: number,\n ) {\n const affectedFields = getAffectedFields(field, index, mode, secondIndex)\n\n const handlers = {\n insert: () => handleInsertMode(affectedFields, field, index),\n remove: () => handleRemoveMode(affectedFields),\n swap: () =>\n secondIndex !== undefined &&\n handleSwapMode(affectedFields, field, index, secondIndex),\n move: () =>\n secondIndex !== undefined &&\n handleMoveMode(affectedFields, field, index, secondIndex),\n }\n\n handlers[mode]()\n }\n\n function getFieldPath(field: DeepKeys<TFormData>, index: number): string {\n return `${field}[${index}]`\n }\n\n function getAffectedFields(\n field: DeepKeys<TFormData>,\n index: number,\n mode: ArrayFieldMode,\n secondIndex?: number,\n ): DeepKeys<TFormData>[] {\n const affectedFieldKeys = [getFieldPath(field, index)]\n\n if (mode === 'swap') {\n affectedFieldKeys.push(getFieldPath(field, secondIndex!))\n } else if (mode === 'move') {\n const [startIndex, endIndex] = [\n Math.min(index, secondIndex!),\n Math.max(index, secondIndex!),\n ]\n for (let i = startIndex; i <= endIndex; i++) {\n affectedFieldKeys.push(getFieldPath(field, i))\n }\n } else {\n const currentValue = formApi.getFieldValue(field)\n const fieldItems = Array.isArray(currentValue)\n ? (currentValue as Array<unknown>).length\n : 0\n for (let i = index + 1; i < fieldItems; i++) {\n affectedFieldKeys.push(getFieldPath(field, i))\n }\n }\n\n return Object.keys(formApi.fieldInfo).filter((fieldKey) =>\n affectedFieldKeys.some((key) => fieldKey.startsWith(key)),\n ) as DeepKeys<TFormData>[]\n }\n\n function updateIndex(\n fieldKey: string,\n direction: 'up' | 'down',\n ): DeepKeys<TFormData> {\n return fieldKey.replace(/\\[(\\d+)\\]/, (_, num) => {\n const currIndex = parseInt(num, 10)\n const newIndex =\n direction === 'up' ? currIndex + 1 : Math.max(0, currIndex - 1)\n return `[${newIndex}]`\n }) as DeepKeys<TFormData>\n }\n\n function shiftMeta(fields: DeepKeys<TFormData>[], direction: 'up' | 'down') {\n const sortedFields = direction === 'up' ? fields : [...fields].reverse()\n\n sortedFields.forEach((fieldKey) => {\n const nextFieldKey = updateIndex(fieldKey.toString(), direction)\n const nextFieldMeta = formApi.getFieldMeta(nextFieldKey)\n if (nextFieldMeta) {\n formApi.setFieldMeta(fieldKey, nextFieldMeta)\n } else {\n formApi.setFieldMeta(fieldKey, getEmptyFieldMeta())\n }\n })\n }\n\n const getEmptyFieldMeta = (): AnyFieldMeta => defaultFieldMeta\n\n const handleInsertMode = (\n fields: DeepKeys<TFormData>[],\n field: DeepKeys<TFormData>,\n insertIndex: number,\n ) => {\n shiftMeta(fields, 'down')\n\n fields.forEach((fieldKey) => {\n if (fieldKey.toString().startsWith(getFieldPath(field, insertIndex))) {\n formApi.setFieldMeta(fieldKey, getEmptyFieldMeta())\n }\n })\n }\n\n const handleRemoveMode = (fields: DeepKeys<TFormData>[]) => {\n shiftMeta(fields, 'up')\n }\n\n const handleMoveMode = (\n fields: DeepKeys<TFormData>[],\n field: DeepKeys<TFormData>,\n fromIndex: number,\n toIndex: number,\n ) => {\n // Store the original field meta that will be reapplied at the destination index\n const fromFields = new Map(\n Object.keys(formApi.fieldInfo)\n .filter((fieldKey) =>\n fieldKey.startsWith(getFieldPath(field, fromIndex)),\n )\n .map((fieldKey) => [\n fieldKey as DeepKeys<TFormData>,\n formApi.getFieldMeta(fieldKey as DeepKeys<TFormData>),\n ]),\n )\n\n shiftMeta(fields, fromIndex < toIndex ? 'up' : 'down')\n\n // Reapply the stored field meta at the destination index\n Object.keys(formApi.fieldInfo)\n .filter((fieldKey) => fieldKey.startsWith(getFieldPath(field, toIndex)))\n .forEach((fieldKey) => {\n const fromKey = fieldKey.replace(\n getFieldPath(field, toIndex),\n getFieldPath(field, fromIndex),\n ) as DeepKeys<TFormData>\n\n const fromMeta = fromFields.get(fromKey)\n if (fromMeta) {\n formApi.setFieldMeta(fieldKey as DeepKeys<TFormData>, fromMeta)\n }\n })\n }\n\n const handleSwapMode = (\n fields: DeepKeys<TFormData>[],\n field: DeepKeys<TFormData>,\n index: number,\n secondIndex: number,\n ) => {\n fields.forEach((fieldKey) => {\n if (!fieldKey.toString().startsWith(getFieldPath(field, index))) return\n\n const swappedKey = fieldKey\n .toString()\n .replace(\n getFieldPath(field, index),\n getFieldPath(field, secondIndex),\n ) as DeepKeys<TFormData>\n\n const [meta1, meta2] = [\n formApi.getFieldMeta(fieldKey),\n formApi.getFieldMeta(swappedKey),\n ]\n\n if (meta1) formApi.setFieldMeta(swappedKey, meta1)\n if (meta2) formApi.setFieldMeta(fieldKey, meta2)\n })\n }\n\n return { handleArrayFieldMetaShift }\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"standardSchemaValidator.js","sources":["../../src/standardSchemaValidator.ts"],"sourcesContent":["import type { ValidationSource } from './types'\n\nexport type TStandardSchemaValidatorValue<\n TData,\n TSource extends ValidationSource = ValidationSource,\n> = {\n value: TData\n validationSource: TSource\n}\n\nexport type TStandardSchemaValidatorIssue<\n TSource extends ValidationSource = ValidationSource,\n> = TSource extends 'form'\n ? {\n form: Record<string, StandardSchemaV1Issue[]>\n fields: Record<string, StandardSchemaV1Issue[]>\n }\n : TSource extends 'field'\n ? StandardSchemaV1Issue[]\n : never\n\nfunction prefixSchemaToErrors(issues: readonly StandardSchemaV1Issue[]) {\n const schema = new Map<string, StandardSchemaV1Issue[]>()\n\n for (const issue of issues) {\n const path = [...(issue.path ?? [])]\n .map((segment) => {\n const normalizedSegment =\n typeof segment === 'object' ? segment.key : segment\n return typeof normalizedSegment === 'number'\n ? `[${normalizedSegment}]`\n : normalizedSegment\n })\n .join('.')\n .replace(/\\.\\[/g, '[')\n\n schema.set(path, (schema.get(path) ?? []).concat(issue))\n }\n\n return Object.fromEntries(schema)\n}\n\nconst transformFormIssues = <TSource extends ValidationSource>(\n issues: readonly StandardSchemaV1Issue[],\n): TStandardSchemaValidatorIssue<TSource> => {\n const schemaErrors = prefixSchemaToErrors(issues)\n return {\n form: schemaErrors,\n fields: schemaErrors,\n } as TStandardSchemaValidatorIssue<TSource>\n}\n\nexport const standardSchemaValidators = {\n validate<TSource extends ValidationSource = ValidationSource>(\n {\n value,\n validationSource,\n }: TStandardSchemaValidatorValue<unknown, TSource>,\n schema: StandardSchemaV1,\n ): TStandardSchemaValidatorIssue<TSource> | undefined {\n const result = schema['~standard'].validate(value)\n\n if (result instanceof Promise) {\n throw new Error('async function passed to sync validator')\n }\n\n if (!result.issues) return\n\n if (validationSource === 'field')\n return result.issues as TStandardSchemaValidatorIssue<TSource>\n return transformFormIssues<TSource>(result.issues)\n },\n async validateAsync<TSource extends ValidationSource>(\n {\n value,\n validationSource,\n }: TStandardSchemaValidatorValue<unknown, TSource>,\n schema: StandardSchemaV1,\n ): Promise<TStandardSchemaValidatorIssue<TSource> | undefined> {\n const result = await schema['~standard'].validate(value)\n\n if (!result.issues) return\n\n if (validationSource === 'field')\n return result.issues as TStandardSchemaValidatorIssue<TSource>\n return transformFormIssues<TSource>(result.issues)\n },\n}\n\nexport const isStandardSchemaValidator = (\n validator: unknown,\n): validator is StandardSchemaV1 =>\n !!validator && '~standard' in (validator as object)\n\n/**\n * The Standard Schema interface.\n */\nexport type StandardSchemaV1<Input = unknown, Output = Input> = {\n /**\n * The Standard Schema properties.\n */\n readonly '~standard': StandardSchemaV1Props<Input, Output>\n}\n\n/**\n * The Standard Schema properties interface.\n */\ninterface StandardSchemaV1Props<Input = unknown, Output = Input> {\n /**\n * The version number of the standard.\n */\n readonly version: 1\n /**\n * The vendor name of the schema library.\n */\n readonly vendor: string\n /**\n * Validates unknown input values.\n */\n readonly validate: (\n value: unknown,\n ) => StandardSchemaV1Result<Output> | Promise<StandardSchemaV1Result<Output>>\n /**\n * Inferred types associated with the schema.\n */\n readonly types?: StandardSchemaV1Types<Input, Output> | undefined\n}\n/**\n * The result interface of the validate function.\n */\ntype StandardSchemaV1Result<Output> =\n | StandardSchemaV1SuccessResult<Output>\n | StandardSchemaV1FailureResult\n/**\n * The result interface if validation succeeds.\n */\ninterface StandardSchemaV1SuccessResult<Output> {\n /**\n * The typed output value.\n */\n readonly value: Output\n /**\n * The non-existent issues.\n */\n readonly issues?: undefined\n}\n/**\n * The result interface if validation fails.\n */\ninterface StandardSchemaV1FailureResult {\n /**\n * The issues of failed validation.\n */\n readonly issues: ReadonlyArray<StandardSchemaV1Issue>\n}\n/**\n * The issue interface of the failure output.\n */\nexport interface StandardSchemaV1Issue {\n /**\n * The error message of the issue.\n */\n readonly message: string\n /**\n * The path of the issue, if any.\n */\n readonly path?:\n | ReadonlyArray<PropertyKey | StandardSchemaV1PathSegment>\n | undefined\n}\n/**\n * The path segment interface of the issue.\n */\ninterface StandardSchemaV1PathSegment {\n /**\n * The key representing a path segment.\n */\n readonly key: PropertyKey\n}\n/**\n * The Standard Schema types interface.\n */\ninterface StandardSchemaV1Types<Input = unknown, Output = Input> {\n /**\n * The input type of the schema.\n */\n readonly input: Input\n /**\n * The output type of the schema.\n */\n readonly output: Output\n}\n"],"names":[],"mappings":"AAqBA,SAAS,qBAAqB,QAA0C;AAChE,QAAA,6BAAa,IAAqC;AAExD,aAAW,SAAS,QAAQ;AACpB,UAAA,OAAO,CAAC,GAAI,MAAM,QAAQ,CAAA,CAAG,EAChC,IAAI,CAAC,YAAY;AAChB,YAAM,oBACJ,OAAO,YAAY,WAAW,QAAQ,MAAM;AAC9C,aAAO,OAAO,sBAAsB,WAChC,IAAI,iBAAiB,MACrB;AAAA,IAAA,CACL,EACA,KAAK,GAAG,EACR,QAAQ,SAAS,GAAG;AAEhB,WAAA,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,CAAC,GAAG,OAAO,KAAK,CAAC;AAAA,EAAA;AAGlD,SAAA,OAAO,YAAY,MAAM;AAClC;AAEA,MAAM,sBAAsB,CAC1B,WAC2C;AACrC,QAAA,eAAe,qBAAqB,MAAM;AACzC,SAAA;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AACF;AAEO,MAAM,2BAA2B;AAAA,EACtC,SACE;AAAA,IACE;AAAA,IACA;AAAA,KAEF,QACoD;AACpD,UAAM,SAAS,OAAO,WAAW,EAAE,SAAS,KAAK;AAEjD,QAAI,kBAAkB,SAAS;AACvB,YAAA,IAAI,MAAM,yCAAyC;AAAA,IAAA;AAGvD,QAAA,CAAC,OAAO,OAAQ;AAEpB,QAAI,qBAAqB;AACvB,aAAO,OAAO;AACT,WAAA,oBAA6B,OAAO,MAAM;AAAA,EACnD;AAAA,EACA,MAAM,cACJ;AAAA,IACE;AAAA,IACA;AAAA,KAEF,QAC6D;AAC7D,UAAM,SAAS,MAAM,OAAO,WAAW,EAAE,SAAS,KAAK;AAEnD,QAAA,CAAC,OAAO,OAAQ;AAEpB,QAAI,qBAAqB;AACvB,aAAO,OAAO;AACT,WAAA,oBAA6B,OAAO,MAAM;AAAA,EAAA;AAErD;AAEO,MAAM,4BAA4B,CACvC,cAEA,CAAC,CAAC,aAAa,eAAgB;"}
1
+ {"version":3,"file":"standardSchemaValidator.js","sources":["../../src/standardSchemaValidator.ts"],"sourcesContent":["import type { ValidationSource } from './types'\n\nexport type TStandardSchemaValidatorValue<\n TData,\n TSource extends ValidationSource = ValidationSource,\n> = {\n value: TData\n validationSource: TSource\n}\n\nexport type TStandardSchemaValidatorIssue<\n TSource extends ValidationSource = ValidationSource,\n> = TSource extends 'form'\n ? {\n form: Record<string, StandardSchemaV1Issue[]>\n fields: Record<string, StandardSchemaV1Issue[]>\n }\n : TSource extends 'field'\n ? StandardSchemaV1Issue[]\n : never\n\nfunction prefixSchemaToErrors(issues: readonly StandardSchemaV1Issue[]) {\n const schema = new Map<string, StandardSchemaV1Issue[]>()\n\n for (const issue of issues) {\n const path = [...(issue.path ?? [])]\n .map((segment) => {\n const normalizedSegment =\n typeof segment === 'object' ? segment.key : segment\n return typeof normalizedSegment === 'number'\n ? `[${normalizedSegment}]`\n : normalizedSegment\n })\n .join('.')\n .replace(/\\.\\[/g, '[')\n\n schema.set(path, (schema.get(path) ?? []).concat(issue))\n }\n\n return Object.fromEntries(schema)\n}\n\nconst transformFormIssues = <TSource extends ValidationSource>(\n issues: readonly StandardSchemaV1Issue[],\n): TStandardSchemaValidatorIssue<TSource> => {\n const schemaErrors = prefixSchemaToErrors(issues)\n return {\n form: schemaErrors,\n fields: schemaErrors,\n } as TStandardSchemaValidatorIssue<TSource>\n}\n\nexport const standardSchemaValidators = {\n validate<TSource extends ValidationSource = ValidationSource>(\n {\n value,\n validationSource,\n }: TStandardSchemaValidatorValue<unknown, TSource>,\n schema: StandardSchemaV1,\n ): TStandardSchemaValidatorIssue<TSource> | undefined {\n const result = schema['~standard'].validate(value)\n\n if (result instanceof Promise) {\n throw new Error('async function passed to sync validator')\n }\n\n if (!result.issues) return\n\n if (validationSource === 'field')\n return result.issues as TStandardSchemaValidatorIssue<TSource>\n return transformFormIssues<TSource>(result.issues)\n },\n async validateAsync<TSource extends ValidationSource>(\n {\n value,\n validationSource,\n }: TStandardSchemaValidatorValue<unknown, TSource>,\n schema: StandardSchemaV1,\n ): Promise<TStandardSchemaValidatorIssue<TSource> | undefined> {\n const result = await schema['~standard'].validate(value)\n\n if (!result.issues) return\n\n if (validationSource === 'field')\n return result.issues as TStandardSchemaValidatorIssue<TSource>\n return transformFormIssues<TSource>(result.issues)\n },\n}\n\nexport const isStandardSchemaValidator = (\n validator: unknown,\n): validator is StandardSchemaV1 =>\n !!validator && '~standard' in (validator as object)\n\n/**\n * The Standard Schema interface.\n */\nexport type StandardSchemaV1<Input = unknown, Output = Input> = {\n /**\n * The Standard Schema properties.\n */\n readonly '~standard': StandardSchemaV1Props<Input, Output>\n}\n\n/**\n * The Standard Schema properties interface.\n */\ninterface StandardSchemaV1Props<Input = unknown, Output = Input> {\n /**\n * The version number of the standard.\n */\n readonly version: 1\n /**\n * The vendor name of the schema library.\n */\n readonly vendor: string\n /**\n * Validates unknown input values.\n */\n readonly validate: (\n value: unknown,\n ) => StandardSchemaV1Result<Output> | Promise<StandardSchemaV1Result<Output>>\n /**\n * Inferred types associated with the schema.\n */\n readonly types?: StandardSchemaV1Types<Input, Output> | undefined\n}\n/**\n * The result interface of the validate function.\n */\ntype StandardSchemaV1Result<Output> =\n | StandardSchemaV1SuccessResult<Output>\n | StandardSchemaV1FailureResult\n/**\n * The result interface if validation succeeds.\n */\ninterface StandardSchemaV1SuccessResult<Output> {\n /**\n * The typed output value.\n */\n readonly value: Output\n /**\n * The non-existent issues.\n */\n readonly issues?: undefined\n}\n/**\n * The result interface if validation fails.\n */\ninterface StandardSchemaV1FailureResult {\n /**\n * The issues of failed validation.\n */\n readonly issues: ReadonlyArray<StandardSchemaV1Issue>\n}\n/**\n * The issue interface of the failure output.\n */\nexport interface StandardSchemaV1Issue {\n /**\n * The error message of the issue.\n */\n readonly message: string\n /**\n * The path of the issue, if any.\n */\n readonly path?:\n | ReadonlyArray<PropertyKey | StandardSchemaV1PathSegment>\n | undefined\n}\n/**\n * The path segment interface of the issue.\n */\ninterface StandardSchemaV1PathSegment {\n /**\n * The key representing a path segment.\n */\n readonly key: PropertyKey\n}\n/**\n * The Standard Schema types interface.\n */\ninterface StandardSchemaV1Types<Input = unknown, Output = Input> {\n /**\n * The input type of the schema.\n */\n readonly input: Input\n /**\n * The output type of the schema.\n */\n readonly output: Output\n}\n"],"names":[],"mappings":"AAqBA,SAAS,qBAAqB,QAA0C;AACtE,QAAM,6BAAa,IAAA;AAEnB,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,CAAC,GAAI,MAAM,QAAQ,CAAA,CAAG,EAChC,IAAI,CAAC,YAAY;AAChB,YAAM,oBACJ,OAAO,YAAY,WAAW,QAAQ,MAAM;AAC9C,aAAO,OAAO,sBAAsB,WAChC,IAAI,iBAAiB,MACrB;AAAA,IACN,CAAC,EACA,KAAK,GAAG,EACR,QAAQ,SAAS,GAAG;AAEvB,WAAO,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,CAAA,GAAI,OAAO,KAAK,CAAC;AAAA,EACzD;AAEA,SAAO,OAAO,YAAY,MAAM;AAClC;AAEA,MAAM,sBAAsB,CAC1B,WAC2C;AAC3C,QAAM,eAAe,qBAAqB,MAAM;AAChD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,EAAA;AAEZ;AAEO,MAAM,2BAA2B;AAAA,EACtC,SACE;AAAA,IACE;AAAA,IACA;AAAA,EAAA,GAEF,QACoD;AACpD,UAAM,SAAS,OAAO,WAAW,EAAE,SAAS,KAAK;AAEjD,QAAI,kBAAkB,SAAS;AAC7B,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,QAAI,CAAC,OAAO,OAAQ;AAEpB,QAAI,qBAAqB;AACvB,aAAO,OAAO;AAChB,WAAO,oBAA6B,OAAO,MAAM;AAAA,EACnD;AAAA,EACA,MAAM,cACJ;AAAA,IACE;AAAA,IACA;AAAA,EAAA,GAEF,QAC6D;AAC7D,UAAM,SAAS,MAAM,OAAO,WAAW,EAAE,SAAS,KAAK;AAEvD,QAAI,CAAC,OAAO,OAAQ;AAEpB,QAAI,qBAAqB;AACvB,aAAO,OAAO;AAChB,WAAO,oBAA6B,OAAO,MAAM;AAAA,EACnD;AACF;AAEO,MAAM,4BAA4B,CACvC,cAEA,CAAC,CAAC,aAAa,eAAgB;"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import { defaultValidationLogic } from './ValidationLogic'\nimport type { ValidationLogicProps } from './ValidationLogic'\nimport type { FieldValidators } from './FieldApi'\nimport type { FormValidators } from './FormApi'\nimport type {\n GlobalFormValidationError,\n ValidationCause,\n ValidationError,\n ValidationSource,\n} from './types'\n\nexport type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\n/**\n * @private\n */\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n * @private\n */\nexport function getBy(obj: any, path: any) {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart: any) => {\n if (current === null) return null\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n * @private\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (\n typeof key === 'string' ||\n (typeof key === 'number' && !Array.isArray(parent))\n ) {\n if (typeof parent === 'object') {\n if (parent === null) {\n parent = {}\n }\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (Array.isArray(parent) && typeof key === 'number') {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n return doSet(obj)\n}\n\n/**\n * Delete a field on an object using a path, including dot notation.\n * @private\n */\nexport function deleteBy(obj: any, _path: any) {\n const path = makePathArray(_path)\n\n function doDelete(parent: any): any {\n if (!parent) return\n if (path.length === 1) {\n const finalPath = path[0]!\n if (Array.isArray(parent) && typeof finalPath === 'number') {\n return parent.filter((_, i) => i !== finalPath)\n }\n const { [finalPath]: remove, ...rest } = parent\n return rest\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doDelete(parent[key]),\n }\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n if (key >= parent.length) {\n return parent\n }\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doDelete(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n }\n\n throw new Error('It seems we have created an infinite loop in deleteBy. ')\n }\n\n return doDelete(obj)\n}\n\nconst reLineOfOnlyDigits = /^(\\d+)$/gm\n// the second dot must be in a lookahead or the engine\n// will skip subsequent numbers (like foo.0.1.)\nconst reDigitsBetweenDots = /\\.(\\d+)(?=\\.)/gm\nconst reStartWithDigitThenDot = /^(\\d+)\\./gm\nconst reDotWithDigitsToEnd = /\\.(\\d+$)/gm\nconst reMultipleDots = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\n/**\n * @private\n */\nexport function makePathArray(str: string | Array<string | number>) {\n if (Array.isArray(str)) {\n return [...str]\n }\n\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return (\n str\n // Leading `[` may lead to wrong parsing down the line\n // (Example: '[0][1]' should be '0.1', not '.0.1')\n .replace(/(^\\[)|]/gm, '')\n .replace(/\\[/g, '.')\n .replace(reLineOfOnlyDigits, intReplace)\n .replace(reDigitsBetweenDots, `.${intReplace}.`)\n .replace(reStartWithDigitThenDot, `${intReplace}.`)\n .replace(reDotWithDigitsToEnd, `.${intReplace}`)\n .replace(reMultipleDots, '.')\n .split('.')\n .map((d) => {\n if (d.startsWith(intPrefix)) {\n const numStr = d.substring(intPrefix.length)\n const num = parseInt(numStr, 10)\n\n if (String(num) === numStr) {\n return num\n }\n return numStr\n }\n return d\n })\n )\n}\n\n/**\n * @private\n */\nexport function concatenatePaths(path1: string, path2: string): string {\n if (path1.length === 0) return path2\n if (path2.length === 0) return path1\n\n if (path2.startsWith('[')) {\n return path1 + path2\n }\n\n // In cases where parent and child withFieldGroup forms are both nested\n if (path2.startsWith('.')) {\n return path1 + path2\n }\n\n return `${path1}.${path2}`\n}\n\n/**\n * @private\n */\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\ninterface AsyncValidatorArrayPartialOptions<T> {\n validators?: T\n asyncDebounceMs?: number\n}\n\n/**\n * @private\n */\nexport interface AsyncValidator<T> {\n cause: ValidationCause\n validate: T\n debounceMs: number\n}\n\ninterface SyncValidatorArrayPartialOptions<T> {\n validators?: T\n}\n\n/**\n * @private\n */\nexport interface SyncValidator<T> {\n cause: ValidationCause\n validate: T\n}\n\n/**\n * @private\n */\nexport function getSyncValidatorArray<T>(\n cause: ValidationCause,\n options: SyncValidatorArrayPartialOptions<T> & {\n validationLogic?: any\n form?: any\n },\n): T extends FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n ? Array<\n SyncValidator<\n | T['onChange']\n | T['onBlur']\n | T['onSubmit']\n | T['onMount']\n | T['onDynamic']\n >\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<\n | T['onChange']\n | T['onBlur']\n | T['onSubmit']\n | T['onMount']\n | T['onDynamic']\n >\n >\n : never {\n const runValidation = (\n props: Parameters<ValidationLogicProps['runValidation']>[0],\n ) => {\n return props.validators.filter(Boolean).map((validator) => {\n return {\n cause: validator!.cause,\n validate: validator!.fn,\n }\n })\n }\n\n return options.validationLogic({\n form: options.form,\n validators: options.validators,\n event: { type: cause, async: false },\n runValidation,\n })\n}\n\n/**\n * @private\n */\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T> & {\n validationLogic?: any\n form?: any\n },\n): T extends FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n ? Array<\n AsyncValidator<\n | T['onChangeAsync']\n | T['onBlurAsync']\n | T['onSubmitAsync']\n | T['onDynamicAsync']\n >\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<\n | T['onChangeAsync']\n | T['onBlurAsync']\n | T['onSubmitAsync']\n | T['onDynamicAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n onDynamicAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n | FormValidators<any, any, any, any, any, any, any, any, any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const runValidation = (\n props: Parameters<ValidationLogicProps['runValidation']>[0],\n ) => {\n return props.validators.filter(Boolean).map((validator) => {\n const validatorCause = validator?.cause || cause\n\n let debounceMs = defaultDebounceMs\n\n switch (validatorCause) {\n case 'change':\n debounceMs = onChangeAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'blur':\n debounceMs = onBlurAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'dynamic':\n debounceMs = onDynamicAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'submit':\n debounceMs = 0 // submit validators are always run immediately\n break\n default:\n break\n }\n\n if (cause === 'submit') {\n debounceMs = 0\n }\n\n return {\n cause: validatorCause,\n validate: validator!.fn,\n debounceMs: debounceMs,\n }\n })\n }\n\n return options.validationLogic({\n form: options.form,\n validators: options.validators,\n event: { type: cause, async: true },\n runValidation,\n })\n}\n\nexport const isGlobalFormValidationError = (\n error: unknown,\n): error is GlobalFormValidationError<unknown> => {\n return !!error && typeof error === 'object' && 'fields' in error\n}\n\nexport function evaluate<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false\n for (const [k, v] of objA) {\n if (!objB.has(k) || !Object.is(v, objB.get(k))) return false\n }\n return true\n }\n\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false\n for (const v of objA) {\n if (!objB.has(v)) return false\n }\n return true\n }\n\n const keysA = Object.keys(objA)\n const keysB = Object.keys(objB)\n\n if (keysA.length !== keysB.length) {\n return false\n }\n\n for (const key of keysA) {\n // performs recursive search down the object tree\n\n if (\n !keysB.includes(key) ||\n !evaluate(objA[key as keyof T], objB[key as keyof T])\n ) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Determines the logic for determining the error source and value to set on the field meta within the form level sync/async validation.\n * @private\n */\nexport const determineFormLevelErrorSourceAndValue = ({\n newFormValidatorError,\n isPreviousErrorFromFormValidator,\n previousErrorValue,\n}: {\n newFormValidatorError: ValidationError\n isPreviousErrorFromFormValidator: boolean\n previousErrorValue: ValidationError\n}): {\n newErrorValue: ValidationError\n newSource: ValidationSource | undefined\n} => {\n // All falsy values are not considered errors\n if (newFormValidatorError) {\n return { newErrorValue: newFormValidatorError, newSource: 'form' }\n }\n\n // Clears form level error since it's now stale\n if (isPreviousErrorFromFormValidator) {\n return { newErrorValue: undefined, newSource: undefined }\n }\n\n // At this point, we have a preivous error which must have been set by the field validator, keep as is\n if (previousErrorValue) {\n return { newErrorValue: previousErrorValue, newSource: 'field' }\n }\n\n // No new or previous error, clear the error\n return { newErrorValue: undefined, newSource: undefined }\n}\n\n/**\n * Determines the logic for determining the error source and value to set on the field meta within the field level sync/async validation.\n * @private\n */\nexport const determineFieldLevelErrorSourceAndValue = ({\n formLevelError,\n fieldLevelError,\n}: {\n formLevelError: ValidationError\n fieldLevelError: ValidationError\n}): {\n newErrorValue: ValidationError\n newSource: ValidationSource | undefined\n} => {\n // At field level, we prioritize the field level error\n if (fieldLevelError) {\n return { newErrorValue: fieldLevelError, newSource: 'field' }\n }\n\n // If there is no field level error, and there is a form level error, we set the form level error\n if (formLevelError) {\n return { newErrorValue: formLevelError, newSource: 'form' }\n }\n\n return { newErrorValue: undefined, newSource: undefined }\n}\n\nexport function createFieldMap<T>(values: Readonly<T>): { [K in keyof T]: K } {\n const output: { [K in keyof T]: K } = {} as any\n\n for (const key in values) {\n output[key] = key\n }\n\n return output\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../src/utils.ts"],"sourcesContent":["import { defaultValidationLogic } from './ValidationLogic'\nimport type { ValidationLogicProps } from './ValidationLogic'\nimport type { FieldValidators } from './FieldApi'\nimport type { FormValidators } from './FormApi'\nimport type {\n GlobalFormValidationError,\n ValidationCause,\n ValidationError,\n ValidationSource,\n} from './types'\n\nexport type UpdaterFn<TInput, TOutput = TInput> = (input: TInput) => TOutput\n\nexport type Updater<TInput, TOutput = TInput> =\n | TOutput\n | UpdaterFn<TInput, TOutput>\n\n/**\n * @private\n */\nexport function functionalUpdate<TInput, TOutput = TInput>(\n updater: Updater<TInput, TOutput>,\n input: TInput,\n): TOutput {\n return typeof updater === 'function'\n ? (updater as UpdaterFn<TInput, TOutput>)(input)\n : updater\n}\n\n/**\n * Get a value from an object using a path, including dot notation.\n * @private\n */\nexport function getBy(obj: any, path: any) {\n const pathObj = makePathArray(path)\n return pathObj.reduce((current: any, pathPart: any) => {\n if (current === null) return null\n if (typeof current !== 'undefined') {\n return current[pathPart]\n }\n return undefined\n }, obj)\n}\n\n/**\n * Set a value on an object using a path, including dot notation.\n * @private\n */\nexport function setBy(obj: any, _path: any, updater: Updater<any>) {\n const path = makePathArray(_path)\n\n function doSet(parent?: any): any {\n if (!path.length) {\n return functionalUpdate(updater, parent)\n }\n\n const key = path.shift()\n\n if (\n typeof key === 'string' ||\n (typeof key === 'number' && !Array.isArray(parent))\n ) {\n if (typeof parent === 'object') {\n if (parent === null) {\n parent = {}\n }\n return {\n ...parent,\n [key]: doSet(parent[key]),\n }\n }\n return {\n [key]: doSet(),\n }\n }\n\n if (Array.isArray(parent) && typeof key === 'number') {\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doSet(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n return [...new Array(key), doSet()]\n }\n\n return doSet(obj)\n}\n\n/**\n * Delete a field on an object using a path, including dot notation.\n * @private\n */\nexport function deleteBy(obj: any, _path: any) {\n const path = makePathArray(_path)\n\n function doDelete(parent: any): any {\n if (!parent) return\n if (path.length === 1) {\n const finalPath = path[0]!\n if (Array.isArray(parent) && typeof finalPath === 'number') {\n return parent.filter((_, i) => i !== finalPath)\n }\n const { [finalPath]: remove, ...rest } = parent\n return rest\n }\n\n const key = path.shift()\n\n if (typeof key === 'string') {\n if (typeof parent === 'object') {\n return {\n ...parent,\n [key]: doDelete(parent[key]),\n }\n }\n }\n\n if (typeof key === 'number') {\n if (Array.isArray(parent)) {\n if (key >= parent.length) {\n return parent\n }\n const prefix = parent.slice(0, key)\n return [\n ...(prefix.length ? prefix : new Array(key)),\n doDelete(parent[key]),\n ...parent.slice(key + 1),\n ]\n }\n }\n\n throw new Error('It seems we have created an infinite loop in deleteBy. ')\n }\n\n return doDelete(obj)\n}\n\nconst reLineOfOnlyDigits = /^(\\d+)$/gm\n// the second dot must be in a lookahead or the engine\n// will skip subsequent numbers (like foo.0.1.)\nconst reDigitsBetweenDots = /\\.(\\d+)(?=\\.)/gm\nconst reStartWithDigitThenDot = /^(\\d+)\\./gm\nconst reDotWithDigitsToEnd = /\\.(\\d+$)/gm\nconst reMultipleDots = /\\.{2,}/gm\n\nconst intPrefix = '__int__'\nconst intReplace = `${intPrefix}$1`\n\n/**\n * @private\n */\nexport function makePathArray(str: string | Array<string | number>) {\n if (Array.isArray(str)) {\n return [...str]\n }\n\n if (typeof str !== 'string') {\n throw new Error('Path must be a string.')\n }\n\n return (\n str\n // Leading `[` may lead to wrong parsing down the line\n // (Example: '[0][1]' should be '0.1', not '.0.1')\n .replace(/(^\\[)|]/gm, '')\n .replace(/\\[/g, '.')\n .replace(reLineOfOnlyDigits, intReplace)\n .replace(reDigitsBetweenDots, `.${intReplace}.`)\n .replace(reStartWithDigitThenDot, `${intReplace}.`)\n .replace(reDotWithDigitsToEnd, `.${intReplace}`)\n .replace(reMultipleDots, '.')\n .split('.')\n .map((d) => {\n if (d.startsWith(intPrefix)) {\n const numStr = d.substring(intPrefix.length)\n const num = parseInt(numStr, 10)\n\n if (String(num) === numStr) {\n return num\n }\n return numStr\n }\n return d\n })\n )\n}\n\n/**\n * @private\n */\nexport function concatenatePaths(path1: string, path2: string): string {\n if (path1.length === 0) return path2\n if (path2.length === 0) return path1\n\n if (path2.startsWith('[')) {\n return path1 + path2\n }\n\n // In cases where parent and child withFieldGroup forms are both nested\n if (path2.startsWith('.')) {\n return path1 + path2\n }\n\n return `${path1}.${path2}`\n}\n\n/**\n * @private\n */\nexport function isNonEmptyArray(obj: any) {\n return !(Array.isArray(obj) && obj.length === 0)\n}\n\ninterface AsyncValidatorArrayPartialOptions<T> {\n validators?: T\n asyncDebounceMs?: number\n}\n\n/**\n * @private\n */\nexport interface AsyncValidator<T> {\n cause: ValidationCause\n validate: T\n debounceMs: number\n}\n\ninterface SyncValidatorArrayPartialOptions<T> {\n validators?: T\n}\n\n/**\n * @private\n */\nexport interface SyncValidator<T> {\n cause: ValidationCause\n validate: T\n}\n\n/**\n * @private\n */\nexport function getSyncValidatorArray<T>(\n cause: ValidationCause,\n options: SyncValidatorArrayPartialOptions<T> & {\n validationLogic?: any\n form?: any\n },\n): T extends FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n ? Array<\n SyncValidator<\n | T['onChange']\n | T['onBlur']\n | T['onSubmit']\n | T['onMount']\n | T['onDynamic']\n >\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n SyncValidator<\n | T['onChange']\n | T['onBlur']\n | T['onSubmit']\n | T['onMount']\n | T['onDynamic']\n >\n >\n : never {\n const runValidation = (\n props: Parameters<ValidationLogicProps['runValidation']>[0],\n ) => {\n return props.validators.filter(Boolean).map((validator) => {\n return {\n cause: validator!.cause,\n validate: validator!.fn,\n }\n })\n }\n\n return options.validationLogic({\n form: options.form,\n validators: options.validators,\n event: { type: cause, async: false },\n runValidation,\n })\n}\n\n/**\n * @private\n */\nexport function getAsyncValidatorArray<T>(\n cause: ValidationCause,\n options: AsyncValidatorArrayPartialOptions<T> & {\n validationLogic?: any\n form?: any\n },\n): T extends FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n ? Array<\n AsyncValidator<\n | T['onChangeAsync']\n | T['onBlurAsync']\n | T['onSubmitAsync']\n | T['onDynamicAsync']\n >\n >\n : T extends FormValidators<any, any, any, any, any, any, any, any, any, any>\n ? Array<\n AsyncValidator<\n | T['onChangeAsync']\n | T['onBlurAsync']\n | T['onSubmitAsync']\n | T['onDynamicAsync']\n >\n >\n : never {\n const { asyncDebounceMs } = options\n const {\n onBlurAsyncDebounceMs,\n onChangeAsyncDebounceMs,\n onDynamicAsyncDebounceMs,\n } = (options.validators || {}) as\n | FieldValidators<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n | FormValidators<any, any, any, any, any, any, any, any, any, any>\n\n const defaultDebounceMs = asyncDebounceMs ?? 0\n\n const runValidation = (\n props: Parameters<ValidationLogicProps['runValidation']>[0],\n ) => {\n return props.validators.filter(Boolean).map((validator) => {\n const validatorCause = validator?.cause || cause\n\n let debounceMs = defaultDebounceMs\n\n switch (validatorCause) {\n case 'change':\n debounceMs = onChangeAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'blur':\n debounceMs = onBlurAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'dynamic':\n debounceMs = onDynamicAsyncDebounceMs ?? defaultDebounceMs\n break\n case 'submit':\n debounceMs = 0 // submit validators are always run immediately\n break\n default:\n break\n }\n\n if (cause === 'submit') {\n debounceMs = 0\n }\n\n return {\n cause: validatorCause,\n validate: validator!.fn,\n debounceMs: debounceMs,\n }\n })\n }\n\n return options.validationLogic({\n form: options.form,\n validators: options.validators,\n event: { type: cause, async: true },\n runValidation,\n })\n}\n\nexport const isGlobalFormValidationError = (\n error: unknown,\n): error is GlobalFormValidationError<unknown> => {\n return !!error && typeof error === 'object' && 'fields' in error\n}\n\nexport function evaluate<T>(objA: T, objB: T) {\n if (Object.is(objA, objB)) {\n return true\n }\n\n if (\n typeof objA !== 'object' ||\n objA === null ||\n typeof objB !== 'object' ||\n objB === null\n ) {\n return false\n }\n\n if (objA instanceof Map && objB instanceof Map) {\n if (objA.size !== objB.size) return false\n for (const [k, v] of objA) {\n if (!objB.has(k) || !Object.is(v, objB.get(k))) return false\n }\n return true\n }\n\n if (objA instanceof Set && objB instanceof Set) {\n if (objA.size !== objB.size) return false\n for (const v of objA) {\n if (!objB.has(v)) return false\n }\n return true\n }\n\n const keysA = Object.keys(objA)\n const keysB = Object.keys(objB)\n\n if (keysA.length !== keysB.length) {\n return false\n }\n\n for (const key of keysA) {\n // performs recursive search down the object tree\n\n if (\n !keysB.includes(key) ||\n !evaluate(objA[key as keyof T], objB[key as keyof T])\n ) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Determines the logic for determining the error source and value to set on the field meta within the form level sync/async validation.\n * @private\n */\nexport const determineFormLevelErrorSourceAndValue = ({\n newFormValidatorError,\n isPreviousErrorFromFormValidator,\n previousErrorValue,\n}: {\n newFormValidatorError: ValidationError\n isPreviousErrorFromFormValidator: boolean\n previousErrorValue: ValidationError\n}): {\n newErrorValue: ValidationError\n newSource: ValidationSource | undefined\n} => {\n // All falsy values are not considered errors\n if (newFormValidatorError) {\n return { newErrorValue: newFormValidatorError, newSource: 'form' }\n }\n\n // Clears form level error since it's now stale\n if (isPreviousErrorFromFormValidator) {\n return { newErrorValue: undefined, newSource: undefined }\n }\n\n // At this point, we have a preivous error which must have been set by the field validator, keep as is\n if (previousErrorValue) {\n return { newErrorValue: previousErrorValue, newSource: 'field' }\n }\n\n // No new or previous error, clear the error\n return { newErrorValue: undefined, newSource: undefined }\n}\n\n/**\n * Determines the logic for determining the error source and value to set on the field meta within the field level sync/async validation.\n * @private\n */\nexport const determineFieldLevelErrorSourceAndValue = ({\n formLevelError,\n fieldLevelError,\n}: {\n formLevelError: ValidationError\n fieldLevelError: ValidationError\n}): {\n newErrorValue: ValidationError\n newSource: ValidationSource | undefined\n} => {\n // At field level, we prioritize the field level error\n if (fieldLevelError) {\n return { newErrorValue: fieldLevelError, newSource: 'field' }\n }\n\n // If there is no field level error, and there is a form level error, we set the form level error\n if (formLevelError) {\n return { newErrorValue: formLevelError, newSource: 'form' }\n }\n\n return { newErrorValue: undefined, newSource: undefined }\n}\n\nexport function createFieldMap<T>(values: Readonly<T>): { [K in keyof T]: K } {\n const output: { [K in keyof T]: K } = {} as any\n\n for (const key in values) {\n output[key] = key\n }\n\n return output\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/form-core",
3
- "version": "1.19.1",
3
+ "version": "1.19.2",
4
4
  "description": "Powerful, type-safe, framework agnostic forms.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
package/src/FormApi.ts CHANGED
@@ -57,6 +57,8 @@ type FormErrorMapFromValidator<
57
57
  TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
58
58
  TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
59
59
  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
60
+ TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
61
+ TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
60
62
  > = Partial<
61
63
  Record<
62
64
  DeepKeys<TFormData>,
@@ -67,7 +69,9 @@ type FormErrorMapFromValidator<
67
69
  TOnBlur,
68
70
  TOnBlurAsync,
69
71
  TOnSubmit,
70
- TOnSubmitAsync
72
+ TOnSubmitAsync,
73
+ TOnDynamic,
74
+ TOnDynamicAsync
71
75
  >
72
76
  >
73
77
  >
@@ -1491,7 +1495,9 @@ export class FormApi<
1491
1495
  TOnBlur,
1492
1496
  TOnBlurAsync,
1493
1497
  TOnSubmit,
1494
- TOnSubmitAsync
1498
+ TOnSubmitAsync,
1499
+ TOnDynamic,
1500
+ TOnDynamicAsync
1495
1501
  >
1496
1502
  } => {
1497
1503
  const validates = getSyncValidatorArray(cause, {
@@ -1511,7 +1517,9 @@ export class FormApi<
1511
1517
  TOnBlur,
1512
1518
  TOnBlurAsync,
1513
1519
  TOnSubmit,
1514
- TOnSubmitAsync
1520
+ TOnSubmitAsync,
1521
+ TOnDynamic,
1522
+ TOnDynamicAsync
1515
1523
  > = {}
1516
1524
 
1517
1525
  batch(() => {
@@ -1654,7 +1662,9 @@ export class FormApi<
1654
1662
  TOnBlur,
1655
1663
  TOnBlurAsync,
1656
1664
  TOnSubmit,
1657
- TOnSubmitAsync
1665
+ TOnSubmitAsync,
1666
+ TOnDynamic,
1667
+ TOnDynamicAsync
1658
1668
  >
1659
1669
  > => {
1660
1670
  const validates = getAsyncValidatorArray(cause, {
@@ -1801,7 +1811,9 @@ export class FormApi<
1801
1811
  TOnBlur,
1802
1812
  TOnBlurAsync,
1803
1813
  TOnSubmit,
1804
- TOnSubmitAsync
1814
+ TOnSubmitAsync,
1815
+ TOnDynamic,
1816
+ TOnDynamicAsync
1805
1817
  > = {}
1806
1818
  if (promises.length) {
1807
1819
  results = await Promise.all(promises)
@@ -1846,7 +1858,9 @@ export class FormApi<
1846
1858
  TOnBlur,
1847
1859
  TOnBlurAsync,
1848
1860
  TOnSubmit,
1849
- TOnSubmitAsync
1861
+ TOnSubmitAsync,
1862
+ TOnDynamic,
1863
+ TOnDynamicAsync
1850
1864
  >
1851
1865
  | Promise<
1852
1866
  FormErrorMapFromValidator<
@@ -1857,7 +1871,9 @@ export class FormApi<
1857
1871
  TOnBlur,
1858
1872
  TOnBlurAsync,
1859
1873
  TOnSubmit,
1860
- TOnSubmitAsync
1874
+ TOnSubmitAsync,
1875
+ TOnDynamic,
1876
+ TOnDynamicAsync
1861
1877
  >
1862
1878
  > => {
1863
1879
  // Attempt to sync validate first
@@ -24,35 +24,45 @@ export function formOptions<
24
24
  TOptions extends Partial<
25
25
  FormOptions<
26
26
  TFormData,
27
- undefined | FormValidateOrFn<TFormData>,
28
- undefined | FormValidateOrFn<TFormData>,
29
- undefined | FormAsyncValidateOrFn<TFormData>,
30
- undefined | FormValidateOrFn<TFormData>,
31
- undefined | FormAsyncValidateOrFn<TFormData>,
32
- undefined | FormValidateOrFn<TFormData>,
33
- undefined | FormAsyncValidateOrFn<TFormData>,
34
- undefined | FormValidateOrFn<TFormData>,
35
- undefined | FormAsyncValidateOrFn<TFormData>,
36
- undefined | FormAsyncValidateOrFn<TFormData>,
27
+ TOnMount,
28
+ TOnChange,
29
+ TOnChangeAsync,
30
+ TOnBlur,
31
+ TOnBlurAsync,
32
+ TOnSubmit,
33
+ TOnSubmitAsync,
34
+ TOnDynamic,
35
+ TOnDynamicAsync,
36
+ TOnServer,
37
37
  TSubmitMeta
38
38
  >
39
39
  >,
40
- TFormData = TOptions['defaultValues'],
41
- TSubmitMeta = TOptions['onSubmitMeta'],
40
+ TFormData,
41
+ TOnMount extends undefined | FormValidateOrFn<TFormData>,
42
+ TOnChange extends undefined | FormValidateOrFn<TFormData>,
43
+ TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
44
+ TOnBlur extends undefined | FormValidateOrFn<TFormData>,
45
+ TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
46
+ TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
47
+ TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
48
+ TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
49
+ TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
50
+ TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
51
+ TSubmitMeta = never,
42
52
  >(
43
53
  defaultOpts: Partial<
44
54
  FormOptions<
45
55
  TFormData,
46
- undefined | FormValidateOrFn<TFormData>,
47
- undefined | FormValidateOrFn<TFormData>,
48
- undefined | FormAsyncValidateOrFn<TFormData>,
49
- undefined | FormValidateOrFn<TFormData>,
50
- undefined | FormAsyncValidateOrFn<TFormData>,
51
- undefined | FormValidateOrFn<TFormData>,
52
- undefined | FormAsyncValidateOrFn<TFormData>,
53
- undefined | FormValidateOrFn<TFormData>,
54
- undefined | FormAsyncValidateOrFn<TFormData>,
55
- undefined | FormAsyncValidateOrFn<TFormData>,
56
+ TOnMount,
57
+ TOnChange,
58
+ TOnChangeAsync,
59
+ TOnBlur,
60
+ TOnBlurAsync,
61
+ TOnSubmit,
62
+ TOnSubmitAsync,
63
+ TOnDynamic,
64
+ TOnDynamicAsync,
65
+ TOnServer,
56
66
  TSubmitMeta
57
67
  >
58
68
  > &