@tanstack/form-core 0.3.6 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/legacy/FieldApi.cjs +49 -26
- package/build/legacy/FieldApi.cjs.map +1 -1
- package/build/legacy/FieldApi.d.cts +1 -0
- package/build/legacy/FieldApi.d.ts +1 -0
- package/build/legacy/FieldApi.js +49 -18
- package/build/legacy/FieldApi.js.map +1 -1
- package/build/legacy/FormApi.cjs +10 -12
- package/build/legacy/FormApi.cjs.map +1 -1
- package/build/legacy/FormApi.d.cts +2 -1
- package/build/legacy/FormApi.d.ts +2 -1
- package/build/legacy/FormApi.js +10 -14
- package/build/legacy/FormApi.js.map +1 -1
- package/build/legacy/index.cjs +3 -1
- package/build/legacy/index.cjs.map +1 -1
- package/build/legacy/index.d.cts +48 -52
- package/build/legacy/index.d.ts +48 -52
- package/build/legacy/index.js +1 -0
- package/build/legacy/index.js.map +1 -1
- package/build/legacy/types.cjs +19 -0
- package/build/legacy/types.cjs.map +1 -0
- package/build/legacy/types.d.cts +7 -0
- package/build/legacy/types.d.ts +7 -0
- package/build/legacy/types.js +1 -0
- package/build/legacy/utils.js +0 -2
- package/build/legacy/utils.js.map +1 -1
- package/build/modern/FieldApi.cjs +47 -9
- package/build/modern/FieldApi.cjs.map +1 -1
- package/build/modern/FieldApi.d.cts +1 -0
- package/build/modern/FieldApi.d.ts +1 -0
- package/build/modern/FieldApi.js +47 -9
- package/build/modern/FieldApi.js.map +1 -1
- package/build/modern/FormApi.cjs +10 -12
- package/build/modern/FormApi.cjs.map +1 -1
- package/build/modern/FormApi.d.cts +2 -1
- package/build/modern/FormApi.d.ts +2 -1
- package/build/modern/FormApi.js +10 -12
- package/build/modern/FormApi.js.map +1 -1
- package/build/modern/index.cjs +3 -1
- package/build/modern/index.cjs.map +1 -1
- package/build/modern/index.d.cts +48 -52
- package/build/modern/index.d.ts +48 -52
- package/build/modern/index.js +1 -0
- package/build/modern/index.js.map +1 -1
- package/build/modern/types.cjs +19 -0
- package/build/modern/types.cjs.map +1 -0
- package/build/modern/types.d.cts +7 -0
- package/build/modern/types.d.ts +7 -0
- package/build/modern/types.js +1 -0
- package/build/modern/types.js.map +1 -0
- package/package.json +1 -1
- package/src/FieldApi.ts +175 -44
- package/src/FormApi.ts +61 -46
- package/src/index.ts +1 -0
- package/src/tests/FieldApi.spec.ts +17 -1
- package/src/tests/FieldApi.test-d.ts +26 -11
- package/src/tests/FormApi.spec.ts +1 -1
- package/src/types.ts +7 -0
- package/build/legacy/chunk-4QZDOMDG.js +0 -19
- /package/build/legacy/{chunk-4QZDOMDG.js.map → types.js.map} +0 -0
package/build/legacy/FormApi.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import "./chunk-4QZDOMDG.js";
|
|
2
|
-
|
|
3
1
|
// src/FormApi.ts
|
|
4
2
|
import { Store } from "@tanstack/store";
|
|
5
3
|
import { functionalUpdate, getBy, isNonEmptyArray, setBy } from "./utils.js";
|
|
@@ -62,18 +60,16 @@ var FormApi = class {
|
|
|
62
60
|
this.validateAllFields = async (cause) => {
|
|
63
61
|
const fieldValidationPromises = [];
|
|
64
62
|
this.store.batch(() => {
|
|
65
|
-
void Object.values(this.fieldInfo).forEach(
|
|
66
|
-
(field) => {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
);
|
|
63
|
+
void Object.values(this.fieldInfo).forEach((field) => {
|
|
64
|
+
Object.values(field.instances).forEach((instance) => {
|
|
65
|
+
if (!instance.state.meta.isTouched) {
|
|
66
|
+
instance.setMeta((prev) => ({ ...prev, isTouched: true }));
|
|
67
|
+
fieldValidationPromises.push(
|
|
68
|
+
Promise.resolve().then(() => instance.validate(cause))
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
77
73
|
});
|
|
78
74
|
return Promise.all(fieldValidationPromises);
|
|
79
75
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\n//\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport { functionalUpdate, getBy, isNonEmptyArray, setBy } from './utils'\nimport type { FieldApi, FieldMeta, ValidationCause } from './FieldApi'\n\nexport type FormOptions<TData> = {\n defaultValues?: TData\n defaultState?: Partial<FormState<TData>>\n asyncDebounceMs?: number\n onMount?: (values: TData, formApi: FormApi<TData>) => ValidationError\n onMountAsync?: (\n values: TData,\n formApi: FormApi<TData>,\n ) => ValidationError | Promise<ValidationError>\n onMountAsyncDebounceMs?: number\n onChange?: (values: TData, formApi: FormApi<TData>) => ValidationError\n onChangeAsync?: (\n values: TData,\n formApi: FormApi<TData>,\n ) => ValidationError | Promise<ValidationError>\n onChangeAsyncDebounceMs?: number\n onBlur?: (values: TData, formApi: FormApi<TData>) => ValidationError\n onBlurAsync?: (\n values: TData,\n formApi: FormApi<TData>,\n ) => ValidationError | Promise<ValidationError>\n onBlurAsyncDebounceMs?: number\n onSubmit?: (values: TData, formApi: FormApi<TData>) => any | Promise<any>\n onSubmitInvalid?: (values: TData, formApi: FormApi<TData>) => void\n}\n\nexport type FieldInfo<TFormData> = {\n instances: Record<string, FieldApi<TFormData, any, any>>\n} & ValidationMeta\n\nexport type ValidationMeta = {\n validationCount?: number\n validationAsyncCount?: number\n validationPromise?: Promise<ValidationError[]>\n validationResolve?: (errors: ValidationError[]) => void\n validationReject?: (errors: unknown) => void\n}\n\nexport type ValidationError = undefined | false | null | string\n\nexport type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`\n\nexport type ValidationErrorMap = {\n [K in ValidationErrorMapKeys]?: ValidationError\n}\n\nexport type FormState<TData> = {\n values: TData\n // Form Validation\n isFormValidating: boolean\n formValidationCount: number\n isFormValid: boolean\n formError?: ValidationError\n // Fields\n fieldMeta: Record<DeepKeys<TData>, FieldMeta>\n isFieldsValidating: boolean\n isFieldsValid: boolean\n isSubmitting: boolean\n // General\n isTouched: boolean\n isSubmitted: boolean\n isValidating: boolean\n isValid: boolean\n canSubmit: boolean\n submissionAttempts: number\n}\n\nfunction getDefaultFormState<TData>(\n defaultState: Partial<FormState<TData>>,\n): FormState<TData> {\n return {\n values: defaultState.values ?? ({} as never),\n fieldMeta: defaultState.fieldMeta ?? ({} as never),\n canSubmit: defaultState.canSubmit ?? true,\n isFieldsValid: defaultState.isFieldsValid ?? false,\n isFieldsValidating: defaultState.isFieldsValidating ?? false,\n isFormValid: defaultState.isFormValid ?? false,\n isFormValidating: defaultState.isFormValidating ?? false,\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isTouched: defaultState.isTouched ?? false,\n isValid: defaultState.isValid ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n formValidationCount: defaultState.formValidationCount ?? 0,\n }\n}\n\nexport class FormApi<TFormData> {\n // // This carries the context for nested fields\n options: FormOptions<TFormData> = {}\n store!: Store<FormState<TFormData>>\n // Do not use __state directly, as it is not reactive.\n // Please use form.useStore() utility to subscribe to state\n state!: FormState<TFormData>\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>> = {} as any\n fieldName?: string\n validationMeta: ValidationMeta = {}\n\n constructor(opts?: FormOptions<TFormData>) {\n this.store = new Store<FormState<TFormData>>(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n {\n onUpdate: () => {\n let { state } = this.store\n // Computed state\n const fieldMetaValues = Object.values(state.fieldMeta) as (\n | FieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some((field) =>\n isNonEmptyArray(field?.errors),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n\n const isValidating = isFieldsValidating || state.isFormValidating\n const isFormValid = !state.formError\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (state.submissionAttempts === 0 && !isTouched) ||\n (!isValidating && !state.isSubmitting && isValid)\n\n state = {\n ...state,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n }\n\n this.store.state = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n\n this.update(opts || {})\n }\n\n update = (options?: FormOptions<TFormData>) => {\n if (!options) return\n\n this.store.batch(() => {\n const shouldUpdateValues =\n options.defaultValues &&\n options.defaultValues !== this.options.defaultValues &&\n !this.state.isTouched\n\n const shouldUpdateState =\n options.defaultState !== this.options.defaultState &&\n !this.state.isTouched\n\n this.store.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateState ? options.defaultState : {},\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n ),\n ),\n )\n })\n\n this.options = options\n }\n\n reset = () =>\n this.store.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values: this.options.defaultValues ?? this.options.defaultState?.values,\n }),\n )\n\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n this.store.batch(() => {\n void (Object.values(this.fieldInfo) as FieldInfo<any>[]).forEach(\n (field) => {\n Object.values(field.instances).forEach((instance) => {\n // If any fields are not touched\n if (!instance.state.meta.isTouched) {\n // Mark them as touched\n instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n // Validate the field\n fieldValidationPromises.push(\n Promise.resolve().then(() => instance.validate(cause)),\n )\n }\n })\n },\n )\n })\n\n return Promise.all(fieldValidationPromises)\n }\n\n handleSubmit = async () => {\n // Check to see that the form and all fields have been touched\n // If they have not, touch them all and run validation\n // Run form validation\n // Submit the form\n\n this.store.setState((old) => ({\n ...old,\n // Submission attempts mark the form as not submitted\n isSubmitted: false,\n // Count submission attempts\n submissionAttempts: old.submissionAttempts + 1,\n }))\n\n // Don't let invalid forms submit\n if (!this.state.canSubmit) return\n\n this.store.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.store.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n // Validate all fields\n await this.validateAllFields('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.(this.state.values, this)\n return\n }\n\n // Run validation for the form\n // await this.validateForm()\n\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.(this.state.values, this)\n return\n }\n\n try {\n // Run the submit code\n await this.options.onSubmit?.(this.state.values, this)\n\n this.store.batch(() => {\n this.store.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n getFieldInfo = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldInfo<TFormData> => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return (this.fieldInfo[field] ||= {\n instances: {},\n })\n }\n\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<FieldMeta>,\n ) => {\n this.store.setState((prev) => {\n return {\n ...prev,\n fieldMeta: {\n ...prev.fieldMeta,\n [field]: functionalUpdate(updater, prev.fieldMeta[field]),\n },\n }\n })\n }\n\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: { touch?: boolean },\n ) => {\n const touch = opts?.touch\n\n this.store.batch(() => {\n if (touch) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n }))\n }\n\n this.store.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n pushFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n value: DeepValue<TFormData, TField>[number],\n opts?: { touch?: boolean },\n ) => {\n return this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n }\n\n insertFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n value: DeepValue<TFormData, TField>[number],\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).map((d, i) =>\n i === index ? value : d,\n ) as any\n },\n opts,\n )\n }\n\n removeFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).filter(\n (_d, i) => i !== index,\n ) as any\n },\n opts,\n )\n }\n\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n ) => {\n this.setFieldValue(field, (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n })\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport { functionalUpdate, getBy, isNonEmptyArray, setBy } from './utils'\nimport type { FieldApi, FieldMeta, ValidationCause } from './FieldApi'\nimport type { ValidationError, Validator } from './types'\n\ntype ValidateFn<TData, ValidatorType> = (\n values: TData,\n formApi: FormApi<TData, ValidatorType>,\n) => ValidationError\n\ntype ValidateOrFn<TData, ValidatorType> = ValidatorType extends Validator<TData>\n ? Parameters<ReturnType<ValidatorType>['validate']>[1]\n : ValidateFn<TData, ValidatorType>\n\ntype ValidateAsyncFn<TData, ValidatorType> = (\n value: TData,\n fieldApi: FormApi<TData, ValidatorType>,\n) => ValidationError | Promise<ValidationError>\n\nexport type FormOptions<TData, ValidatorType> = {\n defaultValues?: TData\n defaultState?: Partial<FormState<TData>>\n asyncDebounceMs?: number\n validator?: ValidatorType\n onMount?: ValidateOrFn<TData, ValidatorType>\n onMountAsync?: ValidateAsyncFn<TData, ValidatorType>\n onMountAsyncDebounceMs?: number\n onChange?: ValidateOrFn<TData, ValidatorType>\n onChangeAsync?: ValidateAsyncFn<TData, ValidatorType>\n onChangeAsyncDebounceMs?: number\n onBlur?: ValidateOrFn<TData, ValidatorType>\n onBlurAsync?: ValidateAsyncFn<TData, ValidatorType>\n onBlurAsyncDebounceMs?: number\n onSubmit?: (\n values: TData,\n formApi: FormApi<TData, ValidatorType>,\n ) => any | Promise<any>\n onSubmitInvalid?: (\n values: TData,\n formApi: FormApi<TData, ValidatorType>,\n ) => void\n}\n\nexport type FieldInfo<TFormData, ValidatorType> = {\n instances: Record<string, FieldApi<TFormData, any, unknown, ValidatorType>>\n} & ValidationMeta\n\nexport type ValidationMeta = {\n validationCount?: number\n validationAsyncCount?: number\n validationPromise?: Promise<ValidationError[]>\n validationResolve?: (errors: ValidationError[]) => void\n validationReject?: (errors: unknown) => void\n}\n\nexport type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`\n\nexport type ValidationErrorMap = {\n [K in ValidationErrorMapKeys]?: ValidationError\n}\n\nexport type FormState<TData> = {\n values: TData\n // Form Validation\n isFormValidating: boolean\n formValidationCount: number\n isFormValid: boolean\n formError?: ValidationError\n // Fields\n fieldMeta: Record<DeepKeys<TData>, FieldMeta>\n isFieldsValidating: boolean\n isFieldsValid: boolean\n isSubmitting: boolean\n // General\n isTouched: boolean\n isSubmitted: boolean\n isValidating: boolean\n isValid: boolean\n canSubmit: boolean\n submissionAttempts: number\n}\n\nfunction getDefaultFormState<TData>(\n defaultState: Partial<FormState<TData>>,\n): FormState<TData> {\n return {\n values: defaultState.values ?? ({} as never),\n fieldMeta: defaultState.fieldMeta ?? ({} as never),\n canSubmit: defaultState.canSubmit ?? true,\n isFieldsValid: defaultState.isFieldsValid ?? false,\n isFieldsValidating: defaultState.isFieldsValidating ?? false,\n isFormValid: defaultState.isFormValid ?? false,\n isFormValidating: defaultState.isFormValidating ?? false,\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isTouched: defaultState.isTouched ?? false,\n isValid: defaultState.isValid ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n formValidationCount: defaultState.formValidationCount ?? 0,\n }\n}\n\nexport class FormApi<TFormData, ValidatorType> {\n // // This carries the context for nested fields\n options: FormOptions<TFormData, ValidatorType> = {}\n store!: Store<FormState<TFormData>>\n // Do not use __state directly, as it is not reactive.\n // Please use form.useStore() utility to subscribe to state\n state!: FormState<TFormData>\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, ValidatorType>> =\n {} as any\n fieldName?: string\n validationMeta: ValidationMeta = {}\n\n constructor(opts?: FormOptions<TFormData, ValidatorType>) {\n this.store = new Store<FormState<TFormData>>(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n {\n onUpdate: () => {\n let { state } = this.store\n // Computed state\n const fieldMetaValues = Object.values(state.fieldMeta) as (\n | FieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some((field) =>\n isNonEmptyArray(field?.errors),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n\n const isValidating = isFieldsValidating || state.isFormValidating\n const isFormValid = !state.formError\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (state.submissionAttempts === 0 && !isTouched) ||\n (!isValidating && !state.isSubmitting && isValid)\n\n state = {\n ...state,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n }\n\n this.store.state = state\n this.state = state\n },\n },\n )\n\n this.state = this.store.state\n\n this.update(opts || {})\n }\n\n update = (options?: FormOptions<TFormData, ValidatorType>) => {\n if (!options) return\n\n this.store.batch(() => {\n const shouldUpdateValues =\n options.defaultValues &&\n options.defaultValues !== this.options.defaultValues &&\n !this.state.isTouched\n\n const shouldUpdateState =\n options.defaultState !== this.options.defaultState &&\n !this.state.isTouched\n\n this.store.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateState ? options.defaultState : {},\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n ),\n ),\n )\n })\n\n this.options = options\n }\n\n reset = () =>\n this.store.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values: this.options.defaultValues ?? this.options.defaultState?.values,\n }),\n )\n\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n this.store.batch(() => {\n void (\n Object.values(this.fieldInfo) as FieldInfo<any, ValidatorType>[]\n ).forEach((field) => {\n Object.values(field.instances).forEach((instance) => {\n // If any fields are not touched\n if (!instance.state.meta.isTouched) {\n // Mark them as touched\n instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n // Validate the field\n fieldValidationPromises.push(\n Promise.resolve().then(() => instance.validate(cause)),\n )\n }\n })\n })\n })\n\n return Promise.all(fieldValidationPromises)\n }\n\n handleSubmit = async () => {\n // Check to see that the form and all fields have been touched\n // If they have not, touch them all and run validation\n // Run form validation\n // Submit the form\n\n this.store.setState((old) => ({\n ...old,\n // Submission attempts mark the form as not submitted\n isSubmitted: false,\n // Count submission attempts\n submissionAttempts: old.submissionAttempts + 1,\n }))\n\n // Don't let invalid forms submit\n if (!this.state.canSubmit) return\n\n this.store.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.store.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n // Validate all fields\n await this.validateAllFields('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.(this.state.values, this)\n return\n }\n\n // Run validation for the form\n // await this.validateForm()\n\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.(this.state.values, this)\n return\n }\n\n try {\n // Run the submit code\n await this.options.onSubmit?.(this.state.values, this)\n\n this.store.batch(() => {\n this.store.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n getFieldInfo = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldInfo<TFormData, ValidatorType> => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return (this.fieldInfo[field] ||= {\n instances: {},\n })\n }\n\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<FieldMeta>,\n ) => {\n this.store.setState((prev) => {\n return {\n ...prev,\n fieldMeta: {\n ...prev.fieldMeta,\n [field]: functionalUpdate(updater, prev.fieldMeta[field]),\n },\n }\n })\n }\n\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: { touch?: boolean },\n ) => {\n const touch = opts?.touch\n\n this.store.batch(() => {\n if (touch) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n }))\n }\n\n this.store.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n pushFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n value: DeepValue<TFormData, TField> extends any[]\n ? DeepValue<TFormData, TField>[number]\n : never,\n opts?: { touch?: boolean },\n ) => {\n return this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n }\n\n insertFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n value: DeepValue<TFormData, TField> extends any[]\n ? DeepValue<TFormData, TField>[number]\n : never,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).map((d, i) =>\n i === index ? value : d,\n ) as any\n },\n opts,\n )\n }\n\n removeFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).filter(\n (_d, i) => i !== index,\n ) as any\n },\n opts,\n )\n }\n\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n ) => {\n this.setFieldValue(field, (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n })\n }\n}\n"],"mappings":"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","names":[]}
|
package/build/legacy/index.cjs
CHANGED
|
@@ -20,10 +20,12 @@ module.exports = __toCommonJS(src_exports);
|
|
|
20
20
|
__reExport(src_exports, require("./FormApi.cjs"), module.exports);
|
|
21
21
|
__reExport(src_exports, require("./FieldApi.cjs"), module.exports);
|
|
22
22
|
__reExport(src_exports, require("./utils.cjs"), module.exports);
|
|
23
|
+
__reExport(src_exports, require("./types.cjs"), module.exports);
|
|
23
24
|
// Annotate the CommonJS export names for ESM import in node:
|
|
24
25
|
0 && (module.exports = {
|
|
25
26
|
...require("./FormApi.cjs"),
|
|
26
27
|
...require("./FieldApi.cjs"),
|
|
27
|
-
...require("./utils.cjs")
|
|
28
|
+
...require("./utils.cjs"),
|
|
29
|
+
...require("./types.cjs")
|
|
28
30
|
});
|
|
29
31
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export * from './FormApi'\nexport * from './FieldApi'\nexport * from './utils'\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,wBAAc,0BAAd;AACA,wBAAc,2BADd;AAEA,wBAAc,wBAFd;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export * from './FormApi'\nexport * from './FieldApi'\nexport * from './utils'\nexport * from './types'\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,wBAAc,0BAAd;AACA,wBAAc,2BADd;AAEA,wBAAc,wBAFd;AAGA,wBAAc,wBAHd;","names":[]}
|
package/build/legacy/index.d.cts
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
import { Store } from '@tanstack/store';
|
|
2
2
|
import { DeepKeys, DeepValue, Updater } from './utils.cjs';
|
|
3
3
|
export { Narrow, Pretty, RequiredByKey, UpdaterFn, functionalUpdate, getBy, isNonEmptyArray, setBy } from './utils.cjs';
|
|
4
|
+
import { ValidationError, Validator } from './types.cjs';
|
|
4
5
|
|
|
5
|
-
type
|
|
6
|
+
type ValidateFn$1<TData, ValidatorType> = (values: TData, formApi: FormApi<TData, ValidatorType>) => ValidationError;
|
|
7
|
+
type ValidateOrFn$1<TData, ValidatorType> = ValidatorType extends Validator<TData> ? Parameters<ReturnType<ValidatorType>['validate']>[1] : ValidateFn$1<TData, ValidatorType>;
|
|
8
|
+
type ValidateAsyncFn$1<TData, ValidatorType> = (value: TData, fieldApi: FormApi<TData, ValidatorType>) => ValidationError | Promise<ValidationError>;
|
|
9
|
+
type FormOptions<TData, ValidatorType> = {
|
|
6
10
|
defaultValues?: TData;
|
|
7
11
|
defaultState?: Partial<FormState<TData>>;
|
|
8
12
|
asyncDebounceMs?: number;
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
validator?: ValidatorType;
|
|
14
|
+
onMount?: ValidateOrFn$1<TData, ValidatorType>;
|
|
15
|
+
onMountAsync?: ValidateAsyncFn$1<TData, ValidatorType>;
|
|
11
16
|
onMountAsyncDebounceMs?: number;
|
|
12
|
-
onChange?:
|
|
13
|
-
onChangeAsync?:
|
|
17
|
+
onChange?: ValidateOrFn$1<TData, ValidatorType>;
|
|
18
|
+
onChangeAsync?: ValidateAsyncFn$1<TData, ValidatorType>;
|
|
14
19
|
onChangeAsyncDebounceMs?: number;
|
|
15
|
-
onBlur?:
|
|
16
|
-
onBlurAsync?:
|
|
20
|
+
onBlur?: ValidateOrFn$1<TData, ValidatorType>;
|
|
21
|
+
onBlurAsync?: ValidateAsyncFn$1<TData, ValidatorType>;
|
|
17
22
|
onBlurAsyncDebounceMs?: number;
|
|
18
|
-
onSubmit?: (values: TData, formApi: FormApi<TData>) => any | Promise<any>;
|
|
19
|
-
onSubmitInvalid?: (values: TData, formApi: FormApi<TData>) => void;
|
|
23
|
+
onSubmit?: (values: TData, formApi: FormApi<TData, ValidatorType>) => any | Promise<any>;
|
|
24
|
+
onSubmitInvalid?: (values: TData, formApi: FormApi<TData, ValidatorType>) => void;
|
|
20
25
|
};
|
|
21
|
-
type FieldInfo<TFormData> = {
|
|
22
|
-
instances: Record<string, FieldApi<TFormData, any,
|
|
26
|
+
type FieldInfo<TFormData, ValidatorType> = {
|
|
27
|
+
instances: Record<string, FieldApi<TFormData, any, unknown, ValidatorType>>;
|
|
23
28
|
} & ValidationMeta;
|
|
24
29
|
type ValidationMeta = {
|
|
25
30
|
validationCount?: number;
|
|
@@ -28,7 +33,6 @@ type ValidationMeta = {
|
|
|
28
33
|
validationResolve?: (errors: ValidationError[]) => void;
|
|
29
34
|
validationReject?: (errors: unknown) => void;
|
|
30
35
|
};
|
|
31
|
-
type ValidationError = undefined | false | null | string;
|
|
32
36
|
type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`;
|
|
33
37
|
type ValidationErrorMap = {
|
|
34
38
|
[K in ValidationErrorMapKeys]?: ValidationError;
|
|
@@ -50,29 +54,29 @@ type FormState<TData> = {
|
|
|
50
54
|
canSubmit: boolean;
|
|
51
55
|
submissionAttempts: number;
|
|
52
56
|
};
|
|
53
|
-
declare class FormApi<TFormData> {
|
|
54
|
-
options: FormOptions<TFormData>;
|
|
57
|
+
declare class FormApi<TFormData, ValidatorType> {
|
|
58
|
+
options: FormOptions<TFormData, ValidatorType>;
|
|
55
59
|
store: Store<FormState<TFormData>>;
|
|
56
60
|
state: FormState<TFormData>;
|
|
57
|
-
fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>>;
|
|
61
|
+
fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, ValidatorType>>;
|
|
58
62
|
fieldName?: string;
|
|
59
63
|
validationMeta: ValidationMeta;
|
|
60
|
-
constructor(opts?: FormOptions<TFormData>);
|
|
61
|
-
update: (options?: FormOptions<TFormData>) => void;
|
|
64
|
+
constructor(opts?: FormOptions<TFormData, ValidatorType>);
|
|
65
|
+
update: (options?: FormOptions<TFormData, ValidatorType>) => void;
|
|
62
66
|
reset: () => void;
|
|
63
67
|
validateAllFields: (cause: ValidationCause) => Promise<ValidationError[][]>;
|
|
64
68
|
handleSubmit: () => Promise<void>;
|
|
65
69
|
getFieldValue: <TField extends DeepKeys<TFormData>>(field: TField) => DeepValue<TFormData, TField>;
|
|
66
70
|
getFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField) => FieldMeta | undefined;
|
|
67
|
-
getFieldInfo: <TField extends DeepKeys<TFormData>>(field: TField) => FieldInfo<TFormData>;
|
|
71
|
+
getFieldInfo: <TField extends DeepKeys<TFormData>>(field: TField) => FieldInfo<TFormData, ValidatorType>;
|
|
68
72
|
setFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<FieldMeta>) => void;
|
|
69
73
|
setFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<DeepValue<TFormData, TField>>, opts?: {
|
|
70
74
|
touch?: boolean;
|
|
71
75
|
}) => void;
|
|
72
|
-
pushFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, value: DeepValue<TFormData, TField>[number], opts?: {
|
|
76
|
+
pushFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, value: DeepValue<TFormData, TField> extends any[] ? DeepValue<TFormData, TField>[number] : never, opts?: {
|
|
73
77
|
touch?: boolean;
|
|
74
78
|
}) => void;
|
|
75
|
-
insertFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, index: number, value: DeepValue<TFormData, TField>[number], opts?: {
|
|
79
|
+
insertFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, index: number, value: DeepValue<TFormData, TField> extends any[] ? DeepValue<TFormData, TField>[number] : never, opts?: {
|
|
76
80
|
touch?: boolean;
|
|
77
81
|
}) => void;
|
|
78
82
|
removeFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, index: number, opts?: {
|
|
@@ -82,35 +86,29 @@ declare class FormApi<TFormData> {
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
type ValidationCause = 'change' | 'blur' | 'submit' | 'mount';
|
|
85
|
-
type ValidateFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (value: TData, fieldApi: FieldApi<TParentData, TName>) => ValidationError;
|
|
86
|
-
type
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
*/
|
|
92
|
-
TName extends DeepKeys<TParentData>,
|
|
93
|
-
/**
|
|
94
|
-
* If TData is unknown, we can use the TName generic to determine the type
|
|
95
|
-
*/
|
|
96
|
-
TData = DeepValue<TParentData, TName>> {
|
|
97
|
-
name: DeepKeys<TParentData>;
|
|
89
|
+
type ValidateFn<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = (value: TData, fieldApi: FieldApi<TParentData, TName, ValidatorType, TData>) => ValidationError;
|
|
90
|
+
type ValidateOrFn<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = ValidatorType extends Validator<TData> ? Parameters<ReturnType<ValidatorType>['validate']>[1] | ValidateFn<TParentData, TName, ValidatorType, TData> : FormValidator extends Validator<TData> ? Parameters<ReturnType<FormValidator>['validate']>[1] | ValidateFn<TParentData, TName, ValidatorType, TData> : ValidateFn<TParentData, TName, ValidatorType, TData>;
|
|
91
|
+
type ValidateAsyncFn<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = (value: TData, fieldApi: FieldApi<TParentData, TName, ValidatorType, TData>) => ValidationError | Promise<ValidationError>;
|
|
92
|
+
type AsyncValidateOrFn<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = ValidatorType extends Validator<TData> ? Parameters<ReturnType<ValidatorType>['validate']>[1] | ValidateAsyncFn<TParentData, TName, ValidatorType, TData> : FormValidator extends Validator<TData> ? Parameters<ReturnType<FormValidator>['validate']>[1] | ValidateAsyncFn<TParentData, TName, ValidatorType, TData> : ValidateAsyncFn<TParentData, TName, ValidatorType, TData>;
|
|
93
|
+
interface FieldOptions<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
|
|
94
|
+
name: TName;
|
|
98
95
|
index?: TData extends any[] ? number : never;
|
|
99
96
|
defaultValue?: TData;
|
|
100
97
|
asyncDebounceMs?: number;
|
|
101
98
|
asyncAlways?: boolean;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
validator?: ValidatorType;
|
|
100
|
+
onMount?: (formApi: FieldApi<TParentData, TName, ValidatorType, TData>) => void;
|
|
101
|
+
onChange?: ValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
102
|
+
onChangeAsync?: AsyncValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
105
103
|
onChangeAsyncDebounceMs?: number;
|
|
106
|
-
onBlur?:
|
|
107
|
-
onBlurAsync?:
|
|
104
|
+
onBlur?: ValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
105
|
+
onBlurAsync?: AsyncValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
108
106
|
onBlurAsyncDebounceMs?: number;
|
|
109
|
-
onSubmitAsync?:
|
|
107
|
+
onSubmitAsync?: AsyncValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
110
108
|
defaultMeta?: Partial<FieldMeta>;
|
|
111
109
|
}
|
|
112
|
-
interface FieldApiOptions<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> extends FieldOptions<TParentData, TName, TData> {
|
|
113
|
-
form: FormApi<TParentData>;
|
|
110
|
+
interface FieldApiOptions<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> extends FieldOptions<TParentData, TName, ValidatorType, FormValidator, TData> {
|
|
111
|
+
form: FormApi<TParentData, FormValidator>;
|
|
114
112
|
}
|
|
115
113
|
type FieldMeta = {
|
|
116
114
|
isTouched: boolean;
|
|
@@ -124,20 +122,17 @@ type FieldState<TData> = {
|
|
|
124
122
|
meta: FieldMeta;
|
|
125
123
|
};
|
|
126
124
|
type ResolveName<TParentData> = unknown extends TParentData ? string : DeepKeys<TParentData>;
|
|
127
|
-
declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> {
|
|
128
|
-
#private;
|
|
125
|
+
declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
|
|
129
126
|
uid: number;
|
|
130
|
-
form: FieldApiOptions<TParentData, TName, TData>['form'];
|
|
127
|
+
form: FieldApiOptions<TParentData, TName, ValidatorType, TData>['form'];
|
|
131
128
|
name: DeepKeys<TParentData>;
|
|
132
|
-
options: FieldApiOptions<TParentData, TName>;
|
|
129
|
+
options: FieldApiOptions<TParentData, TName, ValidatorType, TData>;
|
|
133
130
|
store: Store<FieldState<TData>>;
|
|
134
131
|
state: FieldState<TData>;
|
|
135
132
|
prevState: FieldState<TData>;
|
|
136
|
-
constructor(opts: FieldApiOptions<TParentData, TName, TData>
|
|
137
|
-
form: FormApi<TParentData>;
|
|
138
|
-
});
|
|
133
|
+
constructor(opts: FieldApiOptions<TParentData, TName, ValidatorType, FormValidator, TData>);
|
|
139
134
|
mount: () => () => void;
|
|
140
|
-
update: (opts: FieldApiOptions<TParentData, TName, TData>) => void;
|
|
135
|
+
update: (opts: FieldApiOptions<TParentData, TName, ValidatorType, TData>) => void;
|
|
141
136
|
getValue: () => TData;
|
|
142
137
|
setValue: (updater: Updater<TData>, options?: {
|
|
143
138
|
touch?: boolean;
|
|
@@ -146,13 +141,14 @@ declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData =
|
|
|
146
141
|
_getMeta: () => FieldMeta | undefined;
|
|
147
142
|
getMeta: () => FieldMeta;
|
|
148
143
|
setMeta: (updater: Updater<FieldMeta>) => void;
|
|
149
|
-
getInfo: () => FieldInfo<TParentData>;
|
|
144
|
+
getInfo: () => FieldInfo<TParentData, TData>;
|
|
150
145
|
pushValue: (value: TData extends any[] ? TData[number] : never) => void;
|
|
151
146
|
insertValue: (index: number, value: TData extends any[] ? TData[number] : never) => void;
|
|
152
147
|
removeValue: (index: number) => void;
|
|
153
148
|
swapValues: (aIndex: number, bIndex: number) => void;
|
|
154
|
-
getSubField: <TSubName extends DeepKeys<TData>, TSubData = DeepValue<TData, TSubName>>(name: TSubName) => FieldApi<TData, TSubName, TSubData
|
|
149
|
+
getSubField: <TSubName extends DeepKeys<TData>, TSubData extends DeepValue<TData, TSubName> = DeepValue<TData, TSubName>>(name: TSubName) => FieldApi<TData, TSubName, ValidatorType, TSubData, DeepValue<TData, TSubName>>;
|
|
155
150
|
validateSync: (value: TData | undefined, cause: ValidationCause) => void;
|
|
151
|
+
__leaseValidateAsync: () => number;
|
|
156
152
|
cancelValidateAsync: () => void;
|
|
157
153
|
validateAsync: (value: TData | undefined, cause: ValidationCause) => Promise<ValidationError[]>;
|
|
158
154
|
validate: (cause: ValidationCause, value?: TData) => ValidationError[] | Promise<ValidationError[]>;
|
|
@@ -160,4 +156,4 @@ declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData =
|
|
|
160
156
|
handleBlur: () => void;
|
|
161
157
|
}
|
|
162
158
|
|
|
163
|
-
export { DeepKeys, DeepValue, FieldApi, FieldApiOptions, FieldInfo, FieldMeta, FieldOptions, FieldState, FormApi, FormOptions, FormState, ResolveName, Updater, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta };
|
|
159
|
+
export { DeepKeys, DeepValue, FieldApi, FieldApiOptions, FieldInfo, FieldMeta, FieldOptions, FieldState, FormApi, FormOptions, FormState, ResolveName, Updater, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta, Validator };
|
package/build/legacy/index.d.ts
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
import { Store } from '@tanstack/store';
|
|
2
2
|
import { DeepKeys, DeepValue, Updater } from './utils.js';
|
|
3
3
|
export { Narrow, Pretty, RequiredByKey, UpdaterFn, functionalUpdate, getBy, isNonEmptyArray, setBy } from './utils.js';
|
|
4
|
+
import { ValidationError, Validator } from './types.js';
|
|
4
5
|
|
|
5
|
-
type
|
|
6
|
+
type ValidateFn$1<TData, ValidatorType> = (values: TData, formApi: FormApi<TData, ValidatorType>) => ValidationError;
|
|
7
|
+
type ValidateOrFn$1<TData, ValidatorType> = ValidatorType extends Validator<TData> ? Parameters<ReturnType<ValidatorType>['validate']>[1] : ValidateFn$1<TData, ValidatorType>;
|
|
8
|
+
type ValidateAsyncFn$1<TData, ValidatorType> = (value: TData, fieldApi: FormApi<TData, ValidatorType>) => ValidationError | Promise<ValidationError>;
|
|
9
|
+
type FormOptions<TData, ValidatorType> = {
|
|
6
10
|
defaultValues?: TData;
|
|
7
11
|
defaultState?: Partial<FormState<TData>>;
|
|
8
12
|
asyncDebounceMs?: number;
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
validator?: ValidatorType;
|
|
14
|
+
onMount?: ValidateOrFn$1<TData, ValidatorType>;
|
|
15
|
+
onMountAsync?: ValidateAsyncFn$1<TData, ValidatorType>;
|
|
11
16
|
onMountAsyncDebounceMs?: number;
|
|
12
|
-
onChange?:
|
|
13
|
-
onChangeAsync?:
|
|
17
|
+
onChange?: ValidateOrFn$1<TData, ValidatorType>;
|
|
18
|
+
onChangeAsync?: ValidateAsyncFn$1<TData, ValidatorType>;
|
|
14
19
|
onChangeAsyncDebounceMs?: number;
|
|
15
|
-
onBlur?:
|
|
16
|
-
onBlurAsync?:
|
|
20
|
+
onBlur?: ValidateOrFn$1<TData, ValidatorType>;
|
|
21
|
+
onBlurAsync?: ValidateAsyncFn$1<TData, ValidatorType>;
|
|
17
22
|
onBlurAsyncDebounceMs?: number;
|
|
18
|
-
onSubmit?: (values: TData, formApi: FormApi<TData>) => any | Promise<any>;
|
|
19
|
-
onSubmitInvalid?: (values: TData, formApi: FormApi<TData>) => void;
|
|
23
|
+
onSubmit?: (values: TData, formApi: FormApi<TData, ValidatorType>) => any | Promise<any>;
|
|
24
|
+
onSubmitInvalid?: (values: TData, formApi: FormApi<TData, ValidatorType>) => void;
|
|
20
25
|
};
|
|
21
|
-
type FieldInfo<TFormData> = {
|
|
22
|
-
instances: Record<string, FieldApi<TFormData, any,
|
|
26
|
+
type FieldInfo<TFormData, ValidatorType> = {
|
|
27
|
+
instances: Record<string, FieldApi<TFormData, any, unknown, ValidatorType>>;
|
|
23
28
|
} & ValidationMeta;
|
|
24
29
|
type ValidationMeta = {
|
|
25
30
|
validationCount?: number;
|
|
@@ -28,7 +33,6 @@ type ValidationMeta = {
|
|
|
28
33
|
validationResolve?: (errors: ValidationError[]) => void;
|
|
29
34
|
validationReject?: (errors: unknown) => void;
|
|
30
35
|
};
|
|
31
|
-
type ValidationError = undefined | false | null | string;
|
|
32
36
|
type ValidationErrorMapKeys = `on${Capitalize<ValidationCause>}`;
|
|
33
37
|
type ValidationErrorMap = {
|
|
34
38
|
[K in ValidationErrorMapKeys]?: ValidationError;
|
|
@@ -50,29 +54,29 @@ type FormState<TData> = {
|
|
|
50
54
|
canSubmit: boolean;
|
|
51
55
|
submissionAttempts: number;
|
|
52
56
|
};
|
|
53
|
-
declare class FormApi<TFormData> {
|
|
54
|
-
options: FormOptions<TFormData>;
|
|
57
|
+
declare class FormApi<TFormData, ValidatorType> {
|
|
58
|
+
options: FormOptions<TFormData, ValidatorType>;
|
|
55
59
|
store: Store<FormState<TFormData>>;
|
|
56
60
|
state: FormState<TFormData>;
|
|
57
|
-
fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData>>;
|
|
61
|
+
fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, ValidatorType>>;
|
|
58
62
|
fieldName?: string;
|
|
59
63
|
validationMeta: ValidationMeta;
|
|
60
|
-
constructor(opts?: FormOptions<TFormData>);
|
|
61
|
-
update: (options?: FormOptions<TFormData>) => void;
|
|
64
|
+
constructor(opts?: FormOptions<TFormData, ValidatorType>);
|
|
65
|
+
update: (options?: FormOptions<TFormData, ValidatorType>) => void;
|
|
62
66
|
reset: () => void;
|
|
63
67
|
validateAllFields: (cause: ValidationCause) => Promise<ValidationError[][]>;
|
|
64
68
|
handleSubmit: () => Promise<void>;
|
|
65
69
|
getFieldValue: <TField extends DeepKeys<TFormData>>(field: TField) => DeepValue<TFormData, TField>;
|
|
66
70
|
getFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField) => FieldMeta | undefined;
|
|
67
|
-
getFieldInfo: <TField extends DeepKeys<TFormData>>(field: TField) => FieldInfo<TFormData>;
|
|
71
|
+
getFieldInfo: <TField extends DeepKeys<TFormData>>(field: TField) => FieldInfo<TFormData, ValidatorType>;
|
|
68
72
|
setFieldMeta: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<FieldMeta>) => void;
|
|
69
73
|
setFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, updater: Updater<DeepValue<TFormData, TField>>, opts?: {
|
|
70
74
|
touch?: boolean;
|
|
71
75
|
}) => void;
|
|
72
|
-
pushFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, value: DeepValue<TFormData, TField>[number], opts?: {
|
|
76
|
+
pushFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, value: DeepValue<TFormData, TField> extends any[] ? DeepValue<TFormData, TField>[number] : never, opts?: {
|
|
73
77
|
touch?: boolean;
|
|
74
78
|
}) => void;
|
|
75
|
-
insertFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, index: number, value: DeepValue<TFormData, TField>[number], opts?: {
|
|
79
|
+
insertFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, index: number, value: DeepValue<TFormData, TField> extends any[] ? DeepValue<TFormData, TField>[number] : never, opts?: {
|
|
76
80
|
touch?: boolean;
|
|
77
81
|
}) => void;
|
|
78
82
|
removeFieldValue: <TField extends DeepKeys<TFormData>>(field: TField, index: number, opts?: {
|
|
@@ -82,35 +86,29 @@ declare class FormApi<TFormData> {
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
type ValidationCause = 'change' | 'blur' | 'submit' | 'mount';
|
|
85
|
-
type ValidateFn<TParentData, TName extends DeepKeys<TParentData>, TData> = (value: TData, fieldApi: FieldApi<TParentData, TName>) => ValidationError;
|
|
86
|
-
type
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
*/
|
|
92
|
-
TName extends DeepKeys<TParentData>,
|
|
93
|
-
/**
|
|
94
|
-
* If TData is unknown, we can use the TName generic to determine the type
|
|
95
|
-
*/
|
|
96
|
-
TData = DeepValue<TParentData, TName>> {
|
|
97
|
-
name: DeepKeys<TParentData>;
|
|
89
|
+
type ValidateFn<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = (value: TData, fieldApi: FieldApi<TParentData, TName, ValidatorType, TData>) => ValidationError;
|
|
90
|
+
type ValidateOrFn<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = ValidatorType extends Validator<TData> ? Parameters<ReturnType<ValidatorType>['validate']>[1] | ValidateFn<TParentData, TName, ValidatorType, TData> : FormValidator extends Validator<TData> ? Parameters<ReturnType<FormValidator>['validate']>[1] | ValidateFn<TParentData, TName, ValidatorType, TData> : ValidateFn<TParentData, TName, ValidatorType, TData>;
|
|
91
|
+
type ValidateAsyncFn<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = (value: TData, fieldApi: FieldApi<TParentData, TName, ValidatorType, TData>) => ValidationError | Promise<ValidationError>;
|
|
92
|
+
type AsyncValidateOrFn<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = ValidatorType extends Validator<TData> ? Parameters<ReturnType<ValidatorType>['validate']>[1] | ValidateAsyncFn<TParentData, TName, ValidatorType, TData> : FormValidator extends Validator<TData> ? Parameters<ReturnType<FormValidator>['validate']>[1] | ValidateAsyncFn<TParentData, TName, ValidatorType, TData> : ValidateAsyncFn<TParentData, TName, ValidatorType, TData>;
|
|
93
|
+
interface FieldOptions<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
|
|
94
|
+
name: TName;
|
|
98
95
|
index?: TData extends any[] ? number : never;
|
|
99
96
|
defaultValue?: TData;
|
|
100
97
|
asyncDebounceMs?: number;
|
|
101
98
|
asyncAlways?: boolean;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
99
|
+
validator?: ValidatorType;
|
|
100
|
+
onMount?: (formApi: FieldApi<TParentData, TName, ValidatorType, TData>) => void;
|
|
101
|
+
onChange?: ValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
102
|
+
onChangeAsync?: AsyncValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
105
103
|
onChangeAsyncDebounceMs?: number;
|
|
106
|
-
onBlur?:
|
|
107
|
-
onBlurAsync?:
|
|
104
|
+
onBlur?: ValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
105
|
+
onBlurAsync?: AsyncValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
108
106
|
onBlurAsyncDebounceMs?: number;
|
|
109
|
-
onSubmitAsync?:
|
|
107
|
+
onSubmitAsync?: AsyncValidateOrFn<TParentData, TName, ValidatorType, FormValidator, TData>;
|
|
110
108
|
defaultMeta?: Partial<FieldMeta>;
|
|
111
109
|
}
|
|
112
|
-
interface FieldApiOptions<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> extends FieldOptions<TParentData, TName, TData> {
|
|
113
|
-
form: FormApi<TParentData>;
|
|
110
|
+
interface FieldApiOptions<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> extends FieldOptions<TParentData, TName, ValidatorType, FormValidator, TData> {
|
|
111
|
+
form: FormApi<TParentData, FormValidator>;
|
|
114
112
|
}
|
|
115
113
|
type FieldMeta = {
|
|
116
114
|
isTouched: boolean;
|
|
@@ -124,20 +122,17 @@ type FieldState<TData> = {
|
|
|
124
122
|
meta: FieldMeta;
|
|
125
123
|
};
|
|
126
124
|
type ResolveName<TParentData> = unknown extends TParentData ? string : DeepKeys<TParentData>;
|
|
127
|
-
declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> {
|
|
128
|
-
#private;
|
|
125
|
+
declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
|
|
129
126
|
uid: number;
|
|
130
|
-
form: FieldApiOptions<TParentData, TName, TData>['form'];
|
|
127
|
+
form: FieldApiOptions<TParentData, TName, ValidatorType, TData>['form'];
|
|
131
128
|
name: DeepKeys<TParentData>;
|
|
132
|
-
options: FieldApiOptions<TParentData, TName>;
|
|
129
|
+
options: FieldApiOptions<TParentData, TName, ValidatorType, TData>;
|
|
133
130
|
store: Store<FieldState<TData>>;
|
|
134
131
|
state: FieldState<TData>;
|
|
135
132
|
prevState: FieldState<TData>;
|
|
136
|
-
constructor(opts: FieldApiOptions<TParentData, TName, TData>
|
|
137
|
-
form: FormApi<TParentData>;
|
|
138
|
-
});
|
|
133
|
+
constructor(opts: FieldApiOptions<TParentData, TName, ValidatorType, FormValidator, TData>);
|
|
139
134
|
mount: () => () => void;
|
|
140
|
-
update: (opts: FieldApiOptions<TParentData, TName, TData>) => void;
|
|
135
|
+
update: (opts: FieldApiOptions<TParentData, TName, ValidatorType, TData>) => void;
|
|
141
136
|
getValue: () => TData;
|
|
142
137
|
setValue: (updater: Updater<TData>, options?: {
|
|
143
138
|
touch?: boolean;
|
|
@@ -146,13 +141,14 @@ declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData =
|
|
|
146
141
|
_getMeta: () => FieldMeta | undefined;
|
|
147
142
|
getMeta: () => FieldMeta;
|
|
148
143
|
setMeta: (updater: Updater<FieldMeta>) => void;
|
|
149
|
-
getInfo: () => FieldInfo<TParentData>;
|
|
144
|
+
getInfo: () => FieldInfo<TParentData, TData>;
|
|
150
145
|
pushValue: (value: TData extends any[] ? TData[number] : never) => void;
|
|
151
146
|
insertValue: (index: number, value: TData extends any[] ? TData[number] : never) => void;
|
|
152
147
|
removeValue: (index: number) => void;
|
|
153
148
|
swapValues: (aIndex: number, bIndex: number) => void;
|
|
154
|
-
getSubField: <TSubName extends DeepKeys<TData>, TSubData = DeepValue<TData, TSubName>>(name: TSubName) => FieldApi<TData, TSubName, TSubData
|
|
149
|
+
getSubField: <TSubName extends DeepKeys<TData>, TSubData extends DeepValue<TData, TSubName> = DeepValue<TData, TSubName>>(name: TSubName) => FieldApi<TData, TSubName, ValidatorType, TSubData, DeepValue<TData, TSubName>>;
|
|
155
150
|
validateSync: (value: TData | undefined, cause: ValidationCause) => void;
|
|
151
|
+
__leaseValidateAsync: () => number;
|
|
156
152
|
cancelValidateAsync: () => void;
|
|
157
153
|
validateAsync: (value: TData | undefined, cause: ValidationCause) => Promise<ValidationError[]>;
|
|
158
154
|
validate: (cause: ValidationCause, value?: TData) => ValidationError[] | Promise<ValidationError[]>;
|
|
@@ -160,4 +156,4 @@ declare class FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData =
|
|
|
160
156
|
handleBlur: () => void;
|
|
161
157
|
}
|
|
162
158
|
|
|
163
|
-
export { DeepKeys, DeepValue, FieldApi, FieldApiOptions, FieldInfo, FieldMeta, FieldOptions, FieldState, FormApi, FormOptions, FormState, ResolveName, Updater, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta };
|
|
159
|
+
export { DeepKeys, DeepValue, FieldApi, FieldApiOptions, FieldInfo, FieldMeta, FieldOptions, FieldState, FormApi, FormOptions, FormState, ResolveName, Updater, ValidationCause, ValidationError, ValidationErrorMap, ValidationErrorMapKeys, ValidationMeta, Validator };
|
package/build/legacy/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export * from './FormApi'\nexport * from './FieldApi'\nexport * from './utils'\n"],"mappings":";AAAA,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export * from './FormApi'\nexport * from './FieldApi'\nexport * from './utils'\nexport * from './types'\n"],"mappings":";AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// src/types.ts
|
|
17
|
+
var types_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(types_exports);
|
|
19
|
+
//# sourceMappingURL=types.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/types.ts"],"sourcesContent":["export type ValidationError = undefined | false | null | string\n\n// If/when TypeScript supports higher-kinded types, this should not be `unknown` anymore\nexport type Validator<Type, Fn = unknown> = () => {\n validate(value: Type, fn: Fn): ValidationError\n validateAsync(value: Type, fn: Fn): Promise<ValidationError>\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|