@tanstack/form-core 0.13.0 → 0.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/cjs/FieldApi.cjs +300 -0
  2. package/dist/cjs/FieldApi.cjs.map +1 -0
  3. package/dist/cjs/FormApi.cjs +438 -0
  4. package/dist/cjs/FormApi.cjs.map +1 -0
  5. package/dist/{mjs/FormApi.d.ts → cjs/FormApi.d.cts} +0 -1
  6. package/dist/cjs/index.cjs +15 -923
  7. package/dist/cjs/index.cjs.map +1 -1
  8. package/dist/cjs/mergeForm.cjs +32 -0
  9. package/dist/cjs/mergeForm.cjs.map +1 -0
  10. package/dist/cjs/utils.cjs +173 -0
  11. package/dist/cjs/utils.cjs.map +1 -0
  12. package/dist/esm/FieldApi.js +300 -0
  13. package/dist/esm/FieldApi.js.map +1 -0
  14. package/dist/{cjs → esm}/FormApi.d.ts +0 -1
  15. package/dist/esm/FormApi.js +438 -0
  16. package/dist/esm/FormApi.js.map +1 -0
  17. package/dist/esm/index.js +18 -0
  18. package/dist/esm/index.js.map +1 -0
  19. package/dist/esm/mergeForm.js +32 -0
  20. package/dist/esm/mergeForm.js.map +1 -0
  21. package/dist/esm/utils.js +173 -0
  22. package/dist/esm/utils.js.map +1 -0
  23. package/package.json +11 -11
  24. package/src/tests/utils.spec.ts +7 -0
  25. package/src/utils.ts +4 -0
  26. package/dist/cjs/index.js +0 -926
  27. package/dist/cjs/tests/FieldApi.spec.d.ts +0 -1
  28. package/dist/cjs/tests/FieldApi.test-d.d.ts +0 -1
  29. package/dist/cjs/tests/FormApi.spec.d.ts +0 -1
  30. package/dist/cjs/tests/mutateMergeDeep.spec.d.ts +0 -1
  31. package/dist/cjs/tests/utils.d.ts +0 -1
  32. package/dist/cjs/tests/utils.spec.d.ts +0 -1
  33. package/dist/mjs/index.d.mts +0 -5
  34. package/dist/mjs/index.d.ts +0 -5
  35. package/dist/mjs/index.js +0 -926
  36. package/dist/mjs/index.mjs +0 -926
  37. package/dist/mjs/index.mjs.map +0 -1
  38. package/dist/mjs/tests/FieldApi.spec.d.ts +0 -1
  39. package/dist/mjs/tests/FieldApi.test-d.d.ts +0 -1
  40. package/dist/mjs/tests/FormApi.spec.d.ts +0 -1
  41. package/dist/mjs/tests/mutateMergeDeep.spec.d.ts +0 -1
  42. package/dist/mjs/tests/utils.d.ts +0 -1
  43. package/dist/mjs/tests/utils.spec.d.ts +0 -1
  44. /package/dist/cjs/{FieldApi.d.ts → FieldApi.d.cts} +0 -0
  45. /package/dist/cjs/{mergeForm.d.ts → mergeForm.d.cts} +0 -0
  46. /package/dist/cjs/{types.d.ts → types.d.cts} +0 -0
  47. /package/dist/cjs/{utils.d.ts → utils.d.cts} +0 -0
  48. /package/dist/{mjs → esm}/FieldApi.d.ts +0 -0
  49. /package/dist/{cjs → esm}/index.d.ts +0 -0
  50. /package/dist/{mjs → esm}/mergeForm.d.ts +0 -0
  51. /package/dist/{mjs → esm}/types.d.ts +0 -0
  52. /package/dist/{mjs → esm}/utils.d.ts +0 -0
@@ -0,0 +1,438 @@
1
+ import { Store } from "@tanstack/store";
2
+ import { getSyncValidatorArray, getAsyncValidatorArray, getBy, functionalUpdate, setBy, deleteBy, isNonEmptyArray } from "./utils.js";
3
+ function getDefaultFormState(defaultState) {
4
+ return {
5
+ values: defaultState.values ?? {},
6
+ errors: defaultState.errors ?? [],
7
+ errorMap: defaultState.errorMap ?? {},
8
+ fieldMeta: defaultState.fieldMeta ?? {},
9
+ canSubmit: defaultState.canSubmit ?? true,
10
+ isFieldsValid: defaultState.isFieldsValid ?? false,
11
+ isFieldsValidating: defaultState.isFieldsValidating ?? false,
12
+ isFormValid: defaultState.isFormValid ?? false,
13
+ isFormValidating: defaultState.isFormValidating ?? false,
14
+ isSubmitted: defaultState.isSubmitted ?? false,
15
+ isSubmitting: defaultState.isSubmitting ?? false,
16
+ isTouched: defaultState.isTouched ?? false,
17
+ isValid: defaultState.isValid ?? false,
18
+ isValidating: defaultState.isValidating ?? false,
19
+ submissionAttempts: defaultState.submissionAttempts ?? 0,
20
+ validationMetaMap: defaultState.validationMetaMap ?? {
21
+ onChange: void 0,
22
+ onBlur: void 0,
23
+ onSubmit: void 0,
24
+ onMount: void 0,
25
+ onServer: void 0
26
+ }
27
+ };
28
+ }
29
+ class FormApi {
30
+ constructor(opts) {
31
+ var _a;
32
+ this.options = {};
33
+ this.fieldInfo = {};
34
+ this.prevTransformArray = [];
35
+ this.mount = () => {
36
+ const { onMount } = this.options.validators || {};
37
+ if (!onMount)
38
+ return;
39
+ const error = this.runValidator({
40
+ validate: onMount,
41
+ value: {
42
+ value: this.state.values,
43
+ formApi: this
44
+ },
45
+ type: "validate"
46
+ });
47
+ if (error) {
48
+ this.store.setState((prev) => ({
49
+ ...prev,
50
+ errorMap: { ...prev.errorMap, onMount: error }
51
+ }));
52
+ }
53
+ };
54
+ this.update = (options) => {
55
+ if (!options)
56
+ return;
57
+ const oldOptions = this.options;
58
+ this.options = options;
59
+ this.store.batch(() => {
60
+ const shouldUpdateValues = options.defaultValues && options.defaultValues !== oldOptions.defaultValues && !this.state.isTouched;
61
+ const shouldUpdateState = options.defaultState !== oldOptions.defaultState && !this.state.isTouched;
62
+ this.store.setState(
63
+ () => getDefaultFormState(
64
+ Object.assign(
65
+ {},
66
+ this.state,
67
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
68
+ shouldUpdateState ? options.defaultState : {},
69
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
70
+ shouldUpdateValues ? {
71
+ values: options.defaultValues
72
+ } : {}
73
+ )
74
+ )
75
+ );
76
+ });
77
+ };
78
+ this.reset = () => this.store.setState(
79
+ () => {
80
+ var _a2;
81
+ return getDefaultFormState({
82
+ ...this.options.defaultState,
83
+ values: this.options.defaultValues ?? ((_a2 = this.options.defaultState) == null ? void 0 : _a2.values)
84
+ });
85
+ }
86
+ );
87
+ this.validateAllFields = async (cause) => {
88
+ const fieldValidationPromises = [];
89
+ this.store.batch(() => {
90
+ void Object.values(this.fieldInfo).forEach((field) => {
91
+ Object.values(field.instances).forEach((instance) => {
92
+ fieldValidationPromises.push(
93
+ Promise.resolve().then(() => instance.validate(cause))
94
+ );
95
+ if (!instance.state.meta.isTouched) {
96
+ instance.setMeta((prev) => ({ ...prev, isTouched: true }));
97
+ }
98
+ });
99
+ });
100
+ });
101
+ const fieldErrorMapMap = await Promise.all(fieldValidationPromises);
102
+ return fieldErrorMapMap.flat();
103
+ };
104
+ this.validateSync = (cause) => {
105
+ const validates = getSyncValidatorArray(cause, this.options);
106
+ let hasErrored = false;
107
+ this.store.batch(() => {
108
+ for (const validateObj of validates) {
109
+ if (!validateObj.validate)
110
+ continue;
111
+ const error = normalizeError(
112
+ this.runValidator({
113
+ validate: validateObj.validate,
114
+ value: {
115
+ value: this.state.values,
116
+ formApi: this
117
+ },
118
+ type: "validate"
119
+ })
120
+ );
121
+ const errorMapKey = getErrorMapKey(validateObj.cause);
122
+ if (this.state.errorMap[errorMapKey] !== error) {
123
+ this.store.setState((prev) => ({
124
+ ...prev,
125
+ errorMap: {
126
+ ...prev.errorMap,
127
+ [errorMapKey]: error
128
+ }
129
+ }));
130
+ }
131
+ if (error) {
132
+ hasErrored = true;
133
+ }
134
+ }
135
+ });
136
+ const submitErrKey = getErrorMapKey("submit");
137
+ if (this.state.errorMap[submitErrKey] && cause !== "submit" && !hasErrored) {
138
+ this.store.setState((prev) => ({
139
+ ...prev,
140
+ errorMap: {
141
+ ...prev.errorMap,
142
+ [submitErrKey]: void 0
143
+ }
144
+ }));
145
+ }
146
+ return { hasErrored };
147
+ };
148
+ this.validateAsync = async (cause) => {
149
+ const validates = getAsyncValidatorArray(cause, this.options);
150
+ if (!this.state.isFormValidating) {
151
+ this.store.setState((prev) => ({ ...prev, isFormValidating: true }));
152
+ }
153
+ const promises = [];
154
+ for (const validateObj of validates) {
155
+ if (!validateObj.validate)
156
+ continue;
157
+ const key = getErrorMapKey(validateObj.cause);
158
+ const fieldValidatorMeta = this.state.validationMetaMap[key];
159
+ fieldValidatorMeta == null ? void 0 : fieldValidatorMeta.lastAbortController.abort();
160
+ const controller = new AbortController();
161
+ this.state.validationMetaMap[key] = {
162
+ lastAbortController: controller
163
+ };
164
+ promises.push(
165
+ new Promise(async (resolve) => {
166
+ let rawError;
167
+ try {
168
+ rawError = await new Promise((rawResolve, rawReject) => {
169
+ setTimeout(async () => {
170
+ if (controller.signal.aborted)
171
+ return rawResolve(void 0);
172
+ try {
173
+ rawResolve(
174
+ await this.runValidator({
175
+ validate: validateObj.validate,
176
+ value: {
177
+ value: this.state.values,
178
+ formApi: this,
179
+ signal: controller.signal
180
+ },
181
+ type: "validateAsync"
182
+ })
183
+ );
184
+ } catch (e) {
185
+ rawReject(e);
186
+ }
187
+ }, validateObj.debounceMs);
188
+ });
189
+ } catch (e) {
190
+ rawError = e;
191
+ }
192
+ const error = normalizeError(rawError);
193
+ this.store.setState((prev) => ({
194
+ ...prev,
195
+ errorMap: {
196
+ ...prev.errorMap,
197
+ [getErrorMapKey(cause)]: error
198
+ }
199
+ }));
200
+ resolve(error);
201
+ })
202
+ );
203
+ }
204
+ let results = [];
205
+ if (promises.length) {
206
+ results = await Promise.all(promises);
207
+ }
208
+ this.store.setState((prev) => ({
209
+ ...prev,
210
+ isFormValidating: false
211
+ }));
212
+ return results.filter(Boolean);
213
+ };
214
+ this.validate = (cause) => {
215
+ const { hasErrored } = this.validateSync(cause);
216
+ if (hasErrored && !this.options.asyncAlways) {
217
+ return this.state.errors;
218
+ }
219
+ return this.validateAsync(cause);
220
+ };
221
+ this.handleSubmit = async () => {
222
+ var _a2, _b, _c, _d, _e, _f;
223
+ this.store.setState((old) => ({
224
+ ...old,
225
+ // Submission attempts mark the form as not submitted
226
+ isSubmitted: false,
227
+ // Count submission attempts
228
+ submissionAttempts: old.submissionAttempts + 1
229
+ }));
230
+ if (!this.state.canSubmit)
231
+ return;
232
+ this.store.setState((d) => ({ ...d, isSubmitting: true }));
233
+ const done = () => {
234
+ this.store.setState((prev) => ({ ...prev, isSubmitting: false }));
235
+ };
236
+ await this.validateAllFields("submit");
237
+ if (!this.state.isFieldsValid) {
238
+ done();
239
+ (_b = (_a2 = this.options).onSubmitInvalid) == null ? void 0 : _b.call(_a2, {
240
+ value: this.state.values,
241
+ formApi: this
242
+ });
243
+ return;
244
+ }
245
+ await this.validate("submit");
246
+ if (!this.state.isValid) {
247
+ done();
248
+ (_d = (_c = this.options).onSubmitInvalid) == null ? void 0 : _d.call(_c, {
249
+ value: this.state.values,
250
+ formApi: this
251
+ });
252
+ return;
253
+ }
254
+ try {
255
+ await ((_f = (_e = this.options).onSubmit) == null ? void 0 : _f.call(_e, { value: this.state.values, formApi: this }));
256
+ this.store.batch(() => {
257
+ this.store.setState((prev) => ({ ...prev, isSubmitted: true }));
258
+ done();
259
+ });
260
+ } catch (err) {
261
+ done();
262
+ throw err;
263
+ }
264
+ };
265
+ this.getFieldValue = (field) => getBy(this.state.values, field);
266
+ this.getFieldMeta = (field) => {
267
+ return this.state.fieldMeta[field];
268
+ };
269
+ this.getFieldInfo = (field) => {
270
+ var _a2;
271
+ return (_a2 = this.fieldInfo)[field] || (_a2[field] = {
272
+ instances: {},
273
+ validationMetaMap: {
274
+ onChange: void 0,
275
+ onBlur: void 0,
276
+ onSubmit: void 0,
277
+ onMount: void 0,
278
+ onServer: void 0
279
+ }
280
+ });
281
+ };
282
+ this.setFieldMeta = (field, updater) => {
283
+ this.store.setState((prev) => {
284
+ return {
285
+ ...prev,
286
+ fieldMeta: {
287
+ ...prev.fieldMeta,
288
+ [field]: functionalUpdate(updater, prev.fieldMeta[field])
289
+ }
290
+ };
291
+ });
292
+ };
293
+ this.setFieldValue = (field, updater, opts2) => {
294
+ const touch = opts2 == null ? void 0 : opts2.touch;
295
+ this.store.batch(() => {
296
+ if (touch) {
297
+ this.setFieldMeta(field, (prev) => ({
298
+ ...prev,
299
+ isTouched: true
300
+ }));
301
+ }
302
+ this.store.setState((prev) => {
303
+ return {
304
+ ...prev,
305
+ values: setBy(prev.values, field, updater)
306
+ };
307
+ });
308
+ });
309
+ };
310
+ this.deleteField = (field) => {
311
+ this.store.setState((prev) => {
312
+ const newState = { ...prev };
313
+ newState.values = deleteBy(newState.values, field);
314
+ delete newState.fieldMeta[field];
315
+ return newState;
316
+ });
317
+ };
318
+ this.pushFieldValue = (field, value, opts2) => {
319
+ return this.setFieldValue(
320
+ field,
321
+ (prev) => [...Array.isArray(prev) ? prev : [], value],
322
+ opts2
323
+ );
324
+ };
325
+ this.insertFieldValue = (field, index, value, opts2) => {
326
+ this.setFieldValue(
327
+ field,
328
+ (prev) => {
329
+ return prev.map(
330
+ (d, i) => i === index ? value : d
331
+ );
332
+ },
333
+ opts2
334
+ );
335
+ };
336
+ this.removeFieldValue = (field, index, opts2) => {
337
+ this.setFieldValue(
338
+ field,
339
+ (prev) => {
340
+ return prev.filter(
341
+ (_d, i) => i !== index
342
+ );
343
+ },
344
+ opts2
345
+ );
346
+ };
347
+ this.swapFieldValues = (field, index1, index2) => {
348
+ this.setFieldValue(field, (prev) => {
349
+ const prev1 = prev[index1];
350
+ const prev2 = prev[index2];
351
+ return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1);
352
+ });
353
+ };
354
+ this.store = new Store(
355
+ getDefaultFormState({
356
+ ...opts == null ? void 0 : opts.defaultState,
357
+ values: (opts == null ? void 0 : opts.defaultValues) ?? ((_a = opts == null ? void 0 : opts.defaultState) == null ? void 0 : _a.values),
358
+ isFormValid: true
359
+ }),
360
+ {
361
+ onUpdate: () => {
362
+ var _a2, _b;
363
+ let { state } = this.store;
364
+ const fieldMetaValues = Object.values(state.fieldMeta);
365
+ const isFieldsValidating = fieldMetaValues.some(
366
+ (field) => field == null ? void 0 : field.isValidating
367
+ );
368
+ const isFieldsValid = !fieldMetaValues.some(
369
+ (field) => (field == null ? void 0 : field.errorMap) && isNonEmptyArray(Object.values(field.errorMap).filter(Boolean))
370
+ );
371
+ const isTouched = fieldMetaValues.some((field) => field == null ? void 0 : field.isTouched);
372
+ const isValidating = isFieldsValidating || state.isFormValidating;
373
+ state.errors = Object.values(state.errorMap).filter(
374
+ (val) => val !== void 0
375
+ );
376
+ const isFormValid = state.errors.length === 0;
377
+ const isValid = isFieldsValid && isFormValid;
378
+ const canSubmit = state.submissionAttempts === 0 && !isTouched || !isValidating && !state.isSubmitting && isValid;
379
+ state = {
380
+ ...state,
381
+ isFieldsValidating,
382
+ isFieldsValid,
383
+ isFormValid,
384
+ isValid,
385
+ canSubmit,
386
+ isTouched
387
+ };
388
+ this.state = state;
389
+ this.store.state = this.state;
390
+ const transformArray = ((_a2 = this.options.transform) == null ? void 0 : _a2.deps) ?? [];
391
+ const shouldTransform = transformArray.length !== this.prevTransformArray.length || transformArray.some((val, i) => val !== this.prevTransformArray[i]);
392
+ if (shouldTransform) {
393
+ (_b = this.options.transform) == null ? void 0 : _b.fn(this);
394
+ this.store.state = this.state;
395
+ this.prevTransformArray = transformArray;
396
+ }
397
+ }
398
+ }
399
+ );
400
+ this.state = this.store.state;
401
+ this.update(opts || {});
402
+ }
403
+ runValidator(props) {
404
+ const adapter = this.options.validatorAdapter;
405
+ if (adapter && typeof props.validate !== "function") {
406
+ return adapter()[props.type](props.value, props.validate);
407
+ }
408
+ return props.validate(props.value);
409
+ }
410
+ }
411
+ function normalizeError(rawError) {
412
+ if (rawError) {
413
+ if (typeof rawError !== "string") {
414
+ return "Invalid Form Values";
415
+ }
416
+ return rawError;
417
+ }
418
+ return void 0;
419
+ }
420
+ function getErrorMapKey(cause) {
421
+ switch (cause) {
422
+ case "submit":
423
+ return "onSubmit";
424
+ case "blur":
425
+ return "onBlur";
426
+ case "mount":
427
+ return "onMount";
428
+ case "server":
429
+ return "onServer";
430
+ case "change":
431
+ default:
432
+ return "onChange";
433
+ }
434
+ }
435
+ export {
436
+ FormApi
437
+ };
438
+ //# sourceMappingURL=FormApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormApi.js","sources":["../../src/FormApi.ts"],"sourcesContent":["import { Store } from '@tanstack/store'\nimport type { DeepKeys, DeepValue, Updater } from './utils'\nimport {\n getAsyncValidatorArray,\n getSyncValidatorArray,\n deleteBy,\n functionalUpdate,\n getBy,\n isNonEmptyArray,\n setBy,\n} from './utils'\nimport type { FieldApi, FieldMeta } from './FieldApi'\nimport type {\n ValidationError,\n ValidationErrorMap,\n Validator,\n ValidationCause,\n ValidationErrorMapKeys,\n} from './types'\n\nexport type FormValidateFn<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = (props: {\n value: TFormData\n formApi: FormApi<TFormData, TFormValidator>\n}) => ValidationError\n\nexport type FormValidateOrFn<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = TFormValidator extends Validator<TFormData, infer TFN>\n ? TFN\n : FormValidateFn<TFormData, TFormValidator>\n\nexport type FormValidateAsyncFn<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = (props: {\n value: TFormData\n formApi: FormApi<TFormData, TFormValidator>\n signal: AbortSignal\n}) => ValidationError | Promise<ValidationError>\n\nexport type FormAsyncValidateOrFn<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = TFormValidator extends Validator<TFormData, infer FFN>\n ? FFN | FormValidateAsyncFn<TFormData, TFormValidator>\n : FormValidateAsyncFn<TFormData, TFormValidator>\n\nexport interface FormValidators<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n onMount?: FormValidateOrFn<TFormData, TFormValidator>\n onChange?: FormValidateOrFn<TFormData, TFormValidator>\n onChangeAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\n onChangeAsyncDebounceMs?: number\n onBlur?: FormValidateOrFn<TFormData, TFormValidator>\n onBlurAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\n onBlurAsyncDebounceMs?: number\n onSubmit?: FormValidateOrFn<TFormData, TFormValidator>\n onSubmitAsync?: FormAsyncValidateOrFn<TFormData, TFormValidator>\n onSubmitAsyncDebounceMs?: number\n}\n\nexport interface FormTransform<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n fn: (\n formBase: FormApi<TFormData, TFormValidator>,\n ) => FormApi<TFormData, TFormValidator>\n deps: unknown[]\n}\n\nexport interface FormOptions<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n defaultValues?: TFormData\n defaultState?: Partial<FormState<TFormData>>\n asyncAlways?: boolean\n asyncDebounceMs?: number\n validatorAdapter?: TFormValidator\n validators?: FormValidators<TFormData, TFormValidator>\n onSubmit?: (props: {\n value: TFormData\n formApi: FormApi<TFormData, TFormValidator>\n }) => any | Promise<any>\n onSubmitInvalid?: (props: {\n value: TFormData\n formApi: FormApi<TFormData, TFormValidator>\n }) => void\n transform?: FormTransform<TFormData, TFormValidator>\n}\n\nexport type ValidationMeta = {\n lastAbortController: AbortController\n}\n\nexport type FieldInfo<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n instances: Record<\n string,\n FieldApi<\n TFormData,\n any,\n Validator<unknown, unknown> | undefined,\n TFormValidator\n >\n >\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n}\n\nexport type FormState<TFormData> = {\n values: TFormData\n // Form Validation\n isFormValidating: boolean\n isFormValid: boolean\n errors: ValidationError[]\n errorMap: ValidationErrorMap\n validationMetaMap: Record<ValidationErrorMapKeys, ValidationMeta | undefined>\n // Fields\n fieldMeta: Record<DeepKeys<TFormData>, FieldMeta>\n isFieldsValidating: boolean\n isFieldsValid: boolean\n isSubmitting: boolean\n // General\n isTouched: boolean\n isSubmitted: boolean\n isValidating: boolean\n isValid: boolean\n canSubmit: boolean\n submissionAttempts: number\n}\n\nfunction getDefaultFormState<TFormData>(\n defaultState: Partial<FormState<TFormData>>,\n): FormState<TFormData> {\n return {\n values: defaultState.values ?? ({} as never),\n errors: defaultState.errors ?? [],\n errorMap: defaultState.errorMap ?? {},\n fieldMeta: defaultState.fieldMeta ?? ({} as never),\n canSubmit: defaultState.canSubmit ?? true,\n isFieldsValid: defaultState.isFieldsValid ?? false,\n isFieldsValidating: defaultState.isFieldsValidating ?? false,\n isFormValid: defaultState.isFormValid ?? false,\n isFormValidating: defaultState.isFormValidating ?? false,\n isSubmitted: defaultState.isSubmitted ?? false,\n isSubmitting: defaultState.isSubmitting ?? false,\n isTouched: defaultState.isTouched ?? false,\n isValid: defaultState.isValid ?? false,\n isValidating: defaultState.isValidating ?? false,\n submissionAttempts: defaultState.submissionAttempts ?? 0,\n validationMetaMap: defaultState.validationMetaMap ?? {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n }\n}\n\nexport class FormApi<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> {\n options: FormOptions<TFormData, TFormValidator> = {}\n store!: Store<FormState<TFormData>>\n // Do not use __state directly, as it is not reactive.\n // Please use form.useStore() utility to subscribe to state\n state!: FormState<TFormData>\n // // This carries the context for nested fields\n fieldInfo: Record<DeepKeys<TFormData>, FieldInfo<TFormData, TFormValidator>> =\n {} as any\n\n prevTransformArray: unknown[] = []\n\n constructor(opts?: FormOptions<TFormData, TFormValidator>) {\n this.store = new Store<FormState<TFormData>>(\n getDefaultFormState({\n ...(opts?.defaultState as any),\n values: opts?.defaultValues ?? opts?.defaultState?.values,\n isFormValid: true,\n }),\n {\n onUpdate: () => {\n let { state } = this.store\n // Computed state\n const fieldMetaValues = Object.values(state.fieldMeta) as (\n | FieldMeta\n | undefined\n )[]\n\n const isFieldsValidating = fieldMetaValues.some(\n (field) => field?.isValidating,\n )\n\n const isFieldsValid = !fieldMetaValues.some(\n (field) =>\n field?.errorMap &&\n isNonEmptyArray(Object.values(field.errorMap).filter(Boolean)),\n )\n\n const isTouched = fieldMetaValues.some((field) => field?.isTouched)\n\n const isValidating = isFieldsValidating || state.isFormValidating\n state.errors = Object.values(state.errorMap).filter(\n (val: unknown) => val !== undefined,\n )\n const isFormValid = state.errors.length === 0\n const isValid = isFieldsValid && isFormValid\n const canSubmit =\n (state.submissionAttempts === 0 && !isTouched) ||\n (!isValidating && !state.isSubmitting && isValid)\n\n state = {\n ...state,\n isFieldsValidating,\n isFieldsValid,\n isFormValid,\n isValid,\n canSubmit,\n isTouched,\n }\n\n this.state = state\n this.store.state = this.state\n\n // Only run transform if state has shallowly changed - IE how React.useEffect works\n const transformArray = this.options.transform?.deps ?? []\n const shouldTransform =\n transformArray.length !== this.prevTransformArray.length ||\n transformArray.some((val, i) => val !== this.prevTransformArray[i])\n\n if (shouldTransform) {\n // This mutates the state\n this.options.transform?.fn(this)\n this.store.state = this.state\n this.prevTransformArray = transformArray\n }\n },\n },\n )\n\n this.state = this.store.state\n\n this.update(opts || {})\n }\n\n runValidator<\n TValue extends { value: TFormData; formApi: FormApi<any, any> },\n TType extends 'validate' | 'validateAsync',\n >(props: {\n validate: TType extends 'validate'\n ? FormValidateOrFn<TFormData, TFormValidator>\n : FormAsyncValidateOrFn<TFormData, TFormValidator>\n value: TValue\n type: TType\n }): ReturnType<ReturnType<Validator<any>>[TType]> {\n const adapter = this.options.validatorAdapter\n if (adapter && typeof props.validate !== 'function') {\n return adapter()[props.type](props.value, props.validate) as never\n }\n\n return (props.validate as FormValidateFn<any, any>)(props.value) as never\n }\n\n mount = () => {\n const { onMount } = this.options.validators || {}\n if (!onMount) return\n const error = this.runValidator({\n validate: onMount,\n value: {\n value: this.state.values,\n formApi: this,\n },\n type: 'validate',\n })\n if (error) {\n this.store.setState((prev) => ({\n ...prev,\n errorMap: { ...prev.errorMap, onMount: error },\n }))\n }\n }\n\n update = (options?: FormOptions<TFormData, TFormValidator>) => {\n if (!options) return\n\n const oldOptions = this.options\n\n // Options need to be updated first so that when the store is updated, the state is correct for the derived state\n this.options = options\n\n this.store.batch(() => {\n const shouldUpdateValues =\n options.defaultValues &&\n options.defaultValues !== oldOptions.defaultValues &&\n !this.state.isTouched\n\n const shouldUpdateState =\n options.defaultState !== oldOptions.defaultState &&\n !this.state.isTouched\n\n this.store.setState(() =>\n getDefaultFormState(\n Object.assign(\n {},\n this.state as any,\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateState ? options.defaultState : {},\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n shouldUpdateValues\n ? {\n values: options.defaultValues,\n }\n : {},\n ),\n ),\n )\n })\n }\n\n reset = () =>\n this.store.setState(() =>\n getDefaultFormState({\n ...(this.options.defaultState as any),\n values: this.options.defaultValues ?? this.options.defaultState?.values,\n }),\n )\n\n validateAllFields = async (cause: ValidationCause) => {\n const fieldValidationPromises: Promise<ValidationError[]>[] = [] as any\n this.store.batch(() => {\n void (\n Object.values(this.fieldInfo) as FieldInfo<any, TFormValidator>[]\n ).forEach((field) => {\n Object.values(field.instances).forEach((instance) => {\n // Validate the field\n fieldValidationPromises.push(\n Promise.resolve().then(() => instance.validate(cause)),\n )\n // If any fields are not touched\n if (!instance.state.meta.isTouched) {\n // Mark them as touched\n instance.setMeta((prev) => ({ ...prev, isTouched: true }))\n }\n })\n })\n })\n\n const fieldErrorMapMap = await Promise.all(fieldValidationPromises)\n return fieldErrorMapMap.flat()\n }\n\n // TODO: This code is copied from FieldApi, we should refactor to share\n validateSync = (cause: ValidationCause) => {\n const validates = getSyncValidatorArray(cause, this.options)\n let hasErrored = false as boolean\n\n this.store.batch(() => {\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n\n const error = normalizeError(\n this.runValidator({\n validate: validateObj.validate,\n value: {\n value: this.state.values,\n formApi: this,\n },\n type: 'validate',\n }),\n )\n const errorMapKey = getErrorMapKey(validateObj.cause)\n if (this.state.errorMap[errorMapKey] !== error) {\n this.store.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [errorMapKey]: error,\n },\n }))\n }\n if (error) {\n hasErrored = true\n }\n }\n })\n\n /**\n * when we have an error for onSubmit in the state, we want\n * to clear the error as soon as the user enters a valid value in the field\n */\n const submitErrKey = getErrorMapKey('submit')\n if (\n this.state.errorMap[submitErrKey] &&\n cause !== 'submit' &&\n !hasErrored\n ) {\n this.store.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [submitErrKey]: undefined,\n },\n }))\n }\n\n return { hasErrored }\n }\n\n validateAsync = async (\n cause: ValidationCause,\n ): Promise<ValidationError[]> => {\n const validates = getAsyncValidatorArray(cause, this.options)\n\n if (!this.state.isFormValidating) {\n this.store.setState((prev) => ({ ...prev, isFormValidating: true }))\n }\n\n /**\n * We have to use a for loop and generate our promises this way, otherwise it won't be sync\n * when there are no validators needed to be run\n */\n const promises: Promise<ValidationError | undefined>[] = []\n\n for (const validateObj of validates) {\n if (!validateObj.validate) continue\n const key = getErrorMapKey(validateObj.cause)\n const fieldValidatorMeta = this.state.validationMetaMap[key]\n\n fieldValidatorMeta?.lastAbortController.abort()\n const controller = new AbortController()\n\n this.state.validationMetaMap[key] = {\n lastAbortController: controller,\n }\n\n promises.push(\n new Promise<ValidationError | undefined>(async (resolve) => {\n let rawError!: ValidationError | undefined\n try {\n rawError = await new Promise((rawResolve, rawReject) => {\n setTimeout(async () => {\n if (controller.signal.aborted) return rawResolve(undefined)\n try {\n rawResolve(\n await this.runValidator({\n validate: validateObj.validate!,\n value: {\n value: this.state.values,\n formApi: this,\n signal: controller.signal,\n },\n type: 'validateAsync',\n }),\n )\n } catch (e) {\n rawReject(e)\n }\n }, validateObj.debounceMs)\n })\n } catch (e: unknown) {\n rawError = e as ValidationError\n }\n const error = normalizeError(rawError)\n this.store.setState((prev) => ({\n ...prev,\n errorMap: {\n ...prev.errorMap,\n [getErrorMapKey(cause)]: error,\n },\n }))\n\n resolve(error)\n }),\n )\n }\n\n let results: ValidationError[] = []\n if (promises.length) {\n results = await Promise.all(promises)\n }\n\n this.store.setState((prev) => ({\n ...prev,\n isFormValidating: false,\n }))\n\n return results.filter(Boolean)\n }\n\n validate = (\n cause: ValidationCause,\n ): ValidationError[] | Promise<ValidationError[]> => {\n // Attempt to sync validate first\n const { hasErrored } = this.validateSync(cause)\n\n if (hasErrored && !this.options.asyncAlways) {\n return this.state.errors\n }\n\n // No error? Attempt async validation\n return this.validateAsync(cause)\n }\n\n handleSubmit = async () => {\n // Check to see that the form and all fields have been touched\n // If they have not, touch them all and run validation\n // Run form validation\n // Submit the form\n\n this.store.setState((old) => ({\n ...old,\n // Submission attempts mark the form as not submitted\n isSubmitted: false,\n // Count submission attempts\n submissionAttempts: old.submissionAttempts + 1,\n }))\n\n // Don't let invalid forms submit\n if (!this.state.canSubmit) return\n\n this.store.setState((d) => ({ ...d, isSubmitting: true }))\n\n const done = () => {\n this.store.setState((prev) => ({ ...prev, isSubmitting: false }))\n }\n\n // Validate all fields\n await this.validateAllFields('submit')\n\n // Fields are invalid, do not submit\n if (!this.state.isFieldsValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n // Run validation for the form\n await this.validate('submit')\n\n if (!this.state.isValid) {\n done()\n this.options.onSubmitInvalid?.({\n value: this.state.values,\n formApi: this,\n })\n return\n }\n\n try {\n // Run the submit code\n await this.options.onSubmit?.({ value: this.state.values, formApi: this })\n\n this.store.batch(() => {\n this.store.setState((prev) => ({ ...prev, isSubmitted: true }))\n done()\n })\n } catch (err) {\n done()\n throw err\n }\n }\n\n getFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): DeepValue<TFormData, TField> => getBy(this.state.values, field)\n\n getFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldMeta | undefined => {\n return this.state.fieldMeta[field]\n }\n\n getFieldInfo = <TField extends DeepKeys<TFormData>>(\n field: TField,\n ): FieldInfo<TFormData, TFormValidator> => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return (this.fieldInfo[field] ||= {\n instances: {},\n validationMetaMap: {\n onChange: undefined,\n onBlur: undefined,\n onSubmit: undefined,\n onMount: undefined,\n onServer: undefined,\n },\n })\n }\n\n setFieldMeta = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<FieldMeta>,\n ) => {\n this.store.setState((prev) => {\n return {\n ...prev,\n fieldMeta: {\n ...prev.fieldMeta,\n [field]: functionalUpdate(updater, prev.fieldMeta[field]),\n },\n }\n })\n }\n\n setFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n updater: Updater<DeepValue<TFormData, TField>>,\n opts?: { touch?: boolean },\n ) => {\n const touch = opts?.touch\n\n this.store.batch(() => {\n if (touch) {\n this.setFieldMeta(field, (prev) => ({\n ...prev,\n isTouched: true,\n }))\n }\n\n this.store.setState((prev) => {\n return {\n ...prev,\n values: setBy(prev.values, field, updater),\n }\n })\n })\n }\n\n deleteField = <TField extends DeepKeys<TFormData>>(field: TField) => {\n this.store.setState((prev) => {\n const newState = { ...prev }\n newState.values = deleteBy(newState.values, field)\n delete newState.fieldMeta[field]\n\n return newState\n })\n }\n\n pushFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n value: DeepValue<TFormData, TField> extends any[]\n ? DeepValue<TFormData, TField>[number]\n : never,\n opts?: { touch?: boolean },\n ) => {\n return this.setFieldValue(\n field,\n (prev) => [...(Array.isArray(prev) ? prev : []), value] as any,\n opts,\n )\n }\n\n insertFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n value: DeepValue<TFormData, TField> extends any[]\n ? DeepValue<TFormData, TField>[number]\n : never,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).map((d, i) =>\n i === index ? value : d,\n ) as any\n },\n opts,\n )\n }\n\n removeFieldValue = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index: number,\n opts?: { touch?: boolean },\n ) => {\n this.setFieldValue(\n field,\n (prev) => {\n return (prev as DeepValue<TFormData, TField>[]).filter(\n (_d, i) => i !== index,\n ) as any\n },\n opts,\n )\n }\n\n swapFieldValues = <TField extends DeepKeys<TFormData>>(\n field: TField,\n index1: number,\n index2: number,\n ) => {\n this.setFieldValue(field, (prev: any) => {\n const prev1 = prev[index1]!\n const prev2 = prev[index2]!\n return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1)\n })\n }\n}\n\nfunction normalizeError(rawError?: ValidationError) {\n if (rawError) {\n if (typeof rawError !== 'string') {\n return 'Invalid Form Values'\n }\n\n return rawError\n }\n\n return undefined\n}\n\nfunction getErrorMapKey(cause: ValidationCause) {\n switch (cause) {\n case 'submit':\n return 'onSubmit'\n case 'blur':\n return 'onBlur'\n case 'mount':\n return 'onMount'\n case 'server':\n return 'onServer'\n case 'change':\n default:\n return 'onChange'\n }\n}\n"],"names":["_a","opts"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { FormApi } from "./FormApi.js";
2
+ import { FieldApi } from "./FieldApi.js";
3
+ import { deleteBy, functionalUpdate, getAsyncValidatorArray, getBy, getSyncValidatorArray, isNonEmptyArray, setBy } from "./utils.js";
4
+ import { mergeForm, mutateMergeDeep } from "./mergeForm.js";
5
+ export {
6
+ FieldApi,
7
+ FormApi,
8
+ deleteBy,
9
+ functionalUpdate,
10
+ getAsyncValidatorArray,
11
+ getBy,
12
+ getSyncValidatorArray,
13
+ isNonEmptyArray,
14
+ mergeForm,
15
+ mutateMergeDeep,
16
+ setBy
17
+ };
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -0,0 +1,32 @@
1
+ function mutateMergeDeep(target, source) {
2
+ const targetKeys = Object.keys(target);
3
+ const sourceKeys = Object.keys(source);
4
+ const keySet = /* @__PURE__ */ new Set([...targetKeys, ...sourceKeys]);
5
+ for (const key of keySet) {
6
+ const targetKey = key;
7
+ const sourceKey = key;
8
+ if (Array.isArray(target[targetKey]) && Array.isArray(source[sourceKey])) {
9
+ target[targetKey] = [
10
+ ...target[targetKey],
11
+ ...source[sourceKey]
12
+ ];
13
+ } else if (typeof target[targetKey] === "object" && typeof source[sourceKey] === "object") {
14
+ mutateMergeDeep(target[targetKey], source[sourceKey]);
15
+ } else {
16
+ if (!(sourceKey in source) && source[sourceKey] === void 0) {
17
+ continue;
18
+ }
19
+ target[targetKey] = source[sourceKey];
20
+ }
21
+ }
22
+ return target;
23
+ }
24
+ function mergeForm(baseForm, state) {
25
+ mutateMergeDeep(baseForm.state, state);
26
+ return baseForm;
27
+ }
28
+ export {
29
+ mergeForm,
30
+ mutateMergeDeep
31
+ };
32
+ //# sourceMappingURL=mergeForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mergeForm.js","sources":["../../src/mergeForm.ts"],"sourcesContent":["import type { FormApi } from './FormApi'\nimport type { Validator } from './types'\n\nexport function mutateMergeDeep(target: object, source: object): object {\n const targetKeys = Object.keys(target)\n const sourceKeys = Object.keys(source)\n const keySet = new Set([...targetKeys, ...sourceKeys])\n for (const key of keySet) {\n const targetKey = key as never as keyof typeof target\n const sourceKey = key as never as keyof typeof source\n if (Array.isArray(target[targetKey]) && Array.isArray(source[sourceKey])) {\n target[targetKey] = [\n ...(target[targetKey] as []),\n ...(source[sourceKey] as []),\n ] as never\n } else if (\n typeof target[targetKey] === 'object' &&\n typeof source[sourceKey] === 'object'\n ) {\n mutateMergeDeep(target[targetKey] as {}, source[sourceKey] as {})\n } else {\n // Prevent assigning undefined to target, only if undefined is not explicitly set on source\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!(sourceKey in source) && source[sourceKey] === undefined) {\n continue\n }\n target[targetKey] = source[sourceKey] as never\n }\n }\n return target\n}\n\nexport function mergeForm<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n baseForm: FormApi<TFormData, TFormValidator>,\n state: Partial<FormApi<TFormData, TFormValidator>['state']>,\n) {\n mutateMergeDeep(baseForm.state, state)\n return baseForm\n}\n"],"names":[],"mappings":"AAGgB,SAAA,gBAAgB,QAAgB,QAAwB;AAChE,QAAA,aAAa,OAAO,KAAK,MAAM;AAC/B,QAAA,aAAa,OAAO,KAAK,MAAM;AAC/B,QAAA,6BAAa,IAAI,CAAC,GAAG,YAAY,GAAG,UAAU,CAAC;AACrD,aAAW,OAAO,QAAQ;AACxB,UAAM,YAAY;AAClB,UAAM,YAAY;AACd,QAAA,MAAM,QAAQ,OAAO,SAAS,CAAC,KAAK,MAAM,QAAQ,OAAO,SAAS,CAAC,GAAG;AACxE,aAAO,SAAS,IAAI;AAAA,QAClB,GAAI,OAAO,SAAS;AAAA,QACpB,GAAI,OAAO,SAAS;AAAA,MAAA;AAAA,IACtB,WAEA,OAAO,OAAO,SAAS,MAAM,YAC7B,OAAO,OAAO,SAAS,MAAM,UAC7B;AACA,sBAAgB,OAAO,SAAS,GAAS,OAAO,SAAS,CAAO;AAAA,IAAA,OAC3D;AAGL,UAAI,EAAE,aAAa,WAAW,OAAO,SAAS,MAAM,QAAW;AAC7D;AAAA,MACF;AACO,aAAA,SAAS,IAAI,OAAO,SAAS;AAAA,IACtC;AAAA,EACF;AACO,SAAA;AACT;AAEgB,SAAA,UAId,UACA,OACA;AACgB,kBAAA,SAAS,OAAO,KAAK;AAC9B,SAAA;AACT;"}