@tanstack/react-form 0.13.5 → 0.13.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"createFormFactory.cjs","sources":["../../src/createFormFactory.ts"],"sourcesContent":["import type { FormApi, FormOptions, Validator } from '@tanstack/form-core'\n\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { useForm } from './useForm'\nimport { type ValidateFormData, getValidateFormData } from './validateFormData'\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":";;;;;AAmBO,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: 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,6 +1,6 @@
1
+ import type { ValidateFormData } from './validateFormData.cjs';
2
+ import type { FieldComponent, UseField } from './useField.cjs';
1
3
  import type { FormApi, FormOptions, Validator } from '@tanstack/form-core';
2
- import { type UseField, type FieldComponent } from './useField.cjs';
3
- import { type ValidateFormData } from './validateFormData.cjs';
4
4
  export type FormFactory<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined> = {
5
5
  useForm: (opts?: FormOptions<TFormData, TFormValidator>) => FormApi<TFormData, TFormValidator>;
6
6
  useField: UseField<TFormData>;
@@ -1 +1 @@
1
- {"version":3,"file":"formContext.cjs","sources":["../../src/formContext.ts"],"sourcesContent":["import type { FormApi, Validator } from '@tanstack/form-core'\nimport { createContext, useContext } from 'rehackt'\n\nexport const formContext = createContext<{\n formApi: FormApi<any, Validator<any, unknown> | undefined>\n parentFieldName?: string\n} | null>(null!)\n\nexport function useFormContext() {\n const formApi = useContext(formContext)\n\n if (!formApi) {\n throw new Error(`You are trying to use the form API outside of a form!`)\n }\n\n return formApi\n}\n"],"names":["createContext","useContext"],"mappings":";;;AAGa,MAAA,cAAcA,sBAGjB,IAAK;AAER,SAAS,iBAAiB;AACzB,QAAA,UAAUC,mBAAW,WAAW;AAEtC,MAAI,CAAC,SAAS;AACN,UAAA,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEO,SAAA;AACT;;;"}
1
+ {"version":3,"file":"formContext.cjs","sources":["../../src/formContext.ts"],"sourcesContent":["import { createContext, useContext } from 'rehackt'\nimport type { FormApi, Validator } from '@tanstack/form-core'\n\nexport const formContext = createContext<{\n formApi: FormApi<any, Validator<any, unknown> | undefined>\n parentFieldName?: string\n} | null>(null!)\n\nexport function useFormContext() {\n const formApi = useContext(formContext)\n\n if (!formApi) {\n throw new Error(`You are trying to use the form API outside of a form!`)\n }\n\n return formApi\n}\n"],"names":["createContext","useContext"],"mappings":";;;AAGa,MAAA,cAAcA,sBAGjB,IAAK;AAER,SAAS,iBAAiB;AACzB,QAAA,UAAUC,mBAAW,WAAW;AAEtC,MAAI,CAAC,SAAS;AACN,UAAA,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEO,SAAA;AACT;;;"}
@@ -1,4 +1,4 @@
1
- import type { FieldOptions, DeepKeys, DeepValue, Validator } from '@tanstack/form-core';
1
+ import type { DeepKeys, DeepValue, FieldOptions, Validator } from '@tanstack/form-core';
2
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> & {
3
3
  mode?: 'value' | 'array';
4
4
  };
@@ -6,7 +6,6 @@ const reactStore = require("@tanstack/react-store");
6
6
  const formCore = require("@tanstack/form-core");
7
7
  const formContext = require("./formContext.cjs");
8
8
  const useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect.cjs");
9
- const useIsomorphicEffectOnce = require("./useIsomorphicEffectOnce.cjs");
10
9
  function useField(opts) {
11
10
  const { formApi, parentFieldName } = formContext.useFormContext();
12
11
  const [fieldApi] = rehackt.useState(() => {
@@ -20,6 +19,7 @@ function useField(opts) {
20
19
  api.Field = Field;
21
20
  return api;
22
21
  });
22
+ useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi]);
23
23
  useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
24
24
  fieldApi.update({ ...opts, form: formApi });
25
25
  });
@@ -29,16 +29,6 @@ function useField(opts) {
29
29
  return [state.meta, Object.keys(state.value).length];
30
30
  } : void 0
31
31
  );
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
32
  return fieldApi;
43
33
  }
44
34
  function Field({
@@ -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 type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} from '@tanstack/form-core'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useFormContext, formContext } from './formContext'\nimport type { UseFieldOptions } from './types'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport { useIsomorphicEffectOnce } from './useIsomorphicEffectOnce'\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 { formContext, useFormContext } from './formContext'\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<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 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, 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\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","jsx","formContext","functionalUpdate"],"mappings":";;;;;;;;AAqDO,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;AAEDC,4BAAAA,0BAA0B,SAAS,OAAO,CAAC,QAAQ,CAAC;AAMpDA,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;AAGC,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,8 +1,8 @@
1
1
  /// <reference types="react" />
2
2
  import React from 'rehackt';
3
- import type { DeepKeys, DeepValue, Narrow, Validator } from '@tanstack/form-core';
4
3
  import { FieldApi } from '@tanstack/form-core';
5
4
  import type { UseFieldOptions } from './types.cjs';
5
+ import type { DeepKeys, DeepValue, Narrow, 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>;
@@ -1 +1 @@
1
- {"version":3,"file":"useForm.cjs","sources":["../../src/useForm.tsx"],"sourcesContent":["import type { FormState, FormOptions, Validator } 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, {\n type PropsWithChildren,\n type ReactNode,\n useState,\n} from 'rehackt'\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { formContext } from './formContext'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\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":";;;;;;;;;AA6BO,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, 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 /**\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\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":";;;;;;;;;AAyCO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAIA,QAAAA,SAAS,MAAM;AACzB,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,9 +1,9 @@
1
1
  /// <reference types="react" />
2
- import type { FormState, FormOptions, Validator } from '@tanstack/form-core';
3
2
  import { FormApi } from '@tanstack/form-core';
4
- import type { NoInfer } from '@tanstack/react-store';
5
3
  import { type PropsWithChildren, type ReactNode } from 'rehackt';
6
- import { type UseField, type FieldComponent } from './useField.cjs';
4
+ import type { NoInfer } from '@tanstack/react-store';
5
+ 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
9
  Provider: (props: PropsWithChildren) => JSX.Element;
@@ -11,6 +11,17 @@ declare module '@tanstack/form-core' {
11
11
  useField: UseField<TFormData>;
12
12
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
13
13
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
14
+ /**
15
+ TypeScript versions <=5.0.4 have a bug that prevents
16
+ the type of the `TSelected` generic from being inferred
17
+ from the return type of this method.
18
+
19
+ In these versions, `TSelected` will fall back to the default
20
+ type (or `unknown` if that's not defined).
21
+
22
+ @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}
23
+ @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}
24
+ */
14
25
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected;
15
26
  children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode;
16
27
  }) => JSX.Element;
@@ -1,6 +1,6 @@
1
+ import type { ValidateFormData } from './validateFormData.js';
2
+ import type { FieldComponent, UseField } from './useField.js';
1
3
  import type { FormApi, FormOptions, Validator } from '@tanstack/form-core';
2
- import { type UseField, type FieldComponent } from './useField.js';
3
- import { type ValidateFormData } from './validateFormData.js';
4
4
  export type FormFactory<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined> = {
5
5
  useForm: (opts?: FormOptions<TFormData, TFormValidator>) => FormApi<TFormData, TFormValidator>;
6
6
  useField: UseField<TFormData>;
@@ -1 +1 @@
1
- {"version":3,"file":"createFormFactory.js","sources":["../../src/createFormFactory.ts"],"sourcesContent":["import type { FormApi, FormOptions, Validator } from '@tanstack/form-core'\n\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { useForm } from './useForm'\nimport { type ValidateFormData, getValidateFormData } from './validateFormData'\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":";;;AAmBO,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: 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 +1 @@
1
- {"version":3,"file":"formContext.js","sources":["../../src/formContext.ts"],"sourcesContent":["import type { FormApi, Validator } from '@tanstack/form-core'\nimport { createContext, useContext } from 'rehackt'\n\nexport const formContext = createContext<{\n formApi: FormApi<any, Validator<any, unknown> | undefined>\n parentFieldName?: string\n} | null>(null!)\n\nexport function useFormContext() {\n const formApi = useContext(formContext)\n\n if (!formApi) {\n throw new Error(`You are trying to use the form API outside of a form!`)\n }\n\n return formApi\n}\n"],"names":[],"mappings":";AAGa,MAAA,cAAc,cAGjB,IAAK;AAER,SAAS,iBAAiB;AACzB,QAAA,UAAU,WAAW,WAAW;AAEtC,MAAI,CAAC,SAAS;AACN,UAAA,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEO,SAAA;AACT;"}
1
+ {"version":3,"file":"formContext.js","sources":["../../src/formContext.ts"],"sourcesContent":["import { createContext, useContext } from 'rehackt'\nimport type { FormApi, Validator } from '@tanstack/form-core'\n\nexport const formContext = createContext<{\n formApi: FormApi<any, Validator<any, unknown> | undefined>\n parentFieldName?: string\n} | null>(null!)\n\nexport function useFormContext() {\n const formApi = useContext(formContext)\n\n if (!formApi) {\n throw new Error(`You are trying to use the form API outside of a form!`)\n }\n\n return formApi\n}\n"],"names":[],"mappings":";AAGa,MAAA,cAAc,cAGjB,IAAK;AAER,SAAS,iBAAiB;AACzB,QAAA,UAAU,WAAW,WAAW;AAEtC,MAAI,CAAC,SAAS;AACN,UAAA,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEO,SAAA;AACT;"}
@@ -1,4 +1,4 @@
1
- import type { FieldOptions, DeepKeys, DeepValue, Validator } from '@tanstack/form-core';
1
+ import type { DeepKeys, DeepValue, FieldOptions, Validator } from '@tanstack/form-core';
2
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> & {
3
3
  mode?: 'value' | 'array';
4
4
  };
@@ -1,8 +1,8 @@
1
1
  /// <reference types="react" />
2
2
  import React from 'rehackt';
3
- import type { DeepKeys, DeepValue, Narrow, Validator } from '@tanstack/form-core';
4
3
  import { FieldApi } from '@tanstack/form-core';
5
4
  import type { UseFieldOptions } from './types.js';
5
+ import type { DeepKeys, DeepValue, Narrow, 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>;
@@ -1,10 +1,9 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { useState, useRef } from "rehackt";
2
+ import { useState } from "rehackt";
3
3
  import { useStore } from "@tanstack/react-store";
4
4
  import { FieldApi, functionalUpdate } from "@tanstack/form-core";
5
5
  import { useFormContext, formContext } from "./formContext.js";
6
6
  import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
7
- import { useIsomorphicEffectOnce } from "./useIsomorphicEffectOnce.js";
8
7
  function useField(opts) {
9
8
  const { formApi, parentFieldName } = useFormContext();
10
9
  const [fieldApi] = useState(() => {
@@ -18,6 +17,7 @@ function useField(opts) {
18
17
  api.Field = Field;
19
18
  return api;
20
19
  });
20
+ useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi]);
21
21
  useIsomorphicLayoutEffect(() => {
22
22
  fieldApi.update({ ...opts, form: formApi });
23
23
  });
@@ -27,16 +27,6 @@ function useField(opts) {
27
27
  return [state.meta, Object.keys(state.value).length];
28
28
  } : void 0
29
29
  );
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
30
  return fieldApi;
41
31
  }
42
32
  function 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 type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} from '@tanstack/form-core'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useFormContext, formContext } from './formContext'\nimport type { UseFieldOptions } from './types'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport { useIsomorphicEffectOnce } from './useIsomorphicEffectOnce'\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 { formContext, useFormContext } from './formContext'\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<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 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, 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\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":";;;;;;AAqDO,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;AAED,4BAA0B,SAAS,OAAO,CAAC,QAAQ,CAAC;AAMpD,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;AAGC,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,9 +1,9 @@
1
1
  /// <reference types="react" />
2
- import type { FormState, FormOptions, Validator } from '@tanstack/form-core';
3
2
  import { FormApi } from '@tanstack/form-core';
4
- import type { NoInfer } from '@tanstack/react-store';
5
3
  import { type PropsWithChildren, type ReactNode } from 'rehackt';
6
- import { type UseField, type FieldComponent } from './useField.js';
4
+ import type { NoInfer } from '@tanstack/react-store';
5
+ 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
9
  Provider: (props: PropsWithChildren) => JSX.Element;
@@ -11,6 +11,17 @@ declare module '@tanstack/form-core' {
11
11
  useField: UseField<TFormData>;
12
12
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
13
13
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
14
+ /**
15
+ TypeScript versions <=5.0.4 have a bug that prevents
16
+ the type of the `TSelected` generic from being inferred
17
+ from the return type of this method.
18
+
19
+ In these versions, `TSelected` will fall back to the default
20
+ type (or `unknown` if that's not defined).
21
+
22
+ @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}
23
+ @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}
24
+ */
14
25
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected;
15
26
  children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode;
16
27
  }) => JSX.Element;
@@ -1 +1 @@
1
- {"version":3,"file":"useForm.js","sources":["../../src/useForm.tsx"],"sourcesContent":["import type { FormState, FormOptions, Validator } 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, {\n type PropsWithChildren,\n type ReactNode,\n useState,\n} from 'rehackt'\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { formContext } from './formContext'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\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":";;;;;;;AA6BO,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, 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 /**\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\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":";;;;;;;AAyCO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AACzB,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;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-form",
3
- "version": "0.13.5",
3
+ "version": "0.13.7",
4
4
  "description": "Powerful, type-safe forms for React.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -34,8 +34,7 @@
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/react": "^18.2.45",
37
- "@types/react-dom": "^18.0.5",
38
- "@types/use-sync-external-store": "^0.0.3",
37
+ "@types/react-dom": "^18.2.19",
39
38
  "@vitejs/plugin-react": "^4.2.1",
40
39
  "react": "^18.2.0",
41
40
  "react-dom": "^18.2.0"
@@ -44,26 +43,16 @@
44
43
  "@tanstack/react-store": "^0.3.1",
45
44
  "decode-formdata": "^0.4.0",
46
45
  "rehackt": "^0.0.3",
47
- "@tanstack/form-core": "0.13.5"
46
+ "@tanstack/form-core": "0.13.7"
48
47
  },
49
48
  "peerDependencies": {
50
- "react": "^17.0.0 || ^18.0.0",
51
- "react-dom": "^17.0.0 || ^18.0.0",
52
- "react-native": "*"
53
- },
54
- "peerDependenciesMeta": {
55
- "react-dom": {
56
- "optional": true
57
- },
58
- "react-native": {
59
- "optional": true
60
- }
49
+ "react": "^17.0.0 || ^18.0.0"
61
50
  },
62
51
  "scripts": {
63
52
  "clean": "rimraf ./dist && rimraf ./coverage",
64
53
  "test:eslint": "eslint --ext .ts,.tsx ./src",
65
54
  "test:types:versions49": "node ../../node_modules/typescript49/lib/tsc.js --project tsconfig.legacy.json",
66
- "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",
67
56
  "test:types:versions51": "node ../../node_modules/typescript51/lib/tsc.js",
68
57
  "test:types:versions52": "tsc",
69
58
  "test:types": "pnpm run \"/^test:types:versions.*/\"",
@@ -1,8 +1,9 @@
1
- import type { FormApi, FormOptions, Validator } from '@tanstack/form-core'
2
-
3
- import { type UseField, type FieldComponent, Field, useField } from './useField'
1
+ import { Field, useField } from './useField'
4
2
  import { useForm } from './useForm'
5
- import { type ValidateFormData, getValidateFormData } from './validateFormData'
3
+ import { getValidateFormData } from './validateFormData'
4
+ import type { ValidateFormData } from './validateFormData'
5
+ import type { FieldComponent, UseField } from './useField'
6
+ import type { FormApi, FormOptions, Validator } from '@tanstack/form-core'
6
7
 
7
8
  export type FormFactory<
8
9
  TFormData,
@@ -1,5 +1,5 @@
1
- import type { FormApi, Validator } from '@tanstack/form-core'
2
1
  import { createContext, useContext } from 'rehackt'
2
+ import type { FormApi, Validator } from '@tanstack/form-core'
3
3
 
4
4
  export const formContext = createContext<{
5
5
  formApi: FormApi<any, Validator<any, unknown> | undefined>
@@ -2,7 +2,7 @@
2
2
  import { render } from '@testing-library/react'
3
3
  import '@testing-library/jest-dom'
4
4
  import * as React from 'react'
5
- import { createFormFactory } from '..'
5
+ import { createFormFactory } from '../index'
6
6
 
7
7
  describe('createFormFactory', () => {
8
8
  it('should allow default values to be set', async () => {
@@ -3,8 +3,9 @@ import * as React from 'react'
3
3
  import { render, waitFor } from '@testing-library/react'
4
4
  import userEvent from '@testing-library/user-event'
5
5
  import '@testing-library/jest-dom'
6
- import { type FormApi, createFormFactory } from '..'
6
+ import { createFormFactory, useForm } from '../index'
7
7
  import { sleep } from './utils'
8
+ import type { FieldApi, FormApi } from '../index'
8
9
 
9
10
  const user = userEvent.setup()
10
11
 
@@ -100,7 +101,12 @@ describe('useField', () => {
100
101
  const formFactory = createFormFactory<Person>()
101
102
 
102
103
  function Comp() {
103
- const form = formFactory.useForm()
104
+ const form = formFactory.useForm({
105
+ defaultValues: {
106
+ firstName: '',
107
+ lastName: '',
108
+ },
109
+ })
104
110
 
105
111
  return (
106
112
  <form.Provider>
@@ -142,7 +148,12 @@ describe('useField', () => {
142
148
  const formFactory = createFormFactory<Person>()
143
149
 
144
150
  function Comp() {
145
- const form = formFactory.useForm()
151
+ const form = formFactory.useForm({
152
+ defaultValues: {
153
+ firstName: '',
154
+ lastName: '',
155
+ },
156
+ })
146
157
 
147
158
  return (
148
159
  <form.Provider>
@@ -187,7 +198,12 @@ describe('useField', () => {
187
198
  const formFactory = createFormFactory<Person>()
188
199
 
189
200
  function Comp() {
190
- const form = formFactory.useForm()
201
+ const form = formFactory.useForm({
202
+ defaultValues: {
203
+ firstName: '',
204
+ lastName: '',
205
+ },
206
+ })
191
207
 
192
208
  return (
193
209
  <form.Provider>
@@ -238,7 +254,12 @@ describe('useField', () => {
238
254
  const formFactory = createFormFactory<Person>()
239
255
 
240
256
  function Comp() {
241
- const form = formFactory.useForm()
257
+ const form = formFactory.useForm({
258
+ defaultValues: {
259
+ firstName: '',
260
+ lastName: '',
261
+ },
262
+ })
242
263
 
243
264
  return (
244
265
  <form.Provider>
@@ -287,7 +308,12 @@ describe('useField', () => {
287
308
  const formFactory = createFormFactory<Person>()
288
309
 
289
310
  function Comp() {
290
- const form = formFactory.useForm()
311
+ const form = formFactory.useForm({
312
+ defaultValues: {
313
+ firstName: '',
314
+ lastName: '',
315
+ },
316
+ })
291
317
 
292
318
  return (
293
319
  <form.Provider>
@@ -345,7 +371,12 @@ describe('useField', () => {
345
371
  const formFactory = createFormFactory<Person>()
346
372
 
347
373
  function Comp() {
348
- const form = formFactory.useForm()
374
+ const form = formFactory.useForm({
375
+ defaultValues: {
376
+ firstName: '',
377
+ lastName: '',
378
+ },
379
+ })
349
380
 
350
381
  return (
351
382
  <form.Provider>
@@ -394,7 +425,12 @@ describe('useField', () => {
394
425
  const formFactory = createFormFactory<Person>()
395
426
  let form: FormApi<Person> | null = null
396
427
  function Comp() {
397
- form = formFactory.useForm()
428
+ form = formFactory.useForm({
429
+ defaultValues: {
430
+ firstName: '',
431
+ lastName: '',
432
+ },
433
+ })
398
434
  return (
399
435
  <form.Provider>
400
436
  <form.Field
@@ -432,7 +468,12 @@ describe('useField', () => {
432
468
  const formFactory = createFormFactory<Person>()
433
469
  let form: FormApi<Person> | null = null
434
470
  function Comp() {
435
- form = formFactory.useForm()
471
+ form = formFactory.useForm({
472
+ defaultValues: {
473
+ firstName: '',
474
+ lastName: '',
475
+ },
476
+ })
436
477
  return (
437
478
  <form.Provider>
438
479
  <form.Field
@@ -461,4 +502,115 @@ describe('useField', () => {
461
502
  const info = form!.fieldInfo
462
503
  expect(Object.keys(info)).toHaveLength(0)
463
504
  })
505
+
506
+ it('should handle strict mode properly with conditional fields', async () => {
507
+ function FieldInfo({ field }: { field: FieldApi<any, any> }) {
508
+ return (
509
+ <>
510
+ {field.state.meta.touchedErrors ? (
511
+ <em>{field.state.meta.touchedErrors}</em>
512
+ ) : null}
513
+ {field.state.meta.isValidating ? 'Validating...' : null}
514
+ </>
515
+ )
516
+ }
517
+
518
+ function Comp() {
519
+ const [showField, setShowField] = React.useState(true)
520
+
521
+ const form = useForm({
522
+ defaultValues: {
523
+ firstName: '',
524
+ lastName: '',
525
+ },
526
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
527
+ onSubmit: async () => {},
528
+ })
529
+
530
+ return (
531
+ <div>
532
+ <form.Provider>
533
+ <form
534
+ onSubmit={(e) => {
535
+ e.preventDefault()
536
+ e.stopPropagation()
537
+ void form.handleSubmit()
538
+ }}
539
+ >
540
+ <div>
541
+ {/* A type-safe field component*/}
542
+ {showField ? (
543
+ <form.Field
544
+ name="firstName"
545
+ validators={{
546
+ onChange: ({ value }) =>
547
+ !value ? 'A first name is required' : undefined,
548
+ }}
549
+ children={(field) => {
550
+ // Avoid hasty abstractions. Render props are great!
551
+ return (
552
+ <>
553
+ <label htmlFor={field.name}>First Name:</label>
554
+ <input
555
+ name={field.name}
556
+ value={field.state.value}
557
+ onBlur={field.handleBlur}
558
+ onChange={(e) => field.handleChange(e.target.value)}
559
+ />
560
+ <FieldInfo field={field} />
561
+ </>
562
+ )
563
+ }}
564
+ />
565
+ ) : null}
566
+ </div>
567
+ <div>
568
+ <form.Field
569
+ name="lastName"
570
+ children={(field) => (
571
+ <>
572
+ <label htmlFor={field.name}>Last Name:</label>
573
+ <input
574
+ name={field.name}
575
+ value={field.state.value}
576
+ onBlur={field.handleBlur}
577
+ onChange={(e) => field.handleChange(e.target.value)}
578
+ />
579
+ <FieldInfo field={field} />
580
+ </>
581
+ )}
582
+ />
583
+ </div>
584
+ <form.Subscribe
585
+ selector={(state) => [state.canSubmit, state.isSubmitting]}
586
+ children={([canSubmit, isSubmitting]) => (
587
+ <button type="submit" disabled={!canSubmit}>
588
+ {isSubmitting ? '...' : 'Submit'}
589
+ </button>
590
+ )}
591
+ />
592
+ <button
593
+ type="button"
594
+ onClick={() => setShowField((prev) => !prev)}
595
+ >
596
+ {showField ? 'Hide field' : 'Show field'}
597
+ </button>
598
+ </form>
599
+ </form.Provider>
600
+ </div>
601
+ )
602
+ }
603
+
604
+ const { getByText, findByText, queryByText } = render(
605
+ <React.StrictMode>
606
+ <Comp />
607
+ </React.StrictMode>,
608
+ )
609
+
610
+ await user.click(getByText('Submit'))
611
+ expect(await findByText('A first name is required')).toBeInTheDocument()
612
+ await user.click(getByText('Hide field'))
613
+ await user.click(getByText('Submit'))
614
+ expect(queryByText('A first name is required')).not.toBeInTheDocument()
615
+ })
464
616
  })
@@ -3,7 +3,7 @@ import '@testing-library/jest-dom'
3
3
  import { render, waitFor } from '@testing-library/react'
4
4
  import userEvent from '@testing-library/user-event'
5
5
  import * as React from 'react'
6
- import { createFormFactory, useForm } from '..'
6
+ import { createFormFactory, useForm } from '../index'
7
7
  import { sleep } from './utils'
8
8
 
9
9
  const user = userEvent.setup()
@@ -172,6 +172,10 @@ describe('useForm', () => {
172
172
 
173
173
  function Comp() {
174
174
  const form = formFactory.useForm({
175
+ defaultValues: {
176
+ firstName: '',
177
+ lastName: '',
178
+ },
175
179
  validators: {
176
180
  onChange() {
177
181
  return error
@@ -217,6 +221,10 @@ describe('useForm', () => {
217
221
 
218
222
  function Comp() {
219
223
  const form = formFactory.useForm({
224
+ defaultValues: {
225
+ firstName: '',
226
+ lastName: '',
227
+ },
220
228
  validators: {
221
229
  onChange: ({ value }) =>
222
230
  value.firstName === 'other' ? error : undefined,
@@ -262,6 +270,10 @@ describe('useForm', () => {
262
270
 
263
271
  function Comp() {
264
272
  const form = formFactory.useForm({
273
+ defaultValues: {
274
+ firstName: '',
275
+ lastName: '',
276
+ },
265
277
  validators: {
266
278
  onChange: ({ value }) =>
267
279
  value.firstName === 'other' ? error : undefined,
@@ -362,6 +374,10 @@ describe('useForm', () => {
362
374
 
363
375
  function Comp() {
364
376
  const form = formFactory.useForm({
377
+ defaultValues: {
378
+ firstName: '',
379
+ lastName: '',
380
+ },
365
381
  validators: {
366
382
  onChangeAsync: async () => {
367
383
  await sleep(10)
@@ -412,6 +428,10 @@ describe('useForm', () => {
412
428
 
413
429
  function Comp() {
414
430
  const form = formFactory.useForm({
431
+ defaultValues: {
432
+ firstName: '',
433
+ lastName: '',
434
+ },
415
435
  validators: {
416
436
  onChangeAsync: async () => {
417
437
  await sleep(10)
@@ -472,6 +492,10 @@ describe('useForm', () => {
472
492
 
473
493
  function Comp() {
474
494
  const form = formFactory.useForm({
495
+ defaultValues: {
496
+ firstName: '',
497
+ lastName: '',
498
+ },
475
499
  validators: {
476
500
  onChangeAsyncDebounceMs: 100,
477
501
  onChangeAsync: async () => {
package/src/types.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type {
2
- FieldOptions,
3
2
  DeepKeys,
4
3
  DeepValue,
4
+ FieldOptions,
5
5
  Validator,
6
6
  } from '@tanstack/form-core'
7
7
 
package/src/useField.tsx CHANGED
@@ -1,16 +1,15 @@
1
- import React, { useRef, useState } from 'rehackt'
1
+ import React, { useState } from 'rehackt'
2
2
  import { useStore } from '@tanstack/react-store'
3
+ import { FieldApi, functionalUpdate } from '@tanstack/form-core'
4
+ import { formContext, useFormContext } from './formContext'
5
+ import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
6
+ import type { UseFieldOptions } from './types'
3
7
  import type {
4
8
  DeepKeys,
5
9
  DeepValue,
6
10
  Narrow,
7
11
  Validator,
8
12
  } from '@tanstack/form-core'
9
- import { FieldApi, functionalUpdate } from '@tanstack/form-core'
10
- import { useFormContext, formContext } from './formContext'
11
- import type { UseFieldOptions } from './types'
12
- import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
13
- import { useIsomorphicEffectOnce } from './useIsomorphicEffectOnce'
14
13
 
15
14
  declare module '@tanstack/form-core' {
16
15
  // eslint-disable-next-line no-shadow
@@ -88,6 +87,8 @@ export function useField<
88
87
  return api
89
88
  })
90
89
 
90
+ useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])
91
+
91
92
  /**
92
93
  * fieldApi.update should not have any side effects. Think of it like a `useRef`
93
94
  * that we need to keep updated every render with the most up-to-date information.
@@ -104,19 +105,6 @@ export function useField<
104
105
  }
105
106
  : undefined,
106
107
  )
107
- const unmountFn = useRef<(() => void) | null>(null)
108
-
109
- useIsomorphicEffectOnce(() => {
110
- return () => {
111
- unmountFn.current?.()
112
- }
113
- })
114
-
115
- // We have to mount it right as soon as it renders, otherwise we get:
116
- // https://github.com/TanStack/form/issues/523
117
- if (!unmountFn.current) {
118
- unmountFn.current = fieldApi.mount()
119
- }
120
108
 
121
109
  return fieldApi as never
122
110
  }
package/src/useForm.tsx CHANGED
@@ -1,15 +1,16 @@
1
- import type { FormState, FormOptions, Validator } from '@tanstack/form-core'
2
1
  import { FormApi, functionalUpdate } from '@tanstack/form-core'
3
- import type { NoInfer } from '@tanstack/react-store'
4
2
  import { useStore } from '@tanstack/react-store'
5
3
  import React, {
6
4
  type PropsWithChildren,
7
5
  type ReactNode,
8
6
  useState,
9
7
  } from 'rehackt'
10
- import { type UseField, type FieldComponent, Field, useField } from './useField'
8
+ import { Field, useField } from './useField'
11
9
  import { formContext } from './formContext'
12
10
  import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
11
+ import type { NoInfer } from '@tanstack/react-store'
12
+ import type { FormOptions, FormState, Validator } from '@tanstack/form-core'
13
+ import type { FieldComponent, UseField } from './useField'
13
14
 
14
15
  declare module '@tanstack/form-core' {
15
16
  // eslint-disable-next-line no-shadow
@@ -21,6 +22,17 @@ declare module '@tanstack/form-core' {
21
22
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,
22
23
  ) => TSelected
23
24
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
25
+ /**
26
+ TypeScript versions <=5.0.4 have a bug that prevents
27
+ the type of the `TSelected` generic from being inferred
28
+ from the return type of this method.
29
+
30
+ In these versions, `TSelected` will fall back to the default
31
+ type (or `unknown` if that's not defined).
32
+
33
+ @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}
34
+ @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}
35
+ */
24
36
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected
25
37
  children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode
26
38
  }) => JSX.Element
@@ -34,7 +46,6 @@ export function useForm<
34
46
  opts?: FormOptions<TFormData, TFormValidator>,
35
47
  ): FormApi<TFormData, TFormValidator> {
36
48
  const [formApi] = useState(() => {
37
- // @ts-ignore
38
49
  const api = new FormApi<TFormData, TFormValidator>(opts)
39
50
 
40
51
  api.Provider = function Provider(props) {
@@ -1,30 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const rehackt = require("rehackt");
4
- const useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect.cjs");
5
- const useIsomorphicEffectOnce = (effect) => {
6
- const destroyFunc = rehackt.useRef();
7
- const effectCalled = rehackt.useRef(false);
8
- const renderAfterCalled = rehackt.useRef(false);
9
- const [val, setVal] = rehackt.useState(0);
10
- if (effectCalled.current) {
11
- renderAfterCalled.current = true;
12
- }
13
- useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
14
- if (!effectCalled.current) {
15
- destroyFunc.current = effect();
16
- effectCalled.current = true;
17
- }
18
- setVal((v) => v + 1);
19
- return () => {
20
- if (!renderAfterCalled.current) {
21
- return;
22
- }
23
- if (destroyFunc.current) {
24
- destroyFunc.current();
25
- }
26
- };
27
- }, []);
28
- };
29
- exports.useIsomorphicEffectOnce = useIsomorphicEffectOnce;
30
- //# sourceMappingURL=useIsomorphicEffectOnce.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useIsomorphicEffectOnce.cjs","sources":["../../src/useIsomorphicEffectOnce.ts"],"sourcesContent":["import { useRef, useState, type EffectCallback } from 'rehackt'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\n\n/**\n * This hook handles StrictMode and prod mode\n */\nexport const useIsomorphicEffectOnce = (effect: EffectCallback) => {\n const destroyFunc = useRef<void | (() => void)>()\n const effectCalled = useRef(false)\n const renderAfterCalled = useRef(false)\n const [val, setVal] = useState(0)\n\n if (effectCalled.current) {\n renderAfterCalled.current = true\n }\n\n useIsomorphicLayoutEffect(() => {\n // only execute the effect first time around\n if (!effectCalled.current) {\n destroyFunc.current = effect()\n effectCalled.current = true\n }\n\n // this forces one render after the effect is run\n setVal((v) => v + 1)\n\n return () => {\n // if the comp didn't render since the useEffect was called,\n // we know it's the dummy React cycle\n if (!renderAfterCalled.current) {\n return\n }\n if (destroyFunc.current) {\n destroyFunc.current()\n }\n }\n }, [])\n}\n"],"names":["useRef","useState","useIsomorphicLayoutEffect"],"mappings":";;;;AAMa,MAAA,0BAA0B,CAAC,WAA2B;AACjE,QAAM,cAAcA,QAAAA;AACd,QAAA,eAAeA,eAAO,KAAK;AAC3B,QAAA,oBAAoBA,eAAO,KAAK;AACtC,QAAM,CAAC,KAAK,MAAM,IAAIC,iBAAS,CAAC;AAEhC,MAAI,aAAa,SAAS;AACxB,sBAAkB,UAAU;AAAA,EAC9B;AAEAC,4BAAAA,0BAA0B,MAAM;AAE1B,QAAA,CAAC,aAAa,SAAS;AACzB,kBAAY,UAAU;AACtB,mBAAa,UAAU;AAAA,IACzB;AAGO,WAAA,CAAC,MAAM,IAAI,CAAC;AAEnB,WAAO,MAAM;AAGP,UAAA,CAAC,kBAAkB,SAAS;AAC9B;AAAA,MACF;AACA,UAAI,YAAY,SAAS;AACvB,oBAAY,QAAQ;AAAA,MACtB;AAAA,IAAA;AAAA,EAEJ,GAAG,CAAE,CAAA;AACP;;"}
@@ -1,5 +0,0 @@
1
- import { type EffectCallback } from 'rehackt';
2
- /**
3
- * This hook handles StrictMode and prod mode
4
- */
5
- export declare const useIsomorphicEffectOnce: (effect: EffectCallback) => void;
@@ -1,5 +0,0 @@
1
- import { type EffectCallback } from 'rehackt';
2
- /**
3
- * This hook handles StrictMode and prod mode
4
- */
5
- export declare const useIsomorphicEffectOnce: (effect: EffectCallback) => void;
@@ -1,30 +0,0 @@
1
- import { useRef, useState } from "rehackt";
2
- import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
3
- const useIsomorphicEffectOnce = (effect) => {
4
- const destroyFunc = useRef();
5
- const effectCalled = useRef(false);
6
- const renderAfterCalled = useRef(false);
7
- const [val, setVal] = useState(0);
8
- if (effectCalled.current) {
9
- renderAfterCalled.current = true;
10
- }
11
- useIsomorphicLayoutEffect(() => {
12
- if (!effectCalled.current) {
13
- destroyFunc.current = effect();
14
- effectCalled.current = true;
15
- }
16
- setVal((v) => v + 1);
17
- return () => {
18
- if (!renderAfterCalled.current) {
19
- return;
20
- }
21
- if (destroyFunc.current) {
22
- destroyFunc.current();
23
- }
24
- };
25
- }, []);
26
- };
27
- export {
28
- useIsomorphicEffectOnce
29
- };
30
- //# sourceMappingURL=useIsomorphicEffectOnce.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useIsomorphicEffectOnce.js","sources":["../../src/useIsomorphicEffectOnce.ts"],"sourcesContent":["import { useRef, useState, type EffectCallback } from 'rehackt'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\n\n/**\n * This hook handles StrictMode and prod mode\n */\nexport const useIsomorphicEffectOnce = (effect: EffectCallback) => {\n const destroyFunc = useRef<void | (() => void)>()\n const effectCalled = useRef(false)\n const renderAfterCalled = useRef(false)\n const [val, setVal] = useState(0)\n\n if (effectCalled.current) {\n renderAfterCalled.current = true\n }\n\n useIsomorphicLayoutEffect(() => {\n // only execute the effect first time around\n if (!effectCalled.current) {\n destroyFunc.current = effect()\n effectCalled.current = true\n }\n\n // this forces one render after the effect is run\n setVal((v) => v + 1)\n\n return () => {\n // if the comp didn't render since the useEffect was called,\n // we know it's the dummy React cycle\n if (!renderAfterCalled.current) {\n return\n }\n if (destroyFunc.current) {\n destroyFunc.current()\n }\n }\n }, [])\n}\n"],"names":[],"mappings":";;AAMa,MAAA,0BAA0B,CAAC,WAA2B;AACjE,QAAM,cAAc;AACd,QAAA,eAAe,OAAO,KAAK;AAC3B,QAAA,oBAAoB,OAAO,KAAK;AACtC,QAAM,CAAC,KAAK,MAAM,IAAI,SAAS,CAAC;AAEhC,MAAI,aAAa,SAAS;AACxB,sBAAkB,UAAU;AAAA,EAC9B;AAEA,4BAA0B,MAAM;AAE1B,QAAA,CAAC,aAAa,SAAS;AACzB,kBAAY,UAAU;AACtB,mBAAa,UAAU;AAAA,IACzB;AAGO,WAAA,CAAC,MAAM,IAAI,CAAC;AAEnB,WAAO,MAAM;AAGP,UAAA,CAAC,kBAAkB,SAAS;AAC9B;AAAA,MACF;AACA,UAAI,YAAY,SAAS;AACvB,oBAAY,QAAQ;AAAA,MACtB;AAAA,IAAA;AAAA,EAEJ,GAAG,CAAE,CAAA;AACP;"}
@@ -1,38 +0,0 @@
1
- import { useRef, useState, type EffectCallback } from 'rehackt'
2
- import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
3
-
4
- /**
5
- * This hook handles StrictMode and prod mode
6
- */
7
- export const useIsomorphicEffectOnce = (effect: EffectCallback) => {
8
- const destroyFunc = useRef<void | (() => void)>()
9
- const effectCalled = useRef(false)
10
- const renderAfterCalled = useRef(false)
11
- const [val, setVal] = useState(0)
12
-
13
- if (effectCalled.current) {
14
- renderAfterCalled.current = true
15
- }
16
-
17
- useIsomorphicLayoutEffect(() => {
18
- // only execute the effect first time around
19
- if (!effectCalled.current) {
20
- destroyFunc.current = effect()
21
- effectCalled.current = true
22
- }
23
-
24
- // this forces one render after the effect is run
25
- setVal((v) => v + 1)
26
-
27
- return () => {
28
- // if the comp didn't render since the useEffect was called,
29
- // we know it's the dummy React cycle
30
- if (!renderAfterCalled.current) {
31
- return
32
- }
33
- if (destroyFunc.current) {
34
- destroyFunc.current()
35
- }
36
- }
37
- }, [])
38
- }