@tanstack/react-form 0.23.2 → 0.23.3

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.
@@ -1,6 +1,9 @@
1
1
  import { DeepKeys, DeepValue, FieldApiOptions, Validator } from '@tanstack/form-core';
2
2
  import { FunctionComponent } from 'react';
3
3
 
4
+ /**
5
+ * The field options.
6
+ */
4
7
  export type UseFieldOptions<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = FieldApiOptions<TParentData, TName, TFieldValidator, TFormValidator, TData> & {
5
8
  mode?: 'value' | 'array';
6
9
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useField.cjs","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { type FunctionComponent, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NodeType, UseFieldOptions } from './types'\nimport type { DeepKeys, DeepValue, Validator } from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TParentData, TFormValidator>\n }\n}\n\nexport type UseField<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>,\n 'form'\n >,\n) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData> {\n const [fieldApi] = useState(() => {\n const api = new FieldApi({\n ...opts,\n form: opts.form,\n name: opts.name,\n })\n\n api.Field = Field as never\n\n return api\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 [state.meta, Object.keys(state.value as never).length]\n }\n : undefined,\n )\n\n return fieldApi as never\n}\n\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => NodeType\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\nexport type FieldComponent<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n 'form'\n>) => NodeType\n\nexport const Field = (<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n>): NodeType => {\n const fieldApi = useField(fieldOptions as any)\n\n return (<>{functionalUpdate(children, fieldApi as any)}</>) as never\n}) satisfies FunctionComponent<FieldComponentProps<any, any, any, any, any>>\n"],"names":["useState","FieldApi","useIsomorphicLayoutEffect","useStore","jsx","Fragment","functionalUpdate"],"mappings":";;;;;;;AA0CO,SAAS,SAWd,MAOsE;AACtE,QAAM,CAAC,QAAQ,IAAIA,MAAAA,SAAS,MAAM;AAC1B,UAAA,MAAM,IAAIC,kBAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IAAA,CACZ;AAED,QAAI,QAAQ;AAEL,WAAA;AAAA,EAAA,CACR;AAEDC,4BAAAA,0BAA0B,SAAS,OAAO,CAAC,QAAQ,CAAC;AAMpDA,4BAAAA,0BAA0B,MAAM;AAC9B,aAAS,OAAO,IAAI;AAAA,EAAA,CACrB;AAEDC,aAAA;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACF,aAAA,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAc,EAAE,MAAM;AAAA,IAE9D,IAAA;AAAA,EAAA;AAGC,SAAA;AACT;AAiDO,MAAM,QAAS,CAUpB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAMgB;AACR,QAAA,WAAW,SAAS,YAAmB;AAE7C,SAAWC,2BAAA,IAAAC,WAAA,UAAA,EAAA,UAAAC,SAAA,iBAAiB,UAAU,QAAe,EAAE,CAAA;AACzD;;;"}
1
+ {"version":3,"file":"useField.cjs","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { type FunctionComponent, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NodeType, UseFieldOptions } from './types'\nimport type { DeepKeys, DeepValue, Validator } from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n /**\n * When using `@tanstack/react-form`, the core field API is extended at type level with additional methods for React-specific functionality:\n */\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n /**\n * A pre-bound and type-safe sub-field component using this field as a root.\n */\n Field: FieldComponent<TParentData, TFormValidator>\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 TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>,\n 'form'\n >,\n) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>\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 TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData> {\n const [fieldApi] = useState(() => {\n const api = new FieldApi({\n ...opts,\n form: opts.form,\n name: opts.name,\n })\n\n api.Field = Field as never\n\n return api\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 [state.meta, Object.keys(state.value as never).length]\n }\n : undefined,\n )\n\n return fieldApi as never\n}\n\n/**\n * @param children A render function that takes a field API instance and returns a React element.\n */\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => NodeType\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\n/**\n * A type alias representing a field component for a specific form data type.\n */\nexport type FieldComponent<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n 'form'\n>) => NodeType\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 TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n>): NodeType => {\n const fieldApi = useField(fieldOptions as any)\n\n return (<>{functionalUpdate(children, fieldApi as any)}</>) as never\n}) satisfies FunctionComponent<FieldComponentProps<any, any, any, any, any>>\n"],"names":["useState","FieldApi","useIsomorphicLayoutEffect","useStore","jsx","Fragment","functionalUpdate"],"mappings":";;;;;;;AA2DO,SAAS,SAWd,MAOsE;AACtE,QAAM,CAAC,QAAQ,IAAIA,MAAAA,SAAS,MAAM;AAC1B,UAAA,MAAM,IAAIC,kBAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IAAA,CACZ;AAED,QAAI,QAAQ;AAEL,WAAA;AAAA,EAAA,CACR;AAEDC,4BAAAA,0BAA0B,SAAS,OAAO,CAAC,QAAQ,CAAC;AAMpDA,4BAAAA,0BAA0B,MAAM;AAC9B,aAAS,OAAO,IAAI;AAAA,EAAA,CACrB;AAEDC,aAAA;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACF,aAAA,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAc,EAAE,MAAM;AAAA,IAE9D,IAAA;AAAA,EAAA;AAGC,SAAA;AACT;AA4DO,MAAM,QAAS,CAUpB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAMgB;AACR,QAAA,WAAW,SAAS,YAAmB;AAE7C,SAAWC,2BAAA,IAAAC,WAAA,UAAA,EAAA,UAAAC,SAAA,iBAAiB,UAAU,QAAe,EAAE,CAAA;AACzD;;;"}
@@ -2,15 +2,43 @@ import { FieldApi, DeepKeys, DeepValue, Validator } from '@tanstack/form-core';
2
2
  import { NodeType, UseFieldOptions } from './types.cjs';
3
3
 
4
4
  declare module '@tanstack/form-core' {
5
+ /**
6
+ * When using `@tanstack/react-form`, the core field API is extended at type level with additional methods for React-specific functionality:
7
+ */
5
8
  interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
9
+ /**
10
+ * A pre-bound and type-safe sub-field component using this field as a root.
11
+ */
6
12
  Field: FieldComponent<TParentData, TFormValidator>;
7
13
  }
8
14
  }
15
+ /**
16
+ * A type representing a hook for using a field in a form with the given form data type.
17
+ *
18
+ * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.
19
+ */
9
20
  export type UseField<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>, 'form'>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
21
+ /**
22
+ * A hook for managing a field in a form.
23
+ * @param opts An object with field options.
24
+ *
25
+ * @returns The `FieldApi` instance for the specified field.
26
+ */
10
27
  export declare function useField<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
28
+ /**
29
+ * @param children A render function that takes a field API instance and returns a React element.
30
+ */
11
31
  type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = {
12
32
  children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>) => NodeType;
13
33
  } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>;
34
+ /**
35
+ * A type alias representing a field component for a specific form data type.
36
+ */
14
37
  export type FieldComponent<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: Omit<FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator, TData>, 'form'>) => NodeType;
38
+ /**
39
+ * A function component that takes field options and a render function as children and returns a React component.
40
+ *
41
+ * The `Field` component uses the `useField` hook internally to manage the field instance.
42
+ */
15
43
  export declare const Field: <TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator, TData>) => NodeType;
16
44
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"useForm.cjs","sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport React, { useState } from 'react'\nimport { Field, type FieldComponent, type UseField, useField } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NoInfer } from '@tanstack/react-store'\nimport type { FormOptions, FormState, Validator } from '@tanstack/form-core'\nimport type { NodeType } from './types'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n Field: FieldComponent<TFormData, TFormValidator>\n useField: UseField<TFormData, TFormValidator>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {\n /**\n TypeScript versions <=5.0.4 have a bug that prevents\n the type of the `TSelected` generic from being inferred\n from the return type of this method.\n\n In these versions, `TSelected` will fall back to the default\n type (or `unknown` if that's not defined).\n\n @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}\n @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}\n */\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => NodeType) | NodeType\n }) => NodeType\n }\n}\n\nexport function useForm<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n opts?: FormOptions<TFormData, TFormValidator>,\n): FormApi<TFormData, TFormValidator> {\n const [formApi] = useState(() => {\n const api = new FormApi<TFormData, TFormValidator>(opts)\n api.Field = function APIField(props) {\n return (<Field {...props} form={api} />) as never\n }\n // eslint-disable-next-line react-hooks/rules-of-hooks\n api.useField = (props) => useField({ ...props, form: api })\n api.useStore = (\n // @ts-ignore\n selector,\n ) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useStore(api.store as any, selector as any) as any\n }\n api.Subscribe = (\n // @ts-ignore\n props,\n ) => {\n return functionalUpdate(\n props.children,\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(api.store as any, props.selector as any),\n ) as any\n }\n\n return api\n })\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n formApi.useStore((state) => state.isSubmitting)\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 as any\n}\n"],"names":["useState","FormApi","jsx","Field","useField","useStore","functionalUpdate","useIsomorphicLayoutEffect"],"mappings":";;;;;;;;AAmCO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAIA,MAAAA,SAAS,MAAM;AACzB,UAAA,MAAM,IAAIC,iBAAmC,IAAI;AACnD,QAAA,QAAQ,SAAS,SAAS,OAAO;AACnC,aAASC,2BAAAA,IAAAC,SAAAA,OAAA,EAAO,GAAG,OAAO,MAAM,IAAK,CAAA;AAAA,IAAA;AAGnC,QAAA,WAAW,CAAC,UAAUC,SAAA,SAAS,EAAE,GAAG,OAAO,MAAM,IAAA,CAAK;AACtD,QAAA,WAAW,CAEb,aACG;AAEI,aAAAC,oBAAS,IAAI,OAAc,QAAe;AAAA,IAAA;AAE/C,QAAA,YAAY,CAEd,UACG;AACI,aAAAC,SAAA;AAAA,QACL,MAAM;AAAA;AAAA,QAEND,WAAAA,SAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAAA;AAAA,IAClD;AAGK,WAAA;AAAA,EAAA,CACR;AAEyBE,4BAAAA,0BAAA,QAAQ,OAAO,CAAA,CAAE;AAE3C,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9CA,4BAAAA,0BAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EAAA,CACpB;AAEM,SAAA;AACT;;"}
1
+ {"version":3,"file":"useForm.cjs","sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport React, { useState } from 'react'\nimport { Field, type FieldComponent, type UseField, useField } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NoInfer } from '@tanstack/react-store'\nimport type { FormOptions, FormState, Validator } from '@tanstack/form-core'\nimport type { NodeType } from './types'\n\ndeclare module '@tanstack/form-core' {\n /**\n * When using `@tanstack/react-form`, the core form API is extended at type level with additional methods for React-specific functionality:\n */\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: FieldComponent<TFormData, TFormValidator>\n /**\n * A custom React hook that provides functionalities related to individual form fields. It gives you access to field values, errors, and allows you to set or update field values.\n */\n useField: UseField<TFormData, TFormValidator>\n /**\n * A `useStore` hook that connects to the internal store of the form. It can be used to access the form's current state or any other related state information. You can optionally pass in a selector function to cherry-pick specific parts of the state\n */\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\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<FormState<TFormData>>>(props: {\n /**\n TypeScript versions <=5.0.4 have a bug that prevents\n the type of the `TSelected` generic from being inferred\n from the return type of this method.\n\n In these versions, `TSelected` will fall back to the default\n type (or `unknown` if that's not defined).\n\n @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}\n @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}\n */\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => NodeType) | NodeType\n }) => NodeType\n }\n}\n\n/**\n * A custom React Hook that returns an 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 TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n opts?: FormOptions<TFormData, TFormValidator>,\n): FormApi<TFormData, TFormValidator> {\n const [formApi] = useState(() => {\n const api = new FormApi<TFormData, TFormValidator>(opts)\n api.Field = function APIField(props) {\n return (<Field {...props} form={api} />) as never\n }\n // eslint-disable-next-line react-hooks/rules-of-hooks\n api.useField = (props) => useField({ ...props, form: api })\n api.useStore = (\n // @ts-ignore\n selector,\n ) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useStore(api.store as any, selector as any) as any\n }\n api.Subscribe = (\n // @ts-ignore\n props,\n ) => {\n return functionalUpdate(\n props.children,\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(api.store as any, props.selector as any),\n ) as any\n }\n\n return api\n })\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n formApi.useStore((state) => state.isSubmitting)\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 as any\n}\n"],"names":["useState","FormApi","jsx","Field","useField","useStore","functionalUpdate","useIsomorphicLayoutEffect"],"mappings":";;;;;;;;AAuDO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAIA,MAAAA,SAAS,MAAM;AACzB,UAAA,MAAM,IAAIC,iBAAmC,IAAI;AACnD,QAAA,QAAQ,SAAS,SAAS,OAAO;AACnC,aAASC,2BAAAA,IAAAC,SAAAA,OAAA,EAAO,GAAG,OAAO,MAAM,IAAK,CAAA;AAAA,IAAA;AAGnC,QAAA,WAAW,CAAC,UAAUC,SAAA,SAAS,EAAE,GAAG,OAAO,MAAM,IAAA,CAAK;AACtD,QAAA,WAAW,CAEb,aACG;AAEI,aAAAC,oBAAS,IAAI,OAAc,QAAe;AAAA,IAAA;AAE/C,QAAA,YAAY,CAEd,UACG;AACI,aAAAC,SAAA;AAAA,QACL,MAAM;AAAA;AAAA,QAEND,WAAAA,SAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAAA;AAAA,IAClD;AAGK,WAAA;AAAA,EAAA,CACR;AAEyBE,4BAAAA,0BAAA,QAAQ,OAAO,CAAA,CAAE;AAE3C,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9CA,4BAAAA,0BAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EAAA,CACpB;AAEM,SAAA;AACT;;"}
@@ -4,10 +4,25 @@ import { NoInfer } from '@tanstack/react-store';
4
4
  import { NodeType } from './types.cjs';
5
5
 
6
6
  declare module '@tanstack/form-core' {
7
+ /**
8
+ * When using `@tanstack/react-form`, the core form API is extended at type level with additional methods for React-specific functionality:
9
+ */
7
10
  interface FormApi<TFormData, TFormValidator> {
11
+ /**
12
+ * A React component to render form fields. With this, you can render and manage individual form fields.
13
+ */
8
14
  Field: FieldComponent<TFormData, TFormValidator>;
15
+ /**
16
+ * A custom React hook that provides functionalities related to individual form fields. It gives you access to field values, errors, and allows you to set or update field values.
17
+ */
9
18
  useField: UseField<TFormData, TFormValidator>;
19
+ /**
20
+ * A `useStore` hook that connects to the internal store of the form. It can be used to access the form's current state or any other related state information. You can optionally pass in a selector function to cherry-pick specific parts of the state
21
+ */
10
22
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
23
+ /**
24
+ * 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.
25
+ */
11
26
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
12
27
  /**
13
28
  TypeScript versions <=5.0.4 have a bug that prevents
@@ -25,4 +40,9 @@ declare module '@tanstack/form-core' {
25
40
  }) => NodeType;
26
41
  }
27
42
  }
43
+ /**
44
+ * A custom React Hook that returns an instance of the `FormApi` class.
45
+ *
46
+ * 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
47
+ */
28
48
  export declare function useForm<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined>(opts?: FormOptions<TFormData, TFormValidator>): FormApi<TFormData, TFormValidator>;
@@ -1,6 +1,9 @@
1
1
  import { DeepKeys, DeepValue, FieldApiOptions, Validator } from '@tanstack/form-core';
2
2
  import { FunctionComponent } from 'react';
3
3
 
4
+ /**
5
+ * The field options.
6
+ */
4
7
  export type UseFieldOptions<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = FieldApiOptions<TParentData, TName, TFieldValidator, TFormValidator, TData> & {
5
8
  mode?: 'value' | 'array';
6
9
  };
@@ -2,15 +2,43 @@ import { FieldApi, DeepKeys, DeepValue, Validator } from '@tanstack/form-core';
2
2
  import { NodeType, UseFieldOptions } from './types.js';
3
3
 
4
4
  declare module '@tanstack/form-core' {
5
+ /**
6
+ * When using `@tanstack/react-form`, the core field API is extended at type level with additional methods for React-specific functionality:
7
+ */
5
8
  interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
9
+ /**
10
+ * A pre-bound and type-safe sub-field component using this field as a root.
11
+ */
6
12
  Field: FieldComponent<TParentData, TFormValidator>;
7
13
  }
8
14
  }
15
+ /**
16
+ * A type representing a hook for using a field in a form with the given form data type.
17
+ *
18
+ * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.
19
+ */
9
20
  export type UseField<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>, 'form'>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
21
+ /**
22
+ * A hook for managing a field in a form.
23
+ * @param opts An object with field options.
24
+ *
25
+ * @returns The `FieldApi` instance for the specified field.
26
+ */
10
27
  export declare function useField<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
28
+ /**
29
+ * @param children A render function that takes a field API instance and returns a React element.
30
+ */
11
31
  type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = {
12
32
  children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>) => NodeType;
13
33
  } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>;
34
+ /**
35
+ * A type alias representing a field component for a specific form data type.
36
+ */
14
37
  export type FieldComponent<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: Omit<FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator, TData>, 'form'>) => NodeType;
38
+ /**
39
+ * A function component that takes field options and a render function as children and returns a React component.
40
+ *
41
+ * The `Field` component uses the `useField` hook internally to manage the field instance.
42
+ */
15
43
  export declare const Field: <TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator, TData>) => NodeType;
16
44
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { type FunctionComponent, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NodeType, UseFieldOptions } from './types'\nimport type { DeepKeys, DeepValue, Validator } from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TParentData, TFormValidator>\n }\n}\n\nexport type UseField<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>,\n 'form'\n >,\n) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData> {\n const [fieldApi] = useState(() => {\n const api = new FieldApi({\n ...opts,\n form: opts.form,\n name: opts.name,\n })\n\n api.Field = Field as never\n\n return api\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 [state.meta, Object.keys(state.value as never).length]\n }\n : undefined,\n )\n\n return fieldApi as never\n}\n\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => NodeType\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\nexport type FieldComponent<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n 'form'\n>) => NodeType\n\nexport const Field = (<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n>): NodeType => {\n const fieldApi = useField(fieldOptions as any)\n\n return (<>{functionalUpdate(children, fieldApi as any)}</>) as never\n}) satisfies FunctionComponent<FieldComponentProps<any, any, any, any, any>>\n"],"names":[],"mappings":";;;;;AA0CO,SAAS,SAWd,MAOsE;AACtE,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,QAAI,QAAQ;AAEL,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,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAc,EAAE,MAAM;AAAA,IAE9D,IAAA;AAAA,EAAA;AAGC,SAAA;AACT;AAiDO,MAAM,QAAS,CAUpB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAMgB;AACR,QAAA,WAAW,SAAS,YAAmB;AAE7C,SAAW,oBAAA,UAAA,EAAA,UAAA,iBAAiB,UAAU,QAAe,EAAE,CAAA;AACzD;"}
1
+ {"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { type FunctionComponent, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NodeType, UseFieldOptions } from './types'\nimport type { DeepKeys, DeepValue, Validator } from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n /**\n * When using `@tanstack/react-form`, the core field API is extended at type level with additional methods for React-specific functionality:\n */\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n /**\n * A pre-bound and type-safe sub-field component using this field as a root.\n */\n Field: FieldComponent<TParentData, TFormValidator>\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 TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>,\n 'form'\n >,\n) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>\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 TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData> {\n const [fieldApi] = useState(() => {\n const api = new FieldApi({\n ...opts,\n form: opts.form,\n name: opts.name,\n })\n\n api.Field = Field as never\n\n return api\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 [state.meta, Object.keys(state.value as never).length]\n }\n : undefined,\n )\n\n return fieldApi as never\n}\n\n/**\n * @param children A render function that takes a field API instance and returns a React element.\n */\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => NodeType\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\n/**\n * A type alias representing a field component for a specific form data type.\n */\nexport type FieldComponent<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n 'form'\n>) => NodeType\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 TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n>): NodeType => {\n const fieldApi = useField(fieldOptions as any)\n\n return (<>{functionalUpdate(children, fieldApi as any)}</>) as never\n}) satisfies FunctionComponent<FieldComponentProps<any, any, any, any, any>>\n"],"names":[],"mappings":";;;;;AA2DO,SAAS,SAWd,MAOsE;AACtE,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,QAAI,QAAQ;AAEL,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,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAc,EAAE,MAAM;AAAA,IAE9D,IAAA;AAAA,EAAA;AAGC,SAAA;AACT;AA4DO,MAAM,QAAS,CAUpB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAMgB;AACR,QAAA,WAAW,SAAS,YAAmB;AAE7C,SAAW,oBAAA,UAAA,EAAA,UAAA,iBAAiB,UAAU,QAAe,EAAE,CAAA;AACzD;"}
@@ -4,10 +4,25 @@ import { NoInfer } from '@tanstack/react-store';
4
4
  import { NodeType } from './types.js';
5
5
 
6
6
  declare module '@tanstack/form-core' {
7
+ /**
8
+ * When using `@tanstack/react-form`, the core form API is extended at type level with additional methods for React-specific functionality:
9
+ */
7
10
  interface FormApi<TFormData, TFormValidator> {
11
+ /**
12
+ * A React component to render form fields. With this, you can render and manage individual form fields.
13
+ */
8
14
  Field: FieldComponent<TFormData, TFormValidator>;
15
+ /**
16
+ * A custom React hook that provides functionalities related to individual form fields. It gives you access to field values, errors, and allows you to set or update field values.
17
+ */
9
18
  useField: UseField<TFormData, TFormValidator>;
19
+ /**
20
+ * A `useStore` hook that connects to the internal store of the form. It can be used to access the form's current state or any other related state information. You can optionally pass in a selector function to cherry-pick specific parts of the state
21
+ */
10
22
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
23
+ /**
24
+ * 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.
25
+ */
11
26
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
12
27
  /**
13
28
  TypeScript versions <=5.0.4 have a bug that prevents
@@ -25,4 +40,9 @@ declare module '@tanstack/form-core' {
25
40
  }) => NodeType;
26
41
  }
27
42
  }
43
+ /**
44
+ * A custom React Hook that returns an instance of the `FormApi` class.
45
+ *
46
+ * 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
47
+ */
28
48
  export declare function useForm<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined>(opts?: FormOptions<TFormData, TFormValidator>): FormApi<TFormData, TFormValidator>;
@@ -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 React, { useState } from 'react'\nimport { Field, type FieldComponent, type UseField, useField } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NoInfer } from '@tanstack/react-store'\nimport type { FormOptions, FormState, Validator } from '@tanstack/form-core'\nimport type { NodeType } from './types'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n Field: FieldComponent<TFormData, TFormValidator>\n useField: UseField<TFormData, TFormValidator>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {\n /**\n TypeScript versions <=5.0.4 have a bug that prevents\n the type of the `TSelected` generic from being inferred\n from the return type of this method.\n\n In these versions, `TSelected` will fall back to the default\n type (or `unknown` if that's not defined).\n\n @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}\n @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}\n */\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => NodeType) | NodeType\n }) => NodeType\n }\n}\n\nexport function useForm<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n opts?: FormOptions<TFormData, TFormValidator>,\n): FormApi<TFormData, TFormValidator> {\n const [formApi] = useState(() => {\n const api = new FormApi<TFormData, TFormValidator>(opts)\n api.Field = function APIField(props) {\n return (<Field {...props} form={api} />) as never\n }\n // eslint-disable-next-line react-hooks/rules-of-hooks\n api.useField = (props) => useField({ ...props, form: api })\n api.useStore = (\n // @ts-ignore\n selector,\n ) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useStore(api.store as any, selector as any) as any\n }\n api.Subscribe = (\n // @ts-ignore\n props,\n ) => {\n return functionalUpdate(\n props.children,\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(api.store as any, props.selector as any),\n ) as any\n }\n\n return api\n })\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n formApi.useStore((state) => state.isSubmitting)\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 as any\n}\n"],"names":[],"mappings":";;;;;;AAmCO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AACzB,UAAA,MAAM,IAAI,QAAmC,IAAI;AACnD,QAAA,QAAQ,SAAS,SAAS,OAAO;AACnC,aAAS,oBAAA,OAAA,EAAO,GAAG,OAAO,MAAM,IAAK,CAAA;AAAA,IAAA;AAGnC,QAAA,WAAW,CAAC,UAAU,SAAS,EAAE,GAAG,OAAO,MAAM,IAAA,CAAK;AACtD,QAAA,WAAW,CAEb,aACG;AAEI,aAAA,SAAS,IAAI,OAAc,QAAe;AAAA,IAAA;AAE/C,QAAA,YAAY,CAEd,UACG;AACI,aAAA;AAAA,QACL,MAAM;AAAA;AAAA,QAEN,SAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAAA;AAAA,IAClD;AAGK,WAAA;AAAA,EAAA,CACR;AAEyB,4BAAA,QAAQ,OAAO,CAAA,CAAE;AAE3C,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9C,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 React, { useState } from 'react'\nimport { Field, type FieldComponent, type UseField, useField } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NoInfer } from '@tanstack/react-store'\nimport type { FormOptions, FormState, Validator } from '@tanstack/form-core'\nimport type { NodeType } from './types'\n\ndeclare module '@tanstack/form-core' {\n /**\n * When using `@tanstack/react-form`, the core form API is extended at type level with additional methods for React-specific functionality:\n */\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: FieldComponent<TFormData, TFormValidator>\n /**\n * A custom React hook that provides functionalities related to individual form fields. It gives you access to field values, errors, and allows you to set or update field values.\n */\n useField: UseField<TFormData, TFormValidator>\n /**\n * A `useStore` hook that connects to the internal store of the form. It can be used to access the form's current state or any other related state information. You can optionally pass in a selector function to cherry-pick specific parts of the state\n */\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\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<FormState<TFormData>>>(props: {\n /**\n TypeScript versions <=5.0.4 have a bug that prevents\n the type of the `TSelected` generic from being inferred\n from the return type of this method.\n\n In these versions, `TSelected` will fall back to the default\n type (or `unknown` if that's not defined).\n\n @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}\n @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}\n */\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => NodeType) | NodeType\n }) => NodeType\n }\n}\n\n/**\n * A custom React Hook that returns an 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 TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n opts?: FormOptions<TFormData, TFormValidator>,\n): FormApi<TFormData, TFormValidator> {\n const [formApi] = useState(() => {\n const api = new FormApi<TFormData, TFormValidator>(opts)\n api.Field = function APIField(props) {\n return (<Field {...props} form={api} />) as never\n }\n // eslint-disable-next-line react-hooks/rules-of-hooks\n api.useField = (props) => useField({ ...props, form: api })\n api.useStore = (\n // @ts-ignore\n selector,\n ) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useStore(api.store as any, selector as any) as any\n }\n api.Subscribe = (\n // @ts-ignore\n props,\n ) => {\n return functionalUpdate(\n props.children,\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(api.store as any, props.selector as any),\n ) as any\n }\n\n return api\n })\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n formApi.useStore((state) => state.isSubmitting)\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 as any\n}\n"],"names":[],"mappings":";;;;;;AAuDO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AACzB,UAAA,MAAM,IAAI,QAAmC,IAAI;AACnD,QAAA,QAAQ,SAAS,SAAS,OAAO;AACnC,aAAS,oBAAA,OAAA,EAAO,GAAG,OAAO,MAAM,IAAK,CAAA;AAAA,IAAA;AAGnC,QAAA,WAAW,CAAC,UAAU,SAAS,EAAE,GAAG,OAAO,MAAM,IAAA,CAAK;AACtD,QAAA,WAAW,CAEb,aACG;AAEI,aAAA,SAAS,IAAI,OAAc,QAAe;AAAA,IAAA;AAE/C,QAAA,YAAY,CAEd,UACG;AACI,aAAA;AAAA,QACL,MAAM;AAAA;AAAA,QAEN,SAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAAA;AAAA,IAClD;AAGK,WAAA;AAAA,EAAA,CACR;AAEyB,4BAAA,QAAQ,OAAO,CAAA,CAAE;AAE3C,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9C,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": "0.23.2",
3
+ "version": "0.23.3",
4
4
  "description": "Powerful, type-safe forms for React.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -57,7 +57,7 @@
57
57
  "dependencies": {
58
58
  "@tanstack/react-store": "^0.5.0",
59
59
  "decode-formdata": "^0.7.5",
60
- "@tanstack/form-core": "0.23.2"
60
+ "@tanstack/form-core": "0.23.3"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "react": "^17.0.0 || ^18.0.0"
package/src/types.ts CHANGED
@@ -6,6 +6,9 @@ import type {
6
6
  } from '@tanstack/form-core'
7
7
  import type { FunctionComponent } from 'react'
8
8
 
9
+ /**
10
+ * The field options.
11
+ */
9
12
  export type UseFieldOptions<
10
13
  TParentData,
11
14
  TName extends DeepKeys<TParentData>,
package/src/useField.tsx CHANGED
@@ -6,6 +6,9 @@ import type { NodeType, UseFieldOptions } from './types'
6
6
  import type { DeepKeys, DeepValue, Validator } from '@tanstack/form-core'
7
7
 
8
8
  declare module '@tanstack/form-core' {
9
+ /**
10
+ * When using `@tanstack/react-form`, the core field API is extended at type level with additional methods for React-specific functionality:
11
+ */
9
12
  // eslint-disable-next-line no-shadow
10
13
  interface FieldApi<
11
14
  TParentData,
@@ -18,10 +21,18 @@ declare module '@tanstack/form-core' {
18
21
  | undefined = undefined,
19
22
  TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
20
23
  > {
24
+ /**
25
+ * A pre-bound and type-safe sub-field component using this field as a root.
26
+ */
21
27
  Field: FieldComponent<TParentData, TFormValidator>
22
28
  }
23
29
  }
24
30
 
31
+ /**
32
+ * A type representing a hook for using a field in a form with the given form data type.
33
+ *
34
+ * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.
35
+ */
25
36
  export type UseField<
26
37
  TParentData,
27
38
  TFormValidator extends
@@ -40,6 +51,12 @@ export type UseField<
40
51
  >,
41
52
  ) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>
42
53
 
54
+ /**
55
+ * A hook for managing a field in a form.
56
+ * @param opts An object with field options.
57
+ *
58
+ * @returns The `FieldApi` instance for the specified field.
59
+ */
43
60
  export function useField<
44
61
  TParentData,
45
62
  TName extends DeepKeys<TParentData>,
@@ -93,6 +110,9 @@ export function useField<
93
110
  return fieldApi as never
94
111
  }
95
112
 
113
+ /**
114
+ * @param children A render function that takes a field API instance and returns a React element.
115
+ */
96
116
  type FieldComponentProps<
97
117
  TParentData,
98
118
  TName extends DeepKeys<TParentData>,
@@ -115,6 +135,9 @@ type FieldComponentProps<
115
135
  ) => NodeType
116
136
  } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>
117
137
 
138
+ /**
139
+ * A type alias representing a field component for a specific form data type.
140
+ */
118
141
  export type FieldComponent<
119
142
  TParentData,
120
143
  TFormValidator extends
@@ -140,6 +163,11 @@ export type FieldComponent<
140
163
  'form'
141
164
  >) => NodeType
142
165
 
166
+ /**
167
+ * A function component that takes field options and a render function as children and returns a React component.
168
+ *
169
+ * The `Field` component uses the `useField` hook internally to manage the field instance.
170
+ */
143
171
  export const Field = (<
144
172
  TParentData,
145
173
  TName extends DeepKeys<TParentData>,
package/src/useForm.tsx CHANGED
@@ -8,13 +8,28 @@ import type { FormOptions, FormState, Validator } from '@tanstack/form-core'
8
8
  import type { NodeType } from './types'
9
9
 
10
10
  declare module '@tanstack/form-core' {
11
+ /**
12
+ * When using `@tanstack/react-form`, the core form API is extended at type level with additional methods for React-specific functionality:
13
+ */
11
14
  // eslint-disable-next-line no-shadow
12
15
  interface FormApi<TFormData, TFormValidator> {
16
+ /**
17
+ * A React component to render form fields. With this, you can render and manage individual form fields.
18
+ */
13
19
  Field: FieldComponent<TFormData, TFormValidator>
20
+ /**
21
+ * A custom React hook that provides functionalities related to individual form fields. It gives you access to field values, errors, and allows you to set or update field values.
22
+ */
14
23
  useField: UseField<TFormData, TFormValidator>
24
+ /**
25
+ * A `useStore` hook that connects to the internal store of the form. It can be used to access the form's current state or any other related state information. You can optionally pass in a selector function to cherry-pick specific parts of the state
26
+ */
15
27
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(
16
28
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,
17
29
  ) => TSelected
30
+ /**
31
+ * 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.
32
+ */
18
33
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
19
34
  /**
20
35
  TypeScript versions <=5.0.4 have a bug that prevents
@@ -33,6 +48,11 @@ declare module '@tanstack/form-core' {
33
48
  }
34
49
  }
35
50
 
51
+ /**
52
+ * A custom React Hook that returns an instance of the `FormApi` class.
53
+ *
54
+ * 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
55
+ */
36
56
  export function useForm<
37
57
  TFormData,
38
58
  TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
@@ -1,110 +0,0 @@
1
- import * as React from 'react'
2
- import { assertType, it } from 'vitest'
3
- import { useForm } from '../useForm'
4
-
5
- it('should type state.value properly', () => {
6
- function Comp() {
7
- const form = useForm({
8
- defaultValues: {
9
- firstName: 'test',
10
- age: 84,
11
- },
12
- } as const)
13
-
14
- return (
15
- <>
16
- <form.Field
17
- name="firstName"
18
- children={(field) => {
19
- assertType<'test'>(field.state.value)
20
- return null
21
- }}
22
- />
23
- <form.Field
24
- name="age"
25
- children={(field) => {
26
- assertType<84>(field.state.value)
27
- return null
28
- }}
29
- />
30
- </>
31
- )
32
- }
33
- })
34
-
35
- it('should type onChange properly', () => {
36
- function Comp() {
37
- const form = useForm({
38
- defaultValues: {
39
- firstName: 'test',
40
- age: 84,
41
- },
42
- } as const)
43
-
44
- return (
45
- <>
46
- <form.Field
47
- name="firstName"
48
- validators={{
49
- onChange: ({ value }) => {
50
- assertType<'test'>(value)
51
- return null
52
- },
53
- }}
54
- children={() => null}
55
- />
56
- <form.Field
57
- name="age"
58
- validators={{
59
- onChange: ({ value }) => {
60
- assertType<84>(value)
61
- return null
62
- },
63
- }}
64
- children={() => null}
65
- />
66
- </>
67
- )
68
- }
69
- })
70
-
71
- it('should type array subfields', () => {
72
- type FormDefinition = {
73
- nested: {
74
- people: {
75
- name: string
76
- age: number
77
- }[]
78
- }
79
- }
80
-
81
- function App() {
82
- const form = useForm({
83
- defaultValues: {
84
- nested: {
85
- people: [],
86
- },
87
- } as FormDefinition,
88
- onSubmit({ value }) {
89
- alert(JSON.stringify(value))
90
- },
91
- })
92
-
93
- return (
94
- <form.Field name="nested.people" mode="array">
95
- {(field) =>
96
- field.state.value.map((_, i) => (
97
- <form.Field key={i} name={`nested.people[${i}].name`}>
98
- {(subField) => (
99
- <input
100
- value={subField.state.value}
101
- onChange={(e) => subField.handleChange(e.target.value)}
102
- />
103
- )}
104
- </form.Field>
105
- ))
106
- }
107
- </form.Field>
108
- )
109
- }
110
- })