@tanstack/form-core 0.12.0 → 0.13.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 (50) hide show
  1. package/dist/cjs/FieldApi.cjs +300 -0
  2. package/dist/cjs/FieldApi.cjs.map +1 -0
  3. package/dist/{mjs/FieldApi.d.ts → cjs/FieldApi.d.cts} +0 -1
  4. package/dist/cjs/FormApi.cjs +438 -0
  5. package/dist/cjs/FormApi.cjs.map +1 -0
  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 +168 -0
  11. package/dist/cjs/utils.cjs.map +1 -0
  12. package/dist/{cjs → esm}/FieldApi.d.ts +0 -1
  13. package/dist/esm/FieldApi.js +300 -0
  14. package/dist/esm/FieldApi.js.map +1 -0
  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 +168 -0
  22. package/dist/esm/utils.js.map +1 -0
  23. package/package.json +11 -11
  24. package/dist/cjs/index.js +0 -926
  25. package/dist/cjs/tests/FieldApi.spec.d.ts +0 -1
  26. package/dist/cjs/tests/FieldApi.test-d.d.ts +0 -1
  27. package/dist/cjs/tests/FormApi.spec.d.ts +0 -1
  28. package/dist/cjs/tests/mutateMergeDeep.spec.d.ts +0 -1
  29. package/dist/cjs/tests/utils.d.ts +0 -1
  30. package/dist/cjs/tests/utils.spec.d.ts +0 -1
  31. package/dist/mjs/index.d.mts +0 -5
  32. package/dist/mjs/index.d.ts +0 -5
  33. package/dist/mjs/index.js +0 -926
  34. package/dist/mjs/index.mjs +0 -926
  35. package/dist/mjs/index.mjs.map +0 -1
  36. package/dist/mjs/tests/FieldApi.spec.d.ts +0 -1
  37. package/dist/mjs/tests/FieldApi.test-d.d.ts +0 -1
  38. package/dist/mjs/tests/FormApi.spec.d.ts +0 -1
  39. package/dist/mjs/tests/mutateMergeDeep.spec.d.ts +0 -1
  40. package/dist/mjs/tests/utils.d.ts +0 -1
  41. package/dist/mjs/tests/utils.spec.d.ts +0 -1
  42. /package/dist/cjs/{FormApi.d.ts → FormApi.d.cts} +0 -0
  43. /package/dist/cjs/{mergeForm.d.ts → mergeForm.d.cts} +0 -0
  44. /package/dist/cjs/{types.d.ts → types.d.cts} +0 -0
  45. /package/dist/cjs/{utils.d.ts → utils.d.cts} +0 -0
  46. /package/dist/{mjs → esm}/FormApi.d.ts +0 -0
  47. /package/dist/{cjs → esm}/index.d.ts +0 -0
  48. /package/dist/{mjs → esm}/mergeForm.d.ts +0 -0
  49. /package/dist/{mjs → esm}/types.d.ts +0 -0
  50. /package/dist/{mjs → esm}/utils.d.ts +0 -0
@@ -1,926 +0,0 @@
1
- import { Store } from "@tanstack/store";
2
- function functionalUpdate(updater, input) {
3
- return typeof updater === "function" ? updater(input) : updater;
4
- }
5
- function getBy(obj, path) {
6
- const pathObj = makePathArray(path);
7
- return pathObj.reduce((current, pathPart) => {
8
- if (typeof current !== "undefined") {
9
- return current[pathPart];
10
- }
11
- return void 0;
12
- }, obj);
13
- }
14
- function setBy(obj, _path, updater) {
15
- const path = makePathArray(_path);
16
- function doSet(parent) {
17
- if (!path.length) {
18
- return functionalUpdate(updater, parent);
19
- }
20
- const key = path.shift();
21
- if (typeof key === "string") {
22
- if (typeof parent === "object") {
23
- return {
24
- ...parent,
25
- [key]: doSet(parent[key])
26
- };
27
- }
28
- return {
29
- [key]: doSet()
30
- };
31
- }
32
- if (Array.isArray(parent) && key !== void 0) {
33
- const prefix = parent.slice(0, key);
34
- return [
35
- ...prefix.length ? prefix : new Array(key),
36
- doSet(parent[key]),
37
- ...parent.slice(key + 1)
38
- ];
39
- }
40
- return [...new Array(key), doSet()];
41
- }
42
- return doSet(obj);
43
- }
44
- function deleteBy(obj, _path) {
45
- const path = makePathArray(_path);
46
- function doDelete(parent) {
47
- if (path.length === 1) {
48
- const finalPath = path[0];
49
- const { [finalPath]: remove, ...rest } = parent;
50
- return rest;
51
- }
52
- const key = path.shift();
53
- if (typeof key === "string") {
54
- if (typeof parent === "object") {
55
- return {
56
- ...parent,
57
- [key]: doDelete(parent[key])
58
- };
59
- }
60
- }
61
- if (typeof key === "number") {
62
- if (Array.isArray(parent)) {
63
- const prefix = parent.slice(0, key);
64
- return [
65
- ...prefix.length ? prefix : new Array(key),
66
- doDelete(parent[key]),
67
- ...parent.slice(key + 1)
68
- ];
69
- }
70
- }
71
- throw new Error("It seems we have created an infinite loop in deleteBy. ");
72
- }
73
- return doDelete(obj);
74
- }
75
- const reFindNumbers0 = /^(\d*)$/gm;
76
- const reFindNumbers1 = /\.(\d*)\./gm;
77
- const reFindNumbers2 = /^(\d*)\./gm;
78
- const reFindNumbers3 = /\.(\d*$)/gm;
79
- const reFindMultiplePeriods = /\.{2,}/gm;
80
- const intPrefix = "__int__";
81
- const intReplace = `${intPrefix}$1`;
82
- function makePathArray(str) {
83
- if (typeof str !== "string") {
84
- throw new Error("Path must be a string.");
85
- }
86
- return str.replace("[", ".").replace("]", "").replace(reFindNumbers0, intReplace).replace(reFindNumbers1, `.${intReplace}.`).replace(reFindNumbers2, `${intReplace}.`).replace(reFindNumbers3, `.${intReplace}`).replace(reFindMultiplePeriods, ".").split(".").map((d) => {
87
- if (d.indexOf(intPrefix) === 0) {
88
- return parseInt(d.substring(intPrefix.length), 10);
89
- }
90
- return d;
91
- });
92
- }
93
- function isNonEmptyArray(obj) {
94
- return !(Array.isArray(obj) && obj.length === 0);
95
- }
96
- function getAsyncValidatorArray(cause, options) {
97
- const { asyncDebounceMs } = options;
98
- const {
99
- onChangeAsync,
100
- onBlurAsync,
101
- onSubmitAsync,
102
- onBlurAsyncDebounceMs,
103
- onChangeAsyncDebounceMs,
104
- onSubmitAsyncDebounceMs
105
- } = options.validators || {};
106
- const defaultDebounceMs = asyncDebounceMs ?? 0;
107
- const changeValidator = {
108
- cause: "change",
109
- validate: onChangeAsync,
110
- debounceMs: onChangeAsyncDebounceMs ?? defaultDebounceMs
111
- };
112
- const blurValidator = {
113
- cause: "blur",
114
- validate: onBlurAsync,
115
- debounceMs: onBlurAsyncDebounceMs ?? defaultDebounceMs
116
- };
117
- const submitValidator = {
118
- cause: "submit",
119
- validate: onSubmitAsync,
120
- debounceMs: onSubmitAsyncDebounceMs ?? defaultDebounceMs
121
- };
122
- switch (cause) {
123
- case "submit":
124
- return [changeValidator, blurValidator, submitValidator];
125
- case "server":
126
- return [];
127
- case "blur":
128
- return [blurValidator];
129
- case "change":
130
- default:
131
- return [changeValidator];
132
- }
133
- }
134
- function getSyncValidatorArray(cause, options) {
135
- const { onChange, onBlur, onSubmit } = options.validators || {};
136
- const changeValidator = { cause: "change", validate: onChange };
137
- const blurValidator = { cause: "blur", validate: onBlur };
138
- const submitValidator = { cause: "submit", validate: onSubmit };
139
- const serverValidator = {
140
- cause: "server",
141
- validate: () => void 0
142
- };
143
- switch (cause) {
144
- case "submit":
145
- return [
146
- changeValidator,
147
- blurValidator,
148
- submitValidator,
149
- serverValidator
150
- ];
151
- case "server":
152
- return [serverValidator];
153
- case "blur":
154
- return [blurValidator, serverValidator];
155
- case "change":
156
- default:
157
- return [changeValidator, serverValidator];
158
- }
159
- }
160
- function getDefaultFormState(defaultState) {
161
- return {
162
- values: defaultState.values ?? {},
163
- errors: defaultState.errors ?? [],
164
- errorMap: defaultState.errorMap ?? {},
165
- fieldMeta: defaultState.fieldMeta ?? {},
166
- canSubmit: defaultState.canSubmit ?? true,
167
- isFieldsValid: defaultState.isFieldsValid ?? false,
168
- isFieldsValidating: defaultState.isFieldsValidating ?? false,
169
- isFormValid: defaultState.isFormValid ?? false,
170
- isFormValidating: defaultState.isFormValidating ?? false,
171
- isSubmitted: defaultState.isSubmitted ?? false,
172
- isSubmitting: defaultState.isSubmitting ?? false,
173
- isTouched: defaultState.isTouched ?? false,
174
- isValid: defaultState.isValid ?? false,
175
- isValidating: defaultState.isValidating ?? false,
176
- submissionAttempts: defaultState.submissionAttempts ?? 0,
177
- validationMetaMap: defaultState.validationMetaMap ?? {
178
- onChange: void 0,
179
- onBlur: void 0,
180
- onSubmit: void 0,
181
- onMount: void 0,
182
- onServer: void 0
183
- }
184
- };
185
- }
186
- class FormApi {
187
- constructor(opts) {
188
- var _a;
189
- this.options = {};
190
- this.fieldInfo = {};
191
- this.prevTransformArray = [];
192
- this.mount = () => {
193
- const { onMount } = this.options.validators || {};
194
- if (!onMount)
195
- return;
196
- const error = this.runValidator({
197
- validate: onMount,
198
- value: {
199
- value: this.state.values,
200
- formApi: this
201
- },
202
- type: "validate"
203
- });
204
- if (error) {
205
- this.store.setState((prev) => ({
206
- ...prev,
207
- errorMap: { ...prev.errorMap, onMount: error }
208
- }));
209
- }
210
- };
211
- this.update = (options) => {
212
- if (!options)
213
- return;
214
- const oldOptions = this.options;
215
- this.options = options;
216
- this.store.batch(() => {
217
- const shouldUpdateValues = options.defaultValues && options.defaultValues !== oldOptions.defaultValues && !this.state.isTouched;
218
- const shouldUpdateState = options.defaultState !== oldOptions.defaultState && !this.state.isTouched;
219
- this.store.setState(
220
- () => getDefaultFormState(
221
- Object.assign(
222
- {},
223
- this.state,
224
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
225
- shouldUpdateState ? options.defaultState : {},
226
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
227
- shouldUpdateValues ? {
228
- values: options.defaultValues
229
- } : {}
230
- )
231
- )
232
- );
233
- });
234
- };
235
- this.reset = () => this.store.setState(
236
- () => {
237
- var _a2;
238
- return getDefaultFormState({
239
- ...this.options.defaultState,
240
- values: this.options.defaultValues ?? ((_a2 = this.options.defaultState) == null ? void 0 : _a2.values)
241
- });
242
- }
243
- );
244
- this.validateAllFields = async (cause) => {
245
- const fieldValidationPromises = [];
246
- this.store.batch(() => {
247
- void Object.values(this.fieldInfo).forEach((field) => {
248
- Object.values(field.instances).forEach((instance) => {
249
- fieldValidationPromises.push(
250
- Promise.resolve().then(() => instance.validate(cause))
251
- );
252
- if (!instance.state.meta.isTouched) {
253
- instance.setMeta((prev) => ({ ...prev, isTouched: true }));
254
- }
255
- });
256
- });
257
- });
258
- const fieldErrorMapMap = await Promise.all(fieldValidationPromises);
259
- return fieldErrorMapMap.flat();
260
- };
261
- this.validateSync = (cause) => {
262
- const validates = getSyncValidatorArray(cause, this.options);
263
- let hasErrored = false;
264
- this.store.batch(() => {
265
- for (const validateObj of validates) {
266
- if (!validateObj.validate)
267
- continue;
268
- const error = normalizeError$1(
269
- this.runValidator({
270
- validate: validateObj.validate,
271
- value: {
272
- value: this.state.values,
273
- formApi: this
274
- },
275
- type: "validate"
276
- })
277
- );
278
- const errorMapKey = getErrorMapKey$1(validateObj.cause);
279
- if (this.state.errorMap[errorMapKey] !== error) {
280
- this.store.setState((prev) => ({
281
- ...prev,
282
- errorMap: {
283
- ...prev.errorMap,
284
- [errorMapKey]: error
285
- }
286
- }));
287
- }
288
- if (error) {
289
- hasErrored = true;
290
- }
291
- }
292
- });
293
- const submitErrKey = getErrorMapKey$1("submit");
294
- if (this.state.errorMap[submitErrKey] && cause !== "submit" && !hasErrored) {
295
- this.store.setState((prev) => ({
296
- ...prev,
297
- errorMap: {
298
- ...prev.errorMap,
299
- [submitErrKey]: void 0
300
- }
301
- }));
302
- }
303
- return { hasErrored };
304
- };
305
- this.validateAsync = async (cause) => {
306
- const validates = getAsyncValidatorArray(cause, this.options);
307
- if (!this.state.isFormValidating) {
308
- this.store.setState((prev) => ({ ...prev, isFormValidating: true }));
309
- }
310
- const promises = [];
311
- for (const validateObj of validates) {
312
- if (!validateObj.validate)
313
- continue;
314
- const key = getErrorMapKey$1(validateObj.cause);
315
- const fieldValidatorMeta = this.state.validationMetaMap[key];
316
- fieldValidatorMeta == null ? void 0 : fieldValidatorMeta.lastAbortController.abort();
317
- const controller = new AbortController();
318
- this.state.validationMetaMap[key] = {
319
- lastAbortController: controller
320
- };
321
- promises.push(
322
- new Promise(async (resolve) => {
323
- let rawError;
324
- try {
325
- rawError = await new Promise((rawResolve, rawReject) => {
326
- setTimeout(async () => {
327
- if (controller.signal.aborted)
328
- return rawResolve(void 0);
329
- try {
330
- rawResolve(
331
- await this.runValidator({
332
- validate: validateObj.validate,
333
- value: {
334
- value: this.state.values,
335
- formApi: this,
336
- signal: controller.signal
337
- },
338
- type: "validateAsync"
339
- })
340
- );
341
- } catch (e) {
342
- rawReject(e);
343
- }
344
- }, validateObj.debounceMs);
345
- });
346
- } catch (e) {
347
- rawError = e;
348
- }
349
- const error = normalizeError$1(rawError);
350
- this.store.setState((prev) => ({
351
- ...prev,
352
- errorMap: {
353
- ...prev.errorMap,
354
- [getErrorMapKey$1(cause)]: error
355
- }
356
- }));
357
- resolve(error);
358
- })
359
- );
360
- }
361
- let results = [];
362
- if (promises.length) {
363
- results = await Promise.all(promises);
364
- }
365
- this.store.setState((prev) => ({
366
- ...prev,
367
- isFormValidating: false
368
- }));
369
- return results.filter(Boolean);
370
- };
371
- this.validate = (cause) => {
372
- const { hasErrored } = this.validateSync(cause);
373
- if (hasErrored && !this.options.asyncAlways) {
374
- return this.state.errors;
375
- }
376
- return this.validateAsync(cause);
377
- };
378
- this.handleSubmit = async () => {
379
- var _a2, _b, _c, _d, _e, _f;
380
- this.store.setState((old) => ({
381
- ...old,
382
- // Submission attempts mark the form as not submitted
383
- isSubmitted: false,
384
- // Count submission attempts
385
- submissionAttempts: old.submissionAttempts + 1
386
- }));
387
- if (!this.state.canSubmit)
388
- return;
389
- this.store.setState((d) => ({ ...d, isSubmitting: true }));
390
- const done = () => {
391
- this.store.setState((prev) => ({ ...prev, isSubmitting: false }));
392
- };
393
- await this.validateAllFields("submit");
394
- if (!this.state.isFieldsValid) {
395
- done();
396
- (_b = (_a2 = this.options).onSubmitInvalid) == null ? void 0 : _b.call(_a2, {
397
- value: this.state.values,
398
- formApi: this
399
- });
400
- return;
401
- }
402
- await this.validate("submit");
403
- if (!this.state.isValid) {
404
- done();
405
- (_d = (_c = this.options).onSubmitInvalid) == null ? void 0 : _d.call(_c, {
406
- value: this.state.values,
407
- formApi: this
408
- });
409
- return;
410
- }
411
- try {
412
- await ((_f = (_e = this.options).onSubmit) == null ? void 0 : _f.call(_e, { value: this.state.values, formApi: this }));
413
- this.store.batch(() => {
414
- this.store.setState((prev) => ({ ...prev, isSubmitted: true }));
415
- done();
416
- });
417
- } catch (err) {
418
- done();
419
- throw err;
420
- }
421
- };
422
- this.getFieldValue = (field) => getBy(this.state.values, field);
423
- this.getFieldMeta = (field) => {
424
- return this.state.fieldMeta[field];
425
- };
426
- this.getFieldInfo = (field) => {
427
- var _a2;
428
- return (_a2 = this.fieldInfo)[field] || (_a2[field] = {
429
- instances: {},
430
- validationMetaMap: {
431
- onChange: void 0,
432
- onBlur: void 0,
433
- onSubmit: void 0,
434
- onMount: void 0,
435
- onServer: void 0
436
- }
437
- });
438
- };
439
- this.setFieldMeta = (field, updater) => {
440
- this.store.setState((prev) => {
441
- return {
442
- ...prev,
443
- fieldMeta: {
444
- ...prev.fieldMeta,
445
- [field]: functionalUpdate(updater, prev.fieldMeta[field])
446
- }
447
- };
448
- });
449
- };
450
- this.setFieldValue = (field, updater, opts2) => {
451
- const touch = opts2 == null ? void 0 : opts2.touch;
452
- this.store.batch(() => {
453
- if (touch) {
454
- this.setFieldMeta(field, (prev) => ({
455
- ...prev,
456
- isTouched: true
457
- }));
458
- }
459
- this.store.setState((prev) => {
460
- return {
461
- ...prev,
462
- values: setBy(prev.values, field, updater)
463
- };
464
- });
465
- });
466
- };
467
- this.deleteField = (field) => {
468
- this.store.setState((prev) => {
469
- const newState = { ...prev };
470
- newState.values = deleteBy(newState.values, field);
471
- delete newState.fieldMeta[field];
472
- return newState;
473
- });
474
- };
475
- this.pushFieldValue = (field, value, opts2) => {
476
- return this.setFieldValue(
477
- field,
478
- (prev) => [...Array.isArray(prev) ? prev : [], value],
479
- opts2
480
- );
481
- };
482
- this.insertFieldValue = (field, index, value, opts2) => {
483
- this.setFieldValue(
484
- field,
485
- (prev) => {
486
- return prev.map(
487
- (d, i) => i === index ? value : d
488
- );
489
- },
490
- opts2
491
- );
492
- };
493
- this.removeFieldValue = (field, index, opts2) => {
494
- this.setFieldValue(
495
- field,
496
- (prev) => {
497
- return prev.filter(
498
- (_d, i) => i !== index
499
- );
500
- },
501
- opts2
502
- );
503
- };
504
- this.swapFieldValues = (field, index1, index2) => {
505
- this.setFieldValue(field, (prev) => {
506
- const prev1 = prev[index1];
507
- const prev2 = prev[index2];
508
- return setBy(setBy(prev, `${index1}`, prev2), `${index2}`, prev1);
509
- });
510
- };
511
- this.store = new Store(
512
- getDefaultFormState({
513
- ...opts == null ? void 0 : opts.defaultState,
514
- values: (opts == null ? void 0 : opts.defaultValues) ?? ((_a = opts == null ? void 0 : opts.defaultState) == null ? void 0 : _a.values),
515
- isFormValid: true
516
- }),
517
- {
518
- onUpdate: () => {
519
- var _a2, _b;
520
- let { state } = this.store;
521
- const fieldMetaValues = Object.values(state.fieldMeta);
522
- const isFieldsValidating = fieldMetaValues.some(
523
- (field) => field == null ? void 0 : field.isValidating
524
- );
525
- const isFieldsValid = !fieldMetaValues.some(
526
- (field) => (field == null ? void 0 : field.errorMap) && isNonEmptyArray(Object.values(field.errorMap).filter(Boolean))
527
- );
528
- const isTouched = fieldMetaValues.some((field) => field == null ? void 0 : field.isTouched);
529
- const isValidating = isFieldsValidating || state.isFormValidating;
530
- state.errors = Object.values(state.errorMap).filter(
531
- (val) => val !== void 0
532
- );
533
- const isFormValid = state.errors.length === 0;
534
- const isValid = isFieldsValid && isFormValid;
535
- const canSubmit = state.submissionAttempts === 0 && !isTouched || !isValidating && !state.isSubmitting && isValid;
536
- state = {
537
- ...state,
538
- isFieldsValidating,
539
- isFieldsValid,
540
- isFormValid,
541
- isValid,
542
- canSubmit,
543
- isTouched
544
- };
545
- this.state = state;
546
- this.store.state = this.state;
547
- const transformArray = ((_a2 = this.options.transform) == null ? void 0 : _a2.deps) ?? [];
548
- const shouldTransform = transformArray.length !== this.prevTransformArray.length || transformArray.some((val, i) => val !== this.prevTransformArray[i]);
549
- if (shouldTransform) {
550
- (_b = this.options.transform) == null ? void 0 : _b.fn(this);
551
- this.store.state = this.state;
552
- this.prevTransformArray = transformArray;
553
- }
554
- }
555
- }
556
- );
557
- this.state = this.store.state;
558
- this.update(opts || {});
559
- }
560
- runValidator(props) {
561
- const adapter = this.options.validatorAdapter;
562
- if (adapter && typeof props.validate !== "function") {
563
- return adapter()[props.type](props.value, props.validate);
564
- }
565
- return props.validate(props.value);
566
- }
567
- }
568
- function normalizeError$1(rawError) {
569
- if (rawError) {
570
- if (typeof rawError !== "string") {
571
- return "Invalid Form Values";
572
- }
573
- return rawError;
574
- }
575
- return void 0;
576
- }
577
- function getErrorMapKey$1(cause) {
578
- switch (cause) {
579
- case "submit":
580
- return "onSubmit";
581
- case "blur":
582
- return "onBlur";
583
- case "mount":
584
- return "onMount";
585
- case "server":
586
- return "onServer";
587
- case "change":
588
- default:
589
- return "onChange";
590
- }
591
- }
592
- let uid = 0;
593
- class FieldApi {
594
- constructor(opts) {
595
- this.options = {};
596
- this.mount = () => {
597
- const info = this.getInfo();
598
- info.instances[this.uid] = this;
599
- const unsubscribe = this.form.store.subscribe(() => {
600
- this.store.batch(() => {
601
- const nextValue = this.getValue();
602
- const nextMeta = this.getMeta();
603
- if (nextValue !== this.state.value) {
604
- this.store.setState((prev) => ({ ...prev, value: nextValue }));
605
- }
606
- if (nextMeta !== this.state.meta) {
607
- this.store.setState((prev) => ({ ...prev, meta: nextMeta }));
608
- }
609
- });
610
- });
611
- this.update(this.options);
612
- const { onMount } = this.options.validators || {};
613
- if (onMount) {
614
- const error = this.runValidator({
615
- validate: onMount,
616
- value: {
617
- value: this.state.value,
618
- fieldApi: this
619
- },
620
- type: "validate"
621
- });
622
- if (error) {
623
- this.setMeta((prev) => ({
624
- ...prev,
625
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
626
- errorMap: { ...prev == null ? void 0 : prev.errorMap, onMount: error }
627
- }));
628
- }
629
- }
630
- return () => {
631
- const preserveValue = this.options.preserveValue;
632
- unsubscribe();
633
- if (!preserveValue) {
634
- delete info.instances[this.uid];
635
- this.form.deleteField(this.name);
636
- }
637
- if (!Object.keys(info.instances).length && !preserveValue) {
638
- delete this.form.fieldInfo[this.name];
639
- }
640
- };
641
- };
642
- this.update = (opts2) => {
643
- var _a;
644
- if (this.state.value === void 0) {
645
- const formDefault = (_a = opts2.form.options.defaultValues) == null ? void 0 : _a[opts2.name];
646
- if (opts2.defaultValue !== void 0) {
647
- this.setValue(opts2.defaultValue);
648
- } else if (formDefault !== void 0) {
649
- this.setValue(formDefault);
650
- }
651
- }
652
- if (this._getMeta() === void 0) {
653
- this.setMeta(this.state.meta);
654
- }
655
- this.options = opts2;
656
- };
657
- this.getValue = () => {
658
- return this.form.getFieldValue(this.name);
659
- };
660
- this.setValue = (updater, options) => {
661
- this.form.setFieldValue(this.name, updater, options);
662
- this.validate("change", this.state.value);
663
- };
664
- this._getMeta = () => this.form.getFieldMeta(this.name);
665
- this.getMeta = () => this._getMeta() ?? {
666
- isValidating: false,
667
- isTouched: false,
668
- touchedErrors: [],
669
- errors: [],
670
- errorMap: {},
671
- ...this.options.defaultMeta
672
- };
673
- this.setMeta = (updater) => this.form.setFieldMeta(this.name, updater);
674
- this.getInfo = () => this.form.getFieldInfo(this.name);
675
- this.pushValue = (value) => this.form.pushFieldValue(this.name, value);
676
- this.insertValue = (index, value) => this.form.insertFieldValue(this.name, index, value);
677
- this.removeValue = (index) => this.form.removeFieldValue(this.name, index);
678
- this.swapValues = (aIndex, bIndex) => this.form.swapFieldValues(this.name, aIndex, bIndex);
679
- this.getSubField = (name) => new FieldApi({
680
- name: `${this.name}.${name}`,
681
- form: this.form
682
- });
683
- this.validateSync = (value = this.state.value, cause) => {
684
- const validates = getSyncValidatorArray(cause, this.options);
685
- let hasErrored = false;
686
- this.form.store.batch(() => {
687
- for (const validateObj of validates) {
688
- if (!validateObj.validate)
689
- continue;
690
- const error = normalizeError(
691
- this.runValidator({
692
- validate: validateObj.validate,
693
- value: { value, fieldApi: this },
694
- type: "validate"
695
- })
696
- );
697
- const errorMapKey = getErrorMapKey(validateObj.cause);
698
- if (this.state.meta.errorMap[errorMapKey] !== error) {
699
- this.setMeta((prev) => ({
700
- ...prev,
701
- errorMap: {
702
- ...prev.errorMap,
703
- [getErrorMapKey(validateObj.cause)]: error
704
- }
705
- }));
706
- }
707
- if (error) {
708
- hasErrored = true;
709
- }
710
- }
711
- });
712
- const submitErrKey = getErrorMapKey("submit");
713
- if (this.state.meta.errorMap[submitErrKey] && cause !== "submit" && !hasErrored) {
714
- this.setMeta((prev) => ({
715
- ...prev,
716
- errorMap: {
717
- ...prev.errorMap,
718
- [submitErrKey]: void 0
719
- }
720
- }));
721
- }
722
- return { hasErrored };
723
- };
724
- this.validateAsync = async (value = this.state.value, cause) => {
725
- const validates = getAsyncValidatorArray(cause, this.options);
726
- if (!this.state.meta.isValidating) {
727
- this.setMeta((prev) => ({ ...prev, isValidating: true }));
728
- }
729
- const promises = [];
730
- for (const validateObj of validates) {
731
- if (!validateObj.validate)
732
- continue;
733
- const key = getErrorMapKey(validateObj.cause);
734
- const fieldValidatorMeta = this.getInfo().validationMetaMap[key];
735
- fieldValidatorMeta == null ? void 0 : fieldValidatorMeta.lastAbortController.abort();
736
- const controller = new AbortController();
737
- this.getInfo().validationMetaMap[key] = {
738
- lastAbortController: controller
739
- };
740
- promises.push(
741
- new Promise(async (resolve) => {
742
- let rawError;
743
- try {
744
- rawError = await new Promise((rawResolve, rawReject) => {
745
- setTimeout(async () => {
746
- if (controller.signal.aborted)
747
- return rawResolve(void 0);
748
- try {
749
- rawResolve(
750
- await this.runValidator({
751
- validate: validateObj.validate,
752
- value: {
753
- value,
754
- fieldApi: this,
755
- signal: controller.signal
756
- },
757
- type: "validateAsync"
758
- })
759
- );
760
- } catch (e) {
761
- rawReject(e);
762
- }
763
- }, validateObj.debounceMs);
764
- });
765
- } catch (e) {
766
- rawError = e;
767
- }
768
- const error = normalizeError(rawError);
769
- this.setMeta((prev) => {
770
- return {
771
- ...prev,
772
- errorMap: {
773
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
774
- ...prev == null ? void 0 : prev.errorMap,
775
- [getErrorMapKey(cause)]: error
776
- }
777
- };
778
- });
779
- resolve(error);
780
- })
781
- );
782
- }
783
- let results = [];
784
- if (promises.length) {
785
- results = await Promise.all(promises);
786
- }
787
- this.setMeta((prev) => ({ ...prev, isValidating: false }));
788
- return results.filter(Boolean);
789
- };
790
- this.validate = (cause, value) => {
791
- if (!this.state.meta.isTouched)
792
- return [];
793
- try {
794
- this.form.validate(cause);
795
- } catch (_) {
796
- }
797
- const { hasErrored } = this.validateSync(value, cause);
798
- if (hasErrored && !this.options.asyncAlways) {
799
- return this.state.meta.errors;
800
- }
801
- return this.validateAsync(value, cause);
802
- };
803
- this.handleChange = (updater) => {
804
- this.setValue(updater, { touch: true });
805
- };
806
- this.handleBlur = () => {
807
- const prevTouched = this.state.meta.isTouched;
808
- if (!prevTouched) {
809
- this.setMeta((prev) => ({ ...prev, isTouched: true }));
810
- this.validate("change");
811
- }
812
- this.validate("blur");
813
- };
814
- this.form = opts.form;
815
- this.uid = uid++;
816
- this.name = opts.name;
817
- if (opts.defaultValue !== void 0) {
818
- this.form.setFieldValue(this.name, opts.defaultValue);
819
- }
820
- this.store = new Store(
821
- {
822
- value: this.getValue(),
823
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
824
- meta: this._getMeta() ?? {
825
- isValidating: false,
826
- isTouched: false,
827
- touchedErrors: [],
828
- errors: [],
829
- errorMap: {},
830
- ...opts.defaultMeta
831
- }
832
- },
833
- {
834
- onUpdate: () => {
835
- const state = this.store.state;
836
- state.meta.errors = Object.values(state.meta.errorMap).filter(
837
- (val) => val !== void 0
838
- );
839
- state.meta.touchedErrors = state.meta.isTouched ? state.meta.errors : [];
840
- this.prevState = state;
841
- this.state = state;
842
- }
843
- }
844
- );
845
- this.state = this.store.state;
846
- this.prevState = this.state;
847
- this.options = opts;
848
- }
849
- runValidator(props) {
850
- const adapters = [
851
- this.form.options.validatorAdapter,
852
- this.options.validatorAdapter
853
- ];
854
- for (const adapter of adapters) {
855
- if (adapter && typeof props.validate !== "function") {
856
- return adapter()[props.type](props.value, props.validate);
857
- }
858
- }
859
- return props.validate(props.value);
860
- }
861
- }
862
- function normalizeError(rawError) {
863
- if (rawError) {
864
- if (typeof rawError !== "string") {
865
- return "Invalid Form Values";
866
- }
867
- return rawError;
868
- }
869
- return void 0;
870
- }
871
- function getErrorMapKey(cause) {
872
- switch (cause) {
873
- case "submit":
874
- return "onSubmit";
875
- case "blur":
876
- return "onBlur";
877
- case "mount":
878
- return "onMount";
879
- case "server":
880
- return "onServer";
881
- case "change":
882
- default:
883
- return "onChange";
884
- }
885
- }
886
- function mutateMergeDeep(target, source) {
887
- const targetKeys = Object.keys(target);
888
- const sourceKeys = Object.keys(source);
889
- const keySet = /* @__PURE__ */ new Set([...targetKeys, ...sourceKeys]);
890
- for (const key of keySet) {
891
- const targetKey = key;
892
- const sourceKey = key;
893
- if (Array.isArray(target[targetKey]) && Array.isArray(source[sourceKey])) {
894
- target[targetKey] = [
895
- ...target[targetKey],
896
- ...source[sourceKey]
897
- ];
898
- } else if (typeof target[targetKey] === "object" && typeof source[sourceKey] === "object") {
899
- mutateMergeDeep(target[targetKey], source[sourceKey]);
900
- } else {
901
- if (!(sourceKey in source) && source[sourceKey] === void 0) {
902
- continue;
903
- }
904
- target[targetKey] = source[sourceKey];
905
- }
906
- }
907
- return target;
908
- }
909
- function mergeForm(baseForm, state) {
910
- mutateMergeDeep(baseForm.state, state);
911
- return baseForm;
912
- }
913
- export {
914
- FieldApi,
915
- FormApi,
916
- deleteBy,
917
- functionalUpdate,
918
- getAsyncValidatorArray,
919
- getBy,
920
- getSyncValidatorArray,
921
- isNonEmptyArray,
922
- mergeForm,
923
- mutateMergeDeep,
924
- setBy
925
- };
926
- //# sourceMappingURL=index.mjs.map