@tanstack/solid-form 1.23.9 → 1.26.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.
Files changed (38) hide show
  1. package/dist/cjs/createField.cjs.map +1 -1
  2. package/dist/cjs/createField.d.cts +17 -1
  3. package/dist/cjs/createFieldGroup.cjs +30 -0
  4. package/dist/cjs/createFieldGroup.cjs.map +1 -0
  5. package/dist/cjs/createFieldGroup.d.cts +29 -0
  6. package/dist/cjs/createFormHook.cjs +23 -1
  7. package/dist/cjs/createFormHook.cjs.map +1 -1
  8. package/dist/cjs/createFormHook.d.cts +16 -2
  9. package/dist/cjs/index.cjs +2 -0
  10. package/dist/cjs/index.cjs.map +1 -1
  11. package/dist/cjs/index.d.cts +1 -0
  12. package/dist/esm/createField.d.ts +17 -1
  13. package/dist/esm/createField.js.map +1 -1
  14. package/dist/esm/createFieldGroup.d.ts +29 -0
  15. package/dist/esm/createFieldGroup.js +30 -0
  16. package/dist/esm/createFieldGroup.js.map +1 -0
  17. package/dist/esm/createFormHook.d.ts +16 -2
  18. package/dist/esm/createFormHook.js +23 -1
  19. package/dist/esm/createFormHook.js.map +1 -1
  20. package/dist/esm/index.d.ts +1 -0
  21. package/dist/esm/index.js +2 -0
  22. package/dist/esm/index.js.map +1 -1
  23. package/dist/source/createField.d.ts +17 -1
  24. package/dist/source/createField.jsx.map +1 -1
  25. package/dist/source/createFieldGroup.d.ts +30 -0
  26. package/dist/source/createFieldGroup.jsx +31 -0
  27. package/dist/source/createFieldGroup.jsx.map +1 -0
  28. package/dist/source/createFormHook.d.ts +16 -2
  29. package/dist/source/createFormHook.jsx +14 -0
  30. package/dist/source/createFormHook.jsx.map +1 -1
  31. package/dist/source/index.d.ts +1 -0
  32. package/dist/source/index.jsx +1 -0
  33. package/dist/source/index.jsx.map +1 -1
  34. package/package.json +3 -3
  35. package/src/createField.tsx +90 -1
  36. package/src/createFieldGroup.tsx +239 -0
  37. package/src/createFormHook.tsx +134 -2
  38. package/src/index.tsx +1 -0
@@ -1,5 +1,6 @@
1
1
  import { createContext, splitProps, useContext } from 'solid-js';
2
2
  import { createForm } from './createForm';
3
+ import { createFieldGroup } from './createFieldGroup';
3
4
  export function createFormHookContexts() {
4
5
  // We should never hit the `null` case here
5
6
  const fieldContext = createContext(null);
@@ -52,9 +53,22 @@ export function createFormHook(opts) {
52
53
  function withForm({ render, props, }) {
53
54
  return (innerProps) => render({ ...props, ...innerProps });
54
55
  }
56
+ function withFieldGroup({ render, props, defaultValues, }) {
57
+ return function Render(innerProps) {
58
+ const fieldGroupProps = {
59
+ form: innerProps.form,
60
+ fields: innerProps.fields,
61
+ defaultValues,
62
+ formComponents: opts.formComponents,
63
+ };
64
+ const fieldGroupApi = createFieldGroup(() => fieldGroupProps);
65
+ return render({ ...props, ...innerProps, group: fieldGroupApi });
66
+ };
67
+ }
55
68
  return {
56
69
  useAppForm,
57
70
  withForm,
71
+ withFieldGroup,
58
72
  };
59
73
  }
60
74
  //# sourceMappingURL=createFormHook.jsx.map
@@ -1 +1 @@
1
- {"version":3,"file":"createFormHook.jsx","sourceRoot":"","sources":["../../src/createFormHook.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createFormHook.jsx","sourceRoot":"","sources":["../../src/createFormHook.tsx"],"names":[],"mappings":"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"}
@@ -2,5 +2,6 @@ export * from '@tanstack/form-core';
2
2
  export { useStore } from '@tanstack/solid-store';
3
3
  export * from './createField';
4
4
  export * from './createForm';
5
+ export * from './createFieldGroup';
5
6
  export * from './createFormHook';
6
7
  export * from './types';
@@ -2,6 +2,7 @@ export * from '@tanstack/form-core';
2
2
  export { useStore } from '@tanstack/solid-store';
3
3
  export * from './createField';
4
4
  export * from './createForm';
5
+ export * from './createFieldGroup';
5
6
  export * from './createFormHook';
6
7
  export * from './types';
7
8
  //# sourceMappingURL=index.jsx.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.jsx","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AAEnC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAEhD,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA;AAChC,cAAc,SAAS,CAAA"}
1
+ {"version":3,"file":"index.jsx","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAA;AAEnC,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAEhD,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,SAAS,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/solid-form",
3
- "version": "1.23.9",
3
+ "version": "1.26.0",
4
4
  "description": "Powerful, type-safe forms for Solid.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -42,11 +42,11 @@
42
42
  ],
43
43
  "dependencies": {
44
44
  "@tanstack/solid-store": "^0.7.7",
45
- "@tanstack/form-core": "1.24.5"
45
+ "@tanstack/form-core": "1.26.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "solid-js": "^1.9.9",
49
- "vite": "^7.1.6",
49
+ "vite": "^7.2.2",
50
50
  "vite-plugin-solid": "^2.11.8"
51
51
  },
52
52
  "peerDependencies": {
@@ -11,12 +11,13 @@ import type {
11
11
  DeepValue,
12
12
  FieldAsyncValidateOrFn,
13
13
  FieldValidateOrFn,
14
+ FieldValidators,
14
15
  FormAsyncValidateOrFn,
15
16
  FormValidateOrFn,
16
17
  Narrow,
17
18
  } from '@tanstack/form-core'
18
19
 
19
- import type { Accessor, Component, JSX, JSXElement } from 'solid-js'
20
+ import type { Accessor, JSX, JSXElement } from 'solid-js'
20
21
  import type { CreateFieldOptions, CreateFieldOptionsBound } from './types'
21
22
 
22
23
  interface SolidFieldApi<
@@ -625,6 +626,94 @@ interface FieldComponentProps<
625
626
  ) => JSXElement
626
627
  }
627
628
 
629
+ /**
630
+ * A type alias representing a field component for a form lens data type.
631
+ */
632
+ export type LensFieldComponent<
633
+ in out TLensData,
634
+ in out TParentSubmitMeta,
635
+ in out ExtendedApi = {},
636
+ > = <
637
+ const TName extends DeepKeys<TLensData>,
638
+ TData extends DeepValue<TLensData, TName>,
639
+ TOnMount extends undefined | FieldValidateOrFn<unknown, string, TData>,
640
+ TOnChange extends undefined | FieldValidateOrFn<unknown, string, TData>,
641
+ TOnChangeAsync extends
642
+ | undefined
643
+ | FieldAsyncValidateOrFn<unknown, string, TData>,
644
+ TOnBlur extends undefined | FieldValidateOrFn<unknown, string, TData>,
645
+ TOnBlurAsync extends
646
+ | undefined
647
+ | FieldAsyncValidateOrFn<unknown, string, TData>,
648
+ TOnSubmit extends undefined | FieldValidateOrFn<unknown, string, TData>,
649
+ TOnSubmitAsync extends
650
+ | undefined
651
+ | FieldAsyncValidateOrFn<unknown, string, TData>,
652
+ TOnDynamic extends undefined | FieldValidateOrFn<unknown, string, TData>,
653
+ TOnDynamicAsync extends
654
+ | undefined
655
+ | FieldAsyncValidateOrFn<unknown, string, TData>,
656
+ >({
657
+ children,
658
+ ...fieldOptions
659
+ }: Omit<
660
+ FieldComponentBoundProps<
661
+ unknown,
662
+ string,
663
+ TData,
664
+ TOnMount,
665
+ TOnChange,
666
+ TOnChangeAsync,
667
+ TOnBlur,
668
+ TOnBlurAsync,
669
+ TOnSubmit,
670
+ TOnSubmitAsync,
671
+ TOnDynamic,
672
+ TOnDynamicAsync,
673
+ undefined | FormValidateOrFn<unknown>,
674
+ undefined | FormValidateOrFn<unknown>,
675
+ undefined | FormAsyncValidateOrFn<unknown>,
676
+ undefined | FormValidateOrFn<unknown>,
677
+ undefined | FormAsyncValidateOrFn<unknown>,
678
+ undefined | FormValidateOrFn<unknown>,
679
+ undefined | FormAsyncValidateOrFn<unknown>,
680
+ undefined | FormValidateOrFn<unknown>,
681
+ undefined | FormAsyncValidateOrFn<unknown>,
682
+ undefined | FormAsyncValidateOrFn<unknown>,
683
+ TParentSubmitMeta,
684
+ ExtendedApi
685
+ >,
686
+ 'name' | 'validators'
687
+ > & {
688
+ name: TName
689
+ validators?: Omit<
690
+ FieldValidators<
691
+ unknown,
692
+ string,
693
+ TData,
694
+ TOnMount,
695
+ TOnChange,
696
+ TOnChangeAsync,
697
+ TOnBlur,
698
+ TOnBlurAsync,
699
+ TOnSubmit,
700
+ TOnSubmitAsync,
701
+ TOnDynamic,
702
+ TOnDynamicAsync
703
+ >,
704
+ 'onChangeListenTo' | 'onBlurListenTo'
705
+ > & {
706
+ /**
707
+ * An optional list of field names that should trigger this field's `onChange` and `onChangeAsync` events when its value changes
708
+ */
709
+ onChangeListenTo?: DeepKeys<TLensData>[]
710
+ /**
711
+ * An optional list of field names that should trigger this field's `onBlur` and `onBlurAsync` events when its value changes
712
+ */
713
+ onBlurListenTo?: DeepKeys<TLensData>[]
714
+ }
715
+ }) => JSX.Element
716
+
628
717
  export function Field<
629
718
  TParentData,
630
719
  TName extends DeepKeys<TParentData>,
@@ -0,0 +1,239 @@
1
+ import { FieldGroupApi, functionalUpdate } from '@tanstack/form-core'
2
+ import { useStore } from '@tanstack/solid-store'
3
+ import { onCleanup, onMount } from 'solid-js'
4
+ import type { Component, JSX, ParentProps } from 'solid-js'
5
+ import type {
6
+ DeepKeysOfType,
7
+ FieldGroupState,
8
+ FieldsMap,
9
+ FormAsyncValidateOrFn,
10
+ FormValidateOrFn,
11
+ } from '@tanstack/form-core'
12
+ import type { LensFieldComponent } from './createField'
13
+ import type { AppFieldExtendedSolidFormApi } from './createFormHook'
14
+
15
+ /**
16
+ * @private
17
+ */
18
+ export type AppFieldExtendedSolidFieldGroupApi<
19
+ TFormData,
20
+ TFieldGroupData,
21
+ TFields extends
22
+ | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>
23
+ | FieldsMap<TFormData, TFieldGroupData>,
24
+ TOnMount extends undefined | FormValidateOrFn<TFormData>,
25
+ TOnChange extends undefined | FormValidateOrFn<TFormData>,
26
+ TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
27
+ TOnBlur extends undefined | FormValidateOrFn<TFormData>,
28
+ TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
29
+ TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
30
+ TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
31
+ TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
32
+ TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
33
+ TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
34
+ TSubmitMeta,
35
+ TFieldComponents extends Record<string, Component<any>>,
36
+ TFormComponents extends Record<string, Component<any>>,
37
+ > = FieldGroupApi<
38
+ TFormData,
39
+ TFieldGroupData,
40
+ TFields,
41
+ TOnMount,
42
+ TOnChange,
43
+ TOnChangeAsync,
44
+ TOnBlur,
45
+ TOnBlurAsync,
46
+ TOnSubmit,
47
+ TOnSubmitAsync,
48
+ TOnDynamic,
49
+ TOnDynamicAsync,
50
+ TOnServer,
51
+ TSubmitMeta
52
+ > &
53
+ NoInfer<TFormComponents> & {
54
+ AppField: LensFieldComponent<
55
+ TFieldGroupData,
56
+ TSubmitMeta,
57
+ NoInfer<TFieldComponents>
58
+ >
59
+ AppForm: Component<ParentProps>
60
+ /**
61
+ * A solid component to render form fields. With this, you can render and manage individual form fields.
62
+ */
63
+ Field: LensFieldComponent<TFieldGroupData, TSubmitMeta>
64
+
65
+ /**
66
+ * A `Subscribe` function that allows you to listen and solid to changes in the form's state. It's especially useful when you need to execute side effects or render specific components in response to state updates.
67
+ */
68
+ Subscribe: <TSelected = NoInfer<FieldGroupState<TFieldGroupData>>>(props: {
69
+ selector?: (state: NoInfer<FieldGroupState<TFieldGroupData>>) => TSelected
70
+ children: ((state: NoInfer<TSelected>) => JSX.Element) | JSX.Element
71
+ }) => JSX.Element
72
+ }
73
+
74
+ export function createFieldGroup<
75
+ TFormData,
76
+ TFieldGroupData,
77
+ TFields extends
78
+ | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>
79
+ | FieldsMap<TFormData, TFieldGroupData>,
80
+ TOnMount extends undefined | FormValidateOrFn<TFormData>,
81
+ TOnChange extends undefined | FormValidateOrFn<TFormData>,
82
+ TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
83
+ TOnBlur extends undefined | FormValidateOrFn<TFormData>,
84
+ TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
85
+ TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
86
+ TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
87
+ TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
88
+ TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
89
+ TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
90
+ TComponents extends Record<string, Component<any>>,
91
+ TFormComponents extends Record<string, Component<any>>,
92
+ TSubmitMeta = never,
93
+ >(
94
+ opts: () => {
95
+ form:
96
+ | AppFieldExtendedSolidFormApi<
97
+ TFormData,
98
+ TOnMount,
99
+ TOnChange,
100
+ TOnChangeAsync,
101
+ TOnBlur,
102
+ TOnBlurAsync,
103
+ TOnSubmit,
104
+ TOnSubmitAsync,
105
+ TOnDynamic,
106
+ TOnDynamicAsync,
107
+ TOnServer,
108
+ TSubmitMeta,
109
+ TComponents,
110
+ TFormComponents
111
+ >
112
+ | AppFieldExtendedSolidFieldGroupApi<
113
+ // Since this only occurs if you nest it within other form lenses, it can be more
114
+ // lenient with the types.
115
+ unknown,
116
+ TFormData,
117
+ string | FieldsMap<unknown, TFormData>,
118
+ any,
119
+ any,
120
+ any,
121
+ any,
122
+ any,
123
+ any,
124
+ any,
125
+ any,
126
+ any,
127
+ any,
128
+ TSubmitMeta,
129
+ TComponents,
130
+ TFormComponents
131
+ >
132
+ fields: TFields
133
+ defaultValues?: TFieldGroupData
134
+ onSubmitMeta?: TSubmitMeta
135
+ formComponents: TFormComponents
136
+ },
137
+ ): AppFieldExtendedSolidFieldGroupApi<
138
+ TFormData,
139
+ TFieldGroupData,
140
+ TFields,
141
+ TOnMount,
142
+ TOnChange,
143
+ TOnChangeAsync,
144
+ TOnBlur,
145
+ TOnBlurAsync,
146
+ TOnSubmit,
147
+ TOnSubmitAsync,
148
+ TOnDynamic,
149
+ TOnDynamicAsync,
150
+ TOnServer,
151
+ TSubmitMeta,
152
+ TComponents,
153
+ TFormComponents
154
+ > {
155
+ const options = opts()
156
+ const api = new FieldGroupApi(options)
157
+ const form =
158
+ options.form instanceof FieldGroupApi
159
+ ? (options.form.form as AppFieldExtendedSolidFormApi<
160
+ TFormData,
161
+ TOnMount,
162
+ TOnChange,
163
+ TOnChangeAsync,
164
+ TOnBlur,
165
+ TOnBlurAsync,
166
+ TOnSubmit,
167
+ TOnSubmitAsync,
168
+ TOnDynamic,
169
+ TOnDynamicAsync,
170
+ TOnServer,
171
+ TSubmitMeta,
172
+ TComponents,
173
+ TFormComponents
174
+ >)
175
+ : options.form
176
+
177
+ const extendedApi: AppFieldExtendedSolidFieldGroupApi<
178
+ TFormData,
179
+ TFieldGroupData,
180
+ TFields,
181
+ TOnMount,
182
+ TOnChange,
183
+ TOnChangeAsync,
184
+ TOnBlur,
185
+ TOnBlurAsync,
186
+ TOnSubmit,
187
+ TOnSubmitAsync,
188
+ TOnDynamic,
189
+ TOnDynamicAsync,
190
+ TOnServer,
191
+ TSubmitMeta,
192
+ TComponents,
193
+ TFormComponents
194
+ > = api as never
195
+
196
+ extendedApi.AppForm = (appFormProps) => <form.AppForm {...appFormProps} />
197
+ extendedApi.AppField = (props) => (
198
+ <form.AppField {...(api.getFormFieldOptions(props) as any)} />
199
+ )
200
+ extendedApi.Field = (props) => (
201
+ <form.Field {...(api.getFormFieldOptions(props) as any)} />
202
+ )
203
+ extendedApi.Subscribe = (props) => {
204
+ const data = useStore(api.store, props.selector)
205
+
206
+ return functionalUpdate(props.children, data()) as Element
207
+ }
208
+
209
+ let mounted = false
210
+ onMount(() => {
211
+ const cleanupFn = api.mount()
212
+ mounted = true
213
+ onCleanup(() => {
214
+ cleanupFn()
215
+ mounted = false
216
+ })
217
+ })
218
+
219
+ return Object.assign(extendedApi, {
220
+ ...options.formComponents,
221
+ }) as AppFieldExtendedSolidFieldGroupApi<
222
+ TFormData,
223
+ TFieldGroupData,
224
+ TFields,
225
+ TOnMount,
226
+ TOnChange,
227
+ TOnChangeAsync,
228
+ TOnBlur,
229
+ TOnBlurAsync,
230
+ TOnSubmit,
231
+ TOnSubmitAsync,
232
+ TOnDynamic,
233
+ TOnDynamicAsync,
234
+ TOnServer,
235
+ TSubmitMeta,
236
+ TComponents,
237
+ TFormComponents
238
+ >
239
+ }
@@ -1,9 +1,14 @@
1
1
  import { createContext, splitProps, useContext } from 'solid-js'
2
2
  import { createForm } from './createForm'
3
+ import { createFieldGroup } from './createFieldGroup'
4
+ import type { AppFieldExtendedSolidFieldGroupApi } from './createFieldGroup'
3
5
  import type {
4
6
  AnyFieldApi,
5
7
  AnyFormApi,
8
+ BaseFormOptions,
9
+ DeepKeysOfType,
6
10
  FieldApi,
11
+ FieldsMap,
7
12
  FormAsyncValidateOrFn,
8
13
  FormOptions,
9
14
  FormValidateOrFn,
@@ -142,8 +147,10 @@ interface CreateFormHookProps<
142
147
  formComponents: TFormComponents
143
148
  formContext: Context<AnyFormApi>
144
149
  }
145
-
146
- type AppFieldExtendedSolidFormApi<
150
+ /**
151
+ * @private
152
+ */
153
+ export type AppFieldExtendedSolidFormApi<
147
154
  TFormData,
148
155
  TOnMount extends undefined | FormValidateOrFn<TFormData>,
149
156
  TOnChange extends undefined | FormValidateOrFn<TFormData>,
@@ -247,6 +254,43 @@ export interface WithFormProps<
247
254
  ) => JSXElement
248
255
  }
249
256
 
257
+ export interface WithFieldGroupProps<
258
+ TFieldGroupData,
259
+ TFieldComponents extends Record<string, Component<any>>,
260
+ TFormComponents extends Record<string, Component<any>>,
261
+ TSubmitMeta,
262
+ TRenderProps extends Record<string, unknown> = Record<string, never>,
263
+ > extends BaseFormOptions<TFieldGroupData, TSubmitMeta> {
264
+ // Optional, but adds props to the `render` function outside of `form`
265
+ props?: TRenderProps
266
+ render: (
267
+ props: ParentProps<
268
+ NoInfer<TRenderProps> & {
269
+ group: AppFieldExtendedSolidFieldGroupApi<
270
+ unknown,
271
+ TFieldGroupData,
272
+ string | FieldsMap<unknown, TFieldGroupData>,
273
+ undefined | FormValidateOrFn<unknown>,
274
+ undefined | FormValidateOrFn<unknown>,
275
+ undefined | FormAsyncValidateOrFn<unknown>,
276
+ undefined | FormValidateOrFn<unknown>,
277
+ undefined | FormAsyncValidateOrFn<unknown>,
278
+ undefined | FormValidateOrFn<unknown>,
279
+ undefined | FormAsyncValidateOrFn<unknown>,
280
+ undefined | FormValidateOrFn<unknown>,
281
+ undefined | FormAsyncValidateOrFn<unknown>,
282
+ undefined | FormAsyncValidateOrFn<unknown>,
283
+ // this types it as 'never' in the render prop. It should prevent any
284
+ // untyped meta passed to the handleSubmit by accident.
285
+ unknown extends TSubmitMeta ? never : TSubmitMeta,
286
+ TFieldComponents,
287
+ TFormComponents
288
+ >
289
+ }
290
+ >,
291
+ ) => JSXElement
292
+ }
293
+
250
294
  export function createFormHook<
251
295
  const TComponents extends Record<string, Component<any>>,
252
296
  const TFormComponents extends Record<string, Component<any>>,
@@ -416,8 +460,96 @@ export function createFormHook<
416
460
  return (innerProps) => render({ ...props, ...innerProps })
417
461
  }
418
462
 
463
+ function withFieldGroup<
464
+ TFieldGroupData,
465
+ TSubmitMeta,
466
+ TRenderProps extends Record<string, unknown> = {},
467
+ >({
468
+ render,
469
+ props,
470
+ defaultValues,
471
+ }: WithFieldGroupProps<
472
+ TFieldGroupData,
473
+ TComponents,
474
+ TFormComponents,
475
+ TSubmitMeta,
476
+ TRenderProps
477
+ >): <
478
+ TFormData,
479
+ TFields extends
480
+ | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>
481
+ | FieldsMap<TFormData, TFieldGroupData>,
482
+ TOnMount extends undefined | FormValidateOrFn<TFormData>,
483
+ TOnChange extends undefined | FormValidateOrFn<TFormData>,
484
+ TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
485
+ TOnBlur extends undefined | FormValidateOrFn<TFormData>,
486
+ TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
487
+ TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
488
+ TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
489
+ TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
490
+ TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
491
+ TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
492
+ TFormSubmitMeta,
493
+ >(
494
+ params: ParentProps<
495
+ NoInfer<TRenderProps> & {
496
+ form:
497
+ | AppFieldExtendedSolidFormApi<
498
+ TFormData,
499
+ TOnMount,
500
+ TOnChange,
501
+ TOnChangeAsync,
502
+ TOnBlur,
503
+ TOnBlurAsync,
504
+ TOnSubmit,
505
+ TOnSubmitAsync,
506
+ TOnDynamic,
507
+ TOnDynamicAsync,
508
+ TOnServer,
509
+ unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,
510
+ TComponents,
511
+ TFormComponents
512
+ >
513
+ | AppFieldExtendedSolidFieldGroupApi<
514
+ // Since this only occurs if you nest it within other field groups, it can be more
515
+ // lenient with the types.
516
+ unknown,
517
+ TFormData,
518
+ string | FieldsMap<unknown, TFormData>,
519
+ any,
520
+ any,
521
+ any,
522
+ any,
523
+ any,
524
+ any,
525
+ any,
526
+ any,
527
+ any,
528
+ any,
529
+ unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,
530
+ TComponents,
531
+ TFormComponents
532
+ >
533
+ fields: TFields
534
+ }
535
+ >,
536
+ ) => JSXElement {
537
+ return function Render(innerProps) {
538
+ const fieldGroupProps = {
539
+ form: innerProps.form,
540
+ fields: innerProps.fields,
541
+ defaultValues,
542
+ formComponents: opts.formComponents,
543
+ }
544
+ const fieldGroupApi = createFieldGroup(() => fieldGroupProps)
545
+
546
+ return render({ ...props, ...innerProps, group: fieldGroupApi as any })
547
+ }
548
+ }
549
+
419
550
  return {
420
551
  useAppForm,
421
552
  withForm,
553
+ withFieldGroup,
422
554
  }
423
555
  }
package/src/index.tsx CHANGED
@@ -4,5 +4,6 @@ export { useStore } from '@tanstack/solid-store'
4
4
 
5
5
  export * from './createField'
6
6
  export * from './createForm'
7
+ export * from './createFieldGroup'
7
8
  export * from './createFormHook'
8
9
  export * from './types'