@tanstack/form-core 0.0.9 → 0.0.12

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 (79) hide show
  1. package/build/lib/FieldApi.cjs +307 -0
  2. package/build/lib/FieldApi.cjs.map +1 -0
  3. package/build/lib/FieldApi.d.ts +112 -0
  4. package/build/lib/FieldApi.d.ts.map +1 -0
  5. package/build/lib/FieldApi.js +305 -0
  6. package/build/lib/FieldApi.js.map +1 -0
  7. package/build/lib/FieldApi.legacy.cjs +307 -0
  8. package/build/lib/FieldApi.legacy.cjs.map +1 -0
  9. package/build/lib/FieldApi.legacy.js +305 -0
  10. package/build/lib/FieldApi.legacy.js.map +1 -0
  11. package/build/lib/FormApi.cjs +248 -0
  12. package/build/lib/FormApi.cjs.map +1 -0
  13. package/build/{types → lib}/FormApi.d.ts +16 -11
  14. package/build/lib/FormApi.d.ts.map +1 -0
  15. package/build/lib/FormApi.js +246 -0
  16. package/build/lib/FormApi.js.map +1 -0
  17. package/build/lib/FormApi.legacy.cjs +248 -0
  18. package/build/lib/FormApi.legacy.cjs.map +1 -0
  19. package/build/lib/FormApi.legacy.js +246 -0
  20. package/build/lib/FormApi.legacy.js.map +1 -0
  21. package/build/lib/_virtual/_rollupPluginBabelHelpers.cjs +65 -0
  22. package/build/lib/_virtual/_rollupPluginBabelHelpers.cjs.map +1 -0
  23. package/build/lib/_virtual/_rollupPluginBabelHelpers.js +56 -0
  24. package/build/{cjs → lib}/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
  25. package/build/lib/_virtual/_rollupPluginBabelHelpers.legacy.cjs +65 -0
  26. package/build/lib/_virtual/_rollupPluginBabelHelpers.legacy.cjs.map +1 -0
  27. package/build/lib/_virtual/_rollupPluginBabelHelpers.legacy.js +56 -0
  28. package/build/lib/_virtual/_rollupPluginBabelHelpers.legacy.js.map +1 -0
  29. package/build/lib/index.cjs +14 -0
  30. package/build/lib/index.cjs.map +1 -0
  31. package/build/{types → lib}/index.d.ts +1 -0
  32. package/build/lib/index.d.ts.map +1 -0
  33. package/build/lib/index.js +4 -0
  34. package/build/{cjs → lib}/index.js.map +1 -1
  35. package/build/lib/index.legacy.cjs +14 -0
  36. package/build/lib/index.legacy.cjs.map +1 -0
  37. package/build/lib/index.legacy.js +4 -0
  38. package/build/lib/index.legacy.js.map +1 -0
  39. package/build/lib/tests/FieldApi.spec.d.ts +2 -0
  40. package/build/lib/tests/FieldApi.spec.d.ts.map +1 -0
  41. package/build/lib/tests/FieldApi.test-d.d.ts +2 -0
  42. package/build/lib/tests/FieldApi.test-d.d.ts.map +1 -0
  43. package/build/lib/tests/FormApi.spec.d.ts +2 -0
  44. package/build/lib/tests/FormApi.spec.d.ts.map +1 -0
  45. package/build/{cjs/utils.js → lib/utils.cjs} +18 -27
  46. package/build/lib/utils.cjs.map +1 -0
  47. package/build/{types → lib}/utils.d.ts +10 -0
  48. package/build/lib/utils.d.ts.map +1 -0
  49. package/build/lib/utils.js +77 -0
  50. package/build/lib/utils.js.map +1 -0
  51. package/build/lib/utils.legacy.cjs +81 -0
  52. package/build/lib/utils.legacy.cjs.map +1 -0
  53. package/build/lib/utils.legacy.js +77 -0
  54. package/build/lib/utils.legacy.js.map +1 -0
  55. package/package.json +23 -10
  56. package/src/FieldApi.ts +190 -138
  57. package/src/FormApi.ts +84 -118
  58. package/src/tests/FieldApi.spec.ts +143 -0
  59. package/src/tests/FieldApi.test-d.ts +41 -0
  60. package/src/tests/FormApi.spec.ts +216 -0
  61. package/src/utils.ts +10 -1
  62. package/build/cjs/FieldApi.js +0 -345
  63. package/build/cjs/FieldApi.js.map +0 -1
  64. package/build/cjs/FormApi.js +0 -317
  65. package/build/cjs/FormApi.js.map +0 -1
  66. package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -31
  67. package/build/cjs/index.js +0 -26
  68. package/build/cjs/utils.js.map +0 -1
  69. package/build/esm/index.js +0 -724
  70. package/build/esm/index.js.map +0 -1
  71. package/build/stats-html.html +0 -2689
  72. package/build/stats-react.json +0 -190
  73. package/build/types/FieldApi.d.ts +0 -79
  74. package/build/types/tests/test.test.d.ts +0 -0
  75. package/build/umd/index.development.js +0 -785
  76. package/build/umd/index.development.js.map +0 -1
  77. package/build/umd/index.production.js +0 -22
  78. package/build/umd/index.production.js.map +0 -1
  79. package/src/tests/test.test.tsx +0 -5
@@ -1,724 +0,0 @@
1
- /**
2
- * form-core
3
- *
4
- * Copyright (c) TanStack
5
- *
6
- * This source code is licensed under the MIT license found in the
7
- * LICENSE.md file in the root directory of this source tree.
8
- *
9
- * @license MIT
10
- */
11
- import { Store } from '@tanstack/store';
12
-
13
- function functionalUpdate(updater, input) {
14
- return typeof updater === 'function' ? updater(input) : updater;
15
- }
16
- function getBy(obj, path) {
17
- const pathArray = makePathArray(path);
18
- const pathObj = pathArray;
19
- return pathObj.reduce((current, pathPart) => {
20
- if (typeof current !== 'undefined') {
21
- return current[pathPart];
22
- }
23
-
24
- return undefined;
25
- }, obj);
26
- }
27
- function setBy(obj, _path, updater) {
28
- const path = makePathArray(_path);
29
-
30
- function doSet(parent) {
31
- if (!path.length) {
32
- return functionalUpdate(updater, parent);
33
- }
34
-
35
- const key = path.shift();
36
-
37
- if (typeof key === 'string') {
38
- if (typeof parent === 'object') {
39
- return { ...parent,
40
- [key]: doSet(parent[key])
41
- };
42
- }
43
-
44
- return {
45
- [key]: doSet()
46
- };
47
- }
48
-
49
- if (typeof key === 'number') {
50
- if (Array.isArray(parent)) {
51
- const prefix = parent.slice(0, key);
52
- return [...(prefix.length ? prefix : new Array(key)), doSet(parent[key]), ...parent.slice(key + 1)];
53
- }
54
-
55
- return [...new Array(key), doSet()];
56
- }
57
-
58
- throw new Error('Uh oh!');
59
- }
60
-
61
- return doSet(obj);
62
- }
63
- const reFindNumbers0 = /^(\d*)$/gm;
64
- const reFindNumbers1 = /\.(\d*)\./gm;
65
- const reFindNumbers2 = /^(\d*)\./gm;
66
- const reFindNumbers3 = /\.(\d*$)/gm;
67
- const reFindMultiplePeriods = /\.{2,}/gm;
68
- const intPrefix = '__int__';
69
- const intReplace = intPrefix + "$1";
70
-
71
- function makePathArray(str) {
72
- if (typeof str !== 'string') {
73
- throw new Error();
74
- }
75
-
76
- return str.replace('[', '.').replace(']', '').replace(reFindNumbers0, intReplace).replace(reFindNumbers1, "." + intReplace + ".").replace(reFindNumbers2, intReplace + ".").replace(reFindNumbers3, "." + intReplace).replace(reFindMultiplePeriods, '.').split('.').map(d => {
77
- if (d.indexOf(intPrefix) === 0) {
78
- return parseInt(d.substring(intPrefix.length), 10);
79
- }
80
-
81
- return d;
82
- });
83
- }
84
-
85
- function getDefaultFormState(defaultState) {
86
- return {
87
- values: {},
88
- fieldMeta: {},
89
- canSubmit: true,
90
- isFieldsValid: false,
91
- isFieldsValidating: false,
92
- isFormValid: false,
93
- isFormValidating: false,
94
- isSubmitted: false,
95
- isSubmitting: false,
96
- isTouched: false,
97
- isValid: false,
98
- isValidating: false,
99
- submissionAttempts: 0,
100
- formValidationCount: 0,
101
- ...defaultState
102
- };
103
- }
104
-
105
- class FormApi {
106
- // // This carries the context for nested fields
107
- constructor(_opts) {
108
- var _opts$defaultValues, _opts$defaultState;
109
-
110
- this.options = {};
111
- this.fieldInfo = {};
112
- this.validationMeta = {};
113
-
114
- this.update = options => {
115
- if (!options) return;
116
- this.store.batch(() => {
117
- if (options.defaultState && options.defaultState !== this.options.defaultState) {
118
- this.store.setState(prev => ({ ...prev,
119
- ...options.defaultState
120
- }));
121
- }
122
-
123
- if (options.defaultValues !== this.options.defaultValues) {
124
- this.store.setState(prev => ({ ...prev,
125
- values: options.defaultValues
126
- }));
127
- }
128
- });
129
- this.options = options;
130
- };
131
-
132
- this.reset = () => this.store.setState(() => getDefaultFormState(this.options.defaultValues));
133
-
134
- this.validateAllFields = async () => {
135
- const fieldValidationPromises = [];
136
- this.store.batch(() => {
137
- void Object.values(this.fieldInfo).forEach(field => {
138
- Object.values(field.instances).forEach(instance => {
139
- // If any fields are not touched
140
- if (!instance.state.meta.isTouched) {
141
- // Mark them as touched
142
- instance.setMeta(prev => ({ ...prev,
143
- isTouched: true
144
- })); // Validate the field
145
-
146
- if (instance.options.validate) {
147
- fieldValidationPromises.push(instance.validate());
148
- }
149
- }
150
- });
151
- });
152
- });
153
- return Promise.all(fieldValidationPromises);
154
- };
155
-
156
- this.validateForm = async () => {
157
- const {
158
- validate
159
- } = this.options;
160
-
161
- if (!validate) {
162
- return;
163
- } // Use the formValidationCount for all field instances to
164
- // track freshness of the validation
165
-
166
-
167
- this.store.setState(prev => ({ ...prev,
168
- isValidating: true,
169
- formValidationCount: prev.formValidationCount + 1
170
- }));
171
- const formValidationCount = this.state.formValidationCount;
172
-
173
- const checkLatest = () => formValidationCount === this.state.formValidationCount;
174
-
175
- if (!this.validationMeta.validationPromise) {
176
- this.validationMeta.validationPromise = new Promise((resolve, reject) => {
177
- this.validationMeta.validationResolve = resolve;
178
- this.validationMeta.validationReject = reject;
179
- });
180
- }
181
-
182
- const doValidation = async () => {
183
- try {
184
- const error = await validate(this.state.values, this);
185
-
186
- if (checkLatest()) {
187
- var _this$validationMeta$, _this$validationMeta;
188
-
189
- this.store.setState(prev => ({ ...prev,
190
- isValidating: false,
191
- error: error ? typeof error === 'string' ? error : 'Invalid Form Values' : null
192
- }));
193
- (_this$validationMeta$ = (_this$validationMeta = this.validationMeta).validationResolve) == null ? void 0 : _this$validationMeta$.call(_this$validationMeta, error);
194
- }
195
- } catch (err) {
196
- if (checkLatest()) {
197
- var _this$validationMeta$2, _this$validationMeta2;
198
-
199
- (_this$validationMeta$2 = (_this$validationMeta2 = this.validationMeta).validationReject) == null ? void 0 : _this$validationMeta$2.call(_this$validationMeta2, err);
200
- }
201
- } finally {
202
- delete this.validationMeta.validationPromise;
203
- }
204
- };
205
-
206
- doValidation();
207
- return this.validationMeta.validationPromise;
208
- };
209
-
210
- this.handleSubmit = async e => {
211
- e.preventDefault();
212
- e.stopPropagation(); // Check to see that the form and all fields have been touched
213
- // If they have not, touch them all and run validation
214
- // Run form validation
215
- // Submit the form
216
-
217
- this.store.setState(old => ({ ...old,
218
- // Submittion attempts mark the form as not submitted
219
- isSubmitted: false,
220
- // Count submission attempts
221
- submissionAttempts: old.submissionAttempts + 1
222
- })); // Don't let invalid forms submit
223
-
224
- if (!this.state.canSubmit) return;
225
- this.store.setState(d => ({ ...d,
226
- isSubmitting: true
227
- }));
228
-
229
- const done = () => {
230
- this.store.setState(prev => ({ ...prev,
231
- isSubmitting: false
232
- }));
233
- }; // Validate all fields
234
-
235
-
236
- await this.validateAllFields(); // Fields are invalid, do not submit
237
-
238
- if (!this.state.isFieldsValid) {
239
- var _this$options$onInval, _this$options;
240
-
241
- done();
242
- (_this$options$onInval = (_this$options = this.options).onInvalidSubmit) == null ? void 0 : _this$options$onInval.call(_this$options, this.state.values, this);
243
- return;
244
- } // Run validation for the form
245
-
246
-
247
- await this.validateForm();
248
-
249
- if (!this.state.isValid) {
250
- var _this$options$onInval2, _this$options2;
251
-
252
- done();
253
- (_this$options$onInval2 = (_this$options2 = this.options).onInvalidSubmit) == null ? void 0 : _this$options$onInval2.call(_this$options2, this.state.values, this);
254
- return;
255
- }
256
-
257
- try {
258
- var _this$options$onSubmi, _this$options3;
259
-
260
- // Run the submit code
261
- await ((_this$options$onSubmi = (_this$options3 = this.options).onSubmit) == null ? void 0 : _this$options$onSubmi.call(_this$options3, this.state.values, this));
262
- this.store.batch(() => {
263
- this.store.setState(prev => ({ ...prev,
264
- isSubmitted: true
265
- }));
266
- done();
267
- });
268
- } catch (err) {
269
- done();
270
- throw err;
271
- }
272
- };
273
-
274
- this.getFieldValue = field => getBy(this.state.values, field);
275
-
276
- this.getFieldMeta = field => {
277
- return this.state.fieldMeta[field];
278
- };
279
-
280
- this.getFieldInfo = field => {
281
- var _this$fieldInfo;
282
-
283
- return (_this$fieldInfo = this.fieldInfo)[field] || (_this$fieldInfo[field] = {
284
- instances: {}
285
- });
286
- };
287
-
288
- this.setFieldMeta = (field, updater) => {
289
- this.store.setState(prev => {
290
- return { ...prev,
291
- fieldMeta: { ...prev.fieldMeta,
292
- [field]: functionalUpdate(updater, prev.fieldMeta[field])
293
- }
294
- };
295
- });
296
- };
297
-
298
- this.setFieldValue = (field, updater, opts) => {
299
- var _opts$touch;
300
-
301
- const touch = (_opts$touch = opts == null ? void 0 : opts.touch) != null ? _opts$touch : true;
302
- this.store.batch(() => {
303
- this.store.setState(prev => {
304
- return { ...prev,
305
- values: setBy(prev.values, field, updater)
306
- };
307
- });
308
-
309
- if (touch) {
310
- this.setFieldMeta(field, prev => ({ ...prev,
311
- isTouched: true
312
- }));
313
- }
314
- });
315
- };
316
-
317
- this.pushFieldValue = (field, value, opts) => {
318
- return this.setFieldValue(field, prev => [...(Array.isArray(prev) ? prev : []), value], opts);
319
- };
320
-
321
- this.insertFieldValue = (field, index, value, opts) => {
322
- this.setFieldValue(field, prev => {
323
- // invariant( // TODO: bring in invariant
324
- // Array.isArray(prev),
325
- // `Cannot insert a field value into a non-array field. Check that this field's existing value is an array: ${field}.`
326
- // )
327
- return prev.map((d, i) => i === index ? value : d);
328
- }, opts);
329
- };
330
-
331
- this.removeFieldValue = (field, index, opts) => {
332
- this.setFieldValue(field, prev => {
333
- // invariant( // TODO: bring in invariant
334
- // Array.isArray(prev),
335
- // `Cannot insert a field value into a non-array field. Check that this field's existing value is an array: ${field}.`
336
- // )
337
- return prev.filter((_d, i) => i !== index);
338
- }, opts);
339
- };
340
-
341
- this.swapFieldValues = (field, index1, index2) => {
342
- this.setFieldValue(field, prev => {
343
- const prev1 = prev[index1];
344
- const prev2 = prev[index2];
345
- return setBy(setBy(prev, [index1], prev2), [index2], prev1);
346
- });
347
- };
348
-
349
- this.store = new Store(getDefaultFormState({ ...(_opts == null ? void 0 : _opts.defaultState),
350
- values: (_opts$defaultValues = _opts == null ? void 0 : _opts.defaultValues) != null ? _opts$defaultValues : _opts == null ? void 0 : (_opts$defaultState = _opts.defaultState) == null ? void 0 : _opts$defaultState.values,
351
- isFormValid: !(_opts != null && _opts.validate)
352
- }), {
353
- onUpdate: next => {
354
- // Computed state
355
- const fieldMetaValues = Object.values(next.fieldMeta);
356
- const isFieldsValidating = fieldMetaValues.some(field => field == null ? void 0 : field.isValidating);
357
- const isFieldsValid = !fieldMetaValues.some(field => field == null ? void 0 : field.error);
358
- const isTouched = fieldMetaValues.some(field => field == null ? void 0 : field.isTouched);
359
- const isValidating = isFieldsValidating || next.isFormValidating;
360
- const isFormValid = !next.formError;
361
- const isValid = isFieldsValid && isFormValid;
362
- const canSubmit = next.submissionAttempts === 0 && !isTouched || !isValidating && !next.isSubmitting && isValid;
363
- next = { ...next,
364
- isFieldsValidating,
365
- isFieldsValid,
366
- isFormValid,
367
- isValid,
368
- canSubmit,
369
- isTouched
370
- }; // Create a shortcut for the state
371
- // Write it back to the store
372
-
373
- this.store.state = next;
374
- this.state = next;
375
- }
376
- });
377
- this.state = this.store.state;
378
- this.update(_opts || {});
379
- }
380
-
381
- }
382
-
383
- var id = 0;
384
-
385
- function _classPrivateFieldLooseKey(name) {
386
- return "__private_" + id++ + "_" + name;
387
- }
388
-
389
- function _classPrivateFieldLooseBase(receiver, privateKey) {
390
- if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
391
- throw new TypeError("attempted to use private field on non-instance");
392
- }
393
-
394
- return receiver;
395
- }
396
-
397
- let uid = 0;
398
-
399
- var _updateStore = /*#__PURE__*/_classPrivateFieldLooseKey("updateStore");
400
-
401
- var _leaseValidateAsync = /*#__PURE__*/_classPrivateFieldLooseKey("leaseValidateAsync");
402
-
403
- class FieldApi {
404
- constructor(_opts) {
405
- var _this$getMeta;
406
-
407
- this.options = {};
408
-
409
- this.mount = () => {
410
- const info = this.getInfo();
411
- info.instances[this.uid] = this;
412
- const unsubscribe = this.form.store.subscribe(() => {
413
- _classPrivateFieldLooseBase(this, _updateStore)[_updateStore]();
414
- });
415
- return () => {
416
- unsubscribe();
417
- delete info.instances[this.uid];
418
-
419
- if (!Object.keys(info.instances).length) {
420
- delete this.form.fieldInfo[this.name];
421
- }
422
- };
423
- };
424
-
425
- Object.defineProperty(this, _updateStore, {
426
- writable: true,
427
- value: () => {
428
- this.store.batch(() => {
429
- const nextValue = this.getValue();
430
- const nextMeta = this.getMeta();
431
-
432
- if (nextValue !== this.state.value) {
433
- this.store.setState(prev => ({ ...prev,
434
- value: nextValue
435
- }));
436
- }
437
-
438
- if (nextMeta !== this.state.meta) {
439
- this.store.setState(prev => ({ ...prev,
440
- meta: nextMeta
441
- }));
442
- }
443
- });
444
- }
445
- });
446
-
447
- this.update = opts => {
448
- var _this$form$options$de, _this$form$options$de2, _this$form$options$de3, _this$form$options$de4;
449
-
450
- this.options = {
451
- validatePristine: (_this$form$options$de = this.form.options.defaultValidatePristine) != null ? _this$form$options$de : false,
452
- validateOn: (_this$form$options$de2 = this.form.options.defaultValidateOn) != null ? _this$form$options$de2 : 'change',
453
- validateAsyncOn: (_this$form$options$de3 = this.form.options.defaultValidateAsyncOn) != null ? _this$form$options$de3 : 'blur',
454
- validateAsyncDebounceMs: (_this$form$options$de4 = this.form.options.defaultValidateAsyncDebounceMs) != null ? _this$form$options$de4 : 0,
455
- ...opts
456
- }; // Default Value
457
-
458
- if (this.state.value === undefined && this.options.defaultValue !== undefined) {
459
- this.setValue(this.options.defaultValue);
460
- } // Default Meta
461
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
462
-
463
-
464
- if (this.getMeta() === undefined) {
465
- this.setMeta(this.state.meta);
466
- }
467
- };
468
-
469
- this.getValue = () => {
470
- return this.form.getFieldValue(this.name);
471
- };
472
-
473
- this.setValue = (updater, options) => this.form.setFieldValue(this.name, updater, options);
474
-
475
- this.getMeta = () => this.form.getFieldMeta(this.name);
476
-
477
- this.setMeta = updater => this.form.setFieldMeta(this.name, updater);
478
-
479
- this.getInfo = () => this.form.getFieldInfo(this.name);
480
-
481
- this.pushValue = value => this.form.pushFieldValue(this.name, value);
482
-
483
- this.insertValue = (index, value) => this.form.insertFieldValue(this.name, index, value);
484
-
485
- this.removeValue = index => this.form.removeFieldValue(this.name, index);
486
-
487
- this.swapValues = (aIndex, bIndex) => this.form.swapFieldValues(this.name, aIndex, bIndex);
488
-
489
- this.getSubField = name => new FieldApi({
490
- name: this.name + "." + name,
491
- form: this.form
492
- });
493
-
494
- this.validateSync = async (value = this.state.value) => {
495
- const {
496
- validate
497
- } = this.options;
498
-
499
- if (!validate) {
500
- return;
501
- } // Use the validationCount for all field instances to
502
- // track freshness of the validation
503
-
504
-
505
- const validationCount = (this.getInfo().validationCount || 0) + 1;
506
- this.getInfo().validationCount = validationCount;
507
- const error = normalizeError(validate(value, this));
508
-
509
- if (this.state.meta.error !== error) {
510
- this.setMeta(prev => ({ ...prev,
511
- error
512
- }));
513
- } // If a sync error is encountered, cancel any async validation
514
-
515
-
516
- if (this.state.meta.error) {
517
- this.cancelValidateAsync();
518
- }
519
- };
520
-
521
- Object.defineProperty(this, _leaseValidateAsync, {
522
- writable: true,
523
- value: () => {
524
- const count = (this.getInfo().validationAsyncCount || 0) + 1;
525
- this.getInfo().validationAsyncCount = count;
526
- return count;
527
- }
528
- });
529
-
530
- this.cancelValidateAsync = () => {
531
- // Lease a new validation count to ignore any pending validations
532
- _classPrivateFieldLooseBase(this, _leaseValidateAsync)[_leaseValidateAsync](); // Cancel any pending validation state
533
-
534
-
535
- this.setMeta(prev => ({ ...prev,
536
- isValidating: false
537
- }));
538
- };
539
-
540
- this.validateAsync = async (value = this.state.value) => {
541
- const {
542
- validateAsync,
543
- validateAsyncDebounceMs
544
- } = this.options;
545
-
546
- if (!validateAsync) {
547
- return;
548
- }
549
-
550
- if (this.state.meta.isValidating !== true) this.setMeta(prev => ({ ...prev,
551
- isValidating: true
552
- })); // Use the validationCount for all field instances to
553
- // track freshness of the validation
554
-
555
- const validationAsyncCount = _classPrivateFieldLooseBase(this, _leaseValidateAsync)[_leaseValidateAsync]();
556
-
557
- const checkLatest = () => validationAsyncCount === this.getInfo().validationAsyncCount;
558
-
559
- if (!this.getInfo().validationPromise) {
560
- this.getInfo().validationPromise = new Promise((resolve, reject) => {
561
- this.getInfo().validationResolve = resolve;
562
- this.getInfo().validationReject = reject;
563
- });
564
- }
565
-
566
- if (validateAsyncDebounceMs > 0) {
567
- await new Promise(r => setTimeout(r, validateAsyncDebounceMs));
568
- } // Only kick off validation if this validation is the latest attempt
569
-
570
-
571
- if (checkLatest()) {
572
- try {
573
- const rawError = await validateAsync(value, this);
574
-
575
- if (checkLatest()) {
576
- var _this$getInfo$validat, _this$getInfo;
577
-
578
- const error = normalizeError(rawError);
579
- this.setMeta(prev => ({ ...prev,
580
- isValidating: false,
581
- error
582
- }));
583
- (_this$getInfo$validat = (_this$getInfo = this.getInfo()).validationResolve) == null ? void 0 : _this$getInfo$validat.call(_this$getInfo, error);
584
- }
585
- } catch (error) {
586
- if (checkLatest()) {
587
- var _this$getInfo$validat2, _this$getInfo2;
588
-
589
- (_this$getInfo$validat2 = (_this$getInfo2 = this.getInfo()).validationReject) == null ? void 0 : _this$getInfo$validat2.call(_this$getInfo2, error);
590
- throw error;
591
- }
592
- } finally {
593
- if (checkLatest()) {
594
- this.setMeta(prev => ({ ...prev,
595
- isValidating: false
596
- }));
597
- delete this.getInfo().validationPromise;
598
- }
599
- }
600
- } // Always return the latest validation promise to the caller
601
-
602
-
603
- return this.getInfo().validationPromise;
604
- };
605
-
606
- this.shouldValidate = (isAsync, cause) => {
607
- const {
608
- validateOn,
609
- validateAsyncOn
610
- } = this.options;
611
- const level = getValidationCauseLevel(cause); // Must meet *at least* the validation level to validate,
612
- // e.g. if validateOn is 'change' and validateCause is 'blur',
613
- // the field will still validate
614
-
615
- return Object.keys(validateCauseLevels).some(d => isAsync ? validateAsyncOn : validateOn === d && level >= validateCauseLevels[d]);
616
- };
617
-
618
- this.validate = async (cause, value) => {
619
- // If the field is pristine and validatePristine is false, do not validate
620
- if (!this.options.validatePristine && !this.state.meta.isTouched) return; // Attempt to sync validate first
621
-
622
- if (this.shouldValidate(false, cause)) {
623
- this.validateSync(value);
624
- } // If there is an error, return it, do not attempt async validation
625
-
626
-
627
- if (this.state.meta.error) {
628
- return this.state.meta.error;
629
- } // No error? Attempt async validation
630
-
631
-
632
- if (this.shouldValidate(true, cause)) {
633
- return this.validateAsync(value);
634
- } // If there is no sync error or async validation attempt, there is no error
635
-
636
-
637
- return undefined;
638
- };
639
-
640
- this.getChangeProps = (props = {}) => {
641
- return { ...props,
642
- value: this.state.value,
643
- onChange: value => {
644
- this.setValue(value);
645
- props.onChange == null ? void 0 : props.onChange(value);
646
- },
647
- onBlur: e => {
648
- this.setMeta(prev => ({ ...prev,
649
- isTouched: true
650
- }));
651
- this.validate('blur');
652
- props.onBlur == null ? void 0 : props.onBlur(e);
653
- }
654
- };
655
- };
656
-
657
- this.getInputProps = (props = {}) => {
658
- return { ...props,
659
- value: String(this.state.value),
660
- onChange: e => {
661
- this.setValue(e.target.value);
662
- props.onChange == null ? void 0 : props.onChange(e.target.value);
663
- },
664
- onBlur: this.getChangeProps(props).onBlur
665
- };
666
- };
667
-
668
- this.form = _opts.form;
669
- this.uid = uid++; // Support field prefixing from FieldScope
670
- // let fieldPrefix = ''
671
- // if (this.form.fieldName) {
672
- // fieldPrefix = `${this.form.fieldName}.`
673
- // }
674
-
675
- this.name = _opts.name;
676
- this.store = new Store({
677
- value: this.getValue(),
678
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
679
- meta: (_this$getMeta = this.getMeta()) != null ? _this$getMeta : {
680
- isValidating: false,
681
- isTouched: false,
682
- ...this.options.defaultMeta
683
- }
684
- }, {
685
- onUpdate: next => {
686
- next.meta.touchedError = next.meta.isTouched ? next.meta.error : undefined; // Do not validate pristine fields
687
-
688
- const prevState = this.state;
689
- this.state = next;
690
-
691
- if (next.value !== prevState.value) {
692
- this.validate('change', next.value);
693
- }
694
- }
695
- });
696
- this.state = this.store.state;
697
- this.update(_opts);
698
- }
699
-
700
- }
701
- const validateCauseLevels = {
702
- change: 0,
703
- blur: 1,
704
- submit: 2
705
- };
706
-
707
- function getValidationCauseLevel(cause) {
708
- return !cause ? 3 : validateCauseLevels[cause];
709
- }
710
-
711
- function normalizeError(rawError) {
712
- if (rawError) {
713
- if (typeof rawError !== 'string') {
714
- return 'Invalid Form Values';
715
- }
716
-
717
- return rawError;
718
- }
719
-
720
- return undefined;
721
- }
722
-
723
- export { FieldApi, FormApi, functionalUpdate, getBy, setBy };
724
- //# sourceMappingURL=index.js.map