@tanstack/react-form 1.28.0 → 1.28.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -0
- package/dist/cjs/useForm.cjs +9 -0
- package/dist/cjs/useForm.cjs.map +1 -1
- package/dist/cjs/useFormId.cjs +2 -1
- package/dist/cjs/useFormId.cjs.map +1 -1
- package/dist/cjs/useFormId.d.cts +0 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/useForm.js +11 -2
- package/dist/esm/useForm.js.map +1 -1
- package/dist/esm/useFormId.d.ts +0 -1
- package/dist/esm/useFormId.js +2 -1
- package/dist/esm/useFormId.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/useForm.tsx +14 -2
- package/src/useFormId.ts +7 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -6,6 +6,7 @@ const createFormHook = require("./createFormHook.cjs");
|
|
|
6
6
|
const useField = require("./useField.cjs");
|
|
7
7
|
const useFieldGroup = require("./useFieldGroup.cjs");
|
|
8
8
|
const useForm = require("./useForm.cjs");
|
|
9
|
+
const useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect.cjs");
|
|
9
10
|
Object.defineProperty(exports, "useStore", {
|
|
10
11
|
enumerable: true,
|
|
11
12
|
get: () => reactStore.useStore
|
|
@@ -16,6 +17,7 @@ exports.Field = useField.Field;
|
|
|
16
17
|
exports.useField = useField.useField;
|
|
17
18
|
exports.useFieldGroup = useFieldGroup.useFieldGroup;
|
|
18
19
|
exports.useForm = useForm.useForm;
|
|
20
|
+
exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect.useIsomorphicLayoutEffect;
|
|
19
21
|
Object.keys(formCore).forEach((k) => {
|
|
20
22
|
if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
21
23
|
enumerable: true,
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/cjs/index.d.cts
CHANGED
package/dist/cjs/useForm.cjs
CHANGED
|
@@ -60,6 +60,15 @@ function useForm(opts) {
|
|
|
60
60
|
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
61
61
|
formApi.update(opts);
|
|
62
62
|
});
|
|
63
|
+
const hasRan = React.useRef(false);
|
|
64
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
65
|
+
if (!hasRan.current) return;
|
|
66
|
+
if (!opts?.transform) return;
|
|
67
|
+
formCore.mergeAndUpdate(formApi, opts.transform);
|
|
68
|
+
}, [formApi, opts?.transform]);
|
|
69
|
+
useIsomorphicLayoutEffect.useIsomorphicLayoutEffect(() => {
|
|
70
|
+
hasRan.current = true;
|
|
71
|
+
});
|
|
63
72
|
return extendedFormApi;
|
|
64
73
|
}
|
|
65
74
|
exports.useForm = useForm;
|
package/dist/cjs/useForm.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useForm.cjs","sources":["../../src/useForm.tsx"],"sourcesContent":["'use client'\n\nimport { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport { useMemo, useState } from 'react'\nimport { Field } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport { useFormId } from './useFormId'\nimport type {\n AnyFormApi,\n AnyFormState,\n FormAsyncValidateOrFn,\n FormOptions,\n FormState,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, PropsWithChildren, ReactNode } from 'react'\nimport type { FieldComponent } from './useField'\nimport type { NoInfer } from '@tanstack/react-store'\n\n/**\n * Fields that are added onto the `FormAPI` from `@tanstack/form-core` and returned from `useForm`\n */\nexport interface ReactFormApi<\n in out TFormData,\n in out TOnMount extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChange extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TSubmitMeta,\n> {\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: FieldComponent<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n /**\n * A `Subscribe` function that allows you to listen and react to changes in the form's state. It's especially useful when you need to execute side effects or render specific components in response to state updates.\n */\n Subscribe: <\n TSelected = NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer\n >\n >,\n >(props: {\n selector?: (\n state: NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer\n >\n >,\n ) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => ReturnType<FunctionComponent>\n}\n\n/**\n * An extended version of the `FormApi` class that includes React-specific functionalities from `ReactFormApi`\n */\nexport type ReactFormExtendedApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n> = FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n> &\n ReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n\nfunction LocalSubscribe({\n form,\n selector,\n children,\n}: PropsWithChildren<{\n form: AnyFormApi\n selector: (state: AnyFormState) => AnyFormState\n}>): ReturnType<FunctionComponent> {\n const data = useStore(form.store, selector)\n\n return <>{functionalUpdate(children, data)}</>\n}\n\n/**\n * A custom React Hook that returns an extended instance of the `FormApi` class.\n *\n * This API encapsulates all the necessary functionalities related to the form. It allows you to manage form state, handle submissions, and interact with form fields\n */\nexport function useForm<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n>(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >,\n) {\n const fallbackFormId = useFormId()\n const [prevFormId, setPrevFormId] = useState<string>(opts?.formId as never)\n\n const [formApi, setFormApi] = useState(() => {\n return new FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >({ ...opts, formId: opts?.formId ?? fallbackFormId })\n })\n\n if (prevFormId !== opts?.formId) {\n const formId = opts?.formId ?? fallbackFormId\n setFormApi(new FormApi({ ...opts, formId }))\n setPrevFormId(formId)\n }\n\n const extendedFormApi = useMemo(() => {\n const extendedApi: ReactFormExtendedApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n > = {\n ...formApi,\n handleSubmit: ((...props: never[]) => {\n return formApi._handleSubmit(...props)\n }) as typeof formApi.handleSubmit,\n // We must add all `get`ters from `core`'s `FormApi` here, as otherwise the spread operator won't catch those\n get formId(): string {\n return formApi._formId\n },\n get state() {\n return formApi.store.state\n },\n } as never\n\n extendedApi.Field = function APIField(props) {\n return <Field {...props} form={formApi} />\n }\n\n extendedApi.Subscribe = function Subscribe(props: any) {\n return (\n <LocalSubscribe\n form={formApi}\n selector={props.selector}\n children={props.children}\n />\n )\n }\n\n return extendedApi\n }, [formApi])\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n /**\n * formApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n formApi.update(opts)\n })\n\n return extendedFormApi\n}\n"],"names":["jsx","useIsomorphicLayoutEffect"],"mappings":";;;;;;;;;;AA4IA;AAAwB;AACtB;AACA;AAEF;AAIE;AAEA;AACF;AAOO;AA6BL;AACA;AAEA;AACE;AAaqD;AAGvD;AACE;AACA;AACA;AAAoB;AAGtB;AACE;AAaI;AACC;AAED;AAAqC;AACvC;AAAA;AAGE;AAAe;AACjB;AAEE;AAAqB;AACvB;AAGF;AACE;AAAwC;AAG1C;AACE;AACEA;AAAC;AAAA;AACO;AACU;AACA;AAAA;AAAA;AAKtB;AAAO;AAGTC;AAMAA;AACE;AAAmB;AAGrB;AACF;;"}
|
|
1
|
+
{"version":3,"file":"useForm.cjs","sources":["../../src/useForm.tsx"],"sourcesContent":["'use client'\n\nimport { FormApi, functionalUpdate, mergeAndUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport { useMemo, useRef, useState } from 'react'\nimport { Field } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport { useFormId } from './useFormId'\nimport type {\n AnyFormApi,\n AnyFormState,\n FormAsyncValidateOrFn,\n FormOptions,\n FormState,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, PropsWithChildren, ReactNode } from 'react'\nimport type { FieldComponent } from './useField'\nimport type { NoInfer } from '@tanstack/react-store'\n\n/**\n * Fields that are added onto the `FormAPI` from `@tanstack/form-core` and returned from `useForm`\n */\nexport interface ReactFormApi<\n in out TFormData,\n in out TOnMount extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChange extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TSubmitMeta,\n> {\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: FieldComponent<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n /**\n * A `Subscribe` function that allows you to listen and react to changes in the form's state. It's especially useful when you need to execute side effects or render specific components in response to state updates.\n */\n Subscribe: <\n TSelected = NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer\n >\n >,\n >(props: {\n selector?: (\n state: NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer\n >\n >,\n ) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => ReturnType<FunctionComponent>\n}\n\n/**\n * An extended version of the `FormApi` class that includes React-specific functionalities from `ReactFormApi`\n */\nexport type ReactFormExtendedApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n> = FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n> &\n ReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n\nfunction LocalSubscribe({\n form,\n selector,\n children,\n}: PropsWithChildren<{\n form: AnyFormApi\n selector: (state: AnyFormState) => AnyFormState\n}>): ReturnType<FunctionComponent> {\n const data = useStore(form.store, selector)\n\n return <>{functionalUpdate(children, data)}</>\n}\n\n/**\n * A custom React Hook that returns an extended instance of the `FormApi` class.\n *\n * This API encapsulates all the necessary functionalities related to the form. It allows you to manage form state, handle submissions, and interact with form fields\n */\nexport function useForm<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n>(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >,\n) {\n const fallbackFormId = useFormId()\n const [prevFormId, setPrevFormId] = useState<string>(opts?.formId as never)\n\n const [formApi, setFormApi] = useState(() => {\n return new FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >({ ...opts, formId: opts?.formId ?? fallbackFormId })\n })\n\n if (prevFormId !== opts?.formId) {\n const formId = opts?.formId ?? fallbackFormId\n setFormApi(new FormApi({ ...opts, formId }))\n setPrevFormId(formId)\n }\n\n const extendedFormApi = useMemo(() => {\n const extendedApi: ReactFormExtendedApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n > = {\n ...formApi,\n handleSubmit: ((...props: never[]) => {\n return formApi._handleSubmit(...props)\n }) as typeof formApi.handleSubmit,\n // We must add all `get`ters from `core`'s `FormApi` here, as otherwise the spread operator won't catch those\n get formId(): string {\n return formApi._formId\n },\n get state() {\n return formApi.store.state\n },\n } as never\n\n extendedApi.Field = function APIField(props) {\n return <Field {...props} form={formApi} />\n }\n\n extendedApi.Subscribe = function Subscribe(props: any) {\n return (\n <LocalSubscribe\n form={formApi}\n selector={props.selector}\n children={props.children}\n />\n )\n }\n\n return extendedApi\n }, [formApi])\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n /**\n * formApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n formApi.update(opts)\n })\n\n const hasRan = useRef(false)\n\n useIsomorphicLayoutEffect(() => {\n if (!hasRan.current) return\n if (!opts?.transform) return\n mergeAndUpdate(formApi, opts.transform as never)\n }, [formApi, opts?.transform])\n\n useIsomorphicLayoutEffect(() => {\n hasRan.current = true\n })\n\n return extendedFormApi\n}\n"],"names":["jsx","useIsomorphicLayoutEffect","mergeAndUpdate"],"mappings":";;;;;;;;;;AA4IA;AAAwB;AACtB;AACA;AAEF;AAIE;AAEA;AACF;AAOO;AA6BL;AACA;AAEA;AACE;AAaqD;AAGvD;AACE;AACA;AACA;AAAoB;AAGtB;AACE;AAaI;AACC;AAED;AAAqC;AACvC;AAAA;AAGE;AAAe;AACjB;AAEE;AAAqB;AACvB;AAGF;AACE;AAAwC;AAG1C;AACE;AACEA;AAAC;AAAA;AACO;AACU;AACA;AAAA;AAAA;AAKtB;AAAO;AAGTC;AAMAA;AACE;AAAmB;AAGrB;AAEAA;AACE;AACA;AACAC;AAA+C;AAGjDD;AACE;AAAiB;AAGnB;AACF;;"}
|
package/dist/cjs/useFormId.cjs
CHANGED
|
@@ -19,6 +19,7 @@ function _interopNamespaceDefault(e) {
|
|
|
19
19
|
return Object.freeze(n);
|
|
20
20
|
}
|
|
21
21
|
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
22
|
-
const
|
|
22
|
+
const _React = React__namespace;
|
|
23
|
+
const useFormId = React__namespace.version.split(".")[0] === "17" ? useUUID.useUUID : _React.useId;
|
|
23
24
|
exports.useFormId = useFormId;
|
|
24
25
|
//# sourceMappingURL=useFormId.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormId.cjs","sources":["../../src/useFormId.ts"],"sourcesContent":["import * as React from 'react'\nimport { useUUID } from './useUUID'\n\n
|
|
1
|
+
{"version":3,"file":"useFormId.cjs","sources":["../../src/useFormId.ts"],"sourcesContent":["import * as React from 'react'\nimport { useUUID } from './useUUID'\n\n/**\n * React 17 does not have the useId hook, so we use a random uuid as a fallback.\n * This is needed to avoid bundlers trying to import non-existing export.\n * Read more: https://github.com/webpack/webpack/issues/14814\n */\nconst _React = React\nexport const useFormId =\n React.version.split('.')[0] === '17' ? useUUID : _React.useId\n"],"names":["React","useUUID"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAQA,MAAM,SAASA;AACR,MAAM,YACXA,iBAAM,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM,OAAOC,QAAAA,UAAU,OAAO;;"}
|
package/dist/cjs/useFormId.d.cts
CHANGED
package/dist/esm/index.d.ts
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { createFormHook, createFormHookContexts } from "./createFormHook.js";
|
|
|
4
4
|
import { Field, useField } from "./useField.js";
|
|
5
5
|
import { useFieldGroup } from "./useFieldGroup.js";
|
|
6
6
|
import { useForm } from "./useForm.js";
|
|
7
|
+
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
7
8
|
export {
|
|
8
9
|
Field,
|
|
9
10
|
createFormHook,
|
|
@@ -11,6 +12,7 @@ export {
|
|
|
11
12
|
useField,
|
|
12
13
|
useFieldGroup,
|
|
13
14
|
useForm,
|
|
15
|
+
useIsomorphicLayoutEffect,
|
|
14
16
|
useStore
|
|
15
17
|
};
|
|
16
18
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
package/dist/esm/useForm.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { FormApi, functionalUpdate } from "@tanstack/form-core";
|
|
3
|
+
import { FormApi, mergeAndUpdate, functionalUpdate } from "@tanstack/form-core";
|
|
4
4
|
import { useStore } from "@tanstack/react-store";
|
|
5
|
-
import { useState, useMemo } from "react";
|
|
5
|
+
import { useState, useMemo, useRef } from "react";
|
|
6
6
|
import { Field } from "./useField.js";
|
|
7
7
|
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
8
8
|
import { useFormId } from "./useFormId.js";
|
|
@@ -58,6 +58,15 @@ function useForm(opts) {
|
|
|
58
58
|
useIsomorphicLayoutEffect(() => {
|
|
59
59
|
formApi.update(opts);
|
|
60
60
|
});
|
|
61
|
+
const hasRan = useRef(false);
|
|
62
|
+
useIsomorphicLayoutEffect(() => {
|
|
63
|
+
if (!hasRan.current) return;
|
|
64
|
+
if (!opts?.transform) return;
|
|
65
|
+
mergeAndUpdate(formApi, opts.transform);
|
|
66
|
+
}, [formApi, opts?.transform]);
|
|
67
|
+
useIsomorphicLayoutEffect(() => {
|
|
68
|
+
hasRan.current = true;
|
|
69
|
+
});
|
|
61
70
|
return extendedFormApi;
|
|
62
71
|
}
|
|
63
72
|
export {
|
package/dist/esm/useForm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useForm.js","sources":["../../src/useForm.tsx"],"sourcesContent":["'use client'\n\nimport { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport { useMemo, useState } from 'react'\nimport { Field } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport { useFormId } from './useFormId'\nimport type {\n AnyFormApi,\n AnyFormState,\n FormAsyncValidateOrFn,\n FormOptions,\n FormState,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, PropsWithChildren, ReactNode } from 'react'\nimport type { FieldComponent } from './useField'\nimport type { NoInfer } from '@tanstack/react-store'\n\n/**\n * Fields that are added onto the `FormAPI` from `@tanstack/form-core` and returned from `useForm`\n */\nexport interface ReactFormApi<\n in out TFormData,\n in out TOnMount extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChange extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TSubmitMeta,\n> {\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: FieldComponent<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n /**\n * A `Subscribe` function that allows you to listen and react to changes in the form's state. It's especially useful when you need to execute side effects or render specific components in response to state updates.\n */\n Subscribe: <\n TSelected = NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer\n >\n >,\n >(props: {\n selector?: (\n state: NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer\n >\n >,\n ) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => ReturnType<FunctionComponent>\n}\n\n/**\n * An extended version of the `FormApi` class that includes React-specific functionalities from `ReactFormApi`\n */\nexport type ReactFormExtendedApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n> = FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n> &\n ReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n\nfunction LocalSubscribe({\n form,\n selector,\n children,\n}: PropsWithChildren<{\n form: AnyFormApi\n selector: (state: AnyFormState) => AnyFormState\n}>): ReturnType<FunctionComponent> {\n const data = useStore(form.store, selector)\n\n return <>{functionalUpdate(children, data)}</>\n}\n\n/**\n * A custom React Hook that returns an extended instance of the `FormApi` class.\n *\n * This API encapsulates all the necessary functionalities related to the form. It allows you to manage form state, handle submissions, and interact with form fields\n */\nexport function useForm<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n>(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >,\n) {\n const fallbackFormId = useFormId()\n const [prevFormId, setPrevFormId] = useState<string>(opts?.formId as never)\n\n const [formApi, setFormApi] = useState(() => {\n return new FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >({ ...opts, formId: opts?.formId ?? fallbackFormId })\n })\n\n if (prevFormId !== opts?.formId) {\n const formId = opts?.formId ?? fallbackFormId\n setFormApi(new FormApi({ ...opts, formId }))\n setPrevFormId(formId)\n }\n\n const extendedFormApi = useMemo(() => {\n const extendedApi: ReactFormExtendedApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n > = {\n ...formApi,\n handleSubmit: ((...props: never[]) => {\n return formApi._handleSubmit(...props)\n }) as typeof formApi.handleSubmit,\n // We must add all `get`ters from `core`'s `FormApi` here, as otherwise the spread operator won't catch those\n get formId(): string {\n return formApi._formId\n },\n get state() {\n return formApi.store.state\n },\n } as never\n\n extendedApi.Field = function APIField(props) {\n return <Field {...props} form={formApi} />\n }\n\n extendedApi.Subscribe = function Subscribe(props: any) {\n return (\n <LocalSubscribe\n form={formApi}\n selector={props.selector}\n children={props.children}\n />\n )\n }\n\n return extendedApi\n }, [formApi])\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n /**\n * formApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n formApi.update(opts)\n })\n\n return extendedFormApi\n}\n"],"names":[],"mappings":";;;;;;;;AA4IA;AAAwB;AACtB;AACA;AAEF;AAIE;AAEA;AACF;AAOO;AA6BL;AACA;AAEA;AACE;AAaqD;AAGvD;AACE;AACA;AACA;AAAoB;AAGtB;AACE;AAaI;AACC;AAED;AAAqC;AACvC;AAAA;AAGE;AAAe;AACjB;AAEE;AAAqB;AACvB;AAGF;AACE;AAAwC;AAG1C;AACE;AACE;AAAC;AAAA;AACO;AACU;AACA;AAAA;AAAA;AAKtB;AAAO;AAGT;AAMA;AACE;AAAmB;AAGrB;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"useForm.js","sources":["../../src/useForm.tsx"],"sourcesContent":["'use client'\n\nimport { FormApi, functionalUpdate, mergeAndUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport { useMemo, useRef, useState } from 'react'\nimport { Field } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport { useFormId } from './useFormId'\nimport type {\n AnyFormApi,\n AnyFormState,\n FormAsyncValidateOrFn,\n FormOptions,\n FormState,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, PropsWithChildren, ReactNode } from 'react'\nimport type { FieldComponent } from './useField'\nimport type { NoInfer } from '@tanstack/react-store'\n\n/**\n * Fields that are added onto the `FormAPI` from `@tanstack/form-core` and returned from `useForm`\n */\nexport interface ReactFormApi<\n in out TFormData,\n in out TOnMount extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChange extends undefined | FormValidateOrFn<TFormData>,\n in out TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n in out TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n in out TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n in out TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n in out TSubmitMeta,\n> {\n /**\n * A React component to render form fields. With this, you can render and manage individual form fields.\n */\n Field: FieldComponent<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n /**\n * A `Subscribe` function that allows you to listen and react to changes in the form's state. It's especially useful when you need to execute side effects or render specific components in response to state updates.\n */\n Subscribe: <\n TSelected = NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer\n >\n >,\n >(props: {\n selector?: (\n state: NoInfer<\n FormState<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer\n >\n >,\n ) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => ReturnType<FunctionComponent>\n}\n\n/**\n * An extended version of the `FormApi` class that includes React-specific functionalities from `ReactFormApi`\n */\nexport type ReactFormExtendedApi<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n> = FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n> &\n ReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >\n\nfunction LocalSubscribe({\n form,\n selector,\n children,\n}: PropsWithChildren<{\n form: AnyFormApi\n selector: (state: AnyFormState) => AnyFormState\n}>): ReturnType<FunctionComponent> {\n const data = useStore(form.store, selector)\n\n return <>{functionalUpdate(children, data)}</>\n}\n\n/**\n * A custom React Hook that returns an extended instance of the `FormApi` class.\n *\n * This API encapsulates all the necessary functionalities related to the form. It allows you to manage form state, handle submissions, and interact with form fields\n */\nexport function useForm<\n TFormData,\n TOnMount extends undefined | FormValidateOrFn<TFormData>,\n TOnChange extends undefined | FormValidateOrFn<TFormData>,\n TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n TSubmitMeta,\n>(\n opts?: FormOptions<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >,\n) {\n const fallbackFormId = useFormId()\n const [prevFormId, setPrevFormId] = useState<string>(opts?.formId as never)\n\n const [formApi, setFormApi] = useState(() => {\n return new FormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n >({ ...opts, formId: opts?.formId ?? fallbackFormId })\n })\n\n if (prevFormId !== opts?.formId) {\n const formId = opts?.formId ?? fallbackFormId\n setFormApi(new FormApi({ ...opts, formId }))\n setPrevFormId(formId)\n }\n\n const extendedFormApi = useMemo(() => {\n const extendedApi: ReactFormExtendedApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n TSubmitMeta\n > = {\n ...formApi,\n handleSubmit: ((...props: never[]) => {\n return formApi._handleSubmit(...props)\n }) as typeof formApi.handleSubmit,\n // We must add all `get`ters from `core`'s `FormApi` here, as otherwise the spread operator won't catch those\n get formId(): string {\n return formApi._formId\n },\n get state() {\n return formApi.store.state\n },\n } as never\n\n extendedApi.Field = function APIField(props) {\n return <Field {...props} form={formApi} />\n }\n\n extendedApi.Subscribe = function Subscribe(props: any) {\n return (\n <LocalSubscribe\n form={formApi}\n selector={props.selector}\n children={props.children}\n />\n )\n }\n\n return extendedApi\n }, [formApi])\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n /**\n * formApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n formApi.update(opts)\n })\n\n const hasRan = useRef(false)\n\n useIsomorphicLayoutEffect(() => {\n if (!hasRan.current) return\n if (!opts?.transform) return\n mergeAndUpdate(formApi, opts.transform as never)\n }, [formApi, opts?.transform])\n\n useIsomorphicLayoutEffect(() => {\n hasRan.current = true\n })\n\n return extendedFormApi\n}\n"],"names":[],"mappings":";;;;;;;;AA4IA;AAAwB;AACtB;AACA;AAEF;AAIE;AAEA;AACF;AAOO;AA6BL;AACA;AAEA;AACE;AAaqD;AAGvD;AACE;AACA;AACA;AAAoB;AAGtB;AACE;AAaI;AACC;AAED;AAAqC;AACvC;AAAA;AAGE;AAAe;AACjB;AAEE;AAAqB;AACvB;AAGF;AACE;AAAwC;AAG1C;AACE;AACE;AAAC;AAAA;AACO;AACU;AACA;AAAA;AAAA;AAKtB;AAAO;AAGT;AAMA;AACE;AAAmB;AAGrB;AAEA;AACE;AACA;AACA;AAA+C;AAGjD;AACE;AAAiB;AAGnB;AACF;;;;"}
|
package/dist/esm/useFormId.d.ts
CHANGED
package/dist/esm/useFormId.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { useUUID } from "./useUUID.js";
|
|
3
|
-
const
|
|
3
|
+
const _React = React;
|
|
4
|
+
const useFormId = React.version.split(".")[0] === "17" ? useUUID : _React.useId;
|
|
4
5
|
export {
|
|
5
6
|
useFormId
|
|
6
7
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFormId.js","sources":["../../src/useFormId.ts"],"sourcesContent":["import * as React from 'react'\nimport { useUUID } from './useUUID'\n\n
|
|
1
|
+
{"version":3,"file":"useFormId.js","sources":["../../src/useFormId.ts"],"sourcesContent":["import * as React from 'react'\nimport { useUUID } from './useUUID'\n\n/**\n * React 17 does not have the useId hook, so we use a random uuid as a fallback.\n * This is needed to avoid bundlers trying to import non-existing export.\n * Read more: https://github.com/webpack/webpack/issues/14814\n */\nconst _React = React\nexport const useFormId =\n React.version.split('.')[0] === '17' ? useUUID : _React.useId\n"],"names":[],"mappings":";;AAQA,MAAM,SAAS;AACR,MAAM,YACX,MAAM,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM,OAAO,UAAU,OAAO;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-form",
|
|
3
|
-
"version": "1.28.
|
|
3
|
+
"version": "1.28.2",
|
|
4
4
|
"description": "Powerful, type-safe forms for React.",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@tanstack/react-store": "^0.8.0",
|
|
41
|
-
"@tanstack/form-core": "1.28.
|
|
41
|
+
"@tanstack/form-core": "1.28.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/react": "^19.0.7",
|
package/src/index.ts
CHANGED
package/src/useForm.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { FormApi, functionalUpdate } from '@tanstack/form-core'
|
|
3
|
+
import { FormApi, functionalUpdate, mergeAndUpdate } from '@tanstack/form-core'
|
|
4
4
|
import { useStore } from '@tanstack/react-store'
|
|
5
|
-
import { useMemo, useState } from 'react'
|
|
5
|
+
import { useMemo, useRef, useState } from 'react'
|
|
6
6
|
import { Field } from './useField'
|
|
7
7
|
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
|
|
8
8
|
import { useFormId } from './useFormId'
|
|
@@ -266,5 +266,17 @@ export function useForm<
|
|
|
266
266
|
formApi.update(opts)
|
|
267
267
|
})
|
|
268
268
|
|
|
269
|
+
const hasRan = useRef(false)
|
|
270
|
+
|
|
271
|
+
useIsomorphicLayoutEffect(() => {
|
|
272
|
+
if (!hasRan.current) return
|
|
273
|
+
if (!opts?.transform) return
|
|
274
|
+
mergeAndUpdate(formApi, opts.transform as never)
|
|
275
|
+
}, [formApi, opts?.transform])
|
|
276
|
+
|
|
277
|
+
useIsomorphicLayoutEffect(() => {
|
|
278
|
+
hasRan.current = true
|
|
279
|
+
})
|
|
280
|
+
|
|
269
281
|
return extendedFormApi
|
|
270
282
|
}
|
package/src/useFormId.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { useUUID } from './useUUID'
|
|
3
3
|
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* React 17 does not have the useId hook, so we use a random uuid as a fallback.
|
|
6
|
+
* This is needed to avoid bundlers trying to import non-existing export.
|
|
7
|
+
* Read more: https://github.com/webpack/webpack/issues/14814
|
|
8
|
+
*/
|
|
9
|
+
const _React = React
|
|
5
10
|
export const useFormId =
|
|
6
|
-
React.version.split('.')[0] === '17' ? useUUID :
|
|
11
|
+
React.version.split('.')[0] === '17' ? useUUID : _React.useId
|