@tanstack/react-form 0.3.7 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/build/legacy/createFormFactory.cjs.map +1 -1
  2. package/build/legacy/createFormFactory.d.cts +5 -4
  3. package/build/legacy/createFormFactory.d.ts +5 -4
  4. package/build/legacy/createFormFactory.js.map +1 -1
  5. package/build/legacy/formContext.cjs.map +1 -1
  6. package/build/legacy/formContext.d.cts +2 -2
  7. package/build/legacy/formContext.d.ts +2 -2
  8. package/build/legacy/formContext.js.map +1 -1
  9. package/build/legacy/types.cjs.map +1 -1
  10. package/build/legacy/types.d.cts +1 -1
  11. package/build/legacy/types.d.ts +1 -1
  12. package/build/legacy/useField.cjs +6 -2
  13. package/build/legacy/useField.cjs.map +1 -1
  14. package/build/legacy/useField.d.cts +13 -12
  15. package/build/legacy/useField.d.ts +13 -12
  16. package/build/legacy/useField.js +6 -2
  17. package/build/legacy/useField.js.map +1 -1
  18. package/build/legacy/useForm.cjs.map +1 -1
  19. package/build/legacy/useForm.d.cts +3 -3
  20. package/build/legacy/useForm.d.ts +3 -3
  21. package/build/legacy/useForm.js.map +1 -1
  22. package/build/modern/createFormFactory.cjs.map +1 -1
  23. package/build/modern/createFormFactory.d.cts +5 -4
  24. package/build/modern/createFormFactory.d.ts +5 -4
  25. package/build/modern/createFormFactory.js.map +1 -1
  26. package/build/modern/formContext.cjs.map +1 -1
  27. package/build/modern/formContext.d.cts +2 -2
  28. package/build/modern/formContext.d.ts +2 -2
  29. package/build/modern/formContext.js.map +1 -1
  30. package/build/modern/types.cjs.map +1 -1
  31. package/build/modern/types.d.cts +1 -1
  32. package/build/modern/types.d.ts +1 -1
  33. package/build/modern/useField.cjs +6 -2
  34. package/build/modern/useField.cjs.map +1 -1
  35. package/build/modern/useField.d.cts +13 -12
  36. package/build/modern/useField.d.ts +13 -12
  37. package/build/modern/useField.js +6 -2
  38. package/build/modern/useField.js.map +1 -1
  39. package/build/modern/useForm.cjs.map +1 -1
  40. package/build/modern/useForm.d.cts +3 -3
  41. package/build/modern/useForm.d.ts +3 -3
  42. package/build/modern/useForm.js.map +1 -1
  43. package/package.json +2 -2
  44. package/src/createFormFactory.ts +9 -7
  45. package/src/formContext.ts +1 -1
  46. package/src/tests/createFormFactory.test.tsx +1 -1
  47. package/src/tests/useField.test.tsx +8 -8
  48. package/src/tests/useForm.test.tsx +2 -2
  49. package/src/types.ts +4 -2
  50. package/src/useField.tsx +72 -23
  51. package/src/useForm.tsx +5 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport type { DeepKeys, DeepValue, Narrow } from '@tanstack/form-core'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useFormContext, formContext } from './formContext'\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'\nimport type { UseFieldOptions } from './types'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TData>\n }\n}\n\nexport type UseField<TParentData> = <TName extends DeepKeys<TParentData>>(\n opts?: { name: Narrow<TName> } & UseFieldOptions<TParentData, TName>,\n) => FieldApi<TParentData, TName, DeepValue<TParentData, TName>>\n\nexport function useField<TParentData, TName extends DeepKeys<TParentData>>(\n opts: UseFieldOptions<TParentData, TName>,\n): FieldApi<\n TParentData,\n TName\n // Omit<typeof opts, 'onMount'> & {\n // form: FormApi<TParentData>\n // }\n> {\n // Get the form API either manually or from context\n const { formApi, parentFieldName } = useFormContext()\n\n const [fieldApi] = useState(() => {\n const name = (\n typeof opts.index === 'number'\n ? [parentFieldName, opts.index, opts.name]\n : [parentFieldName, opts.name]\n )\n .filter((d) => d !== undefined)\n .join('.')\n\n const api = new FieldApi({\n ...opts,\n form: formApi,\n name: name,\n } as never)\n\n api.Field = Field as never\n\n return api\n })\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, form: formApi } as never)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state: any) => {\n return [state.meta, Object.keys(state.value || []).length]\n }\n : undefined,\n )\n // Instantiates field meta and removes it when unrendered\n useIsomorphicLayoutEffect(() => fieldApi.mount(), [fieldApi])\n\n return fieldApi as never\n}\n\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n> = {\n children: (fieldApi: FieldApi<TParentData, TName, TData>) => any\n} & (TParentData extends any[]\n ? {\n name?: TName\n index: number\n }\n : {\n name: TName\n index?: never\n }) &\n Omit<UseFieldOptions<TParentData, TName>, 'name' | 'index'>\n\nexport type FieldComponent<TParentData> = <\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<TParentData, TName, TData>) => any\n\nexport function Field<TParentData, TName extends DeepKeys<TParentData>>({\n children,\n ...fieldOptions\n}: {\n children: (fieldApi: FieldApi<TParentData, TName>) => any\n} & UseFieldOptions<TParentData, TName>) {\n const fieldApi = useField(fieldOptions as any)\n\n return (\n <formContext.Provider\n value={{ formApi: fieldApi.form, parentFieldName: fieldApi.name }}\n children={functionalUpdate(children, fieldApi as any)}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAgC;AAChC,yBAAyB;AAEzB,uBAA2C;AAC3C,yBAA4C;AAC5C,0CAAsC;AAkB/B,SAAS,SACd,MAOA;AAEA,QAAM,EAAE,SAAS,gBAAgB,QAAI,mCAAe;AAEpD,QAAM,CAAC,QAAQ,QAAI,uBAAS,MAAM;AAChC,UAAM,QACJ,OAAO,KAAK,UAAU,WAClB,CAAC,iBAAiB,KAAK,OAAO,KAAK,IAAI,IACvC,CAAC,iBAAiB,KAAK,IAAI,GAE9B,OAAO,CAAC,MAAM,MAAM,MAAS,EAC7B,KAAK,GAAG;AAEX,UAAM,MAAM,IAAI,0BAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA,MACN;AAAA,IACF,CAAU;AAEV,QAAI,QAAQ;AAEZ,WAAO;AAAA,EACT,CAAC;AAMD,0CAAAA,SAA0B,MAAM;AAC9B,aAAS,OAAO,EAAE,GAAG,MAAM,MAAM,QAAQ,CAAU;AAAA,EACrD,CAAC;AAED;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAe;AACd,aAAO,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,SAAS,CAAC,CAAC,EAAE,MAAM;AAAA,IAC3D,IACA;AAAA,EACN;AAEA,0CAAAA,SAA0B,MAAM,SAAS,MAAM,GAAG,CAAC,QAAQ,CAAC;AAE5D,SAAO;AACT;AA2BO,SAAS,MAAwD;AAAA,EACtE;AAAA,EACA,GAAG;AACL,GAEyC;AACvC,QAAM,WAAW,SAAS,YAAmB;AAE7C,SACE,6BAAAC,QAAA;AAAA,IAAC,+BAAY;AAAA,IAAZ;AAAA,MACC,OAAO,EAAE,SAAS,SAAS,MAAM,iBAAiB,SAAS,KAAK;AAAA,MAChE,cAAU,mCAAiB,UAAU,QAAe;AAAA;AAAA,EACtD;AAEJ;","names":["useIsomorphicLayoutEffect","React"]}
1
+ {"version":3,"sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport type { DeepKeys, DeepValue, Narrow } from '@tanstack/form-core'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useFormContext, formContext } from './formContext'\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'\nimport type { UseFieldOptions } from './types'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TData, FormValidator>\n }\n}\n\nexport type UseField<TParentData> = <\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n>(\n opts?: { name: Narrow<TName> } & UseFieldOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator\n >,\n) => FieldApi<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n DeepValue<TParentData, TName>\n>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n>(\n opts: UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>,\n): FieldApi<\n TParentData,\n TName,\n ValidatorType,\n FormValidator\n // Omit<typeof opts, 'onMount'> & {\n // form: FormApi<TParentData>\n // }\n> {\n // Get the form API either manually or from context\n const { formApi, parentFieldName } = useFormContext()\n\n const [fieldApi] = useState(() => {\n const name = (\n typeof opts.index === 'number'\n ? [parentFieldName, opts.index, opts.name]\n : [parentFieldName, opts.name]\n )\n .filter((d) => d !== undefined)\n .join('.')\n\n const api = new FieldApi({\n ...opts,\n form: formApi,\n // TODO: Fix typings to include `index` and `parentFieldName`, if present\n name: name as typeof opts.name,\n })\n\n api.Field = Field as never\n\n return api\n })\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, form: formApi } as never)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [state.meta, Object.keys(state.value).length]\n }\n : undefined,\n )\n // Instantiates field meta and removes it when unrendered\n useIsomorphicLayoutEffect(() => fieldApi.mount(), [fieldApi])\n\n return fieldApi\n}\n\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = {\n children: (\n fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>,\n ) => any\n} & (TParentData extends any[]\n ? {\n name?: TName\n index: number\n }\n : {\n name: TName\n index?: never\n }) &\n Omit<\n UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>,\n 'name' | 'index'\n >\n\nexport type FieldComponent<TParentData, FormValidator> = <\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n>) => any\n\nexport function Field<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n>({\n children,\n ...fieldOptions\n}: {\n children: (\n fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator>,\n ) => any\n} & UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>) {\n const fieldApi = useField(fieldOptions as any)\n\n return (\n <formContext.Provider\n value={{\n formApi: fieldApi.form as never,\n parentFieldName: fieldApi.name,\n }}\n children={functionalUpdate(children, fieldApi as any)}\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAgC;AAChC,yBAAyB;AAEzB,uBAA2C;AAC3C,yBAA4C;AAC5C,0CAAsC;AAmC/B,SAAS,SAMd,MASA;AAEA,QAAM,EAAE,SAAS,gBAAgB,QAAI,mCAAe;AAEpD,QAAM,CAAC,QAAQ,QAAI,uBAAS,MAAM;AAChC,UAAM,QACJ,OAAO,KAAK,UAAU,WAClB,CAAC,iBAAiB,KAAK,OAAO,KAAK,IAAI,IACvC,CAAC,iBAAiB,KAAK,IAAI,GAE9B,OAAO,CAAC,MAAM,MAAM,MAAS,EAC7B,KAAK,GAAG;AAEX,UAAM,MAAM,IAAI,0BAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA;AAAA,MAEN;AAAA,IACF,CAAC;AAED,QAAI,QAAQ;AAEZ,WAAO;AAAA,EACT,CAAC;AAMD,0CAAAA,SAA0B,MAAM;AAC9B,aAAS,OAAO,EAAE,GAAG,MAAM,MAAM,QAAQ,CAAU;AAAA,EACrD,CAAC;AAED;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACT,aAAO,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAK,EAAE,MAAM;AAAA,IACrD,IACA;AAAA,EACN;AAEA,0CAAAA,SAA0B,MAAM,SAAS,MAAM,GAAG,CAAC,QAAQ,CAAC;AAE5D,SAAO;AACT;AAyCO,SAAS,MAKd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAIuE;AACrE,QAAM,WAAW,SAAS,YAAmB;AAE7C,SACE,6BAAAC,QAAA;AAAA,IAAC,+BAAY;AAAA,IAAZ;AAAA,MACC,OAAO;AAAA,QACL,SAAS,SAAS;AAAA,QAClB,iBAAiB,SAAS;AAAA,MAC5B;AAAA,MACA,cAAU,mCAAiB,UAAU,QAAe;AAAA;AAAA,EACtD;AAEJ;","names":["useIsomorphicLayoutEffect","React"]}
@@ -1,27 +1,28 @@
1
+ import React__default from 'react';
1
2
  import { DeepKeys, DeepValue, Narrow, FieldApi } from '@tanstack/form-core';
2
3
  import { UseFieldOptions } from './types.cjs';
3
4
 
4
5
  declare module '@tanstack/form-core' {
5
- interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> {
6
- Field: FieldComponent<TData>;
6
+ interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
7
+ Field: FieldComponent<TData, FormValidator>;
7
8
  }
8
9
  }
9
- type UseField<TParentData> = <TName extends DeepKeys<TParentData>>(opts?: {
10
+ type UseField<TParentData> = <TName extends DeepKeys<TParentData>, ValidatorType, FormValidator>(opts?: {
10
11
  name: Narrow<TName>;
11
- } & UseFieldOptions<TParentData, TName>) => FieldApi<TParentData, TName, DeepValue<TParentData, TName>>;
12
- declare function useField<TParentData, TName extends DeepKeys<TParentData>>(opts: UseFieldOptions<TParentData, TName>): FieldApi<TParentData, TName>;
13
- type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> = {
14
- children: (fieldApi: FieldApi<TParentData, TName, TData>) => any;
12
+ } & UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>) => FieldApi<TParentData, TName, ValidatorType, FormValidator, DeepValue<TParentData, TName>>;
13
+ declare function useField<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator>(opts: UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>): FieldApi<TParentData, TName, ValidatorType, FormValidator>;
14
+ type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = {
15
+ children: (fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>) => any;
15
16
  } & (TParentData extends any[] ? {
16
17
  name?: TName;
17
18
  index: number;
18
19
  } : {
19
20
  name: TName;
20
21
  index?: never;
21
- }) & Omit<UseFieldOptions<TParentData, TName>, 'name' | 'index'>;
22
- type FieldComponent<TParentData> = <TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: FieldComponentProps<TParentData, TName, TData>) => any;
23
- declare function Field<TParentData, TName extends DeepKeys<TParentData>>({ children, ...fieldOptions }: {
24
- children: (fieldApi: FieldApi<TParentData, TName>) => any;
25
- } & UseFieldOptions<TParentData, TName>): JSX.Element;
22
+ }) & Omit<UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>, 'name' | 'index'>;
23
+ type FieldComponent<TParentData, FormValidator> = <TName extends DeepKeys<TParentData>, ValidatorType, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: FieldComponentProps<TParentData, TName, ValidatorType, FormValidator, TData>) => any;
24
+ declare function Field<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator>({ children, ...fieldOptions }: {
25
+ children: (fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator>) => any;
26
+ } & UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>): React__default.JSX.Element;
26
27
 
27
28
  export { Field, FieldComponent, UseField, useField };
@@ -1,27 +1,28 @@
1
+ import React__default from 'react';
1
2
  import { DeepKeys, DeepValue, Narrow, FieldApi } from '@tanstack/form-core';
2
3
  import { UseFieldOptions } from './types.js';
3
4
 
4
5
  declare module '@tanstack/form-core' {
5
- interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> {
6
- Field: FieldComponent<TData>;
6
+ interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> {
7
+ Field: FieldComponent<TData, FormValidator>;
7
8
  }
8
9
  }
9
- type UseField<TParentData> = <TName extends DeepKeys<TParentData>>(opts?: {
10
+ type UseField<TParentData> = <TName extends DeepKeys<TParentData>, ValidatorType, FormValidator>(opts?: {
10
11
  name: Narrow<TName>;
11
- } & UseFieldOptions<TParentData, TName>) => FieldApi<TParentData, TName, DeepValue<TParentData, TName>>;
12
- declare function useField<TParentData, TName extends DeepKeys<TParentData>>(opts: UseFieldOptions<TParentData, TName>): FieldApi<TParentData, TName>;
13
- type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> = {
14
- children: (fieldApi: FieldApi<TParentData, TName, TData>) => any;
12
+ } & UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>) => FieldApi<TParentData, TName, ValidatorType, FormValidator, DeepValue<TParentData, TName>>;
13
+ declare function useField<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator>(opts: UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>): FieldApi<TParentData, TName, ValidatorType, FormValidator>;
14
+ type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = {
15
+ children: (fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>) => any;
15
16
  } & (TParentData extends any[] ? {
16
17
  name?: TName;
17
18
  index: number;
18
19
  } : {
19
20
  name: TName;
20
21
  index?: never;
21
- }) & Omit<UseFieldOptions<TParentData, TName>, 'name' | 'index'>;
22
- type FieldComponent<TParentData> = <TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: FieldComponentProps<TParentData, TName, TData>) => any;
23
- declare function Field<TParentData, TName extends DeepKeys<TParentData>>({ children, ...fieldOptions }: {
24
- children: (fieldApi: FieldApi<TParentData, TName>) => any;
25
- } & UseFieldOptions<TParentData, TName>): JSX.Element;
22
+ }) & Omit<UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>, 'name' | 'index'>;
23
+ type FieldComponent<TParentData, FormValidator> = <TName extends DeepKeys<TParentData>, ValidatorType, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: FieldComponentProps<TParentData, TName, ValidatorType, FormValidator, TData>) => any;
24
+ declare function Field<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator>({ children, ...fieldOptions }: {
25
+ children: (fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator>) => any;
26
+ } & UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>): React__default.JSX.Element;
26
27
 
27
28
  export { Field, FieldComponent, UseField, useField };
@@ -11,6 +11,7 @@ function useField(opts) {
11
11
  const api = new FieldApi({
12
12
  ...opts,
13
13
  form: formApi,
14
+ // TODO: Fix typings to include `index` and `parentFieldName`, if present
14
15
  name
15
16
  });
16
17
  api.Field = Field;
@@ -22,7 +23,7 @@ function useField(opts) {
22
23
  useStore(
23
24
  fieldApi.store,
24
25
  opts.mode === "array" ? (state) => {
25
- return [state.meta, Object.keys(state.value || []).length];
26
+ return [state.meta, Object.keys(state.value).length];
26
27
  } : void 0
27
28
  );
28
29
  useIsomorphicLayoutEffect(() => fieldApi.mount(), [fieldApi]);
@@ -36,7 +37,10 @@ function Field({
36
37
  return /* @__PURE__ */ React.createElement(
37
38
  formContext.Provider,
38
39
  {
39
- value: { formApi: fieldApi.form, parentFieldName: fieldApi.name },
40
+ value: {
41
+ formApi: fieldApi.form,
42
+ parentFieldName: fieldApi.name
43
+ },
40
44
  children: functionalUpdate(children, fieldApi)
41
45
  }
42
46
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport type { DeepKeys, DeepValue, Narrow } from '@tanstack/form-core'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useFormContext, formContext } from './formContext'\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'\nimport type { UseFieldOptions } from './types'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TData>\n }\n}\n\nexport type UseField<TParentData> = <TName extends DeepKeys<TParentData>>(\n opts?: { name: Narrow<TName> } & UseFieldOptions<TParentData, TName>,\n) => FieldApi<TParentData, TName, DeepValue<TParentData, TName>>\n\nexport function useField<TParentData, TName extends DeepKeys<TParentData>>(\n opts: UseFieldOptions<TParentData, TName>,\n): FieldApi<\n TParentData,\n TName\n // Omit<typeof opts, 'onMount'> & {\n // form: FormApi<TParentData>\n // }\n> {\n // Get the form API either manually or from context\n const { formApi, parentFieldName } = useFormContext()\n\n const [fieldApi] = useState(() => {\n const name = (\n typeof opts.index === 'number'\n ? [parentFieldName, opts.index, opts.name]\n : [parentFieldName, opts.name]\n )\n .filter((d) => d !== undefined)\n .join('.')\n\n const api = new FieldApi({\n ...opts,\n form: formApi,\n name: name,\n } as never)\n\n api.Field = Field as never\n\n return api\n })\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, form: formApi } as never)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state: any) => {\n return [state.meta, Object.keys(state.value || []).length]\n }\n : undefined,\n )\n // Instantiates field meta and removes it when unrendered\n useIsomorphicLayoutEffect(() => fieldApi.mount(), [fieldApi])\n\n return fieldApi as never\n}\n\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n> = {\n children: (fieldApi: FieldApi<TParentData, TName, TData>) => any\n} & (TParentData extends any[]\n ? {\n name?: TName\n index: number\n }\n : {\n name: TName\n index?: never\n }) &\n Omit<UseFieldOptions<TParentData, TName>, 'name' | 'index'>\n\nexport type FieldComponent<TParentData> = <\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<TParentData, TName, TData>) => any\n\nexport function Field<TParentData, TName extends DeepKeys<TParentData>>({\n children,\n ...fieldOptions\n}: {\n children: (fieldApi: FieldApi<TParentData, TName>) => any\n} & UseFieldOptions<TParentData, TName>) {\n const fieldApi = useField(fieldOptions as any)\n\n return (\n <formContext.Provider\n value={{ formApi: fieldApi.form, parentFieldName: fieldApi.name }}\n children={functionalUpdate(children, fieldApi as any)}\n />\n )\n}\n"],"mappings":";AAAA,OAAO,SAAS,gBAAgB;AAChC,SAAS,gBAAgB;AAEzB,SAAS,UAAU,wBAAwB;AAC3C,SAAS,gBAAgB,mBAAmB;AAC5C,OAAO,+BAA+B;AAkB/B,SAAS,SACd,MAOA;AAEA,QAAM,EAAE,SAAS,gBAAgB,IAAI,eAAe;AAEpD,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM;AAChC,UAAM,QACJ,OAAO,KAAK,UAAU,WAClB,CAAC,iBAAiB,KAAK,OAAO,KAAK,IAAI,IACvC,CAAC,iBAAiB,KAAK,IAAI,GAE9B,OAAO,CAAC,MAAM,MAAM,MAAS,EAC7B,KAAK,GAAG;AAEX,UAAM,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA,MACN;AAAA,IACF,CAAU;AAEV,QAAI,QAAQ;AAEZ,WAAO;AAAA,EACT,CAAC;AAMD,4BAA0B,MAAM;AAC9B,aAAS,OAAO,EAAE,GAAG,MAAM,MAAM,QAAQ,CAAU;AAAA,EACrD,CAAC;AAED;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAe;AACd,aAAO,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,SAAS,CAAC,CAAC,EAAE,MAAM;AAAA,IAC3D,IACA;AAAA,EACN;AAEA,4BAA0B,MAAM,SAAS,MAAM,GAAG,CAAC,QAAQ,CAAC;AAE5D,SAAO;AACT;AA2BO,SAAS,MAAwD;AAAA,EACtE;AAAA,EACA,GAAG;AACL,GAEyC;AACvC,QAAM,WAAW,SAAS,YAAmB;AAE7C,SACE;AAAA,IAAC,YAAY;AAAA,IAAZ;AAAA,MACC,OAAO,EAAE,SAAS,SAAS,MAAM,iBAAiB,SAAS,KAAK;AAAA,MAChE,UAAU,iBAAiB,UAAU,QAAe;AAAA;AAAA,EACtD;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport type { DeepKeys, DeepValue, Narrow } from '@tanstack/form-core'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useFormContext, formContext } from './formContext'\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'\nimport type { UseFieldOptions } from './types'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TData, FormValidator>\n }\n}\n\nexport type UseField<TParentData> = <\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n>(\n opts?: { name: Narrow<TName> } & UseFieldOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator\n >,\n) => FieldApi<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n DeepValue<TParentData, TName>\n>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n>(\n opts: UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>,\n): FieldApi<\n TParentData,\n TName,\n ValidatorType,\n FormValidator\n // Omit<typeof opts, 'onMount'> & {\n // form: FormApi<TParentData>\n // }\n> {\n // Get the form API either manually or from context\n const { formApi, parentFieldName } = useFormContext()\n\n const [fieldApi] = useState(() => {\n const name = (\n typeof opts.index === 'number'\n ? [parentFieldName, opts.index, opts.name]\n : [parentFieldName, opts.name]\n )\n .filter((d) => d !== undefined)\n .join('.')\n\n const api = new FieldApi({\n ...opts,\n form: formApi,\n // TODO: Fix typings to include `index` and `parentFieldName`, if present\n name: name as typeof opts.name,\n })\n\n api.Field = Field as never\n\n return api\n })\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, form: formApi } as never)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [state.meta, Object.keys(state.value).length]\n }\n : undefined,\n )\n // Instantiates field meta and removes it when unrendered\n useIsomorphicLayoutEffect(() => fieldApi.mount(), [fieldApi])\n\n return fieldApi\n}\n\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = {\n children: (\n fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>,\n ) => any\n} & (TParentData extends any[]\n ? {\n name?: TName\n index: number\n }\n : {\n name: TName\n index?: never\n }) &\n Omit<\n UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>,\n 'name' | 'index'\n >\n\nexport type FieldComponent<TParentData, FormValidator> = <\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n>) => any\n\nexport function Field<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n>({\n children,\n ...fieldOptions\n}: {\n children: (\n fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator>,\n ) => any\n} & UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>) {\n const fieldApi = useField(fieldOptions as any)\n\n return (\n <formContext.Provider\n value={{\n formApi: fieldApi.form as never,\n parentFieldName: fieldApi.name,\n }}\n children={functionalUpdate(children, fieldApi as any)}\n />\n )\n}\n"],"mappings":";AAAA,OAAO,SAAS,gBAAgB;AAChC,SAAS,gBAAgB;AAEzB,SAAS,UAAU,wBAAwB;AAC3C,SAAS,gBAAgB,mBAAmB;AAC5C,OAAO,+BAA+B;AAmC/B,SAAS,SAMd,MASA;AAEA,QAAM,EAAE,SAAS,gBAAgB,IAAI,eAAe;AAEpD,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM;AAChC,UAAM,QACJ,OAAO,KAAK,UAAU,WAClB,CAAC,iBAAiB,KAAK,OAAO,KAAK,IAAI,IACvC,CAAC,iBAAiB,KAAK,IAAI,GAE9B,OAAO,CAAC,MAAM,MAAM,MAAS,EAC7B,KAAK,GAAG;AAEX,UAAM,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA;AAAA,MAEN;AAAA,IACF,CAAC;AAED,QAAI,QAAQ;AAEZ,WAAO;AAAA,EACT,CAAC;AAMD,4BAA0B,MAAM;AAC9B,aAAS,OAAO,EAAE,GAAG,MAAM,MAAM,QAAQ,CAAU;AAAA,EACrD,CAAC;AAED;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACT,aAAO,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAK,EAAE,MAAM;AAAA,IACrD,IACA;AAAA,EACN;AAEA,4BAA0B,MAAM,SAAS,MAAM,GAAG,CAAC,QAAQ,CAAC;AAE5D,SAAO;AACT;AAyCO,SAAS,MAKd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAIuE;AACrE,QAAM,WAAW,SAAS,YAAmB;AAE7C,SACE;AAAA,IAAC,YAAY;AAAA,IAAZ;AAAA,MACC,OAAO;AAAA,QACL,SAAS,SAAS;AAAA,QAClB,iBAAiB,SAAS;AAAA,MAC5B;AAAA,MACA,UAAU,iBAAiB,UAAU,QAAe;AAAA;AAAA,EACtD;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useForm.tsx"],"sourcesContent":["import type { FormState, FormOptions } from '@tanstack/form-core'\nimport { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport type { NoInfer } from '@tanstack/react-store'\nimport { useStore } from '@tanstack/react-store'\nimport React, { type ReactNode, useState } from 'react'\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { formContext } from './formContext'\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData> {\n Provider: (props: { children: any }) => any\n Field: FieldComponent<TFormData>\n useField: UseField<TFormData>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => any\n }\n}\n\nexport function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData> {\n const [formApi] = useState(() => {\n // @ts-ignore\n const api = new FormApi<TData>(opts)\n\n api.Provider = function Provider(props) {\n return <formContext.Provider {...props} value={{ formApi: api }} />\n }\n api.Field = Field as any\n api.useField = useField as any\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 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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAA0C;AAE1C,yBAAyB;AACzB,mBAAgD;AAChD,sBAAoE;AACpE,yBAA4B;AAC5B,0CAAsC;AAkB/B,SAAS,QAAe,MAA2C;AACxE,QAAM,CAAC,OAAO,QAAI,uBAAS,MAAM;AAE/B,UAAM,MAAM,IAAI,yBAAe,IAAI;AAEnC,QAAI,WAAW,SAAS,SAAS,OAAO;AACtC,aAAO,6BAAAA,QAAA,cAAC,+BAAY,UAAZ,EAAsB,GAAG,OAAO,OAAO,EAAE,SAAS,IAAI,GAAG;AAAA,IACnE;AACA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,WAAW,CAEb,aACG;AAEH,iBAAO,6BAAS,IAAI,OAAc,QAAe;AAAA,IACnD;AACA,QAAI,YAAY,CAEd,UACG;AACH,iBAAO;AAAA,QACL,MAAM;AAAA;AAAA,YAEN,6BAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAClD;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AAED,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9C,0CAAAC,SAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EACrB,CAAC;AAED,SAAO;AACT;","names":["React","useIsomorphicLayoutEffect"]}
1
+ {"version":3,"sources":["../../src/useForm.tsx"],"sourcesContent":["import type { FormState, FormOptions } from '@tanstack/form-core'\nimport { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport type { NoInfer } from '@tanstack/react-store'\nimport { useStore } from '@tanstack/react-store'\nimport React, { type ReactNode, useState } from 'react'\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { formContext } from './formContext'\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, ValidatorType> {\n Provider: (props: { children: any }) => any\n Field: FieldComponent<TFormData, ValidatorType>\n useField: UseField<TFormData>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => any\n }\n}\n\nexport function useForm<TData, FormValidator>(\n opts?: FormOptions<TData, FormValidator>,\n): FormApi<TData, FormValidator> {\n const [formApi] = useState(() => {\n // @ts-ignore\n const api = new FormApi<TData>(opts)\n\n api.Provider = function Provider(props) {\n return <formContext.Provider {...props} value={{ formApi: api }} />\n }\n api.Field = Field as any\n api.useField = useField as any\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 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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAA0C;AAE1C,yBAAyB;AACzB,mBAAgD;AAChD,sBAAoE;AACpE,yBAA4B;AAC5B,0CAAsC;AAkB/B,SAAS,QACd,MAC+B;AAC/B,QAAM,CAAC,OAAO,QAAI,uBAAS,MAAM;AAE/B,UAAM,MAAM,IAAI,yBAAe,IAAI;AAEnC,QAAI,WAAW,SAAS,SAAS,OAAO;AACtC,aAAO,6BAAAA,QAAA,cAAC,+BAAY,UAAZ,EAAsB,GAAG,OAAO,OAAO,EAAE,SAAS,IAAI,GAAG;AAAA,IACnE;AACA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,WAAW,CAEb,aACG;AAEH,iBAAO,6BAAS,IAAI,OAAc,QAAe;AAAA,IACnD;AACA,QAAI,YAAY,CAEd,UACG;AACH,iBAAO;AAAA,QACL,MAAM;AAAA;AAAA,YAEN,6BAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAClD;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AAED,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9C,0CAAAC,SAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EACrB,CAAC;AAED,SAAO;AACT;","names":["React","useIsomorphicLayoutEffect"]}
@@ -5,11 +5,11 @@ import { FieldComponent, UseField } from './useField.cjs';
5
5
  import './types.cjs';
6
6
 
7
7
  declare module '@tanstack/form-core' {
8
- interface FormApi<TFormData> {
8
+ interface FormApi<TFormData, ValidatorType> {
9
9
  Provider: (props: {
10
10
  children: any;
11
11
  }) => any;
12
- Field: FieldComponent<TFormData>;
12
+ Field: FieldComponent<TFormData, ValidatorType>;
13
13
  useField: UseField<TFormData>;
14
14
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
15
15
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
@@ -18,6 +18,6 @@ declare module '@tanstack/form-core' {
18
18
  }) => any;
19
19
  }
20
20
  }
21
- declare function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData>;
21
+ declare function useForm<TData, FormValidator>(opts?: FormOptions<TData, FormValidator>): FormApi<TData, FormValidator>;
22
22
 
23
23
  export { useForm };
@@ -5,11 +5,11 @@ import { FieldComponent, UseField } from './useField.js';
5
5
  import './types.js';
6
6
 
7
7
  declare module '@tanstack/form-core' {
8
- interface FormApi<TFormData> {
8
+ interface FormApi<TFormData, ValidatorType> {
9
9
  Provider: (props: {
10
10
  children: any;
11
11
  }) => any;
12
- Field: FieldComponent<TFormData>;
12
+ Field: FieldComponent<TFormData, ValidatorType>;
13
13
  useField: UseField<TFormData>;
14
14
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
15
15
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
@@ -18,6 +18,6 @@ declare module '@tanstack/form-core' {
18
18
  }) => any;
19
19
  }
20
20
  }
21
- declare function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData>;
21
+ declare function useForm<TData, FormValidator>(opts?: FormOptions<TData, FormValidator>): FormApi<TData, FormValidator>;
22
22
 
23
23
  export { useForm };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useForm.tsx"],"sourcesContent":["import type { FormState, FormOptions } from '@tanstack/form-core'\nimport { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport type { NoInfer } from '@tanstack/react-store'\nimport { useStore } from '@tanstack/react-store'\nimport React, { type ReactNode, useState } from 'react'\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { formContext } from './formContext'\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData> {\n Provider: (props: { children: any }) => any\n Field: FieldComponent<TFormData>\n useField: UseField<TFormData>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => any\n }\n}\n\nexport function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData> {\n const [formApi] = useState(() => {\n // @ts-ignore\n const api = new FormApi<TData>(opts)\n\n api.Provider = function Provider(props) {\n return <formContext.Provider {...props} value={{ formApi: api }} />\n }\n api.Field = Field as any\n api.useField = useField as any\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 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"],"mappings":";AACA,SAAS,SAAS,wBAAwB;AAE1C,SAAS,gBAAgB;AACzB,OAAO,SAAyB,gBAAgB;AAChD,SAA6C,OAAO,gBAAgB;AACpE,SAAS,mBAAmB;AAC5B,OAAO,+BAA+B;AAkB/B,SAAS,QAAe,MAA2C;AACxE,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AAE/B,UAAM,MAAM,IAAI,QAAe,IAAI;AAEnC,QAAI,WAAW,SAAS,SAAS,OAAO;AACtC,aAAO,oCAAC,YAAY,UAAZ,EAAsB,GAAG,OAAO,OAAO,EAAE,SAAS,IAAI,GAAG;AAAA,IACnE;AACA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,WAAW,CAEb,aACG;AAEH,aAAO,SAAS,IAAI,OAAc,QAAe;AAAA,IACnD;AACA,QAAI,YAAY,CAEd,UACG;AACH,aAAO;AAAA,QACL,MAAM;AAAA;AAAA,QAEN,SAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAClD;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AAED,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9C,4BAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EACrB,CAAC;AAED,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/useForm.tsx"],"sourcesContent":["import type { FormState, FormOptions } from '@tanstack/form-core'\nimport { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport type { NoInfer } from '@tanstack/react-store'\nimport { useStore } from '@tanstack/react-store'\nimport React, { type ReactNode, useState } from 'react'\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { formContext } from './formContext'\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, ValidatorType> {\n Provider: (props: { children: any }) => any\n Field: FieldComponent<TFormData, ValidatorType>\n useField: UseField<TFormData>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => any\n }\n}\n\nexport function useForm<TData, FormValidator>(\n opts?: FormOptions<TData, FormValidator>,\n): FormApi<TData, FormValidator> {\n const [formApi] = useState(() => {\n // @ts-ignore\n const api = new FormApi<TData>(opts)\n\n api.Provider = function Provider(props) {\n return <formContext.Provider {...props} value={{ formApi: api }} />\n }\n api.Field = Field as any\n api.useField = useField as any\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 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"],"mappings":";AACA,SAAS,SAAS,wBAAwB;AAE1C,SAAS,gBAAgB;AACzB,OAAO,SAAyB,gBAAgB;AAChD,SAA6C,OAAO,gBAAgB;AACpE,SAAS,mBAAmB;AAC5B,OAAO,+BAA+B;AAkB/B,SAAS,QACd,MAC+B;AAC/B,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AAE/B,UAAM,MAAM,IAAI,QAAe,IAAI;AAEnC,QAAI,WAAW,SAAS,SAAS,OAAO;AACtC,aAAO,oCAAC,YAAY,UAAZ,EAAsB,GAAG,OAAO,OAAO,EAAE,SAAS,IAAI,GAAG;AAAA,IACnE;AACA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,WAAW,CAEb,aACG;AAEH,aAAO,SAAS,IAAI,OAAc,QAAe;AAAA,IACnD;AACA,QAAI,YAAY,CAEd,UACG;AACH,aAAO;AAAA,QACL,MAAM;AAAA;AAAA,QAEN,SAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAClD;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AAED,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9C,4BAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EACrB,CAAC;AAED,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-form",
3
- "version": "0.3.7",
3
+ "version": "0.4.1",
4
4
  "description": "Powerful, type-safe forms for React.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -54,7 +54,7 @@
54
54
  "@tanstack/react-store": "0.1.3",
55
55
  "@tanstack/store": "0.1.3",
56
56
  "use-isomorphic-layout-effect": "^1.1.2",
57
- "@tanstack/form-core": "0.3.7"
57
+ "@tanstack/form-core": "0.4.1"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "react": "^17.0.0 || ^18.0.0",
@@ -3,19 +3,21 @@ import type { FormApi, FormOptions } from '@tanstack/form-core'
3
3
  import { type UseField, type FieldComponent, Field, useField } from './useField'
4
4
  import { useForm } from './useForm'
5
5
 
6
- export type FormFactory<TFormData> = {
7
- useForm: (opts?: FormOptions<TFormData>) => FormApi<TFormData>
6
+ export type FormFactory<TFormData, FormValidator> = {
7
+ useForm: (
8
+ opts?: FormOptions<TFormData, FormValidator>,
9
+ ) => FormApi<TFormData, FormValidator>
8
10
  useField: UseField<TFormData>
9
- Field: FieldComponent<TFormData>
11
+ Field: FieldComponent<TFormData, FormValidator>
10
12
  }
11
13
 
12
- export function createFormFactory<TFormData>(
13
- defaultOpts?: FormOptions<TFormData>,
14
- ): FormFactory<TFormData> {
14
+ export function createFormFactory<TFormData, FormValidator>(
15
+ defaultOpts?: FormOptions<TFormData, FormValidator>,
16
+ ): FormFactory<TFormData, FormValidator> {
15
17
  return {
16
18
  useForm: (opts) => {
17
19
  const formOptions = Object.assign({}, defaultOpts, opts)
18
- return useForm<TFormData>(formOptions)
20
+ return useForm<TFormData, FormValidator>(formOptions)
19
21
  },
20
22
  useField: useField as any,
21
23
  Field: Field as any,
@@ -2,7 +2,7 @@ import type { FormApi } from '@tanstack/form-core'
2
2
  import * as React from 'react'
3
3
 
4
4
  export const formContext = React.createContext<{
5
- formApi: FormApi<any>
5
+ formApi: FormApi<any, unknown>
6
6
  parentFieldName?: string
7
7
  } | null>(null!)
8
8
 
@@ -11,7 +11,7 @@ describe('createFormFactory', () => {
11
11
  lastName: string
12
12
  }
13
13
 
14
- const formFactory = createFormFactory<Person>({
14
+ const formFactory = createFormFactory<Person, unknown>({
15
15
  defaultValues: {
16
16
  firstName: 'FirstName',
17
17
  lastName: 'LastName',
@@ -15,7 +15,7 @@ describe('useField', () => {
15
15
  lastName: string
16
16
  }
17
17
 
18
- const formFactory = createFormFactory<Person>()
18
+ const formFactory = createFormFactory<Person, unknown>()
19
19
 
20
20
  function Comp() {
21
21
  const form = formFactory.useForm({
@@ -55,7 +55,7 @@ describe('useField', () => {
55
55
  lastName: string
56
56
  }
57
57
 
58
- const formFactory = createFormFactory<Person>()
58
+ const formFactory = createFormFactory<Person, unknown>()
59
59
 
60
60
  function Comp() {
61
61
  const form = formFactory.useForm({
@@ -97,7 +97,7 @@ describe('useField', () => {
97
97
  }
98
98
  const error = 'Please enter a different value'
99
99
 
100
- const formFactory = createFormFactory<Person>()
100
+ const formFactory = createFormFactory<Person, unknown>()
101
101
 
102
102
  function Comp() {
103
103
  const form = formFactory.useForm()
@@ -137,7 +137,7 @@ describe('useField', () => {
137
137
  }
138
138
  const error = 'Please enter a different value'
139
139
 
140
- const formFactory = createFormFactory<Person>()
140
+ const formFactory = createFormFactory<Person, unknown>()
141
141
 
142
142
  function Comp() {
143
143
  const form = formFactory.useForm()
@@ -180,7 +180,7 @@ describe('useField', () => {
180
180
  const onChangeError = 'Please enter a different value (onChangeError)'
181
181
  const onBlurError = 'Please enter a different value (onBlurError)'
182
182
 
183
- const formFactory = createFormFactory<Person>()
183
+ const formFactory = createFormFactory<Person, unknown>()
184
184
 
185
185
  function Comp() {
186
186
  const form = formFactory.useForm()
@@ -229,7 +229,7 @@ describe('useField', () => {
229
229
  }
230
230
  const error = 'Please enter a different value'
231
231
 
232
- const formFactory = createFormFactory<Person>()
232
+ const formFactory = createFormFactory<Person, unknown>()
233
233
 
234
234
  function Comp() {
235
235
  const form = formFactory.useForm()
@@ -276,7 +276,7 @@ describe('useField', () => {
276
276
  const onChangeError = 'Please enter a different value (onChangeError)'
277
277
  const onBlurError = 'Please enter a different value (onBlurError)'
278
278
 
279
- const formFactory = createFormFactory<Person>()
279
+ const formFactory = createFormFactory<Person, unknown>()
280
280
 
281
281
  function Comp() {
282
282
  const form = formFactory.useForm()
@@ -332,7 +332,7 @@ describe('useField', () => {
332
332
  }
333
333
  const mockFn = vi.fn()
334
334
  const error = 'Please enter a different value'
335
- const formFactory = createFormFactory<Person>()
335
+ const formFactory = createFormFactory<Person, unknown>()
336
336
 
337
337
  function Comp() {
338
338
  const form = formFactory.useForm()
@@ -14,7 +14,7 @@ describe('useForm', () => {
14
14
  lastName: string
15
15
  }
16
16
 
17
- const formFactory = createFormFactory<Person>()
17
+ const formFactory = createFormFactory<Person, unknown>()
18
18
 
19
19
  function Comp() {
20
20
  const form = formFactory.useForm()
@@ -52,7 +52,7 @@ describe('useForm', () => {
52
52
  lastName: string
53
53
  }
54
54
 
55
- const formFactory = createFormFactory<Person>()
55
+ const formFactory = createFormFactory<Person, unknown>()
56
56
 
57
57
  function Comp() {
58
58
  const form = formFactory.useForm({
package/src/types.ts CHANGED
@@ -3,7 +3,9 @@ import type { FieldOptions, DeepKeys, DeepValue } from '@tanstack/form-core'
3
3
  export type UseFieldOptions<
4
4
  TParentData,
5
5
  TName extends DeepKeys<TParentData>,
6
- TData = DeepValue<TParentData, TName>,
7
- > = FieldOptions<TParentData, TName, TData> & {
6
+ ValidatorType,
7
+ FormValidator,
8
+ TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
9
+ > = FieldOptions<TParentData, TName, ValidatorType, FormValidator, TData> & {
8
10
  mode?: 'value' | 'array'
9
11
  }
package/src/useField.tsx CHANGED
@@ -11,21 +11,45 @@ declare module '@tanstack/form-core' {
11
11
  interface FieldApi<
12
12
  TParentData,
13
13
  TName extends DeepKeys<TParentData>,
14
- TData = DeepValue<TParentData, TName>,
14
+ ValidatorType,
15
+ FormValidator,
16
+ TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
15
17
  > {
16
- Field: FieldComponent<TData>
18
+ Field: FieldComponent<TData, FormValidator>
17
19
  }
18
20
  }
19
21
 
20
- export type UseField<TParentData> = <TName extends DeepKeys<TParentData>>(
21
- opts?: { name: Narrow<TName> } & UseFieldOptions<TParentData, TName>,
22
- ) => FieldApi<TParentData, TName, DeepValue<TParentData, TName>>
22
+ export type UseField<TParentData> = <
23
+ TName extends DeepKeys<TParentData>,
24
+ ValidatorType,
25
+ FormValidator,
26
+ >(
27
+ opts?: { name: Narrow<TName> } & UseFieldOptions<
28
+ TParentData,
29
+ TName,
30
+ ValidatorType,
31
+ FormValidator
32
+ >,
33
+ ) => FieldApi<
34
+ TParentData,
35
+ TName,
36
+ ValidatorType,
37
+ FormValidator,
38
+ DeepValue<TParentData, TName>
39
+ >
23
40
 
24
- export function useField<TParentData, TName extends DeepKeys<TParentData>>(
25
- opts: UseFieldOptions<TParentData, TName>,
41
+ export function useField<
42
+ TParentData,
43
+ TName extends DeepKeys<TParentData>,
44
+ ValidatorType,
45
+ FormValidator,
46
+ >(
47
+ opts: UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>,
26
48
  ): FieldApi<
27
49
  TParentData,
28
- TName
50
+ TName,
51
+ ValidatorType,
52
+ FormValidator
29
53
  // Omit<typeof opts, 'onMount'> & {
30
54
  // form: FormApi<TParentData>
31
55
  // }
@@ -45,8 +69,9 @@ export function useField<TParentData, TName extends DeepKeys<TParentData>>(
45
69
  const api = new FieldApi({
46
70
  ...opts,
47
71
  form: formApi,
48
- name: name,
49
- } as never)
72
+ // TODO: Fix typings to include `index` and `parentFieldName`, if present
73
+ name: name as typeof opts.name,
74
+ })
50
75
 
51
76
  api.Field = Field as never
52
77
 
@@ -64,23 +89,27 @@ export function useField<TParentData, TName extends DeepKeys<TParentData>>(
64
89
  useStore(
65
90
  fieldApi.store,
66
91
  opts.mode === 'array'
67
- ? (state: any) => {
68
- return [state.meta, Object.keys(state.value || []).length]
92
+ ? (state) => {
93
+ return [state.meta, Object.keys(state.value).length]
69
94
  }
70
95
  : undefined,
71
96
  )
72
97
  // Instantiates field meta and removes it when unrendered
73
98
  useIsomorphicLayoutEffect(() => fieldApi.mount(), [fieldApi])
74
99
 
75
- return fieldApi as never
100
+ return fieldApi
76
101
  }
77
102
 
78
103
  type FieldComponentProps<
79
104
  TParentData,
80
105
  TName extends DeepKeys<TParentData>,
81
- TData = DeepValue<TParentData, TName>,
106
+ ValidatorType,
107
+ FormValidator,
108
+ TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
82
109
  > = {
83
- children: (fieldApi: FieldApi<TParentData, TName, TData>) => any
110
+ children: (
111
+ fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>,
112
+ ) => any
84
113
  } & (TParentData extends any[]
85
114
  ? {
86
115
  name?: TName
@@ -90,27 +119,47 @@ type FieldComponentProps<
90
119
  name: TName
91
120
  index?: never
92
121
  }) &
93
- Omit<UseFieldOptions<TParentData, TName>, 'name' | 'index'>
122
+ Omit<
123
+ UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>,
124
+ 'name' | 'index'
125
+ >
94
126
 
95
- export type FieldComponent<TParentData> = <
127
+ export type FieldComponent<TParentData, FormValidator> = <
96
128
  TName extends DeepKeys<TParentData>,
97
- TData = DeepValue<TParentData, TName>,
129
+ ValidatorType,
130
+ TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
98
131
  >({
99
132
  children,
100
133
  ...fieldOptions
101
- }: FieldComponentProps<TParentData, TName, TData>) => any
134
+ }: FieldComponentProps<
135
+ TParentData,
136
+ TName,
137
+ ValidatorType,
138
+ FormValidator,
139
+ TData
140
+ >) => any
102
141
 
103
- export function Field<TParentData, TName extends DeepKeys<TParentData>>({
142
+ export function Field<
143
+ TParentData,
144
+ TName extends DeepKeys<TParentData>,
145
+ ValidatorType,
146
+ FormValidator,
147
+ >({
104
148
  children,
105
149
  ...fieldOptions
106
150
  }: {
107
- children: (fieldApi: FieldApi<TParentData, TName>) => any
108
- } & UseFieldOptions<TParentData, TName>) {
151
+ children: (
152
+ fieldApi: FieldApi<TParentData, TName, ValidatorType, FormValidator>,
153
+ ) => any
154
+ } & UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>) {
109
155
  const fieldApi = useField(fieldOptions as any)
110
156
 
111
157
  return (
112
158
  <formContext.Provider
113
- value={{ formApi: fieldApi.form, parentFieldName: fieldApi.name }}
159
+ value={{
160
+ formApi: fieldApi.form as never,
161
+ parentFieldName: fieldApi.name,
162
+ }}
114
163
  children={functionalUpdate(children, fieldApi as any)}
115
164
  />
116
165
  )
package/src/useForm.tsx CHANGED
@@ -9,9 +9,9 @@ import useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect'
9
9
 
10
10
  declare module '@tanstack/form-core' {
11
11
  // eslint-disable-next-line no-shadow
12
- interface FormApi<TFormData> {
12
+ interface FormApi<TFormData, ValidatorType> {
13
13
  Provider: (props: { children: any }) => any
14
- Field: FieldComponent<TFormData>
14
+ Field: FieldComponent<TFormData, ValidatorType>
15
15
  useField: UseField<TFormData>
16
16
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(
17
17
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,
@@ -23,7 +23,9 @@ declare module '@tanstack/form-core' {
23
23
  }
24
24
  }
25
25
 
26
- export function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData> {
26
+ export function useForm<TData, FormValidator>(
27
+ opts?: FormOptions<TData, FormValidator>,
28
+ ): FormApi<TData, FormValidator> {
27
29
  const [formApi] = useState(() => {
28
30
  // @ts-ignore
29
31
  const api = new FormApi<TData>(opts)