@tanstack/form-core 1.16.0 → 1.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/FieldApi.cjs +48 -40
- package/dist/cjs/FieldApi.cjs.map +1 -1
- package/dist/cjs/FieldApi.d.cts +33 -30
- package/dist/cjs/FieldGroupApi.cjs.map +1 -1
- package/dist/cjs/FieldGroupApi.d.cts +6 -6
- package/dist/cjs/FormApi.cjs +82 -69
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/FormApi.d.cts +45 -35
- package/dist/cjs/ValidationLogic.cjs +106 -0
- package/dist/cjs/ValidationLogic.cjs.map +1 -0
- package/dist/cjs/ValidationLogic.d.cts +47 -0
- package/dist/cjs/formOptions.cjs.map +1 -1
- package/dist/cjs/formOptions.d.cts +1 -1
- package/dist/cjs/index.cjs +3 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/mergeForm.cjs.map +1 -1
- package/dist/cjs/mergeForm.d.cts +1 -1
- package/dist/cjs/metaHelper.cjs.map +1 -1
- package/dist/cjs/metaHelper.d.cts +1 -1
- package/dist/cjs/types.d.cts +6 -3
- package/dist/cjs/utils.cjs +51 -63
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +11 -5
- package/dist/esm/FieldApi.d.ts +33 -30
- package/dist/esm/FieldApi.js +48 -40
- package/dist/esm/FieldApi.js.map +1 -1
- package/dist/esm/FieldGroupApi.d.ts +6 -6
- package/dist/esm/FieldGroupApi.js.map +1 -1
- package/dist/esm/FormApi.d.ts +45 -35
- package/dist/esm/FormApi.js +82 -69
- package/dist/esm/FormApi.js.map +1 -1
- package/dist/esm/ValidationLogic.d.ts +47 -0
- package/dist/esm/ValidationLogic.js +106 -0
- package/dist/esm/ValidationLogic.js.map +1 -0
- package/dist/esm/formOptions.d.ts +1 -1
- package/dist/esm/formOptions.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mergeForm.d.ts +1 -1
- package/dist/esm/mergeForm.js.map +1 -1
- package/dist/esm/metaHelper.d.ts +1 -1
- package/dist/esm/metaHelper.js.map +1 -1
- package/dist/esm/types.d.ts +6 -3
- package/dist/esm/utils.d.ts +11 -5
- package/dist/esm/utils.js +51 -63
- package/dist/esm/utils.js.map +1 -1
- package/package.json +16 -3
- package/src/FieldApi.ts +185 -14
- package/src/FieldGroupApi.ts +14 -0
- package/src/FormApi.ts +139 -3
- package/src/ValidationLogic.ts +200 -0
- package/src/formOptions.ts +1 -1
- package/src/index.ts +1 -0
- package/src/mergeForm.ts +16 -1
- package/src/metaHelper.ts +4 -0
- package/src/types.ts +17 -1
- package/src/utils.ts +159 -109
package/src/FormApi.ts
CHANGED
|
@@ -11,12 +11,14 @@ import {
|
|
|
11
11
|
isNonEmptyArray,
|
|
12
12
|
setBy,
|
|
13
13
|
} from './utils'
|
|
14
|
+
import { defaultValidationLogic } from './ValidationLogic'
|
|
14
15
|
|
|
15
16
|
import {
|
|
16
17
|
isStandardSchemaValidator,
|
|
17
18
|
standardSchemaValidators,
|
|
18
19
|
} from './standardSchemaValidator'
|
|
19
20
|
import { defaultFieldMeta, metaHelper } from './metaHelper'
|
|
21
|
+
import type { ValidationLogicFn } from './ValidationLogic'
|
|
20
22
|
import type {
|
|
21
23
|
StandardSchemaV1,
|
|
22
24
|
StandardSchemaV1Issue,
|
|
@@ -84,6 +86,8 @@ export type FormValidateFn<TFormData> = (props: {
|
|
|
84
86
|
any,
|
|
85
87
|
any,
|
|
86
88
|
any,
|
|
89
|
+
any,
|
|
90
|
+
any,
|
|
87
91
|
any
|
|
88
92
|
>
|
|
89
93
|
}) => unknown
|
|
@@ -120,6 +124,8 @@ export type FormValidateAsyncFn<TFormData> = (props: {
|
|
|
120
124
|
any,
|
|
121
125
|
any,
|
|
122
126
|
any,
|
|
127
|
+
any,
|
|
128
|
+
any,
|
|
123
129
|
any
|
|
124
130
|
>
|
|
125
131
|
signal: AbortSignal
|
|
@@ -164,6 +170,8 @@ export interface FormValidators<
|
|
|
164
170
|
TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
165
171
|
TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
166
172
|
TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
173
|
+
TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
174
|
+
TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
167
175
|
> {
|
|
168
176
|
/**
|
|
169
177
|
* Optional function that fires as soon as the component mounts.
|
|
@@ -195,6 +203,9 @@ export interface FormValidators<
|
|
|
195
203
|
onBlurAsyncDebounceMs?: number
|
|
196
204
|
onSubmit?: TOnSubmit
|
|
197
205
|
onSubmitAsync?: TOnSubmitAsync
|
|
206
|
+
onDynamic?: TOnDynamic
|
|
207
|
+
onDynamicAsync?: TOnDynamicAsync
|
|
208
|
+
onDynamicAsyncDebounceMs?: number
|
|
198
209
|
}
|
|
199
210
|
|
|
200
211
|
/**
|
|
@@ -209,6 +220,8 @@ export interface FormTransform<
|
|
|
209
220
|
TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
210
221
|
TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
211
222
|
TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
223
|
+
TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
224
|
+
TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
212
225
|
TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
213
226
|
TSubmitMeta = never,
|
|
214
227
|
> {
|
|
@@ -222,6 +235,8 @@ export interface FormTransform<
|
|
|
222
235
|
TOnBlurAsync,
|
|
223
236
|
TOnSubmit,
|
|
224
237
|
TOnSubmitAsync,
|
|
238
|
+
TOnDynamic,
|
|
239
|
+
TOnDynamicAsync,
|
|
225
240
|
TOnServer,
|
|
226
241
|
TSubmitMeta
|
|
227
242
|
>,
|
|
@@ -234,6 +249,8 @@ export interface FormTransform<
|
|
|
234
249
|
TOnBlurAsync,
|
|
235
250
|
TOnSubmit,
|
|
236
251
|
TOnSubmitAsync,
|
|
252
|
+
TOnDynamic,
|
|
253
|
+
TOnDynamicAsync,
|
|
237
254
|
TOnServer,
|
|
238
255
|
TSubmitMeta
|
|
239
256
|
>
|
|
@@ -249,6 +266,8 @@ export interface FormListeners<
|
|
|
249
266
|
TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
250
267
|
TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
251
268
|
TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
269
|
+
TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
270
|
+
TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
252
271
|
TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
253
272
|
TSubmitMeta = never,
|
|
254
273
|
> {
|
|
@@ -262,6 +281,8 @@ export interface FormListeners<
|
|
|
262
281
|
TOnBlurAsync,
|
|
263
282
|
TOnSubmit,
|
|
264
283
|
TOnSubmitAsync,
|
|
284
|
+
TOnDynamic,
|
|
285
|
+
TOnDynamicAsync,
|
|
265
286
|
TOnServer,
|
|
266
287
|
TSubmitMeta
|
|
267
288
|
>
|
|
@@ -279,6 +300,8 @@ export interface FormListeners<
|
|
|
279
300
|
TOnBlurAsync,
|
|
280
301
|
TOnSubmit,
|
|
281
302
|
TOnSubmitAsync,
|
|
303
|
+
TOnDynamic,
|
|
304
|
+
TOnDynamicAsync,
|
|
282
305
|
TOnServer,
|
|
283
306
|
TSubmitMeta
|
|
284
307
|
>
|
|
@@ -296,6 +319,8 @@ export interface FormListeners<
|
|
|
296
319
|
TOnBlurAsync,
|
|
297
320
|
TOnSubmit,
|
|
298
321
|
TOnSubmitAsync,
|
|
322
|
+
TOnDynamic,
|
|
323
|
+
TOnDynamicAsync,
|
|
299
324
|
TOnServer,
|
|
300
325
|
TSubmitMeta
|
|
301
326
|
>
|
|
@@ -311,6 +336,8 @@ export interface FormListeners<
|
|
|
311
336
|
TOnBlurAsync,
|
|
312
337
|
TOnSubmit,
|
|
313
338
|
TOnSubmitAsync,
|
|
339
|
+
TOnDynamic,
|
|
340
|
+
TOnDynamicAsync,
|
|
314
341
|
TOnServer,
|
|
315
342
|
TSubmitMeta
|
|
316
343
|
>
|
|
@@ -344,9 +371,15 @@ export interface FormOptions<
|
|
|
344
371
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
345
372
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
346
373
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
374
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
375
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
347
376
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
348
377
|
in out TSubmitMeta = never,
|
|
349
378
|
> extends BaseFormOptions<TFormData, TSubmitMeta> {
|
|
379
|
+
/**
|
|
380
|
+
* The form name, used for devtools and identification
|
|
381
|
+
*/
|
|
382
|
+
formId?: string
|
|
350
383
|
/**
|
|
351
384
|
* The default state for the form.
|
|
352
385
|
*/
|
|
@@ -360,6 +393,8 @@ export interface FormOptions<
|
|
|
360
393
|
TOnBlurAsync,
|
|
361
394
|
TOnSubmit,
|
|
362
395
|
TOnSubmitAsync,
|
|
396
|
+
TOnDynamic,
|
|
397
|
+
TOnDynamicAsync,
|
|
363
398
|
TOnServer
|
|
364
399
|
>
|
|
365
400
|
>
|
|
@@ -386,9 +421,13 @@ export interface FormOptions<
|
|
|
386
421
|
TOnBlur,
|
|
387
422
|
TOnBlurAsync,
|
|
388
423
|
TOnSubmit,
|
|
389
|
-
TOnSubmitAsync
|
|
424
|
+
TOnSubmitAsync,
|
|
425
|
+
TOnDynamic,
|
|
426
|
+
TOnDynamicAsync
|
|
390
427
|
>
|
|
391
428
|
|
|
429
|
+
validationLogic?: ValidationLogicFn
|
|
430
|
+
|
|
392
431
|
/**
|
|
393
432
|
* form level listeners
|
|
394
433
|
*/
|
|
@@ -401,6 +440,8 @@ export interface FormOptions<
|
|
|
401
440
|
TOnBlurAsync,
|
|
402
441
|
TOnSubmit,
|
|
403
442
|
TOnSubmitAsync,
|
|
443
|
+
TOnDynamic,
|
|
444
|
+
TOnDynamicAsync,
|
|
404
445
|
TOnServer,
|
|
405
446
|
TSubmitMeta
|
|
406
447
|
>
|
|
@@ -419,6 +460,8 @@ export interface FormOptions<
|
|
|
419
460
|
TOnBlurAsync,
|
|
420
461
|
TOnSubmit,
|
|
421
462
|
TOnSubmitAsync,
|
|
463
|
+
TOnDynamic,
|
|
464
|
+
TOnDynamicAsync,
|
|
422
465
|
TOnServer,
|
|
423
466
|
TSubmitMeta
|
|
424
467
|
>
|
|
@@ -438,6 +481,8 @@ export interface FormOptions<
|
|
|
438
481
|
TOnBlurAsync,
|
|
439
482
|
TOnSubmit,
|
|
440
483
|
TOnSubmitAsync,
|
|
484
|
+
TOnDynamic,
|
|
485
|
+
TOnDynamicAsync,
|
|
441
486
|
TOnServer,
|
|
442
487
|
TSubmitMeta
|
|
443
488
|
>
|
|
@@ -452,6 +497,8 @@ export interface FormOptions<
|
|
|
452
497
|
NoInfer<TOnBlurAsync>,
|
|
453
498
|
NoInfer<TOnSubmit>,
|
|
454
499
|
NoInfer<TOnSubmitAsync>,
|
|
500
|
+
NoInfer<TOnDynamic>,
|
|
501
|
+
NoInfer<TOnDynamicAsync>,
|
|
455
502
|
NoInfer<TOnServer>,
|
|
456
503
|
NoInfer<TSubmitMeta>
|
|
457
504
|
>
|
|
@@ -493,6 +540,10 @@ export type FieldInfo<TFormData> = {
|
|
|
493
540
|
any,
|
|
494
541
|
any,
|
|
495
542
|
any,
|
|
543
|
+
any,
|
|
544
|
+
any,
|
|
545
|
+
any,
|
|
546
|
+
any,
|
|
496
547
|
any
|
|
497
548
|
> | null
|
|
498
549
|
/**
|
|
@@ -513,6 +564,8 @@ export type BaseFormState<
|
|
|
513
564
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
514
565
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
515
566
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
567
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
568
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
516
569
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
517
570
|
> = {
|
|
518
571
|
/**
|
|
@@ -530,6 +583,8 @@ export type BaseFormState<
|
|
|
530
583
|
UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,
|
|
531
584
|
UnwrapFormValidateOrFn<TOnSubmit>,
|
|
532
585
|
UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,
|
|
586
|
+
UnwrapFormValidateOrFn<TOnDynamic>,
|
|
587
|
+
UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>,
|
|
533
588
|
UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
534
589
|
>
|
|
535
590
|
/**
|
|
@@ -588,6 +643,8 @@ export type DerivedFormState<
|
|
|
588
643
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
589
644
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
590
645
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
646
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
647
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
591
648
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
592
649
|
> = {
|
|
593
650
|
/**
|
|
@@ -609,6 +666,8 @@ export type DerivedFormState<
|
|
|
609
666
|
| UnwrapFormAsyncValidateOrFn<TOnBlurAsync>
|
|
610
667
|
| UnwrapFormValidateOrFn<TOnSubmit>
|
|
611
668
|
| UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>
|
|
669
|
+
| UnwrapFormValidateOrFn<TOnDynamic>
|
|
670
|
+
| UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>
|
|
612
671
|
| UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
613
672
|
>
|
|
614
673
|
/**
|
|
@@ -662,6 +721,8 @@ export interface FormState<
|
|
|
662
721
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
663
722
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
664
723
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
724
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
725
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
665
726
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
666
727
|
> extends BaseFormState<
|
|
667
728
|
TFormData,
|
|
@@ -672,6 +733,8 @@ export interface FormState<
|
|
|
672
733
|
TOnBlurAsync,
|
|
673
734
|
TOnSubmit,
|
|
674
735
|
TOnSubmitAsync,
|
|
736
|
+
TOnDynamic,
|
|
737
|
+
TOnDynamicAsync,
|
|
675
738
|
TOnServer
|
|
676
739
|
>,
|
|
677
740
|
DerivedFormState<
|
|
@@ -683,6 +746,8 @@ export interface FormState<
|
|
|
683
746
|
TOnBlurAsync,
|
|
684
747
|
TOnSubmit,
|
|
685
748
|
TOnSubmitAsync,
|
|
749
|
+
TOnDynamic,
|
|
750
|
+
TOnDynamicAsync,
|
|
686
751
|
TOnServer
|
|
687
752
|
> {}
|
|
688
753
|
|
|
@@ -695,6 +760,8 @@ export type AnyFormState = FormState<
|
|
|
695
760
|
any,
|
|
696
761
|
any,
|
|
697
762
|
any,
|
|
763
|
+
any,
|
|
764
|
+
any,
|
|
698
765
|
any
|
|
699
766
|
>
|
|
700
767
|
|
|
@@ -707,6 +774,8 @@ function getDefaultFormState<
|
|
|
707
774
|
TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
708
775
|
TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
709
776
|
TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
777
|
+
TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
778
|
+
TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
710
779
|
TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
711
780
|
>(
|
|
712
781
|
defaultState: Partial<
|
|
@@ -719,6 +788,8 @@ function getDefaultFormState<
|
|
|
719
788
|
TOnBlurAsync,
|
|
720
789
|
TOnSubmit,
|
|
721
790
|
TOnSubmitAsync,
|
|
791
|
+
TOnDynamic,
|
|
792
|
+
TOnDynamicAsync,
|
|
722
793
|
TOnServer
|
|
723
794
|
>
|
|
724
795
|
>,
|
|
@@ -731,6 +802,8 @@ function getDefaultFormState<
|
|
|
731
802
|
TOnBlurAsync,
|
|
732
803
|
TOnSubmit,
|
|
733
804
|
TOnSubmitAsync,
|
|
805
|
+
TOnDynamic,
|
|
806
|
+
TOnDynamicAsync,
|
|
734
807
|
TOnServer
|
|
735
808
|
> {
|
|
736
809
|
return {
|
|
@@ -748,6 +821,7 @@ function getDefaultFormState<
|
|
|
748
821
|
onSubmit: undefined,
|
|
749
822
|
onMount: undefined,
|
|
750
823
|
onServer: undefined,
|
|
824
|
+
onDynamic: undefined,
|
|
751
825
|
},
|
|
752
826
|
}
|
|
753
827
|
}
|
|
@@ -767,6 +841,8 @@ export type AnyFormApi = FormApi<
|
|
|
767
841
|
any,
|
|
768
842
|
any,
|
|
769
843
|
any,
|
|
844
|
+
any,
|
|
845
|
+
any,
|
|
770
846
|
any
|
|
771
847
|
>
|
|
772
848
|
|
|
@@ -786,6 +862,8 @@ export class FormApi<
|
|
|
786
862
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
787
863
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
788
864
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
865
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
866
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
789
867
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
790
868
|
in out TSubmitMeta = never,
|
|
791
869
|
> implements FieldManipulator<TFormData, TSubmitMeta>
|
|
@@ -802,6 +880,8 @@ export class FormApi<
|
|
|
802
880
|
TOnBlurAsync,
|
|
803
881
|
TOnSubmit,
|
|
804
882
|
TOnSubmitAsync,
|
|
883
|
+
TOnDynamic,
|
|
884
|
+
TOnDynamicAsync,
|
|
805
885
|
TOnServer,
|
|
806
886
|
TSubmitMeta
|
|
807
887
|
> = {}
|
|
@@ -815,6 +895,8 @@ export class FormApi<
|
|
|
815
895
|
TOnBlurAsync,
|
|
816
896
|
TOnSubmit,
|
|
817
897
|
TOnSubmitAsync,
|
|
898
|
+
TOnDynamic,
|
|
899
|
+
TOnDynamicAsync,
|
|
818
900
|
TOnServer
|
|
819
901
|
>
|
|
820
902
|
>
|
|
@@ -829,6 +911,8 @@ export class FormApi<
|
|
|
829
911
|
TOnBlurAsync,
|
|
830
912
|
TOnSubmit,
|
|
831
913
|
TOnSubmitAsync,
|
|
914
|
+
TOnDynamic,
|
|
915
|
+
TOnDynamicAsync,
|
|
832
916
|
TOnServer
|
|
833
917
|
>
|
|
834
918
|
>
|
|
@@ -859,6 +943,8 @@ export class FormApi<
|
|
|
859
943
|
TOnBlurAsync,
|
|
860
944
|
TOnSubmit,
|
|
861
945
|
TOnSubmitAsync,
|
|
946
|
+
TOnDynamic,
|
|
947
|
+
TOnDynamicAsync,
|
|
862
948
|
TOnServer,
|
|
863
949
|
TSubmitMeta
|
|
864
950
|
>,
|
|
@@ -891,6 +977,8 @@ export class FormApi<
|
|
|
891
977
|
TOnBlurAsync,
|
|
892
978
|
TOnSubmit,
|
|
893
979
|
TOnSubmitAsync,
|
|
980
|
+
TOnDynamic,
|
|
981
|
+
TOnDynamicAsync,
|
|
894
982
|
TOnServer
|
|
895
983
|
>['fieldMeta']
|
|
896
984
|
|
|
@@ -992,6 +1080,8 @@ export class FormApi<
|
|
|
992
1080
|
TOnBlurAsync,
|
|
993
1081
|
TOnSubmit,
|
|
994
1082
|
TOnSubmitAsync,
|
|
1083
|
+
TOnDynamic,
|
|
1084
|
+
TOnDynamicAsync,
|
|
995
1085
|
TOnServer
|
|
996
1086
|
>
|
|
997
1087
|
| undefined
|
|
@@ -1124,6 +1214,8 @@ export class FormApi<
|
|
|
1124
1214
|
TOnBlurAsync,
|
|
1125
1215
|
TOnSubmit,
|
|
1126
1216
|
TOnSubmitAsync,
|
|
1217
|
+
TOnDynamic,
|
|
1218
|
+
TOnDynamicAsync,
|
|
1127
1219
|
TOnServer
|
|
1128
1220
|
>
|
|
1129
1221
|
|
|
@@ -1150,6 +1242,10 @@ export class FormApi<
|
|
|
1150
1242
|
this.update(opts || {})
|
|
1151
1243
|
}
|
|
1152
1244
|
|
|
1245
|
+
get formId(): string | undefined {
|
|
1246
|
+
return this.options.formId
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1153
1249
|
/**
|
|
1154
1250
|
* @private
|
|
1155
1251
|
*/
|
|
@@ -1205,6 +1301,8 @@ export class FormApi<
|
|
|
1205
1301
|
TOnBlurAsync,
|
|
1206
1302
|
TOnSubmit,
|
|
1207
1303
|
TOnSubmitAsync,
|
|
1304
|
+
TOnDynamic,
|
|
1305
|
+
TOnDynamicAsync,
|
|
1208
1306
|
TOnServer,
|
|
1209
1307
|
TSubmitMeta
|
|
1210
1308
|
>,
|
|
@@ -1396,7 +1494,12 @@ export class FormApi<
|
|
|
1396
1494
|
TOnSubmitAsync
|
|
1397
1495
|
>
|
|
1398
1496
|
} => {
|
|
1399
|
-
const validates = getSyncValidatorArray(cause,
|
|
1497
|
+
const validates = getSyncValidatorArray(cause, {
|
|
1498
|
+
...this.options,
|
|
1499
|
+
form: this,
|
|
1500
|
+
validationLogic: this.options.validationLogic || defaultValidationLogic,
|
|
1501
|
+
})
|
|
1502
|
+
|
|
1400
1503
|
let hasErrored = false as boolean
|
|
1401
1504
|
|
|
1402
1505
|
// This map will only include fields that have errors in the current validation cycle
|
|
@@ -1512,6 +1615,26 @@ export class FormApi<
|
|
|
1512
1615
|
},
|
|
1513
1616
|
}))
|
|
1514
1617
|
}
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* when we have an error for onServer in the state, we want
|
|
1621
|
+
* to clear the error as soon as the user enters a valid value in the field
|
|
1622
|
+
*/
|
|
1623
|
+
const serverErrKey = getErrorMapKey('server')
|
|
1624
|
+
if (
|
|
1625
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1626
|
+
this.state.errorMap?.[serverErrKey] &&
|
|
1627
|
+
cause !== 'server' &&
|
|
1628
|
+
!hasErrored
|
|
1629
|
+
) {
|
|
1630
|
+
this.baseStore.setState((prev) => ({
|
|
1631
|
+
...prev,
|
|
1632
|
+
errorMap: {
|
|
1633
|
+
...prev.errorMap,
|
|
1634
|
+
[serverErrKey]: undefined,
|
|
1635
|
+
},
|
|
1636
|
+
}))
|
|
1637
|
+
}
|
|
1515
1638
|
})
|
|
1516
1639
|
|
|
1517
1640
|
return { hasErrored, fieldsErrorMap: currentValidationErrorMap }
|
|
@@ -1534,7 +1657,11 @@ export class FormApi<
|
|
|
1534
1657
|
TOnSubmitAsync
|
|
1535
1658
|
>
|
|
1536
1659
|
> => {
|
|
1537
|
-
const validates = getAsyncValidatorArray(cause,
|
|
1660
|
+
const validates = getAsyncValidatorArray(cause, {
|
|
1661
|
+
...this.options,
|
|
1662
|
+
form: this,
|
|
1663
|
+
validationLogic: this.options.validationLogic || defaultValidationLogic,
|
|
1664
|
+
})
|
|
1538
1665
|
|
|
1539
1666
|
if (!this.state.isFormValidating) {
|
|
1540
1667
|
this.baseStore.setState((prev) => ({ ...prev, isFormValidating: true }))
|
|
@@ -1878,6 +2005,7 @@ export class FormApi<
|
|
|
1878
2005
|
onSubmit: undefined,
|
|
1879
2006
|
onMount: undefined,
|
|
1880
2007
|
onServer: undefined,
|
|
2008
|
+
onDynamic: undefined,
|
|
1881
2009
|
},
|
|
1882
2010
|
})
|
|
1883
2011
|
}
|
|
@@ -2198,6 +2326,8 @@ export class FormApi<
|
|
|
2198
2326
|
UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,
|
|
2199
2327
|
UnwrapFormValidateOrFn<TOnSubmit>,
|
|
2200
2328
|
UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,
|
|
2329
|
+
UnwrapFormValidateOrFn<TOnDynamic>,
|
|
2330
|
+
UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>,
|
|
2201
2331
|
UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
2202
2332
|
>,
|
|
2203
2333
|
) {
|
|
@@ -2260,6 +2390,8 @@ export class FormApi<
|
|
|
2260
2390
|
| UnwrapFormAsyncValidateOrFn<TOnBlurAsync>
|
|
2261
2391
|
| UnwrapFormValidateOrFn<TOnSubmit>
|
|
2262
2392
|
| UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>
|
|
2393
|
+
| UnwrapFormValidateOrFn<TOnDynamic>
|
|
2394
|
+
| UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>
|
|
2263
2395
|
| UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
2264
2396
|
>
|
|
2265
2397
|
errorMap: ValidationErrorMap<
|
|
@@ -2270,6 +2402,8 @@ export class FormApi<
|
|
|
2270
2402
|
UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,
|
|
2271
2403
|
UnwrapFormValidateOrFn<TOnSubmit>,
|
|
2272
2404
|
UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,
|
|
2405
|
+
UnwrapFormValidateOrFn<TOnDynamic>,
|
|
2406
|
+
UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>,
|
|
2273
2407
|
UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
2274
2408
|
>
|
|
2275
2409
|
}
|
|
@@ -2359,6 +2493,8 @@ function getErrorMapKey(cause: ValidationCause) {
|
|
|
2359
2493
|
return 'onMount'
|
|
2360
2494
|
case 'server':
|
|
2361
2495
|
return 'onServer'
|
|
2496
|
+
case 'dynamic':
|
|
2497
|
+
return 'onDynamic'
|
|
2362
2498
|
case 'change':
|
|
2363
2499
|
default:
|
|
2364
2500
|
return 'onChange'
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import type { AnyFormApi, FormValidators } from './FormApi'
|
|
2
|
+
|
|
3
|
+
interface ValidationLogicValidatorsFn {
|
|
4
|
+
// TODO: Type this properly
|
|
5
|
+
fn: FormValidators<
|
|
6
|
+
any,
|
|
7
|
+
any,
|
|
8
|
+
any,
|
|
9
|
+
any,
|
|
10
|
+
any,
|
|
11
|
+
any,
|
|
12
|
+
any,
|
|
13
|
+
any,
|
|
14
|
+
any,
|
|
15
|
+
any
|
|
16
|
+
>[keyof FormValidators<any, any, any, any, any, any, any, any, any, any>]
|
|
17
|
+
cause: 'change' | 'blur' | 'submit' | 'mount' | 'server' | 'dynamic'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ValidationLogicProps {
|
|
21
|
+
// TODO: Type this properly
|
|
22
|
+
form: AnyFormApi
|
|
23
|
+
// TODO: Type this properly
|
|
24
|
+
validators:
|
|
25
|
+
| FormValidators<any, any, any, any, any, any, any, any, any, any>
|
|
26
|
+
| undefined
|
|
27
|
+
| null
|
|
28
|
+
event: {
|
|
29
|
+
type: 'blur' | 'change' | 'submit' | 'mount' | 'server'
|
|
30
|
+
fieldName?: string
|
|
31
|
+
async: boolean
|
|
32
|
+
}
|
|
33
|
+
runValidation: (props: {
|
|
34
|
+
validators: Array<ValidationLogicValidatorsFn | undefined>
|
|
35
|
+
form: AnyFormApi
|
|
36
|
+
}) => void
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface RevalidateLogicProps {
|
|
40
|
+
/**
|
|
41
|
+
* @default 'submit'
|
|
42
|
+
*
|
|
43
|
+
* This is the mode that will be used before the form has been submitted.
|
|
44
|
+
* It will run the validation logic on `submit` by default, but can be set to `change` or `blur`.
|
|
45
|
+
*/
|
|
46
|
+
mode?: 'change' | 'blur' | 'submit'
|
|
47
|
+
/**
|
|
48
|
+
* @default 'change'
|
|
49
|
+
*
|
|
50
|
+
* This is the mode that will be used after the form has been submitted.
|
|
51
|
+
* It will run the validation logic on `change` by default, but can be set to `blur` or `submit`.
|
|
52
|
+
*/
|
|
53
|
+
modeAfterSubmission?: 'change' | 'blur' | 'submit'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type ValidationLogicFn = (props: ValidationLogicProps) => void
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* This forces a form's validation logic to be ran as if it were a React Hook Form validation logic.
|
|
60
|
+
*
|
|
61
|
+
* This means that it will only run the `onDynamic` validator, and it will not run any other validators and changes the validation
|
|
62
|
+
* type based on the state of the form itself.
|
|
63
|
+
*
|
|
64
|
+
* When the form is not yet submitted, it will not run the validation logic.
|
|
65
|
+
* When the form is submitted, it will run the validation logic on `change`
|
|
66
|
+
*/
|
|
67
|
+
export const revalidateLogic =
|
|
68
|
+
({
|
|
69
|
+
mode = 'submit',
|
|
70
|
+
modeAfterSubmission = 'change',
|
|
71
|
+
}: RevalidateLogicProps = {}): ValidationLogicFn =>
|
|
72
|
+
(props) => {
|
|
73
|
+
const validatorNames = Object.keys(props.validators ?? {})
|
|
74
|
+
if (validatorNames.length === 0) {
|
|
75
|
+
// No validators is a valid case, just return
|
|
76
|
+
return props.runValidation({
|
|
77
|
+
validators: [],
|
|
78
|
+
form: props.form,
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const dynamicValidator = {
|
|
83
|
+
fn: props.event.async
|
|
84
|
+
? props.validators!['onDynamicAsync']
|
|
85
|
+
: props.validators!['onDynamic'],
|
|
86
|
+
cause: 'dynamic',
|
|
87
|
+
} as const
|
|
88
|
+
|
|
89
|
+
const validatorsToAdd = [] as ValidationLogicValidatorsFn[]
|
|
90
|
+
|
|
91
|
+
const modeToWatch =
|
|
92
|
+
props.form.state.submissionAttempts === 0 ? mode : modeAfterSubmission
|
|
93
|
+
|
|
94
|
+
if ([modeToWatch, 'submit'].includes(props.event.type)) {
|
|
95
|
+
validatorsToAdd.push(dynamicValidator)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let defaultValidators = [] as ValidationLogicValidatorsFn[]
|
|
99
|
+
|
|
100
|
+
defaultValidationLogic({
|
|
101
|
+
...props,
|
|
102
|
+
runValidation: (vProps) => {
|
|
103
|
+
defaultValidators = vProps.validators as ValidationLogicValidatorsFn[]
|
|
104
|
+
},
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if (validatorsToAdd.length === 0) {
|
|
108
|
+
return props.runValidation({
|
|
109
|
+
validators: defaultValidators,
|
|
110
|
+
form: props.form,
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return props.runValidation({
|
|
115
|
+
validators: [...defaultValidators, ...validatorsToAdd],
|
|
116
|
+
form: props.form,
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const defaultValidationLogic: ValidationLogicFn = (props) => {
|
|
121
|
+
// Handle case where no validators are provided
|
|
122
|
+
if (!props.validators) {
|
|
123
|
+
return props.runValidation({
|
|
124
|
+
validators: [],
|
|
125
|
+
form: props.form,
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const isAsync = props.event.async
|
|
130
|
+
|
|
131
|
+
const onMountValidator = isAsync
|
|
132
|
+
? undefined
|
|
133
|
+
: ({ fn: props.validators.onMount, cause: 'mount' } as const)
|
|
134
|
+
|
|
135
|
+
const onChangeValidator = {
|
|
136
|
+
fn: isAsync ? props.validators.onChangeAsync : props.validators.onChange,
|
|
137
|
+
cause: 'change',
|
|
138
|
+
} as const
|
|
139
|
+
|
|
140
|
+
const onBlurValidator = {
|
|
141
|
+
fn: isAsync ? props.validators.onBlurAsync : props.validators.onBlur,
|
|
142
|
+
cause: 'blur',
|
|
143
|
+
} as const
|
|
144
|
+
|
|
145
|
+
const onSubmitValidator = {
|
|
146
|
+
fn: isAsync ? props.validators.onSubmitAsync : props.validators.onSubmit,
|
|
147
|
+
cause: 'submit',
|
|
148
|
+
} as const
|
|
149
|
+
|
|
150
|
+
// Allows us to clear onServer errors
|
|
151
|
+
const onServerValidator = isAsync
|
|
152
|
+
? undefined
|
|
153
|
+
: ({ fn: () => undefined, cause: 'server' } as const)
|
|
154
|
+
|
|
155
|
+
switch (props.event.type) {
|
|
156
|
+
case 'mount': {
|
|
157
|
+
// Run mount validation
|
|
158
|
+
return props.runValidation({
|
|
159
|
+
validators: [onMountValidator],
|
|
160
|
+
form: props.form,
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
case 'submit': {
|
|
164
|
+
// Run change, blur, submit, server validation
|
|
165
|
+
return props.runValidation({
|
|
166
|
+
validators: [
|
|
167
|
+
onChangeValidator,
|
|
168
|
+
onBlurValidator,
|
|
169
|
+
onSubmitValidator,
|
|
170
|
+
onServerValidator,
|
|
171
|
+
],
|
|
172
|
+
form: props.form,
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
case 'server': {
|
|
176
|
+
// Run server validation
|
|
177
|
+
return props.runValidation({
|
|
178
|
+
validators: [],
|
|
179
|
+
form: props.form,
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
case 'blur': {
|
|
183
|
+
// Run blur, server validation
|
|
184
|
+
return props.runValidation({
|
|
185
|
+
validators: [onBlurValidator, onServerValidator],
|
|
186
|
+
form: props.form,
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
case 'change': {
|
|
190
|
+
// Run change, server validation
|
|
191
|
+
return props.runValidation({
|
|
192
|
+
validators: [onChangeValidator, onServerValidator],
|
|
193
|
+
form: props.form,
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
default: {
|
|
197
|
+
throw new Error(`Unknown validation event type: ${props.event.type}`)
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
package/src/formOptions.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { FormOptions } from './FormApi'
|
|
|
2
2
|
|
|
3
3
|
export function formOptions<
|
|
4
4
|
T extends Partial<
|
|
5
|
-
FormOptions<any, any, any, any, any, any, any, any, any, any>
|
|
5
|
+
FormOptions<any, any, any, any, any, any, any, any, any, any, any, any>
|
|
6
6
|
>,
|
|
7
7
|
>(defaultOpts: T) {
|
|
8
8
|
return defaultOpts
|
package/src/index.ts
CHANGED