@tanstack/form-core 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/package.json +1 -1
  2. package/src/FieldApi.ts +53 -29
  3. package/src/FormApi.ts +14 -7
  4. package/src/tests/FieldApi.spec.ts +84 -17
  5. package/src/utils.ts +4 -0
  6. package/build/legacy/FieldApi.cjs +0 -256
  7. package/build/legacy/FieldApi.cjs.map +0 -1
  8. package/build/legacy/FieldApi.d.cts +0 -3
  9. package/build/legacy/FieldApi.d.ts +0 -3
  10. package/build/legacy/FieldApi.js +0 -223
  11. package/build/legacy/FieldApi.js.map +0 -1
  12. package/build/legacy/FormApi.cjs +0 -255
  13. package/build/legacy/FormApi.cjs.map +0 -1
  14. package/build/legacy/FormApi.d.cts +0 -3
  15. package/build/legacy/FormApi.d.ts +0 -3
  16. package/build/legacy/FormApi.js +0 -232
  17. package/build/legacy/FormApi.js.map +0 -1
  18. package/build/legacy/chunk-4QZDOMDG.js +0 -19
  19. package/build/legacy/chunk-4QZDOMDG.js.map +0 -1
  20. package/build/legacy/index.cjs +0 -29
  21. package/build/legacy/index.cjs.map +0 -1
  22. package/build/legacy/index.d.cts +0 -171
  23. package/build/legacy/index.d.ts +0 -171
  24. package/build/legacy/index.js +0 -5
  25. package/build/legacy/index.js.map +0 -1
  26. package/build/legacy/utils.cjs +0 -98
  27. package/build/legacy/utils.cjs.map +0 -1
  28. package/build/legacy/utils.d.cts +0 -32
  29. package/build/legacy/utils.d.ts +0 -32
  30. package/build/legacy/utils.js +0 -73
  31. package/build/legacy/utils.js.map +0 -1
  32. package/build/modern/FieldApi.cjs +0 -238
  33. package/build/modern/FieldApi.cjs.map +0 -1
  34. package/build/modern/FieldApi.d.cts +0 -3
  35. package/build/modern/FieldApi.d.ts +0 -3
  36. package/build/modern/FieldApi.js +0 -213
  37. package/build/modern/FieldApi.js.map +0 -1
  38. package/build/modern/FormApi.cjs +0 -249
  39. package/build/modern/FormApi.cjs.map +0 -1
  40. package/build/modern/FormApi.d.cts +0 -3
  41. package/build/modern/FormApi.d.ts +0 -3
  42. package/build/modern/FormApi.js +0 -224
  43. package/build/modern/FormApi.js.map +0 -1
  44. package/build/modern/index.cjs +0 -29
  45. package/build/modern/index.cjs.map +0 -1
  46. package/build/modern/index.d.cts +0 -171
  47. package/build/modern/index.d.ts +0 -171
  48. package/build/modern/index.js +0 -5
  49. package/build/modern/index.js.map +0 -1
  50. package/build/modern/utils.cjs +0 -98
  51. package/build/modern/utils.cjs.map +0 -1
  52. package/build/modern/utils.d.cts +0 -32
  53. package/build/modern/utils.d.ts +0 -32
  54. package/build/modern/utils.js +0 -71
  55. package/build/modern/utils.js.map +0 -1
@@ -1,249 +0,0 @@
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 __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/FormApi.ts
21
- var FormApi_exports = {};
22
- __export(FormApi_exports, {
23
- FormApi: () => FormApi
24
- });
25
- module.exports = __toCommonJS(FormApi_exports);
26
- var import_store = require("@tanstack/store");
27
- var import_utils = require("./utils.cjs");
28
- function getDefaultFormState(defaultState) {
29
- return {
30
- values: defaultState.values ?? {},
31
- fieldMeta: defaultState.fieldMeta ?? {},
32
- canSubmit: defaultState.canSubmit ?? true,
33
- isFieldsValid: defaultState.isFieldsValid ?? false,
34
- isFieldsValidating: defaultState.isFieldsValidating ?? false,
35
- isFormValid: defaultState.isFormValid ?? false,
36
- isFormValidating: defaultState.isFormValidating ?? false,
37
- isSubmitted: defaultState.isSubmitted ?? false,
38
- isSubmitting: defaultState.isSubmitting ?? false,
39
- isTouched: defaultState.isTouched ?? false,
40
- isValid: defaultState.isValid ?? false,
41
- isValidating: defaultState.isValidating ?? false,
42
- submissionAttempts: defaultState.submissionAttempts ?? 0,
43
- formValidationCount: defaultState.formValidationCount ?? 0
44
- };
45
- }
46
- var FormApi = class {
47
- constructor(opts) {
48
- // // This carries the context for nested fields
49
- this.options = {};
50
- this.fieldInfo = {};
51
- this.validationMeta = {};
52
- this.update = (options) => {
53
- if (!options)
54
- return;
55
- this.store.batch(() => {
56
- const shouldUpdateValues = options.defaultValues && options.defaultValues !== this.options.defaultValues && !this.state.isTouched;
57
- const shouldUpdateState = options.defaultState !== this.options.defaultState && !this.state.isTouched;
58
- this.store.setState(
59
- () => getDefaultFormState(
60
- Object.assign(
61
- {},
62
- this.state,
63
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
64
- shouldUpdateState ? options.defaultState : {},
65
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
66
- shouldUpdateValues ? {
67
- values: options.defaultValues
68
- } : {}
69
- )
70
- )
71
- );
72
- });
73
- this.options = options;
74
- };
75
- this.reset = () => this.store.setState(
76
- () => getDefaultFormState({
77
- ...this.options.defaultState,
78
- values: this.options.defaultValues ?? this.options.defaultState?.values
79
- })
80
- );
81
- this.validateAllFields = async (cause) => {
82
- const fieldValidationPromises = [];
83
- this.store.batch(() => {
84
- void Object.values(this.fieldInfo).forEach(
85
- (field) => {
86
- Object.values(field.instances).forEach((instance) => {
87
- if (!instance.state.meta.isTouched) {
88
- instance.setMeta((prev) => ({ ...prev, isTouched: true }));
89
- fieldValidationPromises.push(
90
- Promise.resolve().then(() => instance.validate(cause))
91
- );
92
- }
93
- });
94
- }
95
- );
96
- });
97
- return Promise.all(fieldValidationPromises);
98
- };
99
- this.handleSubmit = async () => {
100
- this.store.setState((old) => ({
101
- ...old,
102
- // Submission attempts mark the form as not submitted
103
- isSubmitted: false,
104
- // Count submission attempts
105
- submissionAttempts: old.submissionAttempts + 1
106
- }));
107
- if (!this.state.canSubmit)
108
- return;
109
- this.store.setState((d) => ({ ...d, isSubmitting: true }));
110
- const done = () => {
111
- this.store.setState((prev) => ({ ...prev, isSubmitting: false }));
112
- };
113
- await this.validateAllFields("submit");
114
- if (!this.state.isFieldsValid) {
115
- done();
116
- this.options.onSubmitInvalid?.(this.state.values, this);
117
- return;
118
- }
119
- if (!this.state.isValid) {
120
- done();
121
- this.options.onSubmitInvalid?.(this.state.values, this);
122
- return;
123
- }
124
- try {
125
- await this.options.onSubmit?.(this.state.values, this);
126
- this.store.batch(() => {
127
- this.store.setState((prev) => ({ ...prev, isSubmitted: true }));
128
- done();
129
- });
130
- } catch (err) {
131
- done();
132
- throw err;
133
- }
134
- };
135
- this.getFieldValue = (field) => (0, import_utils.getBy)(this.state.values, field);
136
- this.getFieldMeta = (field) => {
137
- return this.state.fieldMeta[field];
138
- };
139
- this.getFieldInfo = (field) => {
140
- return this.fieldInfo[field] ||= {
141
- instances: {}
142
- };
143
- };
144
- this.setFieldMeta = (field, updater) => {
145
- this.store.setState((prev) => {
146
- return {
147
- ...prev,
148
- fieldMeta: {
149
- ...prev.fieldMeta,
150
- [field]: (0, import_utils.functionalUpdate)(updater, prev.fieldMeta[field])
151
- }
152
- };
153
- });
154
- };
155
- this.setFieldValue = (field, updater, opts) => {
156
- const touch = opts?.touch;
157
- this.store.batch(() => {
158
- if (touch) {
159
- this.setFieldMeta(field, (prev) => ({
160
- ...prev,
161
- isTouched: true
162
- }));
163
- }
164
- this.store.setState((prev) => {
165
- return {
166
- ...prev,
167
- values: (0, import_utils.setBy)(prev.values, field, updater)
168
- };
169
- });
170
- });
171
- };
172
- this.pushFieldValue = (field, value, opts) => {
173
- return this.setFieldValue(
174
- field,
175
- (prev) => [...Array.isArray(prev) ? prev : [], value],
176
- opts
177
- );
178
- };
179
- this.insertFieldValue = (field, index, value, opts) => {
180
- this.setFieldValue(
181
- field,
182
- (prev) => {
183
- return prev.map(
184
- (d, i) => i === index ? value : d
185
- );
186
- },
187
- opts
188
- );
189
- };
190
- this.removeFieldValue = (field, index, opts) => {
191
- this.setFieldValue(
192
- field,
193
- (prev) => {
194
- return prev.filter(
195
- (_d, i) => i !== index
196
- );
197
- },
198
- opts
199
- );
200
- };
201
- this.swapFieldValues = (field, index1, index2) => {
202
- this.setFieldValue(field, (prev) => {
203
- const prev1 = prev[index1];
204
- const prev2 = prev[index2];
205
- return (0, import_utils.setBy)((0, import_utils.setBy)(prev, `${index1}`, prev2), `${index2}`, prev1);
206
- });
207
- };
208
- this.store = new import_store.Store(
209
- getDefaultFormState({
210
- ...opts?.defaultState,
211
- values: opts?.defaultValues ?? opts?.defaultState?.values,
212
- isFormValid: true
213
- }),
214
- {
215
- onUpdate: () => {
216
- let { state } = this.store;
217
- const fieldMetaValues = Object.values(state.fieldMeta);
218
- const isFieldsValidating = fieldMetaValues.some(
219
- (field) => field?.isValidating
220
- );
221
- const isFieldsValid = !fieldMetaValues.some((field) => field?.error);
222
- const isTouched = fieldMetaValues.some((field) => field?.isTouched);
223
- const isValidating = isFieldsValidating || state.isFormValidating;
224
- const isFormValid = !state.formError;
225
- const isValid = isFieldsValid && isFormValid;
226
- const canSubmit = state.submissionAttempts === 0 && !isTouched || !isValidating && !state.isSubmitting && isValid;
227
- state = {
228
- ...state,
229
- isFieldsValidating,
230
- isFieldsValid,
231
- isFormValid,
232
- isValid,
233
- canSubmit,
234
- isTouched
235
- };
236
- this.store.state = state;
237
- this.state = state;
238
- }
239
- }
240
- );
241
- this.state = this.store.state;
242
- this.update(opts || {});
243
- }
244
- };
245
- // Annotate the CommonJS export names for ESM import in node:
246
- 0 && (module.exports = {
247
- FormApi
248
- });
249
- //# sourceMappingURL=FormApi.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\n//\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport { functionalUpdate, getBy, 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<any, TFormData>>\n} & ValidationMeta\n\nexport type ValidationMeta = {\n validationCount?: number\n validationAsyncCount?: number\n validationPromise?: Promise<ValidationError>\n validationResolve?: (error: ValidationError) => void\n validationReject?: (error: unknown) => void\n}\n\nexport type ValidationError = undefined | false | null | string\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,\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) => field?.error)\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,\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,\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\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>>(field: TField) => {\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,3 +0,0 @@
1
- import '@tanstack/store';
2
- import './utils.cjs';
3
- export { FieldInfo, FormApi, FormOptions, FormState, ValidationError, ValidationMeta } from './index.cjs';
@@ -1,3 +0,0 @@
1
- import '@tanstack/store';
2
- import './utils.js';
3
- export { FieldInfo, FormApi, FormOptions, FormState, ValidationError, ValidationMeta } from './index.js';
@@ -1,224 +0,0 @@
1
- // src/FormApi.ts
2
- import { Store } from "@tanstack/store";
3
- import { functionalUpdate, getBy, setBy } from "./utils.js";
4
- function getDefaultFormState(defaultState) {
5
- return {
6
- values: defaultState.values ?? {},
7
- fieldMeta: defaultState.fieldMeta ?? {},
8
- canSubmit: defaultState.canSubmit ?? true,
9
- isFieldsValid: defaultState.isFieldsValid ?? false,
10
- isFieldsValidating: defaultState.isFieldsValidating ?? false,
11
- isFormValid: defaultState.isFormValid ?? false,
12
- isFormValidating: defaultState.isFormValidating ?? false,
13
- isSubmitted: defaultState.isSubmitted ?? false,
14
- isSubmitting: defaultState.isSubmitting ?? false,
15
- isTouched: defaultState.isTouched ?? false,
16
- isValid: defaultState.isValid ?? false,
17
- isValidating: defaultState.isValidating ?? false,
18
- submissionAttempts: defaultState.submissionAttempts ?? 0,
19
- formValidationCount: defaultState.formValidationCount ?? 0
20
- };
21
- }
22
- var FormApi = class {
23
- constructor(opts) {
24
- // // This carries the context for nested fields
25
- this.options = {};
26
- this.fieldInfo = {};
27
- this.validationMeta = {};
28
- this.update = (options) => {
29
- if (!options)
30
- return;
31
- this.store.batch(() => {
32
- const shouldUpdateValues = options.defaultValues && options.defaultValues !== this.options.defaultValues && !this.state.isTouched;
33
- const shouldUpdateState = options.defaultState !== this.options.defaultState && !this.state.isTouched;
34
- this.store.setState(
35
- () => getDefaultFormState(
36
- Object.assign(
37
- {},
38
- this.state,
39
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
40
- shouldUpdateState ? options.defaultState : {},
41
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
42
- shouldUpdateValues ? {
43
- values: options.defaultValues
44
- } : {}
45
- )
46
- )
47
- );
48
- });
49
- this.options = options;
50
- };
51
- this.reset = () => this.store.setState(
52
- () => getDefaultFormState({
53
- ...this.options.defaultState,
54
- values: this.options.defaultValues ?? this.options.defaultState?.values
55
- })
56
- );
57
- this.validateAllFields = async (cause) => {
58
- const fieldValidationPromises = [];
59
- this.store.batch(() => {
60
- void Object.values(this.fieldInfo).forEach(
61
- (field) => {
62
- Object.values(field.instances).forEach((instance) => {
63
- if (!instance.state.meta.isTouched) {
64
- instance.setMeta((prev) => ({ ...prev, isTouched: true }));
65
- fieldValidationPromises.push(
66
- Promise.resolve().then(() => instance.validate(cause))
67
- );
68
- }
69
- });
70
- }
71
- );
72
- });
73
- return Promise.all(fieldValidationPromises);
74
- };
75
- this.handleSubmit = async () => {
76
- this.store.setState((old) => ({
77
- ...old,
78
- // Submission attempts mark the form as not submitted
79
- isSubmitted: false,
80
- // Count submission attempts
81
- submissionAttempts: old.submissionAttempts + 1
82
- }));
83
- if (!this.state.canSubmit)
84
- return;
85
- this.store.setState((d) => ({ ...d, isSubmitting: true }));
86
- const done = () => {
87
- this.store.setState((prev) => ({ ...prev, isSubmitting: false }));
88
- };
89
- await this.validateAllFields("submit");
90
- if (!this.state.isFieldsValid) {
91
- done();
92
- this.options.onSubmitInvalid?.(this.state.values, this);
93
- return;
94
- }
95
- if (!this.state.isValid) {
96
- done();
97
- this.options.onSubmitInvalid?.(this.state.values, this);
98
- return;
99
- }
100
- try {
101
- await this.options.onSubmit?.(this.state.values, this);
102
- this.store.batch(() => {
103
- this.store.setState((prev) => ({ ...prev, isSubmitted: true }));
104
- done();
105
- });
106
- } catch (err) {
107
- done();
108
- throw err;
109
- }
110
- };
111
- this.getFieldValue = (field) => getBy(this.state.values, field);
112
- this.getFieldMeta = (field) => {
113
- return this.state.fieldMeta[field];
114
- };
115
- this.getFieldInfo = (field) => {
116
- return this.fieldInfo[field] ||= {
117
- instances: {}
118
- };
119
- };
120
- this.setFieldMeta = (field, updater) => {
121
- this.store.setState((prev) => {
122
- return {
123
- ...prev,
124
- fieldMeta: {
125
- ...prev.fieldMeta,
126
- [field]: functionalUpdate(updater, prev.fieldMeta[field])
127
- }
128
- };
129
- });
130
- };
131
- this.setFieldValue = (field, updater, opts) => {
132
- const touch = opts?.touch;
133
- this.store.batch(() => {
134
- if (touch) {
135
- this.setFieldMeta(field, (prev) => ({
136
- ...prev,
137
- isTouched: true
138
- }));
139
- }
140
- this.store.setState((prev) => {
141
- return {
142
- ...prev,
143
- values: setBy(prev.values, field, updater)
144
- };
145
- });
146
- });
147
- };
148
- this.pushFieldValue = (field, value, opts) => {
149
- return this.setFieldValue(
150
- field,
151
- (prev) => [...Array.isArray(prev) ? prev : [], value],
152
- opts
153
- );
154
- };
155
- this.insertFieldValue = (field, index, value, opts) => {
156
- this.setFieldValue(
157
- field,
158
- (prev) => {
159
- return prev.map(
160
- (d, i) => i === index ? value : d
161
- );
162
- },
163
- opts
164
- );
165
- };
166
- this.removeFieldValue = (field, index, opts) => {
167
- this.setFieldValue(
168
- field,
169
- (prev) => {
170
- return prev.filter(
171
- (_d, i) => i !== index
172
- );
173
- },
174
- opts
175
- );
176
- };
177
- this.swapFieldValues = (field, index1, index2) => {
178
- this.setFieldValue(field, (prev) => {
179
- const prev1 = prev[index1];
180
- const prev2 = prev[index2];
181
- return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1);
182
- });
183
- };
184
- this.store = new Store(
185
- getDefaultFormState({
186
- ...opts?.defaultState,
187
- values: opts?.defaultValues ?? opts?.defaultState?.values,
188
- isFormValid: true
189
- }),
190
- {
191
- onUpdate: () => {
192
- let { state } = this.store;
193
- const fieldMetaValues = Object.values(state.fieldMeta);
194
- const isFieldsValidating = fieldMetaValues.some(
195
- (field) => field?.isValidating
196
- );
197
- const isFieldsValid = !fieldMetaValues.some((field) => field?.error);
198
- const isTouched = fieldMetaValues.some((field) => field?.isTouched);
199
- const isValidating = isFieldsValidating || state.isFormValidating;
200
- const isFormValid = !state.formError;
201
- const isValid = isFieldsValid && isFormValid;
202
- const canSubmit = state.submissionAttempts === 0 && !isTouched || !isValidating && !state.isSubmitting && isValid;
203
- state = {
204
- ...state,
205
- isFieldsValidating,
206
- isFieldsValid,
207
- isFormValid,
208
- isValid,
209
- canSubmit,
210
- isTouched
211
- };
212
- this.store.state = state;
213
- this.state = state;
214
- }
215
- }
216
- );
217
- this.state = this.store.state;
218
- this.update(opts || {});
219
- }
220
- };
221
- export {
222
- FormApi
223
- };
224
- //# sourceMappingURL=FormApi.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\n//\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport { functionalUpdate, getBy, 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<any, TFormData>>\n} & ValidationMeta\n\nexport type ValidationMeta = {\n validationCount?: number\n validationAsyncCount?: number\n validationPromise?: Promise<ValidationError>\n validationResolve?: (error: ValidationError) => void\n validationReject?: (error: unknown) => void\n}\n\nexport type ValidationError = undefined | false | null | string\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,\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) => field?.error)\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,\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,\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\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>>(field: TField) => {\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,29 +0,0 @@
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 __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
15
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
16
-
17
- // src/index.ts
18
- var src_exports = {};
19
- module.exports = __toCommonJS(src_exports);
20
- __reExport(src_exports, require("./FormApi.cjs"), module.exports);
21
- __reExport(src_exports, require("./FieldApi.cjs"), module.exports);
22
- __reExport(src_exports, require("./utils.cjs"), module.exports);
23
- // Annotate the CommonJS export names for ESM import in node:
24
- 0 && (module.exports = {
25
- ...require("./FormApi.cjs"),
26
- ...require("./FieldApi.cjs"),
27
- ...require("./utils.cjs")
28
- });
29
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
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":[]}