@tanstack/form-core 0.44.0 → 0.45.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/form-core",
3
- "version": "0.44.0",
3
+ "version": "0.45.0",
4
4
  "description": "Powerful, type-safe, framework agnostic forms.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
package/src/FieldApi.ts CHANGED
@@ -19,9 +19,9 @@ import type {
19
19
  FieldInfo,
20
20
  FormApi,
21
21
  FormAsyncValidateOrFn,
22
+ FormValidateAsyncFn,
23
+ FormValidateFn,
22
24
  FormValidateOrFn,
23
- UnwrapFormAsyncValidateOrFn,
24
- UnwrapFormValidateOrFn,
25
25
  } from './FormApi'
26
26
  import type {
27
27
  UpdateMetaOptions,
@@ -96,6 +96,7 @@ export type FieldValidateFn<
96
96
  any,
97
97
  any,
98
98
  any,
99
+ any,
99
100
  any
100
101
  >
101
102
  }) => unknown
@@ -111,6 +112,16 @@ export type FieldValidateOrFn<
111
112
  | FieldValidateFn<TParentData, TName, TData>
112
113
  | StandardSchemaV1<TData, unknown>
113
114
 
115
+ type StandardBrandedSchemaV1<T> = T & { __standardSchemaV1: true }
116
+
117
+ type UnwrapFormValidateOrFnForInner<
118
+ TValidateOrFn extends undefined | FormValidateOrFn<any>,
119
+ > = [TValidateOrFn] extends [FormValidateFn<any>]
120
+ ? ReturnType<TValidateOrFn>
121
+ : [TValidateOrFn] extends [StandardSchemaV1<infer TOut, any>]
122
+ ? StandardBrandedSchemaV1<TOut>
123
+ : undefined
124
+
114
125
  export type UnwrapFieldValidateOrFn<
115
126
  TParentData,
116
127
  TName extends DeepKeys<TParentData>,
@@ -122,12 +133,16 @@ export type UnwrapFieldValidateOrFn<
122
133
  ? StandardSchemaV1Issue[]
123
134
  : undefined
124
135
  : undefined)
125
- | (UnwrapFormValidateOrFn<TFormValidateOrFn> extends infer TFormValidateVal
126
- ? TFormValidateVal extends { fields: any }
127
- ? TName extends keyof TFormValidateVal['fields']
128
- ? TFormValidateVal['fields'][TName]
136
+ | (UnwrapFormValidateOrFnForInner<TFormValidateOrFn> extends infer TFormValidateVal
137
+ ? TFormValidateVal extends { __standardSchemaV1: true }
138
+ ? [DeepValue<TFormValidateVal, TName>] extends [never]
139
+ ? undefined
140
+ : StandardSchemaV1Issue[]
141
+ : TFormValidateVal extends { fields: any }
142
+ ? TName extends keyof TFormValidateVal['fields']
143
+ ? TFormValidateVal['fields'][TName]
144
+ : undefined
129
145
  : undefined
130
- : undefined
131
146
  : never)
132
147
  | ([TValidateOrFn] extends [FieldValidateFn<any, any, any>]
133
148
  ? ReturnType<TValidateOrFn>
@@ -165,6 +180,7 @@ export type FieldValidateAsyncFn<
165
180
  any,
166
181
  any,
167
182
  any,
183
+ any,
168
184
  any
169
185
  >
170
186
  signal: AbortSignal
@@ -181,6 +197,14 @@ export type FieldAsyncValidateOrFn<
181
197
  | FieldValidateAsyncFn<TParentData, TName, TData>
182
198
  | StandardSchemaV1<TData, unknown>
183
199
 
200
+ type UnwrapFormAsyncValidateOrFnForInner<
201
+ TValidateOrFn extends undefined | FormAsyncValidateOrFn<any>,
202
+ > = [TValidateOrFn] extends [FormValidateAsyncFn<any>]
203
+ ? Awaited<ReturnType<TValidateOrFn>>
204
+ : [TValidateOrFn] extends [StandardSchemaV1<infer TOut, any>]
205
+ ? StandardBrandedSchemaV1<TOut>
206
+ : undefined
207
+
184
208
  export type UnwrapFieldAsyncValidateOrFn<
185
209
  TParentData,
186
210
  TName extends DeepKeys<TParentData>,
@@ -192,12 +216,16 @@ export type UnwrapFieldAsyncValidateOrFn<
192
216
  ? StandardSchemaV1Issue[]
193
217
  : undefined
194
218
  : undefined)
195
- | (UnwrapFormAsyncValidateOrFn<TFormValidateOrFn> extends infer TFormValidateVal
196
- ? TFormValidateVal extends { fields: any }
197
- ? TName extends keyof TFormValidateVal['fields']
198
- ? TFormValidateVal['fields'][TName]
219
+ | (UnwrapFormAsyncValidateOrFnForInner<TFormValidateOrFn> extends infer TFormValidateVal
220
+ ? TFormValidateVal extends { __standardSchemaV1: true }
221
+ ? [DeepValue<TFormValidateVal, TName>] extends [never]
222
+ ? undefined
223
+ : StandardSchemaV1Issue[]
224
+ : TFormValidateVal extends { fields: any }
225
+ ? TName extends keyof TFormValidateVal['fields']
226
+ ? TFormValidateVal['fields'][TName]
227
+ : undefined
199
228
  : undefined
200
- : undefined
201
229
  : never)
202
230
  | ([TValidateOrFn] extends [FieldValidateAsyncFn<any, any, any>]
203
231
  ? Awaited<ReturnType<TValidateOrFn>>
@@ -235,6 +263,7 @@ export type FieldListenerFn<
235
263
  any,
236
264
  any,
237
265
  any,
266
+ any,
238
267
  any
239
268
  >
240
269
  }) => void
@@ -445,6 +474,7 @@ export interface FieldApiOptions<
445
474
  TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,
446
475
  TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,
447
476
  TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,
477
+ TParentSubmitMeta,
448
478
  > extends FieldOptions<
449
479
  TParentData,
450
480
  TName,
@@ -466,7 +496,8 @@ export interface FieldApiOptions<
466
496
  TFormOnBlurAsync,
467
497
  TFormOnSubmit,
468
498
  TFormOnSubmitAsync,
469
- TFormOnServer
499
+ TFormOnServer,
500
+ TParentSubmitMeta
470
501
  >
471
502
  }
472
503
 
@@ -817,6 +848,7 @@ export type AnyFieldApi = FieldApi<
817
848
  any,
818
849
  any,
819
850
  any,
851
+ any,
820
852
  any
821
853
  >
822
854
 
@@ -854,6 +886,7 @@ export class FieldApi<
854
886
  TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,
855
887
  TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,
856
888
  TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,
889
+ TParentSubmitMeta,
857
890
  > {
858
891
  /**
859
892
  * A reference to the form API instance.
@@ -876,7 +909,8 @@ export class FieldApi<
876
909
  TFormOnBlurAsync,
877
910
  TFormOnSubmit,
878
911
  TFormOnSubmitAsync,
879
- TFormOnServer
912
+ TFormOnServer,
913
+ TParentSubmitMeta
880
914
  >['form']
881
915
  /**
882
916
  * The field name.
@@ -903,7 +937,8 @@ export class FieldApi<
903
937
  TFormOnBlurAsync,
904
938
  TFormOnSubmit,
905
939
  TFormOnSubmitAsync,
906
- TFormOnServer
940
+ TFormOnServer,
941
+ TParentSubmitMeta
907
942
  > = {} as any
908
943
  /**
909
944
  * The field state store.
@@ -959,7 +994,8 @@ export class FieldApi<
959
994
  TFormOnBlurAsync,
960
995
  TFormOnSubmit,
961
996
  TFormOnSubmitAsync,
962
- TFormOnServer
997
+ TFormOnServer,
998
+ TParentSubmitMeta
963
999
  >,
964
1000
  ) {
965
1001
  this.form = opts.form as never
@@ -1104,7 +1140,8 @@ export class FieldApi<
1104
1140
  TFormOnBlurAsync,
1105
1141
  TFormOnSubmit,
1106
1142
  TFormOnSubmitAsync,
1107
- TFormOnServer
1143
+ TFormOnServer,
1144
+ TParentSubmitMeta
1108
1145
  >,
1109
1146
  ) => {
1110
1147
  // Default Value
@@ -0,0 +1,31 @@
1
+ import { assertType, it } from 'vitest'
2
+ import { FormApi } from '../src/index'
3
+
4
+ it('should type handleSubmit as never when onSubmitMeta is not passed', () => {
5
+ const form = new FormApi({
6
+ defaultValues: {
7
+ name: 'test',
8
+ },
9
+ } as const)
10
+
11
+ assertType<() => Promise<void>>(form.handleSubmit)
12
+ })
13
+
14
+ type OnSubmitMeta = {
15
+ group: string
16
+ }
17
+
18
+ it('should type handleChange correctly', () => {
19
+ const form = new FormApi({
20
+ defaultValues: {
21
+ name: 'test',
22
+ },
23
+ onSubmitMeta: {} as OnSubmitMeta,
24
+ } as const)
25
+
26
+ form.handleSubmit({ group: 'track' })
27
+
28
+ assertType<(submitMeta: { group: string }) => Promise<void>>(
29
+ form.handleSubmit,
30
+ )
31
+ })
package/src/FormApi.ts CHANGED
@@ -74,6 +74,7 @@ export type FormValidateFn<TFormData> = (props: {
74
74
  any,
75
75
  any,
76
76
  any,
77
+ any,
77
78
  any
78
79
  >
79
80
  }) => unknown
@@ -109,6 +110,7 @@ export type FormValidateAsyncFn<TFormData> = (props: {
109
110
  any,
110
111
  any,
111
112
  any,
113
+ any,
112
114
  any
113
115
  >
114
116
  signal: AbortSignal
@@ -199,6 +201,7 @@ export interface FormTransform<
199
201
  TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
200
202
  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
201
203
  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
204
+ TSubmitMeta = never,
202
205
  > {
203
206
  fn: (
204
207
  formBase: FormApi<
@@ -210,7 +213,8 @@ export interface FormTransform<
210
213
  TOnBlurAsync,
211
214
  TOnSubmit,
212
215
  TOnSubmitAsync,
213
- TOnServer
216
+ TOnServer,
217
+ TSubmitMeta
214
218
  >,
215
219
  ) => FormApi<
216
220
  TFormData,
@@ -221,7 +225,8 @@ export interface FormTransform<
221
225
  TOnBlurAsync,
222
226
  TOnSubmit,
223
227
  TOnSubmitAsync,
224
- TOnServer
228
+ TOnServer,
229
+ TSubmitMeta
225
230
  >
226
231
  deps: unknown[]
227
232
  }
@@ -239,6 +244,7 @@ export interface FormOptions<
239
244
  TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
240
245
  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
241
246
  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
247
+ TSubmitMeta = never,
242
248
  > {
243
249
  /**
244
250
  * Set initial values for your form.
@@ -281,6 +287,12 @@ export interface FormOptions<
281
287
  TOnSubmit,
282
288
  TOnSubmitAsync
283
289
  >
290
+
291
+ /**
292
+ * onSubmitMeta, the data passed from the handleSubmit handler, to the onSubmit function props
293
+ */
294
+ onSubmitMeta?: TSubmitMeta
295
+
284
296
  /**
285
297
  * A function to be called when the form is submitted, what should happen once the user submits a valid form returns `any` or a promise `Promise<any>`
286
298
  */
@@ -295,8 +307,10 @@ export interface FormOptions<
295
307
  TOnBlurAsync,
296
308
  TOnSubmit,
297
309
  TOnSubmitAsync,
298
- TOnServer
310
+ TOnServer,
311
+ TSubmitMeta
299
312
  >
313
+ meta: TSubmitMeta
300
314
  }) => any | Promise<any>
301
315
  /**
302
316
  * Specify an action for scenarios where the user tries to submit an invalid form.
@@ -312,7 +326,8 @@ export interface FormOptions<
312
326
  TOnBlurAsync,
313
327
  TOnSubmit,
314
328
  TOnSubmitAsync,
315
- TOnServer
329
+ TOnServer,
330
+ TSubmitMeta
316
331
  >
317
332
  }) => void
318
333
  transform?: FormTransform<
@@ -324,7 +339,8 @@ export interface FormOptions<
324
339
  TOnBlurAsync,
325
340
  TOnSubmit,
326
341
  TOnSubmitAsync,
327
- TOnServer
342
+ TOnServer,
343
+ TSubmitMeta
328
344
  >
329
345
  }
330
346
 
@@ -363,6 +379,7 @@ export type FieldInfo<TFormData> = {
363
379
  any,
364
380
  any,
365
381
  any,
382
+ any,
366
383
  any
367
384
  > | null
368
385
  /**
@@ -610,7 +627,18 @@ function getDefaultFormState<
610
627
  *
611
628
  * A type representing the Form API with all generics set to `any` for convenience.
612
629
  */
613
- export type AnyFormApi = FormApi<any, any, any, any, any, any, any, any, any>
630
+ export type AnyFormApi = FormApi<
631
+ any,
632
+ any,
633
+ any,
634
+ any,
635
+ any,
636
+ any,
637
+ any,
638
+ any,
639
+ any,
640
+ any
641
+ >
614
642
 
615
643
  /**
616
644
  * A class representing the Form API. It handles the logic and interactions with the form state.
@@ -629,6 +657,7 @@ export class FormApi<
629
657
  TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
630
658
  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
631
659
  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
660
+ TSubmitMeta = never,
632
661
  > {
633
662
  /**
634
663
  * The options for the form.
@@ -642,7 +671,8 @@ export class FormApi<
642
671
  TOnBlurAsync,
643
672
  TOnSubmit,
644
673
  TOnSubmitAsync,
645
- TOnServer
674
+ TOnServer,
675
+ TSubmitMeta
646
676
  > = {}
647
677
  baseStore!: Store<
648
678
  BaseFormState<
@@ -698,7 +728,8 @@ export class FormApi<
698
728
  TOnBlurAsync,
699
729
  TOnSubmit,
700
730
  TOnSubmitAsync,
701
- TOnServer
731
+ TOnServer,
732
+ TSubmitMeta
702
733
  >,
703
734
  ) {
704
735
  this.baseStore = new Store(
@@ -958,6 +989,8 @@ export class FormApi<
958
989
  },
959
990
  })
960
991
 
992
+ this.handleSubmit = this.handleSubmit.bind(this)
993
+
961
994
  this.update(opts || {})
962
995
  }
963
996
 
@@ -1013,7 +1046,8 @@ export class FormApi<
1013
1046
  TOnBlurAsync,
1014
1047
  TOnSubmit,
1015
1048
  TOnSubmitAsync,
1016
- TOnServer
1049
+ TOnServer,
1050
+ TSubmitMeta
1017
1051
  >,
1018
1052
  ) => {
1019
1053
  if (!options) return
@@ -1482,7 +1516,9 @@ export class FormApi<
1482
1516
  /**
1483
1517
  * Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks.
1484
1518
  */
1485
- handleSubmit = async () => {
1519
+ handleSubmit(): Promise<void>
1520
+ handleSubmit(submitMeta: TSubmitMeta): Promise<void>
1521
+ async handleSubmit(submitMeta?: TSubmitMeta): Promise<void> {
1486
1522
  this.baseStore.setState((old) => ({
1487
1523
  ...old,
1488
1524
  // Submission attempts mark the form as not submitted
@@ -1536,7 +1572,11 @@ export class FormApi<
1536
1572
 
1537
1573
  try {
1538
1574
  // Run the submit code
1539
- await this.options.onSubmit?.({ value: this.state.values, formApi: this })
1575
+ await this.options.onSubmit?.({
1576
+ value: this.state.values,
1577
+ formApi: this,
1578
+ meta: submitMeta ?? this.options.onSubmitMeta,
1579
+ } as any)
1540
1580
 
1541
1581
  batch(() => {
1542
1582
  this.baseStore.setState((prev) => ({ ...prev, isSubmitted: true }))
@@ -14,6 +14,7 @@ export function formOptions<
14
14
  TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
15
15
  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
16
16
  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
17
+ TSubmitMeta,
17
18
  >(
18
19
  defaultOpts?: FormOptions<
19
20
  TFormData,
@@ -24,7 +25,8 @@ export function formOptions<
24
25
  TOnBlurAsync,
25
26
  TOnSubmit,
26
27
  TOnSubmitAsync,
27
- TOnServer
28
+ TOnServer,
29
+ TSubmitMeta
28
30
  >,
29
31
  ) {
30
32
  return defaultOpts
package/src/mergeForm.ts CHANGED
@@ -72,9 +72,20 @@ export function mutateMergeDeep(
72
72
  }
73
73
 
74
74
  export function mergeForm<TFormData>(
75
- baseForm: FormApi<NoInfer<TFormData>, any, any, any, any, any, any, any, any>,
75
+ baseForm: FormApi<
76
+ NoInfer<TFormData>,
77
+ any,
78
+ any,
79
+ any,
80
+ any,
81
+ any,
82
+ any,
83
+ any,
84
+ any,
85
+ any
86
+ >,
76
87
  state: Partial<
77
- FormApi<TFormData, any, any, any, any, any, any, any, any>['state']
88
+ FormApi<TFormData, any, any, any, any, any, any, any, any, any>['state']
78
89
  >,
79
90
  ) {
80
91
  mutateMergeDeep(baseForm.state, state)
package/src/metaHelper.ts CHANGED
@@ -18,6 +18,7 @@ export function metaHelper<
18
18
  TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
19
19
  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
20
20
  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
21
+ TSubmitMeta,
21
22
  >(
22
23
  formApi: FormApi<
23
24
  TFormData,
@@ -28,7 +29,8 @@ export function metaHelper<
28
29
  TOnBlurAsync,
29
30
  TOnSubmit,
30
31
  TOnSubmitAsync,
31
- TOnServer
32
+ TOnServer,
33
+ TSubmitMeta
32
34
  >,
33
35
  ) {
34
36
  function handleArrayFieldMetaShift(