@tanstack/react-form 1.14.2 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/createFormHook.cjs +21 -1
- package/dist/cjs/createFormHook.cjs.map +1 -1
- package/dist/cjs/createFormHook.d.cts +16 -2
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/useField.cjs.map +1 -1
- package/dist/cjs/useField.d.cts +6 -0
- package/dist/cjs/useFieldGroup.cjs +60 -0
- package/dist/cjs/useFieldGroup.cjs.map +1 -0
- package/dist/cjs/useFieldGroup.d.cts +29 -0
- package/dist/cjs/useForm.cjs.map +1 -1
- package/dist/esm/createFormHook.d.ts +16 -2
- package/dist/esm/createFormHook.js +21 -1
- package/dist/esm/createFormHook.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/useField.d.ts +6 -0
- package/dist/esm/useField.js.map +1 -1
- package/dist/esm/useFieldGroup.d.ts +29 -0
- package/dist/esm/useFieldGroup.js +60 -0
- package/dist/esm/useFieldGroup.js.map +1 -0
- package/dist/esm/useForm.js.map +1 -1
- package/package.json +2 -2
- package/src/createFormHook.tsx +129 -2
- package/src/index.ts +4 -1
- package/src/useField.tsx +49 -0
- package/src/useFieldGroup.tsx +248 -0
- package/src/useForm.tsx +2 -1
package/dist/esm/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/esm/useField.d.ts
CHANGED
|
@@ -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
|
*
|
package/dist/esm/useField.js.map
CHANGED
|
@@ -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;"}
|
package/dist/esm/useForm.js.map
CHANGED
|
@@ -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":";;;;;;
|
|
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.
|
|
3
|
+
"version": "1.15.0",
|
|
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.
|
|
73
|
+
"@tanstack/form-core": "1.15.0"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
76
|
"@tanstack/react-start": "^1.121.16",
|
package/src/createFormHook.tsx
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
*
|