@tanstack/react-form 0.13.6 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/cjs/createFormFactory.cjs.map +1 -1
  2. package/dist/cjs/createFormFactory.d.cts +3 -3
  3. package/dist/cjs/types.d.cts +2 -2
  4. package/dist/cjs/useField.cjs +5 -28
  5. package/dist/cjs/useField.cjs.map +1 -1
  6. package/dist/cjs/useField.d.cts +4 -12
  7. package/dist/cjs/useForm.cjs +4 -6
  8. package/dist/cjs/useForm.cjs.map +1 -1
  9. package/dist/cjs/useForm.d.cts +14 -4
  10. package/dist/esm/createFormFactory.d.ts +3 -3
  11. package/dist/esm/createFormFactory.js.map +1 -1
  12. package/dist/esm/types.d.ts +2 -2
  13. package/dist/esm/useField.d.ts +4 -12
  14. package/dist/esm/useField.js +7 -30
  15. package/dist/esm/useField.js.map +1 -1
  16. package/dist/esm/useForm.d.ts +14 -4
  17. package/dist/esm/useForm.js +4 -6
  18. package/dist/esm/useForm.js.map +1 -1
  19. package/package.json +3 -3
  20. package/src/createFormFactory.ts +4 -4
  21. package/src/tests/createFormFactory.test.tsx +4 -5
  22. package/src/tests/useField.test-d.tsx +5 -5
  23. package/src/tests/useField.test.tsx +257 -32
  24. package/src/tests/useForm.test-d.tsx +1 -1
  25. package/src/tests/useForm.test.tsx +48 -25
  26. package/src/types.ts +8 -2
  27. package/src/useField.tsx +26 -68
  28. package/src/useForm.tsx +19 -14
  29. package/dist/cjs/formContext.cjs +0 -14
  30. package/dist/cjs/formContext.cjs.map +0 -1
  31. package/dist/cjs/formContext.d.cts +0 -10
  32. package/dist/cjs/useIsomorphicEffectOnce.cjs +0 -30
  33. package/dist/cjs/useIsomorphicEffectOnce.cjs.map +0 -1
  34. package/dist/cjs/useIsomorphicEffectOnce.d.cts +0 -5
  35. package/dist/esm/formContext.d.ts +0 -10
  36. package/dist/esm/formContext.js +0 -14
  37. package/dist/esm/formContext.js.map +0 -1
  38. package/dist/esm/useIsomorphicEffectOnce.d.ts +0 -5
  39. package/dist/esm/useIsomorphicEffectOnce.js +0 -30
  40. package/dist/esm/useIsomorphicEffectOnce.js.map +0 -1
  41. package/src/formContext.ts +0 -17
  42. package/src/useIsomorphicEffectOnce.ts +0 -39
@@ -1 +1 @@
1
- {"version":3,"file":"createFormFactory.cjs","sources":["../../src/createFormFactory.ts"],"sourcesContent":["import { Field, useField } from './useField'\nimport { useForm } from './useForm'\nimport { getValidateFormData } from './validateFormData'\nimport type { ValidateFormData } from './validateFormData'\nimport type { FieldComponent, UseField } from './useField'\nimport type { FormApi, FormOptions, Validator } from '@tanstack/form-core'\n\nexport type FormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n useForm: (\n opts?: FormOptions<TFormData, TFormValidator>,\n ) => FormApi<TFormData, TFormValidator>\n useField: UseField<TFormData>\n Field: FieldComponent<TFormData, TFormValidator>\n validateFormData: ValidateFormData<TFormData, TFormValidator>\n initialFormState: Partial<FormApi<TFormData, TFormValidator>['state']>\n}\n\nexport function createFormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n defaultOpts?: FormOptions<TFormData, TFormValidator>,\n): FormFactory<TFormData, TFormValidator> {\n return {\n useForm: (opts) => {\n const formOptions = Object.assign({}, defaultOpts, opts)\n return useForm<TFormData, TFormValidator>(formOptions)\n },\n useField: useField as any,\n Field: Field as any,\n validateFormData: getValidateFormData(defaultOpts) as never,\n initialFormState: {\n errorMap: {\n onServer: undefined,\n },\n errors: [],\n },\n }\n}\n"],"names":["useForm","useField","Field","getValidateFormData"],"mappings":";;;;;AAoBO,SAAS,kBAId,aACwC;AACjC,SAAA;AAAA,IACL,SAAS,CAAC,SAAS;AACjB,YAAM,cAAc,OAAO,OAAO,CAAA,GAAI,aAAa,IAAI;AACvD,aAAOA,QAAAA,QAAmC,WAAW;AAAA,IACvD;AAAA,IAAA,UACAC,SAAA;AAAA,IAAA,OACAC,SAAA;AAAA,IACA,kBAAkBC,qCAAoB,WAAW;AAAA,IACjD,kBAAkB;AAAA,MAChB,UAAU;AAAA,QACR,UAAU;AAAA,MACZ;AAAA,MACA,QAAQ,CAAC;AAAA,IACX;AAAA,EAAA;AAEJ;;"}
1
+ {"version":3,"file":"createFormFactory.cjs","sources":["../../src/createFormFactory.ts"],"sourcesContent":["import { Field, useField } from './useField'\nimport { useForm } from './useForm'\nimport { getValidateFormData } from './validateFormData'\nimport type { ValidateFormData } from './validateFormData'\nimport type { FieldComponent, UseField } from './useField'\nimport type { FormApi, FormOptions, Validator } from '@tanstack/form-core'\n\nexport type FormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n useForm: (\n opts?: FormOptions<TFormData, TFormValidator>,\n ) => FormApi<TFormData, TFormValidator>\n useField: typeof useField\n Field: typeof Field\n validateFormData: ValidateFormData<TFormData, TFormValidator>\n initialFormState: Partial<FormApi<TFormData, TFormValidator>['state']>\n}\n\nexport function createFormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n defaultOpts?: FormOptions<TFormData, TFormValidator>,\n): FormFactory<TFormData, TFormValidator> {\n return {\n useForm: (opts) => {\n const formOptions = Object.assign({}, defaultOpts, opts)\n return useForm<TFormData, TFormValidator>(formOptions)\n },\n useField: useField,\n Field: Field,\n validateFormData: getValidateFormData(defaultOpts) as never,\n initialFormState: {\n errorMap: {\n onServer: undefined,\n },\n errors: [],\n },\n }\n}\n"],"names":["useForm","useField","Field","getValidateFormData"],"mappings":";;;;;AAoBO,SAAS,kBAId,aACwC;AACjC,SAAA;AAAA,IACL,SAAS,CAAC,SAAS;AACjB,YAAM,cAAc,OAAO,OAAO,CAAA,GAAI,aAAa,IAAI;AACvD,aAAOA,QAAAA,QAAmC,WAAW;AAAA,IACvD;AAAA,IAAA,UACAC,SAAA;AAAA,IAAA,OACAC,SAAA;AAAA,IACA,kBAAkBC,qCAAoB,WAAW;AAAA,IACjD,kBAAkB;AAAA,MAChB,UAAU;AAAA,QACR,UAAU;AAAA,MACZ;AAAA,MACA,QAAQ,CAAC;AAAA,IACX;AAAA,EAAA;AAEJ;;"}
@@ -1,10 +1,10 @@
1
+ import { Field, useField } from './useField.cjs';
1
2
  import type { ValidateFormData } from './validateFormData.cjs';
2
- import type { FieldComponent, UseField } from './useField.cjs';
3
3
  import type { FormApi, FormOptions, Validator } from '@tanstack/form-core';
4
4
  export type FormFactory<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined> = {
5
5
  useForm: (opts?: FormOptions<TFormData, TFormValidator>) => FormApi<TFormData, TFormValidator>;
6
- useField: UseField<TFormData>;
7
- Field: FieldComponent<TFormData, TFormValidator>;
6
+ useField: typeof useField;
7
+ Field: typeof Field;
8
8
  validateFormData: ValidateFormData<TFormData, TFormValidator>;
9
9
  initialFormState: Partial<FormApi<TFormData, TFormValidator>['state']>;
10
10
  };
@@ -1,4 +1,4 @@
1
- import type { DeepKeys, DeepValue, FieldOptions, Validator } from '@tanstack/form-core';
2
- 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>> = FieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData> & {
1
+ import type { DeepKeys, DeepValue, FieldApiOptions, Validator } from '@tanstack/form-core';
2
+ 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> & {
3
3
  mode?: 'value' | 'array';
4
4
  };
@@ -4,24 +4,20 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const rehackt = require("rehackt");
5
5
  const reactStore = require("@tanstack/react-store");
6
6
  const formCore = require("@tanstack/form-core");
7
- const formContext = require("./formContext.cjs");
8
7
  const useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect.cjs");
9
- const useIsomorphicEffectOnce = require("./useIsomorphicEffectOnce.cjs");
10
8
  function useField(opts) {
11
- const { formApi, parentFieldName } = formContext.useFormContext();
12
9
  const [fieldApi] = rehackt.useState(() => {
13
- const name = (typeof opts.index === "number" ? [parentFieldName, opts.index, opts.name] : [parentFieldName, opts.name]).filter((d) => d !== void 0).join(".");
14
10
  const api = new formCore.FieldApi({
15
11
  ...opts,
16
- form: formApi,
17
- // TODO: Fix typings to include `index` and `parentFieldName`, if present
18
- name
12
+ form: opts.form,
13
+ name: opts.name
19
14
  });
20
15
  api.Field = Field;
21
16
  return api;
22
17
  });
18
+ useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi]);
23
19
  useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
24
- fieldApi.update({ ...opts, form: formApi });
20
+ fieldApi.update(opts);
25
21
  });
26
22
  reactStore.useStore(
27
23
  fieldApi.store,
@@ -29,16 +25,6 @@ function useField(opts) {
29
25
  return [state.meta, Object.keys(state.value).length];
30
26
  } : void 0
31
27
  );
32
- const unmountFn = rehackt.useRef(null);
33
- useIsomorphicEffectOnce.useIsomorphicEffectOnce(() => {
34
- return () => {
35
- var _a;
36
- (_a = unmountFn.current) == null ? void 0 : _a.call(unmountFn);
37
- };
38
- });
39
- if (!unmountFn.current) {
40
- unmountFn.current = fieldApi.mount();
41
- }
42
28
  return fieldApi;
43
29
  }
44
30
  function Field({
@@ -46,16 +32,7 @@ function Field({
46
32
  ...fieldOptions
47
33
  }) {
48
34
  const fieldApi = useField(fieldOptions);
49
- return /* @__PURE__ */ jsxRuntime.jsx(
50
- formContext.formContext.Provider,
51
- {
52
- value: {
53
- formApi: fieldApi.form,
54
- parentFieldName: fieldApi.name
55
- },
56
- children: formCore.functionalUpdate(children, fieldApi)
57
- }
58
- );
35
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: formCore.functionalUpdate(children, fieldApi) });
59
36
  }
60
37
  exports.Field = Field;
61
38
  exports.useField = useField;
@@ -1 +1 @@
1
- {"version":3,"file":"useField.cjs","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useRef, useState } from 'rehackt'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { formContext, useFormContext } from './formContext'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport { useIsomorphicEffectOnce } from './useIsomorphicEffectOnce'\nimport type { UseFieldOptions } from './types'\nimport type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} 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<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>(\n opts?: { name: Narrow<TName> } & UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator\n >,\n) => FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n DeepValue<TParentData, TName>\n>\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>(\n opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator> {\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 as never,\n // TODO: Fix typings to include `index` and `parentFieldName`, if present\n name: name as typeof opts.name as never,\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 const unmountFn = useRef<(() => void) | null>(null)\n\n useIsomorphicEffectOnce(() => {\n return () => {\n unmountFn.current?.()\n }\n })\n\n // We have to mount it right as soon as it renders, otherwise we get:\n // https://github.com/TanStack/form/issues/523\n if (!unmountFn.current) {\n unmountFn.current = fieldApi.mount()\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 ) => 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, TFieldValidator, TFormValidator>,\n 'name' | 'index'\n >\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}: FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n>) => any\n\nexport function 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>({\n children,\n ...fieldOptions\n}: {\n children: (\n fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>,\n ) => any\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>) {\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"],"names":["useFormContext","useState","FieldApi","useIsomorphicLayoutEffect","useStore","useRef","useIsomorphicEffectOnce","jsx","formContext","functionalUpdate"],"mappings":";;;;;;;;;AAsDO,SAAS,SAUd,MAC+D;AAE/D,QAAM,EAAE,SAAS,gBAAgB,IAAIA,YAAe,eAAA;AAEpD,QAAM,CAAC,QAAQ,IAAIC,QAAAA,SAAS,MAAM;AAC1B,UAAA,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;AAEL,UAAA,MAAM,IAAIC,kBAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA;AAAA,MAEN;AAAA,IAAA,CACD;AAED,QAAI,QAAQ;AAEL,WAAA;AAAA,EAAA,CACR;AAMDC,4BAAAA,0BAA0B,MAAM;AAC9B,aAAS,OAAO,EAAE,GAAG,MAAM,MAAM,SAAkB;AAAA,EAAA,CACpD;AAEDC,aAAA;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACF,aAAA,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAK,EAAE,MAAM;AAAA,IAErD,IAAA;AAAA,EAAA;AAEA,QAAA,YAAYC,eAA4B,IAAI;AAElDC,0BAAAA,wBAAwB,MAAM;AAC5B,WAAO,MAAM;;AACX,sBAAU,YAAV;AAAA,IAAoB;AAAA,EACtB,CACD;AAIG,MAAA,CAAC,UAAU,SAAS;AACZ,cAAA,UAAU,SAAS;EAC/B;AAEO,SAAA;AACT;AA0DO,SAAS,MASd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAI0E;AAClE,QAAA,WAAW,SAAS,YAAmB;AAG3C,SAAAC,2BAAA;AAAA,IAACC,YAAAA,YAAY;AAAA,IAAZ;AAAA,MACC,OAAO;AAAA,QACL,SAAS,SAAS;AAAA,QAClB,iBAAiB,SAAS;AAAA,MAC5B;AAAA,MACA,UAAUC,SAAAA,iBAAiB,UAAU,QAAe;AAAA,IAAA;AAAA,EAAA;AAG1D;;;"}
1
+ {"version":3,"file":"useField.cjs","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'rehackt'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { UseFieldOptions } from './types'\nimport type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} 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>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n 'form'\n >,\n) => FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n DeepValue<TParentData, TName>\n>\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>(\n opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator> {\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).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 ) => any\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>\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>) => any\n\nexport function 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>({\n children,\n ...fieldOptions\n}: {\n children: (\n fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>,\n ) => any\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>) {\n const fieldApi = useField(fieldOptions as any)\n\n return <>{functionalUpdate(children, fieldApi as any)}</>\n}\n"],"names":["useState","FieldApi","useIsomorphicLayoutEffect","useStore","jsx","Fragment","functionalUpdate"],"mappings":";;;;;;;AAoDO,SAAS,SAUd,MAC+D;AAC/D,QAAM,CAAC,QAAQ,IAAIA,QAAAA,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,KAAK,EAAE,MAAM;AAAA,IAErD,IAAA;AAAA,EAAA;AAGC,SAAA;AACT;AAiDO,SAAS,MASd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAI0E;AAClE,QAAA,WAAW,SAAS,YAAmB;AAE7C,SAAUC,2BAAA,IAAAC,WAAA,UAAA,EAAA,UAAAC,SAAA,iBAAiB,UAAU,QAAe,EAAE,CAAA;AACxD;;;"}
@@ -2,26 +2,18 @@
2
2
  import React from 'rehackt';
3
3
  import { FieldApi } from '@tanstack/form-core';
4
4
  import type { UseFieldOptions } from './types.cjs';
5
- import type { DeepKeys, DeepValue, Narrow, Validator } from '@tanstack/form-core';
5
+ import type { DeepKeys, DeepValue, Validator } from '@tanstack/form-core';
6
6
  declare module '@tanstack/form-core' {
7
7
  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>> {
8
8
  Field: FieldComponent<TParentData, TFormValidator>;
9
9
  }
10
10
  }
11
- export type UseField<TParentData> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>(opts?: {
12
- name: Narrow<TName>;
13
- } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, DeepValue<TParentData, TName>>;
11
+ export type UseField<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined>(opts: Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>, 'form'>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, DeepValue<TParentData, TName>>;
14
12
  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>(opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): FieldApi<TParentData, TName, TFieldValidator, TFormValidator>;
15
13
  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>> = {
16
14
  children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>) => any;
17
- } & (TParentData extends any[] ? {
18
- name?: TName;
19
- index: number;
20
- } : {
21
- name: TName;
22
- index?: never;
23
- }) & Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>, 'name' | 'index'>;
24
- 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 }: FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator, TData>) => any;
15
+ } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>;
16
+ 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'>) => any;
25
17
  export declare function Field<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>({ children, ...fieldOptions }: {
26
18
  children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>) => any;
27
19
  } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): React.JSX.Element;
@@ -5,17 +5,14 @@ const formCore = require("@tanstack/form-core");
5
5
  const reactStore = require("@tanstack/react-store");
6
6
  const rehackt = require("rehackt");
7
7
  const useField = require("./useField.cjs");
8
- const formContext = require("./formContext.cjs");
9
8
  const useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect.cjs");
10
9
  function useForm(opts) {
11
10
  const [formApi] = rehackt.useState(() => {
12
11
  const api = new formCore.FormApi(opts);
13
- api.Provider = function Provider(props) {
14
- useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(api.mount, []);
15
- return /* @__PURE__ */ jsxRuntime.jsx(formContext.formContext.Provider, { ...props, value: { formApi: api } });
12
+ api.Field = function APIField(props) {
13
+ return /* @__PURE__ */ jsxRuntime.jsx(useField.Field, { ...props, form: api });
16
14
  };
17
- api.Field = useField.Field;
18
- api.useField = useField.useField;
15
+ api.useField = (props) => useField.useField({ ...props, form: api });
19
16
  api.useStore = (selector) => {
20
17
  return reactStore.useStore(api.store, selector);
21
18
  };
@@ -28,6 +25,7 @@ function useForm(opts) {
28
25
  };
29
26
  return api;
30
27
  });
28
+ useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(formApi.mount, []);
31
29
  formApi.useStore((state) => state.isSubmitting);
32
30
  useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
33
31
  formApi.update(opts);
@@ -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, {\n type PropsWithChildren,\n type ReactNode,\n useState,\n} from 'rehackt'\nimport { Field, useField } from './useField'\nimport { formContext } from './formContext'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NoInfer } from '@tanstack/react-store'\nimport type { FormOptions, FormState, Validator } from '@tanstack/form-core'\nimport type { FieldComponent, UseField } from './useField'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n Provider: (props: PropsWithChildren) => JSX.Element\n Field: FieldComponent<TFormData, TFormValidator>\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 }) => JSX.Element\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 // @ts-ignore\n const api = new FormApi<TFormData, TFormValidator>(opts)\n\n api.Provider = function Provider(props) {\n useIsomorphicLayoutEffect(api.mount, [])\n return (\n <formContext.Provider {...props} value={{ formApi: api as never }} />\n )\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"],"names":["useState","FormApi","useIsomorphicLayoutEffect","jsx","formContext","Field","useField","useStore","functionalUpdate"],"mappings":";;;;;;;;;AA8BO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAIA,QAAAA,SAAS,MAAM;AAEzB,UAAA,MAAM,IAAIC,iBAAmC,IAAI;AAEnD,QAAA,WAAW,SAAS,SAAS,OAAO;AACZC,gCAAAA,0BAAA,IAAI,OAAO,CAAA,CAAE;AAErC,aAAAC,+BAACC,YAAAA,YAAY,UAAZ,EAAsB,GAAG,OAAO,OAAO,EAAE,SAAS,IAAgB,EAAA,CAAA;AAAA,IAAA;AAGvE,QAAI,QAAQC;AACZ,QAAI,WAAWC;AACX,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;AAED,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9CL,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, {\n type PropsWithChildren,\n type ReactNode,\n useState,\n} from 'rehackt'\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'\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>) => ReactNode) | ReactNode\n }) => JSX.Element\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} />\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":";;;;;;;;AAsCO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAIA,QAAAA,SAAS,MAAM;AACzB,UAAA,MAAM,IAAIC,iBAAmC,IAAI;AACnD,QAAA,QAAQ,SAAS,SAAS,OAAO;AACnC,aAAQC,2BAAAA,IAAAC,SAAAA,OAAA,EAAO,GAAG,OAAO,MAAM,IAAK,CAAA;AAAA,IAAA;AAGlC,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,16 +1,26 @@
1
1
  /// <reference types="react" />
2
2
  import { FormApi } from '@tanstack/form-core';
3
- import { type PropsWithChildren, type ReactNode } from 'rehackt';
3
+ import { type ReactNode } from 'rehackt';
4
+ import { type FieldComponent, type UseField } from './useField.cjs';
4
5
  import type { NoInfer } from '@tanstack/react-store';
5
6
  import type { FormOptions, FormState, Validator } from '@tanstack/form-core';
6
- import type { FieldComponent, UseField } from './useField.cjs';
7
7
  declare module '@tanstack/form-core' {
8
8
  interface FormApi<TFormData, TFormValidator> {
9
- Provider: (props: PropsWithChildren) => JSX.Element;
10
9
  Field: FieldComponent<TFormData, TFormValidator>;
11
- useField: UseField<TFormData>;
10
+ useField: UseField<TFormData, TFormValidator>;
12
11
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
13
12
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
13
+ /**
14
+ TypeScript versions <=5.0.4 have a bug that prevents
15
+ the type of the `TSelected` generic from being inferred
16
+ from the return type of this method.
17
+
18
+ In these versions, `TSelected` will fall back to the default
19
+ type (or `unknown` if that's not defined).
20
+
21
+ @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}
22
+ @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}
23
+ */
14
24
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected;
15
25
  children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode;
16
26
  }) => JSX.Element;
@@ -1,10 +1,10 @@
1
+ import { Field, useField } from './useField.js';
1
2
  import type { ValidateFormData } from './validateFormData.js';
2
- import type { FieldComponent, UseField } from './useField.js';
3
3
  import type { FormApi, FormOptions, Validator } from '@tanstack/form-core';
4
4
  export type FormFactory<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined> = {
5
5
  useForm: (opts?: FormOptions<TFormData, TFormValidator>) => FormApi<TFormData, TFormValidator>;
6
- useField: UseField<TFormData>;
7
- Field: FieldComponent<TFormData, TFormValidator>;
6
+ useField: typeof useField;
7
+ Field: typeof Field;
8
8
  validateFormData: ValidateFormData<TFormData, TFormValidator>;
9
9
  initialFormState: Partial<FormApi<TFormData, TFormValidator>['state']>;
10
10
  };
@@ -1 +1 @@
1
- {"version":3,"file":"createFormFactory.js","sources":["../../src/createFormFactory.ts"],"sourcesContent":["import { Field, useField } from './useField'\nimport { useForm } from './useForm'\nimport { getValidateFormData } from './validateFormData'\nimport type { ValidateFormData } from './validateFormData'\nimport type { FieldComponent, UseField } from './useField'\nimport type { FormApi, FormOptions, Validator } from '@tanstack/form-core'\n\nexport type FormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n useForm: (\n opts?: FormOptions<TFormData, TFormValidator>,\n ) => FormApi<TFormData, TFormValidator>\n useField: UseField<TFormData>\n Field: FieldComponent<TFormData, TFormValidator>\n validateFormData: ValidateFormData<TFormData, TFormValidator>\n initialFormState: Partial<FormApi<TFormData, TFormValidator>['state']>\n}\n\nexport function createFormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n defaultOpts?: FormOptions<TFormData, TFormValidator>,\n): FormFactory<TFormData, TFormValidator> {\n return {\n useForm: (opts) => {\n const formOptions = Object.assign({}, defaultOpts, opts)\n return useForm<TFormData, TFormValidator>(formOptions)\n },\n useField: useField as any,\n Field: Field as any,\n validateFormData: getValidateFormData(defaultOpts) as never,\n initialFormState: {\n errorMap: {\n onServer: undefined,\n },\n errors: [],\n },\n }\n}\n"],"names":[],"mappings":";;;AAoBO,SAAS,kBAId,aACwC;AACjC,SAAA;AAAA,IACL,SAAS,CAAC,SAAS;AACjB,YAAM,cAAc,OAAO,OAAO,CAAA,GAAI,aAAa,IAAI;AACvD,aAAO,QAAmC,WAAW;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB,oBAAoB,WAAW;AAAA,IACjD,kBAAkB;AAAA,MAChB,UAAU;AAAA,QACR,UAAU;AAAA,MACZ;AAAA,MACA,QAAQ,CAAC;AAAA,IACX;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"createFormFactory.js","sources":["../../src/createFormFactory.ts"],"sourcesContent":["import { Field, useField } from './useField'\nimport { useForm } from './useForm'\nimport { getValidateFormData } from './validateFormData'\nimport type { ValidateFormData } from './validateFormData'\nimport type { FieldComponent, UseField } from './useField'\nimport type { FormApi, FormOptions, Validator } from '@tanstack/form-core'\n\nexport type FormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n useForm: (\n opts?: FormOptions<TFormData, TFormValidator>,\n ) => FormApi<TFormData, TFormValidator>\n useField: typeof useField\n Field: typeof Field\n validateFormData: ValidateFormData<TFormData, TFormValidator>\n initialFormState: Partial<FormApi<TFormData, TFormValidator>['state']>\n}\n\nexport function createFormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n defaultOpts?: FormOptions<TFormData, TFormValidator>,\n): FormFactory<TFormData, TFormValidator> {\n return {\n useForm: (opts) => {\n const formOptions = Object.assign({}, defaultOpts, opts)\n return useForm<TFormData, TFormValidator>(formOptions)\n },\n useField: useField,\n Field: Field,\n validateFormData: getValidateFormData(defaultOpts) as never,\n initialFormState: {\n errorMap: {\n onServer: undefined,\n },\n errors: [],\n },\n }\n}\n"],"names":[],"mappings":";;;AAoBO,SAAS,kBAId,aACwC;AACjC,SAAA;AAAA,IACL,SAAS,CAAC,SAAS;AACjB,YAAM,cAAc,OAAO,OAAO,CAAA,GAAI,aAAa,IAAI;AACvD,aAAO,QAAmC,WAAW;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB,oBAAoB,WAAW;AAAA,IACjD,kBAAkB;AAAA,MAChB,UAAU;AAAA,QACR,UAAU;AAAA,MACZ;AAAA,MACA,QAAQ,CAAC;AAAA,IACX;AAAA,EAAA;AAEJ;"}
@@ -1,4 +1,4 @@
1
- import type { DeepKeys, DeepValue, FieldOptions, Validator } from '@tanstack/form-core';
2
- 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>> = FieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData> & {
1
+ import type { DeepKeys, DeepValue, FieldApiOptions, Validator } from '@tanstack/form-core';
2
+ 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> & {
3
3
  mode?: 'value' | 'array';
4
4
  };
@@ -2,26 +2,18 @@
2
2
  import React from 'rehackt';
3
3
  import { FieldApi } from '@tanstack/form-core';
4
4
  import type { UseFieldOptions } from './types.js';
5
- import type { DeepKeys, DeepValue, Narrow, Validator } from '@tanstack/form-core';
5
+ import type { DeepKeys, DeepValue, Validator } from '@tanstack/form-core';
6
6
  declare module '@tanstack/form-core' {
7
7
  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>> {
8
8
  Field: FieldComponent<TParentData, TFormValidator>;
9
9
  }
10
10
  }
11
- export type UseField<TParentData> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>(opts?: {
12
- name: Narrow<TName>;
13
- } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, DeepValue<TParentData, TName>>;
11
+ export type UseField<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined>(opts: Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>, 'form'>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, DeepValue<TParentData, TName>>;
14
12
  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>(opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): FieldApi<TParentData, TName, TFieldValidator, TFormValidator>;
15
13
  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>> = {
16
14
  children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>) => any;
17
- } & (TParentData extends any[] ? {
18
- name?: TName;
19
- index: number;
20
- } : {
21
- name: TName;
22
- index?: never;
23
- }) & Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>, 'name' | 'index'>;
24
- 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 }: FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator, TData>) => any;
15
+ } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>;
16
+ 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'>) => any;
25
17
  export declare function Field<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>({ children, ...fieldOptions }: {
26
18
  children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>) => any;
27
19
  } & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): React.JSX.Element;
@@ -1,25 +1,21 @@
1
- import { jsx } from "react/jsx-runtime";
2
- import { useState, useRef } from "rehackt";
1
+ import { jsx, Fragment } from "react/jsx-runtime";
2
+ import { useState } from "rehackt";
3
3
  import { useStore } from "@tanstack/react-store";
4
4
  import { FieldApi, functionalUpdate } from "@tanstack/form-core";
5
- import { useFormContext, formContext } from "./formContext.js";
6
5
  import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
7
- import { useIsomorphicEffectOnce } from "./useIsomorphicEffectOnce.js";
8
6
  function useField(opts) {
9
- const { formApi, parentFieldName } = useFormContext();
10
7
  const [fieldApi] = useState(() => {
11
- const name = (typeof opts.index === "number" ? [parentFieldName, opts.index, opts.name] : [parentFieldName, opts.name]).filter((d) => d !== void 0).join(".");
12
8
  const api = new FieldApi({
13
9
  ...opts,
14
- form: formApi,
15
- // TODO: Fix typings to include `index` and `parentFieldName`, if present
16
- name
10
+ form: opts.form,
11
+ name: opts.name
17
12
  });
18
13
  api.Field = Field;
19
14
  return api;
20
15
  });
16
+ useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi]);
21
17
  useIsomorphicLayoutEffect(() => {
22
- fieldApi.update({ ...opts, form: formApi });
18
+ fieldApi.update(opts);
23
19
  });
24
20
  useStore(
25
21
  fieldApi.store,
@@ -27,16 +23,6 @@ function useField(opts) {
27
23
  return [state.meta, Object.keys(state.value).length];
28
24
  } : void 0
29
25
  );
30
- const unmountFn = useRef(null);
31
- useIsomorphicEffectOnce(() => {
32
- return () => {
33
- var _a;
34
- (_a = unmountFn.current) == null ? void 0 : _a.call(unmountFn);
35
- };
36
- });
37
- if (!unmountFn.current) {
38
- unmountFn.current = fieldApi.mount();
39
- }
40
26
  return fieldApi;
41
27
  }
42
28
  function Field({
@@ -44,16 +30,7 @@ function Field({
44
30
  ...fieldOptions
45
31
  }) {
46
32
  const fieldApi = useField(fieldOptions);
47
- return /* @__PURE__ */ jsx(
48
- formContext.Provider,
49
- {
50
- value: {
51
- formApi: fieldApi.form,
52
- parentFieldName: fieldApi.name
53
- },
54
- children: functionalUpdate(children, fieldApi)
55
- }
56
- );
33
+ return /* @__PURE__ */ jsx(Fragment, { children: functionalUpdate(children, fieldApi) });
57
34
  }
58
35
  export {
59
36
  Field,
@@ -1 +1 @@
1
- {"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useRef, useState } from 'rehackt'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { formContext, useFormContext } from './formContext'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport { useIsomorphicEffectOnce } from './useIsomorphicEffectOnce'\nimport type { UseFieldOptions } from './types'\nimport type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} 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<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>(\n opts?: { name: Narrow<TName> } & UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator\n >,\n) => FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n DeepValue<TParentData, TName>\n>\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>(\n opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator> {\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 as never,\n // TODO: Fix typings to include `index` and `parentFieldName`, if present\n name: name as typeof opts.name as never,\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 const unmountFn = useRef<(() => void) | null>(null)\n\n useIsomorphicEffectOnce(() => {\n return () => {\n unmountFn.current?.()\n }\n })\n\n // We have to mount it right as soon as it renders, otherwise we get:\n // https://github.com/TanStack/form/issues/523\n if (!unmountFn.current) {\n unmountFn.current = fieldApi.mount()\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 ) => 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, TFieldValidator, TFormValidator>,\n 'name' | 'index'\n >\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}: FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n>) => any\n\nexport function 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>({\n children,\n ...fieldOptions\n}: {\n children: (\n fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>,\n ) => any\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>) {\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"],"names":[],"mappings":";;;;;;;AAsDO,SAAS,SAUd,MAC+D;AAE/D,QAAM,EAAE,SAAS,gBAAgB,IAAI,eAAe;AAEpD,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM;AAC1B,UAAA,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;AAEL,UAAA,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA;AAAA,MAEN;AAAA,IAAA,CACD;AAED,QAAI,QAAQ;AAEL,WAAA;AAAA,EAAA,CACR;AAMD,4BAA0B,MAAM;AAC9B,aAAS,OAAO,EAAE,GAAG,MAAM,MAAM,SAAkB;AAAA,EAAA,CACpD;AAED;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACF,aAAA,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAK,EAAE,MAAM;AAAA,IAErD,IAAA;AAAA,EAAA;AAEA,QAAA,YAAY,OAA4B,IAAI;AAElD,0BAAwB,MAAM;AAC5B,WAAO,MAAM;;AACX,sBAAU,YAAV;AAAA,IAAoB;AAAA,EACtB,CACD;AAIG,MAAA,CAAC,UAAU,SAAS;AACZ,cAAA,UAAU,SAAS;EAC/B;AAEO,SAAA;AACT;AA0DO,SAAS,MASd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAI0E;AAClE,QAAA,WAAW,SAAS,YAAmB;AAG3C,SAAA;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,IAAA;AAAA,EAAA;AAG1D;"}
1
+ {"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'rehackt'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { UseFieldOptions } from './types'\nimport type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} 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>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n 'form'\n >,\n) => FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n DeepValue<TParentData, TName>\n>\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>(\n opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator> {\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).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 ) => any\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>\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>) => any\n\nexport function 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>({\n children,\n ...fieldOptions\n}: {\n children: (\n fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>,\n ) => any\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>) {\n const fieldApi = useField(fieldOptions as any)\n\n return <>{functionalUpdate(children, fieldApi as any)}</>\n}\n"],"names":[],"mappings":";;;;;AAoDO,SAAS,SAUd,MAC+D;AAC/D,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,KAAK,EAAE,MAAM;AAAA,IAErD,IAAA;AAAA,EAAA;AAGC,SAAA;AACT;AAiDO,SAAS,MASd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAI0E;AAClE,QAAA,WAAW,SAAS,YAAmB;AAE7C,SAAU,oBAAA,UAAA,EAAA,UAAA,iBAAiB,UAAU,QAAe,EAAE,CAAA;AACxD;"}
@@ -1,16 +1,26 @@
1
1
  /// <reference types="react" />
2
2
  import { FormApi } from '@tanstack/form-core';
3
- import { type PropsWithChildren, type ReactNode } from 'rehackt';
3
+ import { type ReactNode } from 'rehackt';
4
+ import { type FieldComponent, type UseField } from './useField.js';
4
5
  import type { NoInfer } from '@tanstack/react-store';
5
6
  import type { FormOptions, FormState, Validator } from '@tanstack/form-core';
6
- import type { FieldComponent, UseField } from './useField.js';
7
7
  declare module '@tanstack/form-core' {
8
8
  interface FormApi<TFormData, TFormValidator> {
9
- Provider: (props: PropsWithChildren) => JSX.Element;
10
9
  Field: FieldComponent<TFormData, TFormValidator>;
11
- useField: UseField<TFormData>;
10
+ useField: UseField<TFormData, TFormValidator>;
12
11
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
13
12
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
13
+ /**
14
+ TypeScript versions <=5.0.4 have a bug that prevents
15
+ the type of the `TSelected` generic from being inferred
16
+ from the return type of this method.
17
+
18
+ In these versions, `TSelected` will fall back to the default
19
+ type (or `unknown` if that's not defined).
20
+
21
+ @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}
22
+ @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}
23
+ */
14
24
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected;
15
25
  children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode;
16
26
  }) => JSX.Element;
@@ -3,17 +3,14 @@ import { FormApi, functionalUpdate } from "@tanstack/form-core";
3
3
  import { useStore } from "@tanstack/react-store";
4
4
  import { useState } from "rehackt";
5
5
  import { Field, useField } from "./useField.js";
6
- import { formContext } from "./formContext.js";
7
6
  import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
8
7
  function useForm(opts) {
9
8
  const [formApi] = useState(() => {
10
9
  const api = new FormApi(opts);
11
- api.Provider = function Provider(props) {
12
- useIsomorphicLayoutEffect(api.mount, []);
13
- return /* @__PURE__ */ jsx(formContext.Provider, { ...props, value: { formApi: api } });
10
+ api.Field = function APIField(props) {
11
+ return /* @__PURE__ */ jsx(Field, { ...props, form: api });
14
12
  };
15
- api.Field = Field;
16
- api.useField = useField;
13
+ api.useField = (props) => useField({ ...props, form: api });
17
14
  api.useStore = (selector) => {
18
15
  return useStore(api.store, selector);
19
16
  };
@@ -26,6 +23,7 @@ function useForm(opts) {
26
23
  };
27
24
  return api;
28
25
  });
26
+ useIsomorphicLayoutEffect(formApi.mount, []);
29
27
  formApi.useStore((state) => state.isSubmitting);
30
28
  useIsomorphicLayoutEffect(() => {
31
29
  formApi.update(opts);
@@ -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, {\n type PropsWithChildren,\n type ReactNode,\n useState,\n} from 'rehackt'\nimport { Field, useField } from './useField'\nimport { formContext } from './formContext'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NoInfer } from '@tanstack/react-store'\nimport type { FormOptions, FormState, Validator } from '@tanstack/form-core'\nimport type { FieldComponent, UseField } from './useField'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n Provider: (props: PropsWithChildren) => JSX.Element\n Field: FieldComponent<TFormData, TFormValidator>\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 }) => JSX.Element\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 // @ts-ignore\n const api = new FormApi<TFormData, TFormValidator>(opts)\n\n api.Provider = function Provider(props) {\n useIsomorphicLayoutEffect(api.mount, [])\n return (\n <formContext.Provider {...props} value={{ formApi: api as never }} />\n )\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"],"names":[],"mappings":";;;;;;;AA8BO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AAEzB,UAAA,MAAM,IAAI,QAAmC,IAAI;AAEnD,QAAA,WAAW,SAAS,SAAS,OAAO;AACZ,gCAAA,IAAI,OAAO,CAAA,CAAE;AAErC,aAAA,oBAAC,YAAY,UAAZ,EAAsB,GAAG,OAAO,OAAO,EAAE,SAAS,IAAgB,EAAA,CAAA;AAAA,IAAA;AAGvE,QAAI,QAAQ;AACZ,QAAI,WAAW;AACX,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;AAED,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, {\n type PropsWithChildren,\n type ReactNode,\n useState,\n} from 'rehackt'\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'\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>) => ReactNode) | ReactNode\n }) => JSX.Element\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} />\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":";;;;;;AAsCO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AACzB,UAAA,MAAM,IAAI,QAAmC,IAAI;AACnD,QAAA,QAAQ,SAAS,SAAS,OAAO;AACnC,aAAQ,oBAAA,OAAA,EAAO,GAAG,OAAO,MAAM,IAAK,CAAA;AAAA,IAAA;AAGlC,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.13.6",
3
+ "version": "0.14.0",
4
4
  "description": "Powerful, type-safe forms for React.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -43,7 +43,7 @@
43
43
  "@tanstack/react-store": "^0.3.1",
44
44
  "decode-formdata": "^0.4.0",
45
45
  "rehackt": "^0.0.3",
46
- "@tanstack/form-core": "0.13.6"
46
+ "@tanstack/form-core": "0.14.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "react": "^17.0.0 || ^18.0.0"
@@ -52,7 +52,7 @@
52
52
  "clean": "rimraf ./dist && rimraf ./coverage",
53
53
  "test:eslint": "eslint --ext .ts,.tsx ./src",
54
54
  "test:types:versions49": "node ../../node_modules/typescript49/lib/tsc.js --project tsconfig.legacy.json",
55
- "test:types:versions50": "node ../../node_modules/typescript50/lib/tsc.js",
55
+ "test:types:versions50": "node ../../node_modules/typescript50/lib/tsc.js --project tsconfig.50.json",
56
56
  "test:types:versions51": "node ../../node_modules/typescript51/lib/tsc.js",
57
57
  "test:types:versions52": "tsc",
58
58
  "test:types": "pnpm run \"/^test:types:versions.*/\"",
@@ -12,8 +12,8 @@ export type FormFactory<
12
12
  useForm: (
13
13
  opts?: FormOptions<TFormData, TFormValidator>,
14
14
  ) => FormApi<TFormData, TFormValidator>
15
- useField: UseField<TFormData>
16
- Field: FieldComponent<TFormData, TFormValidator>
15
+ useField: typeof useField
16
+ Field: typeof Field
17
17
  validateFormData: ValidateFormData<TFormData, TFormValidator>
18
18
  initialFormState: Partial<FormApi<TFormData, TFormValidator>['state']>
19
19
  }
@@ -29,8 +29,8 @@ export function createFormFactory<
29
29
  const formOptions = Object.assign({}, defaultOpts, opts)
30
30
  return useForm<TFormData, TFormValidator>(formOptions)
31
31
  },
32
- useField: useField as any,
33
- Field: Field as any,
32
+ useField: useField,
33
+ Field: Field,
34
34
  validateFormData: getValidateFormData(defaultOpts) as never,
35
35
  initialFormState: {
36
36
  errorMap: {
@@ -1,7 +1,6 @@
1
- /// <reference lib="dom" />
2
- import { render } from '@testing-library/react'
3
- import '@testing-library/jest-dom'
4
1
  import * as React from 'react'
2
+ import { describe, expect, it } from 'vitest'
3
+ import { render } from '@testing-library/react'
5
4
  import { createFormFactory } from '../index'
6
5
 
7
6
  describe('createFormFactory', () => {
@@ -22,14 +21,14 @@ describe('createFormFactory', () => {
22
21
  const form = formFactory.useForm({})
23
22
 
24
23
  return (
25
- <form.Provider>
24
+ <>
26
25
  <form.Field
27
26
  name="firstName"
28
27
  children={(field) => {
29
28
  return <p>{field.state.value}</p>
30
29
  }}
31
30
  />
32
- </form.Provider>
31
+ </>
33
32
  )
34
33
  }
35
34