@tanstack/react-form 1.14.2 → 1.15.1

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.
@@ -5,5 +5,5 @@ export { useForm } from './useForm.js';
5
5
  export type { UseField, FieldComponent } from './useField.js';
6
6
  export { useField, Field } from './useField.js';
7
7
  export { useTransform } from './useTransform.js';
8
- export type { WithFormProps } from './createFormHook.js';
8
+ export type { WithFormProps, WithFieldGroupProps as WithFormLensProps, } from './createFormHook.js';
9
9
  export { createFormHook, createFormHookContexts } from './createFormHook.js';
@@ -33,6 +33,12 @@ interface FieldComponentBoundProps<TParentData, TName extends DeepKeys<TParentDa
33
33
  * A type alias representing a field component for a specific form data type.
34
34
  */
35
35
  export type FieldComponent<in out TParentData, in out TFormOnMount extends undefined | FormValidateOrFn<TParentData>, in out TFormOnChange extends undefined | FormValidateOrFn<TParentData>, in out TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>, in out TFormOnBlur extends undefined | FormValidateOrFn<TParentData>, in out TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>, in out TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>, in out TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>, in out TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>, in out TPatentSubmitMeta, in out ExtendedApi = {}> = <const TName extends DeepKeys<TParentData>, TData extends DeepValue<TParentData, TName>, TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>, TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>, TOnChangeAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData>, TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>, TOnBlurAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData>, TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>, TOnSubmitAsync extends undefined | FieldAsyncValidateOrFn<TParentData, TName, TData>>({ children, ...fieldOptions }: FieldComponentBoundProps<TParentData, TName, TData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TFormOnMount, TFormOnChange, TFormOnChangeAsync, TFormOnBlur, TFormOnBlurAsync, TFormOnSubmit, TFormOnSubmitAsync, TFormOnServer, TPatentSubmitMeta, ExtendedApi>) => ReactNode;
36
+ /**
37
+ * A type alias representing a field component for a form lens data type.
38
+ */
39
+ export type LensFieldComponent<in out TLensData, in out TParentSubmitMeta, in out ExtendedApi = {}> = <const TName extends DeepKeys<TLensData>, TData extends DeepValue<TLensData, TName>, TOnMount extends undefined | FieldValidateOrFn<unknown, string, TData>, TOnChange extends undefined | FieldValidateOrFn<unknown, string, TData>, TOnChangeAsync extends undefined | FieldAsyncValidateOrFn<unknown, string, TData>, TOnBlur extends undefined | FieldValidateOrFn<unknown, string, TData>, TOnBlurAsync extends undefined | FieldAsyncValidateOrFn<unknown, string, TData>, TOnSubmit extends undefined | FieldValidateOrFn<unknown, string, TData>, TOnSubmitAsync extends undefined | FieldAsyncValidateOrFn<unknown, string, TData>>({ children, ...fieldOptions }: FieldComponentBoundProps<unknown, string, TData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, undefined | FormValidateOrFn<unknown>, undefined | FormValidateOrFn<unknown>, undefined | FormAsyncValidateOrFn<unknown>, undefined | FormValidateOrFn<unknown>, undefined | FormAsyncValidateOrFn<unknown>, undefined | FormValidateOrFn<unknown>, undefined | FormAsyncValidateOrFn<unknown>, undefined | FormAsyncValidateOrFn<unknown>, TParentSubmitMeta, ExtendedApi> & {
40
+ name: TName;
41
+ }) => ReactNode;
36
42
  /**
37
43
  * A function component that takes field options and a render function as children and returns a React component.
38
44
  *
@@ -1 +1 @@
1
- {"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n DeepKeys,\n DeepValue,\n FieldAsyncValidateOrFn,\n FieldValidateOrFn,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, ReactNode } from 'react'\nimport type { UseFieldOptions, UseFieldOptionsBound } from './types'\n\ninterface ReactFieldApi<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> {\n /**\n * A pre-bound and type-safe sub-field component using this field as a root.\n */\n Field: FieldComponent<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >\n}\n\n/**\n * A type representing a hook for using a field in a form with the given form data type.\n *\n * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.\n */\nexport type UseField<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> = <\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>(\n opts: UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >,\n) => FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>\n\n/**\n * A hook for managing a field in a form.\n * @param opts An object with field options.\n *\n * @returns The `FieldApi` instance for the specified field.\n */\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >,\n) {\n const [fieldApi] = useState(() => {\n const api = new FieldApi({\n ...opts,\n form: opts.form,\n name: opts.name,\n })\n\n const extendedApi: typeof api &\n ReactFieldApi<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > = api as never\n\n extendedApi.Field = Field as never\n\n return extendedApi\n })\n\n useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])\n\n /**\n * fieldApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n fieldApi.update(opts)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [\n state.meta,\n Object.keys((state.value as unknown) ?? []).length,\n ]\n }\n : undefined,\n )\n\n return fieldApi\n}\n\n/**\n * @param children A render function that takes a field API instance and returns a React element.\n */\ninterface FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\ninterface FieldComponentBoundProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\n/**\n * A type alias representing a field component for a specific form data type.\n */\nexport type FieldComponent<\n in out TParentData,\n in out TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChangeAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnBlurAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnSubmitAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n in out TPatentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentBoundProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta,\n ExtendedApi\n>) => ReactNode\n\n/**\n * A function component that takes field options and a render function as children and returns a React component.\n *\n * The `Field` component uses the `useField` hook internally to manage the field instance.\n */\nexport const Field = (<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>): ReactNode => {\n const fieldApi = useField(fieldOptions as any)\n\n const jsxToDisplay = useMemo(\n () => functionalUpdate(children, fieldApi as any),\n /**\n * The reason this exists is to fix an issue with the React Compiler.\n * Namely, functionalUpdate is memoized where it checks for `fieldApi`, which is a static type.\n * This means that when `state.value` changes, it does not trigger a re-render. The useMemo explicitly fixes this problem\n */\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [children, fieldApi, fieldApi.state.value, fieldApi.state.meta],\n )\n return (<>{jsxToDisplay}</>) as never\n}) satisfies FunctionComponent<\n FieldComponentProps<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n>\n"],"names":[],"mappings":";;;;;AAqHO,SAAS,SA2Bd,MAqBA;AACA,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM;AAC1B,UAAA,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IAAA,CACZ;AAED,UAAM,cAYA;AAEN,gBAAY,QAAQ;AAEb,WAAA;AAAA,EAAA,CACR;AAED,4BAA0B,SAAS,OAAO,CAAC,QAAQ,CAAC;AAMpD,4BAA0B,MAAM;AAC9B,aAAS,OAAO,IAAI;AAAA,EAAA,CACrB;AAED;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACF,aAAA;AAAA,QACL,MAAM;AAAA,QACN,OAAO,KAAM,MAAM,SAAqB,CAAE,CAAA,EAAE;AAAA,MAC9C;AAAA,IAAA,IAEF;AAAA,EACN;AAEO,SAAA;AACT;AAoNO,MAAM,QAAS,CA0BpB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAoBiB;AACT,QAAA,WAAW,SAAS,YAAmB;AAE7C,QAAM,eAAe;AAAA,IACnB,MAAM,iBAAiB,UAAU,QAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOhD,CAAC,UAAU,UAAU,SAAS,MAAM,OAAO,SAAS,MAAM,IAAI;AAAA,EAChE;AACA,yCAAW,UAAa,aAAA,CAAA;AAC1B;"}
1
+ {"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useMemo, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n DeepKeys,\n DeepValue,\n FieldAsyncValidateOrFn,\n FieldValidateOrFn,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, ReactNode } from 'react'\nimport type { UseFieldOptions, UseFieldOptionsBound } from './types'\n\ninterface ReactFieldApi<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> {\n /**\n * A pre-bound and type-safe sub-field component using this field as a root.\n */\n Field: FieldComponent<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >\n}\n\n/**\n * A type representing a hook for using a field in a form with the given form data type.\n *\n * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.\n */\nexport type UseField<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> = <\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>(\n opts: UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n >,\n) => FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>\n\n/**\n * A hook for managing a field in a form.\n * @param opts An object with field options.\n *\n * @returns The `FieldApi` instance for the specified field.\n */\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >,\n) {\n const [fieldApi] = useState(() => {\n const api = new FieldApi({\n ...opts,\n form: opts.form,\n name: opts.name,\n })\n\n const extendedApi: typeof api &\n ReactFieldApi<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > = api as never\n\n extendedApi.Field = Field as never\n\n return extendedApi\n })\n\n useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])\n\n /**\n * fieldApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n fieldApi.update(opts)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [\n state.meta,\n Object.keys((state.value as unknown) ?? []).length,\n ]\n }\n : undefined,\n )\n\n return fieldApi\n}\n\n/**\n * @param children A render function that takes a field API instance and returns a React element.\n */\ninterface FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\ninterface FieldComponentBoundProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync\n > {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\n/**\n * A type alias representing a field component for a specific form data type.\n */\nexport type FieldComponent<\n in out TParentData,\n in out TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChangeAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnBlurAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnSubmitAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n in out TPatentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentBoundProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta,\n ExtendedApi\n>) => ReactNode\n\n/**\n * A type alias representing a field component for a form lens data type.\n */\nexport type LensFieldComponent<\n in out TLensData,\n in out TParentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TLensData>,\n TData extends DeepValue<TLensData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChange extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentBoundProps<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n TParentSubmitMeta,\n ExtendedApi\n> & { name: TName }) => ReactNode\n\n/**\n * A function component that takes field options and a render function as children and returns a React component.\n *\n * The `Field` component uses the `useField` hook internally to manage the field instance.\n */\nexport const Field = (<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>): ReactNode => {\n const fieldApi = useField(fieldOptions as any)\n\n const jsxToDisplay = useMemo(\n () => functionalUpdate(children, fieldApi as any),\n /**\n * The reason this exists is to fix an issue with the React Compiler.\n * Namely, functionalUpdate is memoized where it checks for `fieldApi`, which is a static type.\n * This means that when `state.value` changes, it does not trigger a re-render. The useMemo explicitly fixes this problem\n */\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [children, fieldApi, fieldApi.state.value, fieldApi.state.meta],\n )\n return (<>{jsxToDisplay}</>) as never\n}) satisfies FunctionComponent<\n FieldComponentProps<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n>\n"],"names":[],"mappings":";;;;;AAqHO,SAAS,SA2Bd,MAqBA;AACA,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM;AAC1B,UAAA,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IAAA,CACZ;AAED,UAAM,cAYA;AAEN,gBAAY,QAAQ;AAEb,WAAA;AAAA,EAAA,CACR;AAED,4BAA0B,SAAS,OAAO,CAAC,QAAQ,CAAC;AAMpD,4BAA0B,MAAM;AAC9B,aAAS,OAAO,IAAI;AAAA,EAAA,CACrB;AAED;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACF,aAAA;AAAA,QACL,MAAM;AAAA,QACN,OAAO,KAAM,MAAM,SAAqB,CAAE,CAAA,EAAE;AAAA,MAC9C;AAAA,IAAA,IAEF;AAAA,EACN;AAEO,SAAA;AACT;AAqQO,MAAM,QAAS,CA0BpB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAoBiB;AACT,QAAA,WAAW,SAAS,YAAmB;AAE7C,QAAM,eAAe;AAAA,IACnB,MAAM,iBAAiB,UAAU,QAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOhD,CAAC,UAAU,UAAU,SAAS,MAAM,OAAO,SAAS,MAAM,IAAI;AAAA,EAChE;AACA,yCAAW,UAAa,aAAA,CAAA;AAC1B;"}
@@ -0,0 +1,29 @@
1
+ import { FieldGroupApi, DeepKeysOfType, FieldGroupState, FieldsMap, FormAsyncValidateOrFn, FormValidateOrFn } from '@tanstack/form-core';
2
+ import { AppFieldExtendedReactFormApi } from './createFormHook.js';
3
+ import { ComponentType, PropsWithChildren, ReactNode } from 'react';
4
+ import { LensFieldComponent } from './useField.js';
5
+ /**
6
+ * @private
7
+ */
8
+ export type AppFieldExtendedReactFieldGroupApi<TFormData, TFieldGroupData, TFields extends DeepKeysOfType<TFormData, TFieldGroupData | null | undefined> | FieldsMap<TFormData, TFieldGroupData>, TOnMount extends undefined | FormValidateOrFn<TFormData>, TOnChange extends undefined | FormValidateOrFn<TFormData>, TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnBlur extends undefined | FormValidateOrFn<TFormData>, TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnSubmit extends undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>, TSubmitMeta, TFieldComponents extends Record<string, ComponentType<any>>, TFormComponents extends Record<string, ComponentType<any>>> = FieldGroupApi<TFormData, TFieldGroupData, TFields, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta> & NoInfer<TFormComponents> & {
9
+ AppField: LensFieldComponent<TFieldGroupData, TSubmitMeta, NoInfer<TFieldComponents>>;
10
+ AppForm: ComponentType<PropsWithChildren>;
11
+ /**
12
+ * A React component to render form fields. With this, you can render and manage individual form fields.
13
+ */
14
+ Field: LensFieldComponent<TFieldGroupData, TSubmitMeta>;
15
+ /**
16
+ * A `Subscribe` function that allows you to listen and react 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.
17
+ */
18
+ Subscribe: <TSelected = NoInfer<FieldGroupState<TFieldGroupData>>>(props: {
19
+ selector?: (state: NoInfer<FieldGroupState<TFieldGroupData>>) => TSelected;
20
+ children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode;
21
+ }) => ReactNode;
22
+ };
23
+ export declare function useFieldGroup<TFormData, TFieldGroupData, TFields extends DeepKeysOfType<TFormData, TFieldGroupData | null | undefined> | FieldsMap<TFormData, TFieldGroupData>, TOnMount extends undefined | FormValidateOrFn<TFormData>, TOnChange extends undefined | FormValidateOrFn<TFormData>, TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnBlur extends undefined | FormValidateOrFn<TFormData>, TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnSubmit extends undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>, TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>, TComponents extends Record<string, ComponentType<any>>, TFormComponents extends Record<string, ComponentType<any>>, TSubmitMeta = never>(opts: {
24
+ form: AppFieldExtendedReactFormApi<TFormData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta, TComponents, TFormComponents> | AppFieldExtendedReactFieldGroupApi<unknown, TFormData, string | FieldsMap<unknown, TFormData>, any, any, any, any, any, any, any, any, TSubmitMeta, TComponents, TFormComponents>;
25
+ fields: TFields;
26
+ defaultValues?: TFieldGroupData;
27
+ onSubmitMeta?: TSubmitMeta;
28
+ formComponents: TFormComponents;
29
+ }): AppFieldExtendedReactFieldGroupApi<TFormData, TFieldGroupData, TFields, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnServer, TSubmitMeta, TComponents, TFormComponents>;
@@ -0,0 +1,60 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { useStore } from "@tanstack/react-store";
4
+ import { FieldGroupApi, functionalUpdate } from "@tanstack/form-core";
5
+ import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
6
+ function LocalSubscribe({
7
+ lens,
8
+ selector,
9
+ children
10
+ }) {
11
+ const data = useStore(lens.store, selector);
12
+ return functionalUpdate(children, data);
13
+ }
14
+ function useFieldGroup(opts) {
15
+ const [formLensApi] = useState(() => {
16
+ const api = new FieldGroupApi(opts);
17
+ const form = opts.form instanceof FieldGroupApi ? opts.form.form : opts.form;
18
+ const extendedApi = api;
19
+ extendedApi.AppForm = function AppForm(appFormProps) {
20
+ return /* @__PURE__ */ jsx(form.AppForm, { ...appFormProps });
21
+ };
22
+ extendedApi.AppField = function AppField({ name, ...appFieldProps }) {
23
+ return /* @__PURE__ */ jsx(
24
+ form.AppField,
25
+ {
26
+ name: formLensApi.getFormFieldName(name),
27
+ ...appFieldProps
28
+ }
29
+ );
30
+ };
31
+ extendedApi.Field = function Field({ name, ...fieldProps }) {
32
+ return /* @__PURE__ */ jsx(
33
+ form.Field,
34
+ {
35
+ name: formLensApi.getFormFieldName(name),
36
+ ...fieldProps
37
+ }
38
+ );
39
+ };
40
+ extendedApi.Subscribe = function Subscribe(props) {
41
+ return /* @__PURE__ */ jsx(
42
+ LocalSubscribe,
43
+ {
44
+ lens: formLensApi,
45
+ selector: props.selector,
46
+ children: props.children
47
+ }
48
+ );
49
+ };
50
+ return Object.assign(extendedApi, {
51
+ ...opts.formComponents
52
+ });
53
+ });
54
+ useIsomorphicLayoutEffect(formLensApi.mount, [formLensApi]);
55
+ return formLensApi;
56
+ }
57
+ export {
58
+ useFieldGroup
59
+ };
60
+ //# sourceMappingURL=useFieldGroup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFieldGroup.js","sources":["../../src/useFieldGroup.tsx"],"sourcesContent":["import { useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldGroupApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n AnyFieldGroupApi,\n DeepKeysOfType,\n FieldGroupState,\n FieldsMap,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { AppFieldExtendedReactFormApi } from './createFormHook'\nimport type { ComponentType, PropsWithChildren, ReactNode } from 'react'\nimport type { LensFieldComponent } from './useField'\n\nfunction LocalSubscribe({\n lens,\n selector,\n children,\n}: PropsWithChildren<{\n lens: AnyFieldGroupApi\n selector: (state: FieldGroupState<any>) => FieldGroupState<any>\n}>) {\n const data = useStore(lens.store, selector)\n\n return functionalUpdate(children, data)\n}\n\n/**\n * @private\n */\nexport type AppFieldExtendedReactFieldGroupApi<\n TFormData,\n TFieldGroupData,\n TFields extends\n | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>\n | FieldsMap<TFormData, TFieldGroupData>,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> = FieldGroupApi<\n TFormData,\n TFieldGroupData,\n TFields,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n> &\n NoInfer<TFormComponents> & {\n AppField: LensFieldComponent<\n TFieldGroupData,\n TSubmitMeta,\n NoInfer<TFieldComponents>\n >\n AppForm: ComponentType<PropsWithChildren>\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: LensFieldComponent<TFieldGroupData, TSubmitMeta>\n\n /**\n * A `Subscribe` function that allows you to listen and react 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.\n */\n Subscribe: <TSelected = NoInfer<FieldGroupState<TFieldGroupData>>>(props: {\n selector?: (state: NoInfer<FieldGroupState<TFieldGroupData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => ReactNode\n }\n\nexport function useFieldGroup<\n TFormData,\n TFieldGroupData,\n TFields extends\n | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>\n | FieldsMap<TFormData, TFieldGroupData>,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TSubmitMeta = never,\n>(opts: {\n form:\n | AppFieldExtendedReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta,\n TComponents,\n TFormComponents\n >\n | AppFieldExtendedReactFieldGroupApi<\n // Since this only occurs if you nest it within other form lenses, it can be more\n // lenient with the types.\n unknown,\n TFormData,\n string | FieldsMap<unknown, TFormData>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n TSubmitMeta,\n TComponents,\n TFormComponents\n >\n fields: TFields\n defaultValues?: TFieldGroupData\n onSubmitMeta?: TSubmitMeta\n formComponents: TFormComponents\n}): AppFieldExtendedReactFieldGroupApi<\n TFormData,\n TFieldGroupData,\n TFields,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta,\n TComponents,\n TFormComponents\n> {\n const [formLensApi] = useState(() => {\n const api = new FieldGroupApi(opts)\n const form =\n opts.form instanceof FieldGroupApi\n ? (opts.form.form as AppFieldExtendedReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta,\n TComponents,\n TFormComponents\n >)\n : opts.form\n\n const extendedApi: AppFieldExtendedReactFieldGroupApi<\n TFormData,\n TFieldGroupData,\n TFields,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta,\n TComponents,\n TFormComponents\n > = api as never\n\n extendedApi.AppForm = function AppForm(appFormProps) {\n return <form.AppForm {...appFormProps} />\n }\n\n extendedApi.AppField = function AppField({ name, ...appFieldProps }) {\n return (\n <form.AppField\n name={formLensApi.getFormFieldName(name)}\n {...(appFieldProps as any)}\n />\n ) as never\n }\n\n extendedApi.Field = function Field({ name, ...fieldProps }) {\n return (\n <form.Field\n name={formLensApi.getFormFieldName(name)}\n {...(fieldProps as any)}\n />\n ) as never\n }\n\n extendedApi.Subscribe = function Subscribe(props: any) {\n return (\n <LocalSubscribe\n lens={formLensApi}\n selector={props.selector}\n children={props.children}\n />\n )\n }\n\n return Object.assign(extendedApi, {\n ...opts.formComponents,\n }) as AppFieldExtendedReactFieldGroupApi<\n TFormData,\n TFieldGroupData,\n TFields,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta,\n TComponents,\n TFormComponents\n >\n })\n\n useIsomorphicLayoutEffect(formLensApi.mount, [formLensApi])\n\n return formLensApi\n}\n"],"names":[],"mappings":";;;;;AAgBA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF,GAGI;AACF,QAAM,OAAO,SAAS,KAAK,OAAO,QAAQ;AAEnC,SAAA,iBAAiB,UAAU,IAAI;AACxC;AAyDO,SAAS,cAiBd,MAqDA;AACA,QAAM,CAAC,WAAW,IAAI,SAAS,MAAM;AAC7B,UAAA,MAAM,IAAI,cAAc,IAAI;AAClC,UAAM,OACJ,KAAK,gBAAgB,gBAChB,KAAK,KAAK,OAcX,KAAK;AAEX,UAAM,cAeF;AAEQ,gBAAA,UAAU,SAAS,QAAQ,cAAc;AACnD,aAAQ,oBAAA,KAAK,SAAL,EAAc,GAAG,aAAc,CAAA;AAAA,IACzC;AAEA,gBAAY,WAAW,SAAS,SAAS,EAAE,MAAM,GAAG,iBAAiB;AAEjE,aAAA;AAAA,QAAC,KAAK;AAAA,QAAL;AAAA,UACC,MAAM,YAAY,iBAAiB,IAAI;AAAA,UACtC,GAAI;AAAA,QAAA;AAAA,MACP;AAAA,IAEJ;AAEA,gBAAY,QAAQ,SAAS,MAAM,EAAE,MAAM,GAAG,cAAc;AAExD,aAAA;AAAA,QAAC,KAAK;AAAA,QAAL;AAAA,UACC,MAAM,YAAY,iBAAiB,IAAI;AAAA,UACtC,GAAI;AAAA,QAAA;AAAA,MACP;AAAA,IAEJ;AAEY,gBAAA,YAAY,SAAS,UAAU,OAAY;AAEnD,aAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAM;AAAA,UACN,UAAU,MAAM;AAAA,UAChB,UAAU,MAAM;AAAA,QAAA;AAAA,MAClB;AAAA,IAEJ;AAEO,WAAA,OAAO,OAAO,aAAa;AAAA,MAChC,GAAG,KAAK;AAAA,IAAA,CACT;AAAA,EAAA,CAgBF;AAED,4BAA0B,YAAY,OAAO,CAAC,WAAW,CAAC;AAEnD,SAAA;AACT;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useForm.js","sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport { useState } from 'react'\nimport { Field } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n AnyFormApi,\n AnyFormState,\n FormAsyncValidateOrFn,\n FormOptions,\n FormState,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { PropsWithChildren, ReactNode } from 'react'\nimport type { FieldComponent } from './useField'\nimport type { NoInfer } from '@tanstack/react-store'\n\n/**\n * Fields that are added onto the `FormAPI` from `@tanstack/form-core` and returned from `useForm`\n */\nexport interface ReactFormApi<\n in out TFormData,\n in out TOnMount extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChange extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TSubmitMeta,\n> {\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: FieldComponent<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n /**\n * A `Subscribe` function that allows you to listen and react 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.\n */\n Subscribe: <\n TSelected = NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >,\n >(props: {\n selector?: (\n state: NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >,\n ) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => ReactNode\n}\n\n/**\n * An extended version of the `FormApi` class that includes React-specific functionalities from `ReactFormApi`\n */\nexport type ReactFormExtendedApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n> = FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n> &\n ReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n\nfunction LocalSubscribe({\n form,\n selector,\n children,\n}: PropsWithChildren<{\n form: AnyFormApi\n selector: (state: AnyFormState) => AnyFormState\n}>) {\n const data = useStore(form.store, selector)\n\n return functionalUpdate(children, data)\n}\n\n/**\n * A custom React Hook that returns an extended instance of the `FormApi` class.\n *\n * This API encapsulates all the necessary functionalities related to the form. It allows you to manage form state, handle submissions, and interact with form fields\n */\nexport function useForm<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n>(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n) {\n const [formApi] = useState(() => {\n const api = new FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >(opts)\n\n const extendedApi: ReactFormExtendedApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n > = api as never\n\n extendedApi.Field = function APIField(props) {\n return <Field {...props} form={api} />\n }\n\n extendedApi.Subscribe = function Subscribe(props: any) {\n return (\n <LocalSubscribe\n form={api}\n selector={props.selector}\n children={props.children}\n />\n )\n }\n\n return extendedApi\n })\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n /**\n * formApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n formApi.update(opts)\n })\n\n return formApi\n}\n"],"names":[],"mappings":";;;;;;AA2HA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF,GAGI;AACF,QAAM,OAAO,SAAS,KAAK,OAAO,QAAQ;AAEnC,SAAA,iBAAiB,UAAU,IAAI;AACxC;AAOO,SAAS,QAYd,MAYA;AACA,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AACzB,UAAA,MAAM,IAAI,QAWd,IAAI;AAEN,UAAM,cAWF;AAEQ,gBAAA,QAAQ,SAAS,SAAS,OAAO;AAC3C,aAAQ,oBAAA,OAAA,EAAO,GAAG,OAAO,MAAM,KAAK;AAAA,IACtC;AAEY,gBAAA,YAAY,SAAS,UAAU,OAAY;AAEnD,aAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAM;AAAA,UACN,UAAU,MAAM;AAAA,UAChB,UAAU,MAAM;AAAA,QAAA;AAAA,MAClB;AAAA,IAEJ;AAEO,WAAA;AAAA,EAAA,CACR;AAEyB,4BAAA,QAAQ,OAAO,EAAE;AAM3C,4BAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EAAA,CACpB;AAEM,SAAA;AACT;"}
1
+ {"version":3,"file":"useForm.js","sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport { useState } from 'react'\nimport { Field } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n AnyFormApi,\n AnyFormState,\n BaseFormOptions,\n FormAsyncValidateOrFn,\n FormOptions,\n FormState,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { ComponentType, JSX, PropsWithChildren, ReactNode } from 'react'\nimport type { FieldComponent } from './useField'\nimport type { NoInfer } from '@tanstack/react-store'\n\n/**\n * Fields that are added onto the `FormAPI` from `@tanstack/form-core` and returned from `useForm`\n */\nexport interface ReactFormApi<\n in out TFormData,\n in out TOnMount extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChange extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TSubmitMeta,\n> {\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: FieldComponent<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n /**\n * A `Subscribe` function that allows you to listen and react 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.\n */\n Subscribe: <\n TSelected = NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >,\n >(props: {\n selector?: (\n state: NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer\n >\n >,\n ) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => ReactNode\n}\n\n/**\n * An extended version of the `FormApi` class that includes React-specific functionalities from `ReactFormApi`\n */\nexport type ReactFormExtendedApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n> = FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n> &\n ReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >\n\nfunction LocalSubscribe({\n form,\n selector,\n children,\n}: PropsWithChildren<{\n form: AnyFormApi\n selector: (state: AnyFormState) => AnyFormState\n}>) {\n const data = useStore(form.store, selector)\n\n return functionalUpdate(children, data)\n}\n\n/**\n * A custom React Hook that returns an extended instance of the `FormApi` class.\n *\n * This API encapsulates all the necessary functionalities related to the form. It allows you to manage form state, handle submissions, and interact with form fields\n */\nexport function useForm<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n>(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >,\n) {\n const [formApi] = useState(() => {\n const api = new FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n >(opts)\n\n const extendedApi: ReactFormExtendedApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnServer,\n TSubmitMeta\n > = api as never\n\n extendedApi.Field = function APIField(props) {\n return <Field {...props} form={api} />\n }\n\n extendedApi.Subscribe = function Subscribe(props: any) {\n return (\n <LocalSubscribe\n form={api}\n selector={props.selector}\n children={props.children}\n />\n )\n }\n\n return extendedApi\n })\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n /**\n * formApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n formApi.update(opts)\n })\n\n return formApi\n}\n"],"names":[],"mappings":";;;;;;AA4HA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF,GAGI;AACF,QAAM,OAAO,SAAS,KAAK,OAAO,QAAQ;AAEnC,SAAA,iBAAiB,UAAU,IAAI;AACxC;AAOO,SAAS,QAYd,MAYA;AACA,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AACzB,UAAA,MAAM,IAAI,QAWd,IAAI;AAEN,UAAM,cAWF;AAEQ,gBAAA,QAAQ,SAAS,SAAS,OAAO;AAC3C,aAAQ,oBAAA,OAAA,EAAO,GAAG,OAAO,MAAM,KAAK;AAAA,IACtC;AAEY,gBAAA,YAAY,SAAS,UAAU,OAAY;AAEnD,aAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAM;AAAA,UACN,UAAU,MAAM;AAAA,UAChB,UAAU,MAAM;AAAA,QAAA;AAAA,MAClB;AAAA,IAEJ;AAEO,WAAA;AAAA,EAAA,CACR;AAEyB,4BAAA,QAAQ,OAAO,EAAE;AAM3C,4BAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EAAA,CACpB;AAEM,SAAA;AACT;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-form",
3
- "version": "1.14.2",
3
+ "version": "1.15.1",
4
4
  "description": "Powerful, type-safe forms for React.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -70,7 +70,7 @@
70
70
  "@tanstack/react-store": "^0.7.3",
71
71
  "decode-formdata": "^0.9.0",
72
72
  "devalue": "^5.1.1",
73
- "@tanstack/form-core": "1.14.2"
73
+ "@tanstack/form-core": "1.15.1"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@tanstack/react-start": "^1.121.16",
@@ -1,10 +1,14 @@
1
+ /* eslint-disable @eslint-react/no-context-provider */
1
2
  import { createContext, useContext, useMemo } from 'react'
2
3
  import { useForm } from './useForm'
4
+ import { useFieldGroup } from './useFieldGroup'
3
5
  import type {
4
6
  AnyFieldApi,
5
7
  AnyFormApi,
8
+ BaseFormOptions,
9
+ DeepKeysOfType,
6
10
  FieldApi,
7
- FormApi,
11
+ FieldsMap,
8
12
  FormAsyncValidateOrFn,
9
13
  FormOptions,
10
14
  FormValidateOrFn,
@@ -12,6 +16,7 @@ import type {
12
16
  import type { ComponentType, Context, JSX, PropsWithChildren } from 'react'
13
17
  import type { FieldComponent } from './useField'
14
18
  import type { ReactFormExtendedApi } from './useForm'
19
+ import type { AppFieldExtendedReactFieldGroupApi } from './useFieldGroup'
15
20
 
16
21
  /**
17
22
  * TypeScript inferencing is weird.
@@ -128,7 +133,10 @@ interface CreateFormHookProps<
128
133
  formContext: Context<AnyFormApi>
129
134
  }
130
135
 
131
- type AppFieldExtendedReactFormApi<
136
+ /**
137
+ * @private
138
+ */
139
+ export type AppFieldExtendedReactFormApi<
132
140
  TFormData,
133
141
  TOnMount extends undefined | FormValidateOrFn<TFormData>,
134
142
  TOnChange extends undefined | FormValidateOrFn<TFormData>,
@@ -220,6 +228,41 @@ export interface WithFormProps<
220
228
  ) => JSX.Element
221
229
  }
222
230
 
231
+ export interface WithFieldGroupProps<
232
+ TFieldGroupData,
233
+ TFieldComponents extends Record<string, ComponentType<any>>,
234
+ TFormComponents extends Record<string, ComponentType<any>>,
235
+ TSubmitMeta,
236
+ TRenderProps extends Record<string, unknown> = Record<string, never>,
237
+ > extends BaseFormOptions<TFieldGroupData, TSubmitMeta> {
238
+ // Optional, but adds props to the `render` function outside of `form`
239
+ props?: TRenderProps
240
+ render: (
241
+ props: PropsWithChildren<
242
+ NoInfer<TRenderProps> & {
243
+ group: AppFieldExtendedReactFieldGroupApi<
244
+ unknown,
245
+ TFieldGroupData,
246
+ string | FieldsMap<unknown, TFieldGroupData>,
247
+ undefined | FormValidateOrFn<unknown>,
248
+ undefined | FormValidateOrFn<unknown>,
249
+ undefined | FormAsyncValidateOrFn<unknown>,
250
+ undefined | FormValidateOrFn<unknown>,
251
+ undefined | FormAsyncValidateOrFn<unknown>,
252
+ undefined | FormValidateOrFn<unknown>,
253
+ undefined | FormAsyncValidateOrFn<unknown>,
254
+ undefined | FormAsyncValidateOrFn<unknown>,
255
+ // this types it as 'never' in the render prop. It should prevent any
256
+ // untyped meta passed to the handleSubmit by accident.
257
+ unknown extends TSubmitMeta ? never : TSubmitMeta,
258
+ TFieldComponents,
259
+ TFormComponents
260
+ >
261
+ }
262
+ >,
263
+ ) => JSX.Element
264
+ }
265
+
223
266
  export function createFormHook<
224
267
  const TComponents extends Record<string, ComponentType<any>>,
225
268
  const TFormComponents extends Record<string, ComponentType<any>>,
@@ -364,8 +407,92 @@ export function createFormHook<
364
407
  return (innerProps) => render({ ...props, ...innerProps })
365
408
  }
366
409
 
410
+ function withFieldGroup<
411
+ TFieldGroupData,
412
+ TSubmitMeta,
413
+ TRenderProps extends Record<string, unknown> = {},
414
+ >({
415
+ render,
416
+ props,
417
+ defaultValues,
418
+ }: WithFieldGroupProps<
419
+ TFieldGroupData,
420
+ TComponents,
421
+ TFormComponents,
422
+ TSubmitMeta,
423
+ TRenderProps
424
+ >): <
425
+ TFormData,
426
+ TFields extends
427
+ | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>
428
+ | FieldsMap<TFormData, TFieldGroupData>,
429
+ TOnMount extends undefined | FormValidateOrFn<TFormData>,
430
+ TOnChange extends undefined | FormValidateOrFn<TFormData>,
431
+ TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
432
+ TOnBlur extends undefined | FormValidateOrFn<TFormData>,
433
+ TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
434
+ TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
435
+ TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
436
+ TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
437
+ TFormSubmitMeta,
438
+ >(
439
+ params: PropsWithChildren<
440
+ NoInfer<TRenderProps> & {
441
+ form:
442
+ | AppFieldExtendedReactFormApi<
443
+ TFormData,
444
+ TOnMount,
445
+ TOnChange,
446
+ TOnChangeAsync,
447
+ TOnBlur,
448
+ TOnBlurAsync,
449
+ TOnSubmit,
450
+ TOnSubmitAsync,
451
+ TOnServer,
452
+ unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,
453
+ TComponents,
454
+ TFormComponents
455
+ >
456
+ | AppFieldExtendedReactFieldGroupApi<
457
+ // Since this only occurs if you nest it within other field groups, it can be more
458
+ // lenient with the types.
459
+ unknown,
460
+ TFormData,
461
+ string | FieldsMap<unknown, TFormData>,
462
+ any,
463
+ any,
464
+ any,
465
+ any,
466
+ any,
467
+ any,
468
+ any,
469
+ any,
470
+ unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,
471
+ TComponents,
472
+ TFormComponents
473
+ >
474
+ fields: TFields
475
+ }
476
+ >,
477
+ ) => JSX.Element {
478
+ return function Render(innerProps) {
479
+ const fieldGroupProps = useMemo(() => {
480
+ return {
481
+ form: innerProps.form,
482
+ fields: innerProps.fields,
483
+ defaultValues,
484
+ formComponents,
485
+ }
486
+ }, [innerProps.form, innerProps.fields])
487
+ const fieldGroupApi = useFieldGroup(fieldGroupProps as any)
488
+
489
+ return render({ ...props, ...innerProps, group: fieldGroupApi as any })
490
+ }
491
+ }
492
+
367
493
  return {
368
494
  useAppForm,
369
495
  withForm,
496
+ withFieldGroup,
370
497
  }
371
498
  }
package/src/index.ts CHANGED
@@ -10,5 +10,8 @@ export { useField, Field } from './useField'
10
10
 
11
11
  export { useTransform } from './useTransform'
12
12
 
13
- export type { WithFormProps } from './createFormHook'
13
+ export type {
14
+ WithFormProps,
15
+ WithFieldGroupProps as WithFormLensProps,
16
+ } from './createFormHook'
14
17
  export { createFormHook, createFormHookContexts } from './createFormHook'
package/src/useField.tsx CHANGED
@@ -420,6 +420,55 @@ export type FieldComponent<
420
420
  ExtendedApi
421
421
  >) => ReactNode
422
422
 
423
+ /**
424
+ * A type alias representing a field component for a form lens data type.
425
+ */
426
+ export type LensFieldComponent<
427
+ in out TLensData,
428
+ in out TParentSubmitMeta,
429
+ in out ExtendedApi = {},
430
+ > = <
431
+ const TName extends DeepKeys<TLensData>,
432
+ TData extends DeepValue<TLensData, TName>,
433
+ TOnMount extends undefined | FieldValidateOrFn<unknown, string, TData>,
434
+ TOnChange extends undefined | FieldValidateOrFn<unknown, string, TData>,
435
+ TOnChangeAsync extends
436
+ | undefined
437
+ | FieldAsyncValidateOrFn<unknown, string, TData>,
438
+ TOnBlur extends undefined | FieldValidateOrFn<unknown, string, TData>,
439
+ TOnBlurAsync extends
440
+ | undefined
441
+ | FieldAsyncValidateOrFn<unknown, string, TData>,
442
+ TOnSubmit extends undefined | FieldValidateOrFn<unknown, string, TData>,
443
+ TOnSubmitAsync extends
444
+ | undefined
445
+ | FieldAsyncValidateOrFn<unknown, string, TData>,
446
+ >({
447
+ children,
448
+ ...fieldOptions
449
+ }: FieldComponentBoundProps<
450
+ unknown,
451
+ string,
452
+ TData,
453
+ TOnMount,
454
+ TOnChange,
455
+ TOnChangeAsync,
456
+ TOnBlur,
457
+ TOnBlurAsync,
458
+ TOnSubmit,
459
+ TOnSubmitAsync,
460
+ undefined | FormValidateOrFn<unknown>,
461
+ undefined | FormValidateOrFn<unknown>,
462
+ undefined | FormAsyncValidateOrFn<unknown>,
463
+ undefined | FormValidateOrFn<unknown>,
464
+ undefined | FormAsyncValidateOrFn<unknown>,
465
+ undefined | FormValidateOrFn<unknown>,
466
+ undefined | FormAsyncValidateOrFn<unknown>,
467
+ undefined | FormAsyncValidateOrFn<unknown>,
468
+ TParentSubmitMeta,
469
+ ExtendedApi
470
+ > & { name: TName }) => ReactNode
471
+
423
472
  /**
424
473
  * A function component that takes field options and a render function as children and returns a React component.
425
474
  *