@tanstack/form-core 1.16.0 → 1.17.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 +79 -69
- package/dist/cjs/FormApi.cjs.map +1 -1
- package/dist/cjs/FormApi.d.cts +40 -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/standardSchemaValidator.cjs.map +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 +40 -35
- package/dist/esm/FormApi.js +79 -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/standardSchemaValidator.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 +131 -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,6 +371,8 @@ 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> {
|
|
@@ -360,6 +389,8 @@ export interface FormOptions<
|
|
|
360
389
|
TOnBlurAsync,
|
|
361
390
|
TOnSubmit,
|
|
362
391
|
TOnSubmitAsync,
|
|
392
|
+
TOnDynamic,
|
|
393
|
+
TOnDynamicAsync,
|
|
363
394
|
TOnServer
|
|
364
395
|
>
|
|
365
396
|
>
|
|
@@ -386,9 +417,13 @@ export interface FormOptions<
|
|
|
386
417
|
TOnBlur,
|
|
387
418
|
TOnBlurAsync,
|
|
388
419
|
TOnSubmit,
|
|
389
|
-
TOnSubmitAsync
|
|
420
|
+
TOnSubmitAsync,
|
|
421
|
+
TOnDynamic,
|
|
422
|
+
TOnDynamicAsync
|
|
390
423
|
>
|
|
391
424
|
|
|
425
|
+
validationLogic?: ValidationLogicFn
|
|
426
|
+
|
|
392
427
|
/**
|
|
393
428
|
* form level listeners
|
|
394
429
|
*/
|
|
@@ -401,6 +436,8 @@ export interface FormOptions<
|
|
|
401
436
|
TOnBlurAsync,
|
|
402
437
|
TOnSubmit,
|
|
403
438
|
TOnSubmitAsync,
|
|
439
|
+
TOnDynamic,
|
|
440
|
+
TOnDynamicAsync,
|
|
404
441
|
TOnServer,
|
|
405
442
|
TSubmitMeta
|
|
406
443
|
>
|
|
@@ -419,6 +456,8 @@ export interface FormOptions<
|
|
|
419
456
|
TOnBlurAsync,
|
|
420
457
|
TOnSubmit,
|
|
421
458
|
TOnSubmitAsync,
|
|
459
|
+
TOnDynamic,
|
|
460
|
+
TOnDynamicAsync,
|
|
422
461
|
TOnServer,
|
|
423
462
|
TSubmitMeta
|
|
424
463
|
>
|
|
@@ -438,6 +477,8 @@ export interface FormOptions<
|
|
|
438
477
|
TOnBlurAsync,
|
|
439
478
|
TOnSubmit,
|
|
440
479
|
TOnSubmitAsync,
|
|
480
|
+
TOnDynamic,
|
|
481
|
+
TOnDynamicAsync,
|
|
441
482
|
TOnServer,
|
|
442
483
|
TSubmitMeta
|
|
443
484
|
>
|
|
@@ -452,6 +493,8 @@ export interface FormOptions<
|
|
|
452
493
|
NoInfer<TOnBlurAsync>,
|
|
453
494
|
NoInfer<TOnSubmit>,
|
|
454
495
|
NoInfer<TOnSubmitAsync>,
|
|
496
|
+
NoInfer<TOnDynamic>,
|
|
497
|
+
NoInfer<TOnDynamicAsync>,
|
|
455
498
|
NoInfer<TOnServer>,
|
|
456
499
|
NoInfer<TSubmitMeta>
|
|
457
500
|
>
|
|
@@ -493,6 +536,10 @@ export type FieldInfo<TFormData> = {
|
|
|
493
536
|
any,
|
|
494
537
|
any,
|
|
495
538
|
any,
|
|
539
|
+
any,
|
|
540
|
+
any,
|
|
541
|
+
any,
|
|
542
|
+
any,
|
|
496
543
|
any
|
|
497
544
|
> | null
|
|
498
545
|
/**
|
|
@@ -513,6 +560,8 @@ export type BaseFormState<
|
|
|
513
560
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
514
561
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
515
562
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
563
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
564
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
516
565
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
517
566
|
> = {
|
|
518
567
|
/**
|
|
@@ -530,6 +579,8 @@ export type BaseFormState<
|
|
|
530
579
|
UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,
|
|
531
580
|
UnwrapFormValidateOrFn<TOnSubmit>,
|
|
532
581
|
UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,
|
|
582
|
+
UnwrapFormValidateOrFn<TOnDynamic>,
|
|
583
|
+
UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>,
|
|
533
584
|
UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
534
585
|
>
|
|
535
586
|
/**
|
|
@@ -588,6 +639,8 @@ export type DerivedFormState<
|
|
|
588
639
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
589
640
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
590
641
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
642
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
643
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
591
644
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
592
645
|
> = {
|
|
593
646
|
/**
|
|
@@ -609,6 +662,8 @@ export type DerivedFormState<
|
|
|
609
662
|
| UnwrapFormAsyncValidateOrFn<TOnBlurAsync>
|
|
610
663
|
| UnwrapFormValidateOrFn<TOnSubmit>
|
|
611
664
|
| UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>
|
|
665
|
+
| UnwrapFormValidateOrFn<TOnDynamic>
|
|
666
|
+
| UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>
|
|
612
667
|
| UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
613
668
|
>
|
|
614
669
|
/**
|
|
@@ -662,6 +717,8 @@ export interface FormState<
|
|
|
662
717
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
663
718
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
664
719
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
720
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
721
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
665
722
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
666
723
|
> extends BaseFormState<
|
|
667
724
|
TFormData,
|
|
@@ -672,6 +729,8 @@ export interface FormState<
|
|
|
672
729
|
TOnBlurAsync,
|
|
673
730
|
TOnSubmit,
|
|
674
731
|
TOnSubmitAsync,
|
|
732
|
+
TOnDynamic,
|
|
733
|
+
TOnDynamicAsync,
|
|
675
734
|
TOnServer
|
|
676
735
|
>,
|
|
677
736
|
DerivedFormState<
|
|
@@ -683,6 +742,8 @@ export interface FormState<
|
|
|
683
742
|
TOnBlurAsync,
|
|
684
743
|
TOnSubmit,
|
|
685
744
|
TOnSubmitAsync,
|
|
745
|
+
TOnDynamic,
|
|
746
|
+
TOnDynamicAsync,
|
|
686
747
|
TOnServer
|
|
687
748
|
> {}
|
|
688
749
|
|
|
@@ -695,6 +756,8 @@ export type AnyFormState = FormState<
|
|
|
695
756
|
any,
|
|
696
757
|
any,
|
|
697
758
|
any,
|
|
759
|
+
any,
|
|
760
|
+
any,
|
|
698
761
|
any
|
|
699
762
|
>
|
|
700
763
|
|
|
@@ -707,6 +770,8 @@ function getDefaultFormState<
|
|
|
707
770
|
TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
708
771
|
TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
709
772
|
TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
773
|
+
TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
774
|
+
TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
710
775
|
TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
711
776
|
>(
|
|
712
777
|
defaultState: Partial<
|
|
@@ -719,6 +784,8 @@ function getDefaultFormState<
|
|
|
719
784
|
TOnBlurAsync,
|
|
720
785
|
TOnSubmit,
|
|
721
786
|
TOnSubmitAsync,
|
|
787
|
+
TOnDynamic,
|
|
788
|
+
TOnDynamicAsync,
|
|
722
789
|
TOnServer
|
|
723
790
|
>
|
|
724
791
|
>,
|
|
@@ -731,6 +798,8 @@ function getDefaultFormState<
|
|
|
731
798
|
TOnBlurAsync,
|
|
732
799
|
TOnSubmit,
|
|
733
800
|
TOnSubmitAsync,
|
|
801
|
+
TOnDynamic,
|
|
802
|
+
TOnDynamicAsync,
|
|
734
803
|
TOnServer
|
|
735
804
|
> {
|
|
736
805
|
return {
|
|
@@ -748,6 +817,7 @@ function getDefaultFormState<
|
|
|
748
817
|
onSubmit: undefined,
|
|
749
818
|
onMount: undefined,
|
|
750
819
|
onServer: undefined,
|
|
820
|
+
onDynamic: undefined,
|
|
751
821
|
},
|
|
752
822
|
}
|
|
753
823
|
}
|
|
@@ -767,6 +837,8 @@ export type AnyFormApi = FormApi<
|
|
|
767
837
|
any,
|
|
768
838
|
any,
|
|
769
839
|
any,
|
|
840
|
+
any,
|
|
841
|
+
any,
|
|
770
842
|
any
|
|
771
843
|
>
|
|
772
844
|
|
|
@@ -786,6 +858,8 @@ export class FormApi<
|
|
|
786
858
|
in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
787
859
|
in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
|
|
788
860
|
in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
861
|
+
in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
|
|
862
|
+
in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
789
863
|
in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
|
|
790
864
|
in out TSubmitMeta = never,
|
|
791
865
|
> implements FieldManipulator<TFormData, TSubmitMeta>
|
|
@@ -802,6 +876,8 @@ export class FormApi<
|
|
|
802
876
|
TOnBlurAsync,
|
|
803
877
|
TOnSubmit,
|
|
804
878
|
TOnSubmitAsync,
|
|
879
|
+
TOnDynamic,
|
|
880
|
+
TOnDynamicAsync,
|
|
805
881
|
TOnServer,
|
|
806
882
|
TSubmitMeta
|
|
807
883
|
> = {}
|
|
@@ -815,6 +891,8 @@ export class FormApi<
|
|
|
815
891
|
TOnBlurAsync,
|
|
816
892
|
TOnSubmit,
|
|
817
893
|
TOnSubmitAsync,
|
|
894
|
+
TOnDynamic,
|
|
895
|
+
TOnDynamicAsync,
|
|
818
896
|
TOnServer
|
|
819
897
|
>
|
|
820
898
|
>
|
|
@@ -829,6 +907,8 @@ export class FormApi<
|
|
|
829
907
|
TOnBlurAsync,
|
|
830
908
|
TOnSubmit,
|
|
831
909
|
TOnSubmitAsync,
|
|
910
|
+
TOnDynamic,
|
|
911
|
+
TOnDynamicAsync,
|
|
832
912
|
TOnServer
|
|
833
913
|
>
|
|
834
914
|
>
|
|
@@ -859,6 +939,8 @@ export class FormApi<
|
|
|
859
939
|
TOnBlurAsync,
|
|
860
940
|
TOnSubmit,
|
|
861
941
|
TOnSubmitAsync,
|
|
942
|
+
TOnDynamic,
|
|
943
|
+
TOnDynamicAsync,
|
|
862
944
|
TOnServer,
|
|
863
945
|
TSubmitMeta
|
|
864
946
|
>,
|
|
@@ -891,6 +973,8 @@ export class FormApi<
|
|
|
891
973
|
TOnBlurAsync,
|
|
892
974
|
TOnSubmit,
|
|
893
975
|
TOnSubmitAsync,
|
|
976
|
+
TOnDynamic,
|
|
977
|
+
TOnDynamicAsync,
|
|
894
978
|
TOnServer
|
|
895
979
|
>['fieldMeta']
|
|
896
980
|
|
|
@@ -992,6 +1076,8 @@ export class FormApi<
|
|
|
992
1076
|
TOnBlurAsync,
|
|
993
1077
|
TOnSubmit,
|
|
994
1078
|
TOnSubmitAsync,
|
|
1079
|
+
TOnDynamic,
|
|
1080
|
+
TOnDynamicAsync,
|
|
995
1081
|
TOnServer
|
|
996
1082
|
>
|
|
997
1083
|
| undefined
|
|
@@ -1124,6 +1210,8 @@ export class FormApi<
|
|
|
1124
1210
|
TOnBlurAsync,
|
|
1125
1211
|
TOnSubmit,
|
|
1126
1212
|
TOnSubmitAsync,
|
|
1213
|
+
TOnDynamic,
|
|
1214
|
+
TOnDynamicAsync,
|
|
1127
1215
|
TOnServer
|
|
1128
1216
|
>
|
|
1129
1217
|
|
|
@@ -1205,6 +1293,8 @@ export class FormApi<
|
|
|
1205
1293
|
TOnBlurAsync,
|
|
1206
1294
|
TOnSubmit,
|
|
1207
1295
|
TOnSubmitAsync,
|
|
1296
|
+
TOnDynamic,
|
|
1297
|
+
TOnDynamicAsync,
|
|
1208
1298
|
TOnServer,
|
|
1209
1299
|
TSubmitMeta
|
|
1210
1300
|
>,
|
|
@@ -1396,7 +1486,12 @@ export class FormApi<
|
|
|
1396
1486
|
TOnSubmitAsync
|
|
1397
1487
|
>
|
|
1398
1488
|
} => {
|
|
1399
|
-
const validates = getSyncValidatorArray(cause,
|
|
1489
|
+
const validates = getSyncValidatorArray(cause, {
|
|
1490
|
+
...this.options,
|
|
1491
|
+
form: this,
|
|
1492
|
+
validationLogic: this.options.validationLogic || defaultValidationLogic,
|
|
1493
|
+
})
|
|
1494
|
+
|
|
1400
1495
|
let hasErrored = false as boolean
|
|
1401
1496
|
|
|
1402
1497
|
// This map will only include fields that have errors in the current validation cycle
|
|
@@ -1512,6 +1607,26 @@ export class FormApi<
|
|
|
1512
1607
|
},
|
|
1513
1608
|
}))
|
|
1514
1609
|
}
|
|
1610
|
+
|
|
1611
|
+
/**
|
|
1612
|
+
* when we have an error for onServer in the state, we want
|
|
1613
|
+
* to clear the error as soon as the user enters a valid value in the field
|
|
1614
|
+
*/
|
|
1615
|
+
const serverErrKey = getErrorMapKey('server')
|
|
1616
|
+
if (
|
|
1617
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1618
|
+
this.state.errorMap?.[serverErrKey] &&
|
|
1619
|
+
cause !== 'server' &&
|
|
1620
|
+
!hasErrored
|
|
1621
|
+
) {
|
|
1622
|
+
this.baseStore.setState((prev) => ({
|
|
1623
|
+
...prev,
|
|
1624
|
+
errorMap: {
|
|
1625
|
+
...prev.errorMap,
|
|
1626
|
+
[serverErrKey]: undefined,
|
|
1627
|
+
},
|
|
1628
|
+
}))
|
|
1629
|
+
}
|
|
1515
1630
|
})
|
|
1516
1631
|
|
|
1517
1632
|
return { hasErrored, fieldsErrorMap: currentValidationErrorMap }
|
|
@@ -1534,7 +1649,11 @@ export class FormApi<
|
|
|
1534
1649
|
TOnSubmitAsync
|
|
1535
1650
|
>
|
|
1536
1651
|
> => {
|
|
1537
|
-
const validates = getAsyncValidatorArray(cause,
|
|
1652
|
+
const validates = getAsyncValidatorArray(cause, {
|
|
1653
|
+
...this.options,
|
|
1654
|
+
form: this,
|
|
1655
|
+
validationLogic: this.options.validationLogic || defaultValidationLogic,
|
|
1656
|
+
})
|
|
1538
1657
|
|
|
1539
1658
|
if (!this.state.isFormValidating) {
|
|
1540
1659
|
this.baseStore.setState((prev) => ({ ...prev, isFormValidating: true }))
|
|
@@ -1878,6 +1997,7 @@ export class FormApi<
|
|
|
1878
1997
|
onSubmit: undefined,
|
|
1879
1998
|
onMount: undefined,
|
|
1880
1999
|
onServer: undefined,
|
|
2000
|
+
onDynamic: undefined,
|
|
1881
2001
|
},
|
|
1882
2002
|
})
|
|
1883
2003
|
}
|
|
@@ -2198,6 +2318,8 @@ export class FormApi<
|
|
|
2198
2318
|
UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,
|
|
2199
2319
|
UnwrapFormValidateOrFn<TOnSubmit>,
|
|
2200
2320
|
UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,
|
|
2321
|
+
UnwrapFormValidateOrFn<TOnDynamic>,
|
|
2322
|
+
UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>,
|
|
2201
2323
|
UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
2202
2324
|
>,
|
|
2203
2325
|
) {
|
|
@@ -2260,6 +2382,8 @@ export class FormApi<
|
|
|
2260
2382
|
| UnwrapFormAsyncValidateOrFn<TOnBlurAsync>
|
|
2261
2383
|
| UnwrapFormValidateOrFn<TOnSubmit>
|
|
2262
2384
|
| UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>
|
|
2385
|
+
| UnwrapFormValidateOrFn<TOnDynamic>
|
|
2386
|
+
| UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>
|
|
2263
2387
|
| UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
2264
2388
|
>
|
|
2265
2389
|
errorMap: ValidationErrorMap<
|
|
@@ -2270,6 +2394,8 @@ export class FormApi<
|
|
|
2270
2394
|
UnwrapFormAsyncValidateOrFn<TOnBlurAsync>,
|
|
2271
2395
|
UnwrapFormValidateOrFn<TOnSubmit>,
|
|
2272
2396
|
UnwrapFormAsyncValidateOrFn<TOnSubmitAsync>,
|
|
2397
|
+
UnwrapFormValidateOrFn<TOnDynamic>,
|
|
2398
|
+
UnwrapFormAsyncValidateOrFn<TOnDynamicAsync>,
|
|
2273
2399
|
UnwrapFormAsyncValidateOrFn<TOnServer>
|
|
2274
2400
|
>
|
|
2275
2401
|
}
|
|
@@ -2359,6 +2485,8 @@ function getErrorMapKey(cause: ValidationCause) {
|
|
|
2359
2485
|
return 'onMount'
|
|
2360
2486
|
case 'server':
|
|
2361
2487
|
return 'onServer'
|
|
2488
|
+
case 'dynamic':
|
|
2489
|
+
return 'onDynamic'
|
|
2362
2490
|
case 'change':
|
|
2363
2491
|
default:
|
|
2364
2492
|
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