@tanstack/react-form 1.27.0 → 1.27.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/createFormHook.cjs +9 -9
- package/dist/cjs/createFormHook.cjs.map +1 -1
- package/dist/cjs/useField.cjs +5 -5
- package/dist/cjs/useField.cjs.map +1 -1
- package/dist/cjs/useFieldGroup.cjs +2 -2
- package/dist/cjs/useForm.cjs +9 -5
- package/dist/cjs/useForm.cjs.map +1 -1
- package/dist/cjs/useFormId.cjs +24 -0
- package/dist/cjs/useFormId.cjs.map +1 -0
- package/dist/cjs/useFormId.d.cts +3 -0
- package/dist/cjs/useIsomorphicLayoutEffect.cjs +2 -2
- package/dist/cjs/useUUID.cjs +9 -0
- package/dist/cjs/useUUID.cjs.map +1 -0
- package/dist/cjs/useUUID.d.cts +2 -0
- package/dist/esm/createFormHook.js.map +1 -1
- package/dist/esm/useField.js.map +1 -1
- package/dist/esm/useForm.js +6 -2
- package/dist/esm/useForm.js.map +1 -1
- package/dist/esm/useFormId.d.ts +3 -0
- package/dist/esm/useFormId.js +7 -0
- package/dist/esm/useFormId.js.map +1 -0
- package/dist/esm/useUUID.d.ts +2 -0
- package/dist/esm/useUUID.js +9 -0
- package/dist/esm/useUUID.js.map +1 -0
- package/package.json +3 -3
- package/src/createFormHook.tsx +13 -13
- package/src/types.ts +6 -2
- package/src/useField.tsx +37 -37
- package/src/useForm.tsx +6 -2
- package/src/useFormId.ts +6 -0
- package/src/useUUID.ts +7 -0
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
4
|
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
-
const
|
|
5
|
+
const React = require("react");
|
|
6
6
|
const useForm = require("./useForm.cjs");
|
|
7
7
|
const useFieldGroup = require("./useFieldGroup.cjs");
|
|
8
|
-
const fieldContext =
|
|
9
|
-
const formContext =
|
|
8
|
+
const fieldContext = React.createContext(null);
|
|
9
|
+
const formContext = React.createContext(null);
|
|
10
10
|
function createFormHookContexts() {
|
|
11
11
|
function useFieldContext() {
|
|
12
|
-
const field =
|
|
12
|
+
const field = React.useContext(fieldContext);
|
|
13
13
|
if (!field) {
|
|
14
14
|
throw new Error(
|
|
15
15
|
"`fieldContext` only works when within a `fieldComponent` passed to `createFormHook`"
|
|
@@ -18,7 +18,7 @@ function createFormHookContexts() {
|
|
|
18
18
|
return field;
|
|
19
19
|
}
|
|
20
20
|
function useFormContext() {
|
|
21
|
-
const form =
|
|
21
|
+
const form = React.useContext(formContext);
|
|
22
22
|
if (!form) {
|
|
23
23
|
throw new Error(
|
|
24
24
|
"`formContext` only works when within a `formComponent` passed to `createFormHook`"
|
|
@@ -36,12 +36,12 @@ function createFormHook({
|
|
|
36
36
|
}) {
|
|
37
37
|
function useAppForm(props) {
|
|
38
38
|
const form = useForm.useForm(props);
|
|
39
|
-
const AppForm =
|
|
39
|
+
const AppForm = React.useMemo(() => {
|
|
40
40
|
return ({ children }) => {
|
|
41
41
|
return /* @__PURE__ */ jsxRuntime.jsx(formContext2.Provider, { value: form, children });
|
|
42
42
|
};
|
|
43
43
|
}, [form]);
|
|
44
|
-
const AppField =
|
|
44
|
+
const AppField = React.useMemo(() => {
|
|
45
45
|
const AppField2 = (({ children, ...props2 }) => {
|
|
46
46
|
return /* @__PURE__ */ jsxRuntime.jsx(form.Field, { ...props2, children: (field) => (
|
|
47
47
|
// eslint-disable-next-line @eslint-react/no-context-provider
|
|
@@ -50,7 +50,7 @@ function createFormHook({
|
|
|
50
50
|
});
|
|
51
51
|
return AppField2;
|
|
52
52
|
}, [form]);
|
|
53
|
-
const extendedForm =
|
|
53
|
+
const extendedForm = React.useMemo(() => {
|
|
54
54
|
return Object.assign(form, {
|
|
55
55
|
AppField,
|
|
56
56
|
AppForm,
|
|
@@ -71,7 +71,7 @@ function createFormHook({
|
|
|
71
71
|
defaultValues
|
|
72
72
|
}) {
|
|
73
73
|
return function Render(innerProps) {
|
|
74
|
-
const fieldGroupProps =
|
|
74
|
+
const fieldGroupProps = React.useMemo(() => {
|
|
75
75
|
return {
|
|
76
76
|
form: innerProps.form,
|
|
77
77
|
fields: innerProps.fields,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFormHook.cjs","sources":["../../src/createFormHook.tsx"],"sourcesContent":["'use client'\n/* eslint-disable @eslint-react/no-context-provider */\nimport { createContext, useContext, useMemo } from 'react'\nimport { useForm } from './useForm'\nimport { useFieldGroup } from './useFieldGroup'\nimport type {\n AnyFieldApi,\n AnyFormApi,\n BaseFormOptions,\n DeepKeysOfType,\n FieldApi,\n FieldsMap,\n FormAsyncValidateOrFn,\n FormOptions,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type {\n ComponentType,\n Context,\n FunctionComponent,\n PropsWithChildren,\n} from 'react'\nimport type { FieldComponent } from './useField'\nimport type { ReactFormExtendedApi } from './useForm'\nimport type { AppFieldExtendedReactFieldGroupApi } from './useFieldGroup'\n\n// We should never hit the `null` case here\nconst fieldContext = createContext<AnyFieldApi>(null as never)\nconst formContext = createContext<AnyFormApi>(null as never)\n\n/**\n * TypeScript inferencing is weird.\n *\n * If you have:\n *\n * @example\n *\n * interface Args<T> {\n * arg?: T\n * }\n *\n * function test<T>(arg?: Partial<Args<T>>): T {\n * return 0 as any;\n * }\n *\n * const a = test({});\n *\n * Then `T` will default to `unknown`.\n *\n * However, if we change `test` to be:\n *\n * @example\n *\n * function test<T extends undefined>(arg?: Partial<Args<T>>): T;\n *\n * Then `T` becomes `undefined`.\n *\n * Here, we are checking if the passed type `T` extends `DefaultT` and **only**\n * `DefaultT`, as if that's the case we assume that inferencing has not occurred.\n */\ntype UnwrapOrAny<T> = [unknown] extends [T] ? any : T\ntype UnwrapDefaultOrAny<DefaultT, T> = [DefaultT] extends [T]\n ? [T] extends [DefaultT]\n ? any\n : T\n : T\n\nexport function createFormHookContexts() {\n function useFieldContext<TData>() {\n const field = useContext(fieldContext)\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!field) {\n throw new Error(\n '`fieldContext` only works when within a `fieldComponent` passed to `createFormHook`',\n )\n }\n\n return field as FieldApi<\n any,\n string,\n TData,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n }\n\n function useFormContext() {\n const form = useContext(formContext)\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!form) {\n throw new Error(\n '`formContext` only works when within a `formComponent` passed to `createFormHook`',\n )\n }\n\n return form as ReactFormExtendedApi<\n // If you need access to the form data, you need to use `withForm` instead\n Record<string, never>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n }\n\n return { fieldContext, useFieldContext, useFormContext, formContext }\n}\n\ninterface CreateFormHookProps<\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> {\n fieldComponents: TFieldComponents\n fieldContext: Context<AnyFieldApi>\n formComponents: TFormComponents\n formContext: Context<AnyFormApi>\n}\n\n/**\n * @private\n */\nexport type AppFieldExtendedReactFormApi<\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 TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> = 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 NoInfer<TFormComponents> & {\n AppField: 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 NoInfer<TFieldComponents>\n >\n AppForm: ComponentType<\n // PropsWithChildren<P> is not optional in React 17\n PropsWithChildren<{}>\n >\n }\n\nexport interface WithFormProps<\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 TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TRenderProps extends object = Record<string, never>,\n> extends 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 // Optional, but adds props to the `render` function outside of `form`\n props?: TRenderProps\n render: FunctionComponent<\n PropsWithChildren<\n NoInfer<TRenderProps> & {\n form: AppFieldExtendedReactFormApi<\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 TFieldComponents,\n TFormComponents\n >\n }\n >\n >\n}\n\nexport interface WithFieldGroupProps<\n TFieldGroupData,\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TSubmitMeta,\n TRenderProps extends object = Record<string, never>,\n> extends BaseFormOptions<TFieldGroupData, TSubmitMeta> {\n // Optional, but adds props to the `render` function outside of `form`\n props?: TRenderProps\n render: FunctionComponent<\n PropsWithChildren<\n NoInfer<TRenderProps> & {\n group: AppFieldExtendedReactFieldGroupApi<\n unknown,\n TFieldGroupData,\n string | FieldsMap<unknown, TFieldGroupData>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n // this types it as 'never' in the render prop. It should prevent any\n // untyped meta passed to the handleSubmit by accident.\n unknown extends TSubmitMeta ? never : TSubmitMeta,\n TFieldComponents,\n TFormComponents\n >\n }\n >\n >\n}\n\nexport function createFormHook<\n const TComponents extends Record<string, ComponentType<any>>,\n const TFormComponents extends Record<string, ComponentType<any>>,\n>({\n fieldComponents,\n fieldContext,\n formContext,\n formComponents,\n}: CreateFormHookProps<TComponents, TFormComponents>) {\n function useAppForm<\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 props: 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 ): AppFieldExtendedReactFormApi<\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 TComponents,\n TFormComponents\n > {\n const form = useForm(props)\n\n // PropsWithChildren<P> is not optional in React 17\n const AppForm = useMemo<ComponentType<PropsWithChildren<{}>>>(() => {\n return ({ children }) => {\n return (\n <formContext.Provider value={form}>{children}</formContext.Provider>\n )\n }\n }, [form])\n\n const AppField = useMemo(() => {\n const AppField = (({ children, ...props }) => {\n return (\n <form.Field {...props}>\n {(field) => (\n // eslint-disable-next-line @eslint-react/no-context-provider\n <fieldContext.Provider value={field}>\n {children(Object.assign(field, fieldComponents))}\n </fieldContext.Provider>\n )}\n </form.Field>\n )\n }) as 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 TComponents\n >\n return AppField\n }, [form])\n\n const extendedForm = useMemo(() => {\n return Object.assign(form, {\n AppField,\n AppForm,\n ...formComponents,\n })\n }, [form, AppField, AppForm])\n\n return extendedForm\n }\n\n function withForm<\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 TRenderProps extends object = {},\n >({\n render,\n props,\n }: WithFormProps<\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 TComponents,\n TFormComponents,\n TRenderProps\n >): WithFormProps<\n UnwrapOrAny<TFormData>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnMount>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnChange>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnChangeAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnBlur>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnBlurAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnSubmit>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnDynamic>,\n UnwrapDefaultOrAny<\n undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync\n >,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnServer>,\n UnwrapOrAny<TSubmitMeta>,\n UnwrapOrAny<TComponents>,\n UnwrapOrAny<TFormComponents>,\n UnwrapOrAny<TRenderProps>\n >['render'] {\n return (innerProps) => render({ ...props, ...innerProps })\n }\n\n function withFieldGroup<\n TFieldGroupData,\n TSubmitMeta,\n TRenderProps extends object = {},\n >({\n render,\n props,\n defaultValues,\n }: WithFieldGroupProps<\n TFieldGroupData,\n TComponents,\n TFormComponents,\n TSubmitMeta,\n TRenderProps\n >): <\n TFormData,\n TFields extends\n | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>\n | FieldsMap<TFormData, TFieldGroupData>,\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 TFormSubmitMeta,\n >(\n params: PropsWithChildren<\n NoInfer<TRenderProps> & {\n form:\n | AppFieldExtendedReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,\n TComponents,\n TFormComponents\n >\n | AppFieldExtendedReactFieldGroupApi<\n // Since this only occurs if you nest it within other field groups, it can be more\n // lenient with the types.\n unknown,\n TFormData,\n string | FieldsMap<unknown, TFormData>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,\n TComponents,\n TFormComponents\n >\n fields: TFields\n }\n >,\n ) => ReturnType<FunctionComponent> {\n return function Render(innerProps) {\n const fieldGroupProps = useMemo(() => {\n return {\n form: innerProps.form,\n fields: innerProps.fields,\n defaultValues,\n formComponents,\n }\n }, [innerProps.form, innerProps.fields])\n const fieldGroupApi = useFieldGroup(fieldGroupProps as any)\n\n return render({ ...props, ...innerProps, group: fieldGroupApi as any })\n }\n }\n\n return {\n useAppForm,\n withForm,\n withFieldGroup,\n }\n}\n"],"names":["fieldContext","formContext","AppField"],"mappings":";;;;;;;AA2BA;AACA;AAuCO;AACL;AACE;AAGA;AACE;AAAU;AACR;AAAA;AAIJ;AAAO;AA2BT;AACE;AAGA;AACE;AAAU;AACR;AAAA;AAIJ;AAAO;AAiBT;AACF;AA+JO;AAGL;AACA;AACAA;AACAC;AAEF;AACE;AA4CE;AAGA;AACE;AACE;AAC+C;AAEjD;AAGF;AACE;AACE;AAEM;AAAA;AAIA;AAEJ;AAiBJ;AAAOC;AAGT;AACE;AAA2B;AACzB;AACA;AACG;AACJ;AAGH;AAAO;AAGT;AAcE;AACA;AACA;AAqCA;AAAyD;AAG3D;AAIE;AACA;AACA;AACA;AAmEA;AACE;AACE;AAAO;AACY;AACE;AACnB;AACA;AAAA;AAGJ;AAEA;AAAsE;AACxE;AAGF;AAAO;AACL;AACA;AACA;AAEJ;;;"}
|
|
1
|
+
{"version":3,"file":"createFormHook.cjs","sources":["../../src/createFormHook.tsx"],"sourcesContent":["'use client'\n/* eslint-disable @eslint-react/no-context-provider */\nimport { createContext, useContext, useMemo } from 'react'\nimport { useForm } from './useForm'\nimport { useFieldGroup } from './useFieldGroup'\nimport type {\n AnyFieldApi,\n AnyFormApi,\n BaseFormOptions,\n DeepKeysOfType,\n FieldApi,\n FieldsMap,\n FormAsyncValidateOrFn,\n FormOptions,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type {\n ComponentType,\n Context,\n FunctionComponent,\n PropsWithChildren,\n} from 'react'\nimport type { FieldComponent } from './useField'\nimport type { ReactFormExtendedApi } from './useForm'\nimport type { AppFieldExtendedReactFieldGroupApi } from './useFieldGroup'\n\n// We should never hit the `null` case here\nconst fieldContext = createContext<AnyFieldApi>(null as never)\nconst formContext = createContext<AnyFormApi>(null as never)\n\n/**\n * TypeScript inferencing is weird.\n *\n * If you have:\n *\n * @example\n *\n * interface Args<T> {\n * arg?: T\n * }\n *\n * function test<T>(arg?: Partial<Args<T>>): T {\n * return 0 as any;\n * }\n *\n * const a = test({});\n *\n * Then `T` will default to `unknown`.\n *\n * However, if we change `test` to be:\n *\n * @example\n *\n * function test<T extends undefined>(arg?: Partial<Args<T>>): T;\n *\n * Then `T` becomes `undefined`.\n *\n * Here, we are checking if the passed type `T` extends `DefaultT` and **only**\n * `DefaultT`, as if that's the case we assume that inferencing has not occurred.\n */\ntype UnwrapOrAny<T> = [unknown] extends [T] ? any : T\ntype UnwrapDefaultOrAny<DefaultT, T> = [DefaultT] extends [T]\n ? [T] extends [DefaultT]\n ? any\n : T\n : T\n\nexport function createFormHookContexts() {\n function useFieldContext<TData>() {\n const field = useContext(fieldContext)\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!field) {\n throw new Error(\n '`fieldContext` only works when within a `fieldComponent` passed to `createFormHook`',\n )\n }\n\n return field as FieldApi<\n any,\n string,\n TData,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n }\n\n function useFormContext() {\n const form = useContext(formContext)\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!form) {\n throw new Error(\n '`formContext` only works when within a `formComponent` passed to `createFormHook`',\n )\n }\n\n return form as ReactFormExtendedApi<\n // If you need access to the form data, you need to use `withForm` instead\n Record<string, never>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n }\n\n return { fieldContext, useFieldContext, useFormContext, formContext }\n}\n\ninterface CreateFormHookProps<\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> {\n fieldComponents: TFieldComponents\n fieldContext: Context<AnyFieldApi>\n formComponents: TFormComponents\n formContext: Context<AnyFormApi>\n}\n\n/**\n * @private\n */\nexport type AppFieldExtendedReactFormApi<\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 TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> = 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 NoInfer<TFormComponents> & {\n AppField: 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 NoInfer<TFieldComponents>\n >\n AppForm: ComponentType<\n // PropsWithChildren<P> is not optional in React 17\n PropsWithChildren<{}>\n >\n }\n\nexport interface WithFormProps<\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 TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TRenderProps extends object = Record<string, never>,\n> extends 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 // Optional, but adds props to the `render` function outside of `form`\n props?: TRenderProps\n render: FunctionComponent<\n PropsWithChildren<\n NoInfer<TRenderProps> & {\n form: AppFieldExtendedReactFormApi<\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 TFieldComponents,\n TFormComponents\n >\n }\n >\n >\n}\n\nexport interface WithFieldGroupProps<\n TFieldGroupData,\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TSubmitMeta,\n TRenderProps extends object = Record<string, never>,\n> extends BaseFormOptions<TFieldGroupData, TSubmitMeta> {\n // Optional, but adds props to the `render` function outside of `form`\n props?: TRenderProps\n render: FunctionComponent<\n PropsWithChildren<\n NoInfer<TRenderProps> & {\n group: AppFieldExtendedReactFieldGroupApi<\n unknown,\n TFieldGroupData,\n string | FieldsMap<unknown, TFieldGroupData>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n // this types it as 'never' in the render prop. It should prevent any\n // untyped meta passed to the handleSubmit by accident.\n unknown extends TSubmitMeta ? never : TSubmitMeta,\n TFieldComponents,\n TFormComponents\n >\n }\n >\n >\n}\n\nexport function createFormHook<\n const TComponents extends Record<string, ComponentType<any>>,\n const TFormComponents extends Record<string, ComponentType<any>>,\n>({\n fieldComponents,\n fieldContext,\n formContext,\n formComponents,\n}: CreateFormHookProps<TComponents, TFormComponents>) {\n function useAppForm<\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 props: 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 ): AppFieldExtendedReactFormApi<\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 TComponents,\n TFormComponents\n > {\n const form = useForm(props)\n\n // PropsWithChildren<P> is not optional in React 17\n const AppForm = useMemo<ComponentType<PropsWithChildren<{}>>>(() => {\n return ({ children }) => {\n return (\n <formContext.Provider value={form}>{children}</formContext.Provider>\n )\n }\n }, [form])\n\n const AppField = useMemo(() => {\n const AppField = (({ children, ...props }) => {\n return (\n <form.Field {...props}>\n {(field) => (\n // eslint-disable-next-line @eslint-react/no-context-provider\n <fieldContext.Provider value={field}>\n {children(Object.assign(field, fieldComponents))}\n </fieldContext.Provider>\n )}\n </form.Field>\n )\n }) as 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 TComponents\n >\n return AppField\n }, [form])\n\n const extendedForm = useMemo(() => {\n return Object.assign(form, {\n AppField,\n AppForm,\n ...formComponents,\n })\n }, [form, AppField, AppForm])\n\n return extendedForm\n }\n\n function withForm<\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 TRenderProps extends object = {},\n >({\n render,\n props,\n }: WithFormProps<\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 TComponents,\n TFormComponents,\n TRenderProps\n >): WithFormProps<\n UnwrapOrAny<TFormData>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnMount>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnChange>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnChangeAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnBlur>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnBlurAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnSubmit>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnDynamic>,\n UnwrapDefaultOrAny<\n undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync\n >,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnServer>,\n UnwrapOrAny<TSubmitMeta>,\n UnwrapOrAny<TComponents>,\n UnwrapOrAny<TFormComponents>,\n UnwrapOrAny<TRenderProps>\n >['render'] {\n return (innerProps) => render({ ...props, ...innerProps })\n }\n\n function withFieldGroup<\n TFieldGroupData,\n TSubmitMeta,\n TRenderProps extends object = {},\n >({\n render,\n props,\n defaultValues,\n }: WithFieldGroupProps<\n TFieldGroupData,\n TComponents,\n TFormComponents,\n TSubmitMeta,\n TRenderProps\n >): <\n TFormData,\n TFields extends\n | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>\n | FieldsMap<TFormData, TFieldGroupData>,\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 TFormSubmitMeta,\n >(\n params: PropsWithChildren<\n NoInfer<TRenderProps> & {\n form:\n | AppFieldExtendedReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,\n TComponents,\n TFormComponents\n >\n | AppFieldExtendedReactFieldGroupApi<\n // Since this only occurs if you nest it within other field groups, it can be more\n // lenient with the types.\n unknown,\n TFormData,\n string | FieldsMap<unknown, TFormData>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,\n TComponents,\n TFormComponents\n >\n fields: TFields\n }\n >,\n ) => ReturnType<FunctionComponent> {\n return function Render(innerProps) {\n const fieldGroupProps = useMemo(() => {\n return {\n form: innerProps.form,\n fields: innerProps.fields,\n defaultValues,\n formComponents,\n }\n }, [innerProps.form, innerProps.fields])\n const fieldGroupApi = useFieldGroup(fieldGroupProps as any)\n\n return render({ ...props, ...innerProps, group: fieldGroupApi as any })\n }\n }\n\n return {\n useAppForm,\n withForm,\n withFieldGroup,\n }\n}\n"],"names":["fieldContext","formContext","AppField"],"mappings":";;;;;;;AA2BA;AACA;AAuCO;AACL;AACE;AAGA;AACE;AAAU;AACR;AAAA;AAIJ;AAAO;AA2BT;AACE;AAGA;AACE;AAAU;AACR;AAAA;AAIJ;AAAO;AAiBT;AACF;AA+JO;AAGL;AACA;AACAA;AACAC;AAEF;AACE;AA4CE;AAGA;AACE;AACE;AAC+C;AAEjD;AAGF;AACE;AACE;AAEM;AAAA;AAIA;AAEJ;AAiBJ;AAAOC;AAGT;AACE;AAA2B;AACzB;AACA;AACG;AACJ;AAGH;AAAO;AAGT;AAcE;AACA;AACA;AAqCA;AAAyD;AAG3D;AAIE;AACA;AACA;AACA;AAmEA;AACE;AACE;AAAO;AACY;AACE;AACnB;AACA;AAAA;AAGJ;AAEA;AAAsE;AACxE;AAGF;AAAO;AACL;AACA;AACA;AAEJ;;;"}
|
package/dist/cjs/useField.cjs
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
4
|
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
-
const
|
|
5
|
+
const React = require("react");
|
|
6
6
|
const reactStore = require("@tanstack/react-store");
|
|
7
7
|
const formCore = require("@tanstack/form-core");
|
|
8
8
|
const useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect.cjs");
|
|
9
9
|
function useField(opts) {
|
|
10
|
-
const [prevOptions, setPrevOptions] =
|
|
10
|
+
const [prevOptions, setPrevOptions] = React.useState(() => ({
|
|
11
11
|
form: opts.form,
|
|
12
12
|
name: opts.name
|
|
13
13
|
}));
|
|
14
|
-
const [fieldApi, setFieldApi] =
|
|
14
|
+
const [fieldApi, setFieldApi] = React.useState(() => {
|
|
15
15
|
return new formCore.FieldApi({
|
|
16
16
|
...opts
|
|
17
17
|
});
|
|
@@ -49,7 +49,7 @@ function useField(opts) {
|
|
|
49
49
|
fieldApi.store,
|
|
50
50
|
(state) => state.meta.isValidating
|
|
51
51
|
);
|
|
52
|
-
const extendedFieldApi =
|
|
52
|
+
const extendedFieldApi = React.useMemo(() => {
|
|
53
53
|
const reactiveFieldApi = {
|
|
54
54
|
...fieldApi,
|
|
55
55
|
get state() {
|
|
@@ -102,7 +102,7 @@ const Field = (({
|
|
|
102
102
|
...fieldOptions
|
|
103
103
|
}) => {
|
|
104
104
|
const fieldApi = useField(fieldOptions);
|
|
105
|
-
const jsxToDisplay =
|
|
105
|
+
const jsxToDisplay = React.useMemo(
|
|
106
106
|
() => formCore.functionalUpdate(children, fieldApi),
|
|
107
107
|
[children, fieldApi]
|
|
108
108
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useField.cjs","sources":["../../src/useField.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, useRef, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n AnyFieldApi,\n AnyFieldMeta,\n DeepKeys,\n DeepValue,\n FieldAsyncValidateOrFn,\n FieldValidateOrFn,\n FieldValidators,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, ReactElement, ReactNode } from 'react'\nimport type { UseFieldOptions, UseFieldOptionsBound } from './types'\n\ninterface ReactFieldApi<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> {\n /**\n * A pre-bound and type-safe sub-field component using this field as a root.\n */\n Field: FieldComponent<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >\n}\n\n/**\n * A type representing a hook for using a field in a form with the given form data type.\n *\n * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.\n */\nexport type UseField<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> = <\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>(\n opts: UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n >,\n) => FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>\n\n/**\n * A hook for managing a field in a form.\n * @param opts An object with field options.\n *\n * @returns The `FieldApi` instance for the specified field.\n */\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >,\n) {\n // Keep a snapshot of options so that React Compiler doesn't\n // wrongly optimize fieldApi.\n const [prevOptions, setPrevOptions] = useState(() => ({\n form: opts.form,\n name: opts.name,\n }))\n\n const [fieldApi, setFieldApi] = useState(() => {\n return new FieldApi({\n ...opts,\n })\n })\n\n // We only want to\n // update on name changes since those are at risk of becoming stale. The field\n // state must be up to date for the internal JSX render.\n // The other options can freely be in `fieldApi.update`\n if (prevOptions.form !== opts.form || prevOptions.name !== opts.name) {\n setFieldApi(\n new FieldApi({\n ...opts,\n }),\n )\n setPrevOptions({ form: opts.form, name: opts.name })\n }\n\n const reactiveStateValue = useStore(fieldApi.store, (state) => state.value)\n const reactiveMetaIsTouched = useStore(\n fieldApi.store,\n (state) => state.meta.isTouched,\n )\n const reactiveMetaIsBlurred = useStore(\n fieldApi.store,\n (state) => state.meta.isBlurred,\n )\n const reactiveMetaIsDirty = useStore(\n fieldApi.store,\n (state) => state.meta.isDirty,\n )\n const reactiveMetaErrorMap = useStore(\n fieldApi.store,\n (state) => state.meta.errorMap,\n )\n const reactiveMetaErrorSourceMap = useStore(\n fieldApi.store,\n (state) => state.meta.errorSourceMap,\n )\n const reactiveMetaIsValidating = useStore(\n fieldApi.store,\n (state) => state.meta.isValidating,\n )\n\n // This makes me sad, but if I understand correctly, this is what we have to do for reactivity to work properly with React compiler.\n const extendedFieldApi = useMemo(() => {\n const reactiveFieldApi = {\n ...fieldApi,\n get state() {\n return {\n value: reactiveStateValue,\n get meta() {\n return {\n ...fieldApi.state.meta,\n isTouched: reactiveMetaIsTouched,\n isBlurred: reactiveMetaIsBlurred,\n isDirty: reactiveMetaIsDirty,\n errorMap: reactiveMetaErrorMap,\n errorSourceMap: reactiveMetaErrorSourceMap,\n isValidating: reactiveMetaIsValidating,\n } satisfies AnyFieldMeta\n },\n } satisfies AnyFieldApi['state']\n },\n }\n\n const extendedApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ReactFieldApi<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > = reactiveFieldApi as never\n\n extendedApi.Field = Field as never\n\n return extendedApi\n }, [\n fieldApi,\n reactiveStateValue,\n reactiveMetaIsTouched,\n reactiveMetaIsBlurred,\n reactiveMetaIsDirty,\n reactiveMetaErrorMap,\n reactiveMetaErrorSourceMap,\n reactiveMetaIsValidating,\n ])\n\n useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])\n\n /**\n * fieldApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n fieldApi.update(opts)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [\n state.meta,\n Object.keys((state.value as unknown) ?? []).length,\n ]\n }\n : undefined,\n )\n\n return extendedFieldApi\n}\n\n/**\n * @param children A render function that takes a field API instance and returns a React element.\n */\ninterface FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\ninterface FieldComponentBoundProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n > {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\n/**\n * A type alias representing a field component for a specific form data type.\n */\nexport type FieldComponent<\n in out TParentData,\n in out TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChangeAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnBlurAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnSubmitAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnDynamicAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n in out TPatentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentBoundProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta,\n ExtendedApi\n>) => ReturnType<FunctionComponent>\n\n/**\n * A type alias representing a field component for a form lens data type.\n */\nexport type LensFieldComponent<\n in out TLensData,\n in out TParentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TLensData>,\n TData extends DeepValue<TLensData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChange extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentBoundProps<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n TParentSubmitMeta,\n ExtendedApi\n >,\n 'name' | 'validators'\n> & {\n name: TName\n validators?: Omit<\n FieldValidators<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n >,\n 'onChangeListenTo' | 'onBlurListenTo'\n > & {\n /**\n * An optional list of field names that should trigger this field's `onChange` and `onChangeAsync` events when its value changes\n */\n onChangeListenTo?: DeepKeys<TLensData>[]\n /**\n * An optional list of field names that should trigger this field's `onBlur` and `onBlurAsync` events when its value changes\n */\n onBlurListenTo?: DeepKeys<TLensData>[]\n }\n}) => ReturnType<FunctionComponent>\n\n/**\n * A function component that takes field options and a render function as children and returns a React component.\n *\n * The `Field` component uses the `useField` hook internally to manage the field instance.\n */\nexport const Field = (<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>): ReturnType<FunctionComponent> => {\n const fieldApi = useField(fieldOptions as any)\n\n const jsxToDisplay = useMemo(\n () => functionalUpdate(children, fieldApi as any),\n [children, fieldApi],\n )\n return (<>{jsxToDisplay}</>) as never\n}) satisfies FunctionComponent<\n FieldComponentProps<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n>\n"],"names":["useStore","useIsomorphicLayoutEffect","useMemo"],"mappings":";;;;;;;;AA0IO;AA6DL;AAAsD;AACzC;AACA;AAGb;AACE;AAAoB;AACf;AACJ;AAOH;AACE;AAAA;AACe;AACR;AACJ;AAEH;AAAmD;AAGrD;AACA;AAA8BA;AACnB;AACa;AAExB;AAA8BA;AACnB;AACa;AAExB;AAA4BA;AACjB;AACa;AAExB;AAA6BA;AAClB;AACa;AAExB;AAAmCA;AACxB;AACa;AAExB;AAAiCA;AACtB;AACa;AAIxB;AACE;AAAyB;AACpB;AAED;AAAO;AACE;AAEL;AAAO;AACa;AACP;AACA;AACF;AACC;AACM;AACF;AAAA;AAElB;AAAA;AAEJ;AAGF;AAwCA;AAEA;AAAO;AACN;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGFC;AAMAA;AACE;AAAoB;AAGtBD;AAAAA;AACW;AAGH;AAAO;AACC;AACsC;AAAA;AAGhD;AAGN;AACF;AAkVO;AAgCL;AACA;AAEF;AAyBE;AAEA;AAAqBE;AAC6B;AAC7B;AAErB;AACF;;;"}
|
|
1
|
+
{"version":3,"file":"useField.cjs","sources":["../../src/useField.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, useRef, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n AnyFieldApi,\n AnyFieldMeta,\n DeepKeys,\n DeepValue,\n FieldAsyncValidateOrFn,\n FieldValidateOrFn,\n FieldValidators,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, ReactElement, ReactNode } from 'react'\nimport type { UseFieldOptions, UseFieldOptionsBound } from './types'\n\ninterface ReactFieldApi<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> {\n /**\n * A pre-bound and type-safe sub-field component using this field as a root.\n */\n Field: FieldComponent<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >\n}\n\n/**\n * A type representing a hook for using a field in a form with the given form data type.\n *\n * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.\n */\nexport type UseField<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> = <\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>(\n opts: UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n >,\n) => FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>\n\n/**\n * A hook for managing a field in a form.\n * @param opts An object with field options.\n *\n * @returns The `FieldApi` instance for the specified field.\n */\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >,\n) {\n // Keep a snapshot of options so that React Compiler doesn't\n // wrongly optimize fieldApi.\n const [prevOptions, setPrevOptions] = useState(() => ({\n form: opts.form,\n name: opts.name,\n }))\n\n const [fieldApi, setFieldApi] = useState(() => {\n return new FieldApi({\n ...opts,\n })\n })\n\n // We only want to\n // update on name changes since those are at risk of becoming stale. The field\n // state must be up to date for the internal JSX render.\n // The other options can freely be in `fieldApi.update`\n if (prevOptions.form !== opts.form || prevOptions.name !== opts.name) {\n setFieldApi(\n new FieldApi({\n ...opts,\n }),\n )\n setPrevOptions({ form: opts.form, name: opts.name })\n }\n\n const reactiveStateValue = useStore(fieldApi.store, (state) => state.value)\n const reactiveMetaIsTouched = useStore(\n fieldApi.store,\n (state) => state.meta.isTouched,\n )\n const reactiveMetaIsBlurred = useStore(\n fieldApi.store,\n (state) => state.meta.isBlurred,\n )\n const reactiveMetaIsDirty = useStore(\n fieldApi.store,\n (state) => state.meta.isDirty,\n )\n const reactiveMetaErrorMap = useStore(\n fieldApi.store,\n (state) => state.meta.errorMap,\n )\n const reactiveMetaErrorSourceMap = useStore(\n fieldApi.store,\n (state) => state.meta.errorSourceMap,\n )\n const reactiveMetaIsValidating = useStore(\n fieldApi.store,\n (state) => state.meta.isValidating,\n )\n\n // This makes me sad, but if I understand correctly, this is what we have to do for reactivity to work properly with React compiler.\n const extendedFieldApi = useMemo(() => {\n const reactiveFieldApi = {\n ...fieldApi,\n get state() {\n return {\n value: reactiveStateValue,\n get meta() {\n return {\n ...fieldApi.state.meta,\n isTouched: reactiveMetaIsTouched,\n isBlurred: reactiveMetaIsBlurred,\n isDirty: reactiveMetaIsDirty,\n errorMap: reactiveMetaErrorMap,\n errorSourceMap: reactiveMetaErrorSourceMap,\n isValidating: reactiveMetaIsValidating,\n } satisfies AnyFieldMeta\n },\n } satisfies AnyFieldApi['state']\n },\n }\n\n const extendedApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ReactFieldApi<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > = reactiveFieldApi as never\n\n extendedApi.Field = Field as never\n\n return extendedApi\n }, [\n fieldApi,\n reactiveStateValue,\n reactiveMetaIsTouched,\n reactiveMetaIsBlurred,\n reactiveMetaIsDirty,\n reactiveMetaErrorMap,\n reactiveMetaErrorSourceMap,\n reactiveMetaIsValidating,\n ])\n\n useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])\n\n /**\n * fieldApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n fieldApi.update(opts)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [\n state.meta,\n Object.keys((state.value as unknown) ?? []).length,\n ]\n }\n : undefined,\n )\n\n return extendedFieldApi\n}\n\n/**\n * @param children A render function that takes a field API instance and returns a React element.\n */\ninterface FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n> {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\ninterface FieldComponentBoundProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n> {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\n/**\n * A type alias representing a field component for a specific form data type.\n */\nexport type FieldComponent<\n in out TParentData,\n in out TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChangeAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnBlurAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnSubmitAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnDynamicAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n in out TPatentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentBoundProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta,\n ExtendedApi\n>) => ReturnType<FunctionComponent>\n\n/**\n * A type alias representing a field component for a form lens data type.\n */\nexport type LensFieldComponent<\n in out TLensData,\n in out TParentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TLensData>,\n TData extends DeepValue<TLensData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChange extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentBoundProps<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n TParentSubmitMeta,\n ExtendedApi\n >,\n 'name' | 'validators'\n> & {\n name: TName\n validators?: Omit<\n FieldValidators<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n >,\n 'onChangeListenTo' | 'onBlurListenTo'\n > & {\n /**\n * An optional list of field names that should trigger this field's `onChange` and `onChangeAsync` events when its value changes\n */\n onChangeListenTo?: DeepKeys<TLensData>[]\n /**\n * An optional list of field names that should trigger this field's `onBlur` and `onBlurAsync` events when its value changes\n */\n onBlurListenTo?: DeepKeys<TLensData>[]\n }\n}) => ReturnType<FunctionComponent>\n\n/**\n * A function component that takes field options and a render function as children and returns a React component.\n *\n * The `Field` component uses the `useField` hook internally to manage the field instance.\n */\nexport const Field = (<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>): ReturnType<FunctionComponent> => {\n const fieldApi = useField(fieldOptions as any)\n\n const jsxToDisplay = useMemo(\n () => functionalUpdate(children, fieldApi as any),\n [children, fieldApi],\n )\n return (<>{jsxToDisplay}</>) as never\n}) satisfies FunctionComponent<\n FieldComponentProps<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n>\n"],"names":["useStore","useIsomorphicLayoutEffect","useMemo"],"mappings":";;;;;;;;AA0IO;AA6DL;AAAsD;AACzC;AACA;AAGb;AACE;AAAoB;AACf;AACJ;AAOH;AACE;AAAA;AACe;AACR;AACJ;AAEH;AAAmD;AAGrD;AACA;AAA8BA;AACnB;AACa;AAExB;AAA8BA;AACnB;AACa;AAExB;AAA4BA;AACjB;AACa;AAExB;AAA6BA;AAClB;AACa;AAExB;AAAmCA;AACxB;AACa;AAExB;AAAiCA;AACtB;AACa;AAIxB;AACE;AAAyB;AACpB;AAED;AAAO;AACE;AAEL;AAAO;AACa;AACP;AACA;AACF;AACC;AACM;AACF;AAAA;AAElB;AAAA;AAEJ;AAGF;AAwCA;AAEA;AAAO;AACN;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGFC;AAMAA;AACE;AAAoB;AAGtBD;AAAAA;AACW;AAGH;AAAO;AACC;AACsC;AAAA;AAGhD;AAGN;AACF;AAkVO;AAgCL;AACA;AAEF;AAyBE;AAEA;AAAqBE;AAC6B;AAC7B;AAErB;AACF;;;"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
4
4
|
const jsxRuntime = require("react/jsx-runtime");
|
|
5
|
-
const
|
|
5
|
+
const React = require("react");
|
|
6
6
|
const reactStore = require("@tanstack/react-store");
|
|
7
7
|
const formCore = require("@tanstack/form-core");
|
|
8
8
|
const useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect.cjs");
|
|
@@ -15,7 +15,7 @@ function LocalSubscribe({
|
|
|
15
15
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: formCore.functionalUpdate(children, data) });
|
|
16
16
|
}
|
|
17
17
|
function useFieldGroup(opts) {
|
|
18
|
-
const [formLensApi] =
|
|
18
|
+
const [formLensApi] = React.useState(() => {
|
|
19
19
|
const api = new formCore.FieldGroupApi(opts);
|
|
20
20
|
const form = opts.form instanceof formCore.FieldGroupApi ? opts.form.form : opts.form;
|
|
21
21
|
const extendedApi = api;
|
package/dist/cjs/useForm.cjs
CHANGED
|
@@ -4,9 +4,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
4
4
|
const jsxRuntime = require("react/jsx-runtime");
|
|
5
5
|
const formCore = require("@tanstack/form-core");
|
|
6
6
|
const reactStore = require("@tanstack/react-store");
|
|
7
|
-
const
|
|
7
|
+
const React = require("react");
|
|
8
8
|
const useField = require("./useField.cjs");
|
|
9
9
|
const useIsomorphicLayoutEffect = require("./useIsomorphicLayoutEffect.cjs");
|
|
10
|
+
const useFormId = require("./useFormId.cjs");
|
|
10
11
|
function LocalSubscribe({
|
|
11
12
|
form,
|
|
12
13
|
selector,
|
|
@@ -16,9 +17,9 @@ function LocalSubscribe({
|
|
|
16
17
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: formCore.functionalUpdate(children, data) });
|
|
17
18
|
}
|
|
18
19
|
function useForm(opts) {
|
|
19
|
-
const fallbackFormId =
|
|
20
|
-
const [prevFormId, setPrevFormId] =
|
|
21
|
-
const [formApi, setFormApi] =
|
|
20
|
+
const fallbackFormId = useFormId.useFormId();
|
|
21
|
+
const [prevFormId, setPrevFormId] = React.useState(opts?.formId);
|
|
22
|
+
const [formApi, setFormApi] = React.useState(() => {
|
|
22
23
|
return new formCore.FormApi({ ...opts, formId: opts?.formId ?? fallbackFormId });
|
|
23
24
|
});
|
|
24
25
|
if (prevFormId !== opts?.formId) {
|
|
@@ -26,9 +27,12 @@ function useForm(opts) {
|
|
|
26
27
|
setFormApi(new formCore.FormApi({ ...opts, formId }));
|
|
27
28
|
setPrevFormId(formId);
|
|
28
29
|
}
|
|
29
|
-
const extendedFormApi =
|
|
30
|
+
const extendedFormApi = React.useMemo(() => {
|
|
30
31
|
const extendedApi = {
|
|
31
32
|
...formApi,
|
|
33
|
+
handleSubmit: ((...props) => {
|
|
34
|
+
return formApi._handleSubmit(...props);
|
|
35
|
+
}),
|
|
32
36
|
// We must add all `get`ters from `core`'s `FormApi` here, as otherwise the spread operator won't catch those
|
|
33
37
|
get formId() {
|
|
34
38
|
return formApi._formId;
|
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
|
|
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;;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const React = require("react");
|
|
4
|
+
const useUUID = require("./useUUID.cjs");
|
|
5
|
+
function _interopNamespaceDefault(e) {
|
|
6
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
7
|
+
if (e) {
|
|
8
|
+
for (const k in e) {
|
|
9
|
+
if (k !== "default") {
|
|
10
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
11
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: () => e[k]
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
n.default = e;
|
|
19
|
+
return Object.freeze(n);
|
|
20
|
+
}
|
|
21
|
+
const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
|
|
22
|
+
const useFormId = React__namespace.version.split(".")[0] === "17" ? useUUID.useUUID : React__namespace.useId;
|
|
23
|
+
exports.useFormId = useFormId;
|
|
24
|
+
//# sourceMappingURL=useFormId.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFormId.cjs","sources":["../../src/useFormId.ts"],"sourcesContent":["import * as React from 'react'\nimport { useUUID } from './useUUID'\n\n/** React 17 does not have the useId hook, so we use a random uuid as a fallback. */\nexport const useFormId =\n React.version.split('.')[0] === '17' ? useUUID : React.useId\n"],"names":["React","useUUID"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAIO,MAAM,YACXA,iBAAM,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM,OAAOC,QAAAA,UAAUD,iBAAM;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
4
|
-
const useIsomorphicLayoutEffect = typeof window !== "undefined" ?
|
|
3
|
+
const React = require("react");
|
|
4
|
+
const useIsomorphicLayoutEffect = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;
|
|
5
5
|
exports.useIsomorphicLayoutEffect = useIsomorphicLayoutEffect;
|
|
6
6
|
//# sourceMappingURL=useIsomorphicLayoutEffect.cjs.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const React = require("react");
|
|
4
|
+
const formCore = require("@tanstack/form-core");
|
|
5
|
+
function useUUID() {
|
|
6
|
+
return React.useState(() => formCore.uuid())[0];
|
|
7
|
+
}
|
|
8
|
+
exports.useUUID = useUUID;
|
|
9
|
+
//# sourceMappingURL=useUUID.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUUID.cjs","sources":["../../src/useUUID.ts"],"sourcesContent":["import { useState } from 'react'\nimport { uuid } from '@tanstack/form-core'\n\n/** Generates a random UUID. and returns a stable reference to it. */\nexport function useUUID() {\n return useState<string>(() => uuid())[0]\n}\n"],"names":["useState","uuid"],"mappings":";;;;AAIO,SAAS,UAAU;AACxB,SAAOA,eAAiB,MAAMC,cAAA,CAAM,EAAE,CAAC;AACzC;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFormHook.js","sources":["../../src/createFormHook.tsx"],"sourcesContent":["'use client'\n/* eslint-disable @eslint-react/no-context-provider */\nimport { createContext, useContext, useMemo } from 'react'\nimport { useForm } from './useForm'\nimport { useFieldGroup } from './useFieldGroup'\nimport type {\n AnyFieldApi,\n AnyFormApi,\n BaseFormOptions,\n DeepKeysOfType,\n FieldApi,\n FieldsMap,\n FormAsyncValidateOrFn,\n FormOptions,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type {\n ComponentType,\n Context,\n FunctionComponent,\n PropsWithChildren,\n} from 'react'\nimport type { FieldComponent } from './useField'\nimport type { ReactFormExtendedApi } from './useForm'\nimport type { AppFieldExtendedReactFieldGroupApi } from './useFieldGroup'\n\n// We should never hit the `null` case here\nconst fieldContext = createContext<AnyFieldApi>(null as never)\nconst formContext = createContext<AnyFormApi>(null as never)\n\n/**\n * TypeScript inferencing is weird.\n *\n * If you have:\n *\n * @example\n *\n * interface Args<T> {\n * arg?: T\n * }\n *\n * function test<T>(arg?: Partial<Args<T>>): T {\n * return 0 as any;\n * }\n *\n * const a = test({});\n *\n * Then `T` will default to `unknown`.\n *\n * However, if we change `test` to be:\n *\n * @example\n *\n * function test<T extends undefined>(arg?: Partial<Args<T>>): T;\n *\n * Then `T` becomes `undefined`.\n *\n * Here, we are checking if the passed type `T` extends `DefaultT` and **only**\n * `DefaultT`, as if that's the case we assume that inferencing has not occurred.\n */\ntype UnwrapOrAny<T> = [unknown] extends [T] ? any : T\ntype UnwrapDefaultOrAny<DefaultT, T> = [DefaultT] extends [T]\n ? [T] extends [DefaultT]\n ? any\n : T\n : T\n\nexport function createFormHookContexts() {\n function useFieldContext<TData>() {\n const field = useContext(fieldContext)\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!field) {\n throw new Error(\n '`fieldContext` only works when within a `fieldComponent` passed to `createFormHook`',\n )\n }\n\n return field as FieldApi<\n any,\n string,\n TData,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n }\n\n function useFormContext() {\n const form = useContext(formContext)\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!form) {\n throw new Error(\n '`formContext` only works when within a `formComponent` passed to `createFormHook`',\n )\n }\n\n return form as ReactFormExtendedApi<\n // If you need access to the form data, you need to use `withForm` instead\n Record<string, never>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n }\n\n return { fieldContext, useFieldContext, useFormContext, formContext }\n}\n\ninterface CreateFormHookProps<\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> {\n fieldComponents: TFieldComponents\n fieldContext: Context<AnyFieldApi>\n formComponents: TFormComponents\n formContext: Context<AnyFormApi>\n}\n\n/**\n * @private\n */\nexport type AppFieldExtendedReactFormApi<\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 TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> = 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 NoInfer<TFormComponents> & {\n AppField: 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 NoInfer<TFieldComponents>\n >\n AppForm: ComponentType<\n // PropsWithChildren<P> is not optional in React 17\n PropsWithChildren<{}>\n >\n }\n\nexport interface WithFormProps<\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 TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TRenderProps extends object = Record<string, never>,\n> extends 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 // Optional, but adds props to the `render` function outside of `form`\n props?: TRenderProps\n render: FunctionComponent<\n PropsWithChildren<\n NoInfer<TRenderProps> & {\n form: AppFieldExtendedReactFormApi<\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 TFieldComponents,\n TFormComponents\n >\n }\n >\n >\n}\n\nexport interface WithFieldGroupProps<\n TFieldGroupData,\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TSubmitMeta,\n TRenderProps extends object = Record<string, never>,\n> extends BaseFormOptions<TFieldGroupData, TSubmitMeta> {\n // Optional, but adds props to the `render` function outside of `form`\n props?: TRenderProps\n render: FunctionComponent<\n PropsWithChildren<\n NoInfer<TRenderProps> & {\n group: AppFieldExtendedReactFieldGroupApi<\n unknown,\n TFieldGroupData,\n string | FieldsMap<unknown, TFieldGroupData>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n // this types it as 'never' in the render prop. It should prevent any\n // untyped meta passed to the handleSubmit by accident.\n unknown extends TSubmitMeta ? never : TSubmitMeta,\n TFieldComponents,\n TFormComponents\n >\n }\n >\n >\n}\n\nexport function createFormHook<\n const TComponents extends Record<string, ComponentType<any>>,\n const TFormComponents extends Record<string, ComponentType<any>>,\n>({\n fieldComponents,\n fieldContext,\n formContext,\n formComponents,\n}: CreateFormHookProps<TComponents, TFormComponents>) {\n function useAppForm<\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 props: 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 ): AppFieldExtendedReactFormApi<\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 TComponents,\n TFormComponents\n > {\n const form = useForm(props)\n\n // PropsWithChildren<P> is not optional in React 17\n const AppForm = useMemo<ComponentType<PropsWithChildren<{}>>>(() => {\n return ({ children }) => {\n return (\n <formContext.Provider value={form}>{children}</formContext.Provider>\n )\n }\n }, [form])\n\n const AppField = useMemo(() => {\n const AppField = (({ children, ...props }) => {\n return (\n <form.Field {...props}>\n {(field) => (\n // eslint-disable-next-line @eslint-react/no-context-provider\n <fieldContext.Provider value={field}>\n {children(Object.assign(field, fieldComponents))}\n </fieldContext.Provider>\n )}\n </form.Field>\n )\n }) as 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 TComponents\n >\n return AppField\n }, [form])\n\n const extendedForm = useMemo(() => {\n return Object.assign(form, {\n AppField,\n AppForm,\n ...formComponents,\n })\n }, [form, AppField, AppForm])\n\n return extendedForm\n }\n\n function withForm<\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 TRenderProps extends object = {},\n >({\n render,\n props,\n }: WithFormProps<\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 TComponents,\n TFormComponents,\n TRenderProps\n >): WithFormProps<\n UnwrapOrAny<TFormData>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnMount>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnChange>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnChangeAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnBlur>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnBlurAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnSubmit>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnDynamic>,\n UnwrapDefaultOrAny<\n undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync\n >,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnServer>,\n UnwrapOrAny<TSubmitMeta>,\n UnwrapOrAny<TComponents>,\n UnwrapOrAny<TFormComponents>,\n UnwrapOrAny<TRenderProps>\n >['render'] {\n return (innerProps) => render({ ...props, ...innerProps })\n }\n\n function withFieldGroup<\n TFieldGroupData,\n TSubmitMeta,\n TRenderProps extends object = {},\n >({\n render,\n props,\n defaultValues,\n }: WithFieldGroupProps<\n TFieldGroupData,\n TComponents,\n TFormComponents,\n TSubmitMeta,\n TRenderProps\n >): <\n TFormData,\n TFields extends\n | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>\n | FieldsMap<TFormData, TFieldGroupData>,\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 TFormSubmitMeta,\n >(\n params: PropsWithChildren<\n NoInfer<TRenderProps> & {\n form:\n | AppFieldExtendedReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,\n TComponents,\n TFormComponents\n >\n | AppFieldExtendedReactFieldGroupApi<\n // Since this only occurs if you nest it within other field groups, it can be more\n // lenient with the types.\n unknown,\n TFormData,\n string | FieldsMap<unknown, TFormData>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,\n TComponents,\n TFormComponents\n >\n fields: TFields\n }\n >,\n ) => ReturnType<FunctionComponent> {\n return function Render(innerProps) {\n const fieldGroupProps = useMemo(() => {\n return {\n form: innerProps.form,\n fields: innerProps.fields,\n defaultValues,\n formComponents,\n }\n }, [innerProps.form, innerProps.fields])\n const fieldGroupApi = useFieldGroup(fieldGroupProps as any)\n\n return render({ ...props, ...innerProps, group: fieldGroupApi as any })\n }\n }\n\n return {\n useAppForm,\n withForm,\n withFieldGroup,\n }\n}\n"],"names":["fieldContext","formContext","AppField"],"mappings":";;;;;AA2BA;AACA;AAuCO;AACL;AACE;AAGA;AACE;AAAU;AACR;AAAA;AAIJ;AAAO;AA2BT;AACE;AAGA;AACE;AAAU;AACR;AAAA;AAIJ;AAAO;AAiBT;AACF;AA+JO;AAGL;AACA;AACAA;AACAC;AAEF;AACE;AA4CE;AAGA;AACE;AACE;AAC+C;AAEjD;AAGF;AACE;AACE;AAEM;AAAA;AAIA;AAEJ;AAiBJ;AAAOC;AAGT;AACE;AAA2B;AACzB;AACA;AACG;AACJ;AAGH;AAAO;AAGT;AAcE;AACA;AACA;AAqCA;AAAyD;AAG3D;AAIE;AACA;AACA;AACA;AAmEA;AACE;AACE;AAAO;AACY;AACE;AACnB;AACA;AAAA;AAGJ;AAEA;AAAsE;AACxE;AAGF;AAAO;AACL;AACA;AACA;AAEJ;;;;;"}
|
|
1
|
+
{"version":3,"file":"createFormHook.js","sources":["../../src/createFormHook.tsx"],"sourcesContent":["'use client'\n/* eslint-disable @eslint-react/no-context-provider */\nimport { createContext, useContext, useMemo } from 'react'\nimport { useForm } from './useForm'\nimport { useFieldGroup } from './useFieldGroup'\nimport type {\n AnyFieldApi,\n AnyFormApi,\n BaseFormOptions,\n DeepKeysOfType,\n FieldApi,\n FieldsMap,\n FormAsyncValidateOrFn,\n FormOptions,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type {\n ComponentType,\n Context,\n FunctionComponent,\n PropsWithChildren,\n} from 'react'\nimport type { FieldComponent } from './useField'\nimport type { ReactFormExtendedApi } from './useForm'\nimport type { AppFieldExtendedReactFieldGroupApi } from './useFieldGroup'\n\n// We should never hit the `null` case here\nconst fieldContext = createContext<AnyFieldApi>(null as never)\nconst formContext = createContext<AnyFormApi>(null as never)\n\n/**\n * TypeScript inferencing is weird.\n *\n * If you have:\n *\n * @example\n *\n * interface Args<T> {\n * arg?: T\n * }\n *\n * function test<T>(arg?: Partial<Args<T>>): T {\n * return 0 as any;\n * }\n *\n * const a = test({});\n *\n * Then `T` will default to `unknown`.\n *\n * However, if we change `test` to be:\n *\n * @example\n *\n * function test<T extends undefined>(arg?: Partial<Args<T>>): T;\n *\n * Then `T` becomes `undefined`.\n *\n * Here, we are checking if the passed type `T` extends `DefaultT` and **only**\n * `DefaultT`, as if that's the case we assume that inferencing has not occurred.\n */\ntype UnwrapOrAny<T> = [unknown] extends [T] ? any : T\ntype UnwrapDefaultOrAny<DefaultT, T> = [DefaultT] extends [T]\n ? [T] extends [DefaultT]\n ? any\n : T\n : T\n\nexport function createFormHookContexts() {\n function useFieldContext<TData>() {\n const field = useContext(fieldContext)\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!field) {\n throw new Error(\n '`fieldContext` only works when within a `fieldComponent` passed to `createFormHook`',\n )\n }\n\n return field as FieldApi<\n any,\n string,\n TData,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n }\n\n function useFormContext() {\n const form = useContext(formContext)\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!form) {\n throw new Error(\n '`formContext` only works when within a `formComponent` passed to `createFormHook`',\n )\n }\n\n return form as ReactFormExtendedApi<\n // If you need access to the form data, you need to use `withForm` instead\n Record<string, never>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n }\n\n return { fieldContext, useFieldContext, useFormContext, formContext }\n}\n\ninterface CreateFormHookProps<\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> {\n fieldComponents: TFieldComponents\n fieldContext: Context<AnyFieldApi>\n formComponents: TFormComponents\n formContext: Context<AnyFormApi>\n}\n\n/**\n * @private\n */\nexport type AppFieldExtendedReactFormApi<\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 TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n> = 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 NoInfer<TFormComponents> & {\n AppField: 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 NoInfer<TFieldComponents>\n >\n AppForm: ComponentType<\n // PropsWithChildren<P> is not optional in React 17\n PropsWithChildren<{}>\n >\n }\n\nexport interface WithFormProps<\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 TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TRenderProps extends object = Record<string, never>,\n> extends 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 // Optional, but adds props to the `render` function outside of `form`\n props?: TRenderProps\n render: FunctionComponent<\n PropsWithChildren<\n NoInfer<TRenderProps> & {\n form: AppFieldExtendedReactFormApi<\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 TFieldComponents,\n TFormComponents\n >\n }\n >\n >\n}\n\nexport interface WithFieldGroupProps<\n TFieldGroupData,\n TFieldComponents extends Record<string, ComponentType<any>>,\n TFormComponents extends Record<string, ComponentType<any>>,\n TSubmitMeta,\n TRenderProps extends object = Record<string, never>,\n> extends BaseFormOptions<TFieldGroupData, TSubmitMeta> {\n // Optional, but adds props to the `render` function outside of `form`\n props?: TRenderProps\n render: FunctionComponent<\n PropsWithChildren<\n NoInfer<TRenderProps> & {\n group: AppFieldExtendedReactFieldGroupApi<\n unknown,\n TFieldGroupData,\n string | FieldsMap<unknown, TFieldGroupData>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n // this types it as 'never' in the render prop. It should prevent any\n // untyped meta passed to the handleSubmit by accident.\n unknown extends TSubmitMeta ? never : TSubmitMeta,\n TFieldComponents,\n TFormComponents\n >\n }\n >\n >\n}\n\nexport function createFormHook<\n const TComponents extends Record<string, ComponentType<any>>,\n const TFormComponents extends Record<string, ComponentType<any>>,\n>({\n fieldComponents,\n fieldContext,\n formContext,\n formComponents,\n}: CreateFormHookProps<TComponents, TFormComponents>) {\n function useAppForm<\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 props: 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 ): AppFieldExtendedReactFormApi<\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 TComponents,\n TFormComponents\n > {\n const form = useForm(props)\n\n // PropsWithChildren<P> is not optional in React 17\n const AppForm = useMemo<ComponentType<PropsWithChildren<{}>>>(() => {\n return ({ children }) => {\n return (\n <formContext.Provider value={form}>{children}</formContext.Provider>\n )\n }\n }, [form])\n\n const AppField = useMemo(() => {\n const AppField = (({ children, ...props }) => {\n return (\n <form.Field {...props}>\n {(field) => (\n // eslint-disable-next-line @eslint-react/no-context-provider\n <fieldContext.Provider value={field}>\n {children(Object.assign(field, fieldComponents))}\n </fieldContext.Provider>\n )}\n </form.Field>\n )\n }) as 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 TComponents\n >\n return AppField\n }, [form])\n\n const extendedForm = useMemo(() => {\n return Object.assign(form, {\n AppField,\n AppForm,\n ...formComponents,\n })\n }, [form, AppField, AppForm])\n\n return extendedForm\n }\n\n function withForm<\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 TRenderProps extends object = {},\n >({\n render,\n props,\n }: WithFormProps<\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 TComponents,\n TFormComponents,\n TRenderProps\n >): WithFormProps<\n UnwrapOrAny<TFormData>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnMount>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnChange>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnChangeAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnBlur>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnBlurAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnSubmit>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnSubmitAsync>,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnDynamic>,\n UnwrapDefaultOrAny<\n undefined | FormValidateOrFn<TFormData>,\n TOnDynamicAsync\n >,\n UnwrapDefaultOrAny<undefined | FormValidateOrFn<TFormData>, TOnServer>,\n UnwrapOrAny<TSubmitMeta>,\n UnwrapOrAny<TComponents>,\n UnwrapOrAny<TFormComponents>,\n UnwrapOrAny<TRenderProps>\n >['render'] {\n return (innerProps) => render({ ...props, ...innerProps })\n }\n\n function withFieldGroup<\n TFieldGroupData,\n TSubmitMeta,\n TRenderProps extends object = {},\n >({\n render,\n props,\n defaultValues,\n }: WithFieldGroupProps<\n TFieldGroupData,\n TComponents,\n TFormComponents,\n TSubmitMeta,\n TRenderProps\n >): <\n TFormData,\n TFields extends\n | DeepKeysOfType<TFormData, TFieldGroupData | null | undefined>\n | FieldsMap<TFormData, TFieldGroupData>,\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 TFormSubmitMeta,\n >(\n params: PropsWithChildren<\n NoInfer<TRenderProps> & {\n form:\n | AppFieldExtendedReactFormApi<\n TFormData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TOnServer,\n unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,\n TComponents,\n TFormComponents\n >\n | AppFieldExtendedReactFieldGroupApi<\n // Since this only occurs if you nest it within other field groups, it can be more\n // lenient with the types.\n unknown,\n TFormData,\n string | FieldsMap<unknown, TFormData>,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n unknown extends TSubmitMeta ? TFormSubmitMeta : TSubmitMeta,\n TComponents,\n TFormComponents\n >\n fields: TFields\n }\n >,\n ) => ReturnType<FunctionComponent> {\n return function Render(innerProps) {\n const fieldGroupProps = useMemo(() => {\n return {\n form: innerProps.form,\n fields: innerProps.fields,\n defaultValues,\n formComponents,\n }\n }, [innerProps.form, innerProps.fields])\n const fieldGroupApi = useFieldGroup(fieldGroupProps as any)\n\n return render({ ...props, ...innerProps, group: fieldGroupApi as any })\n }\n }\n\n return {\n useAppForm,\n withForm,\n withFieldGroup,\n }\n}\n"],"names":["fieldContext","formContext","AppField"],"mappings":";;;;;AA2BA;AACA;AAuCO;AACL;AACE;AAGA;AACE;AAAU;AACR;AAAA;AAIJ;AAAO;AA2BT;AACE;AAGA;AACE;AAAU;AACR;AAAA;AAIJ;AAAO;AAiBT;AACF;AA+JO;AAGL;AACA;AACAA;AACAC;AAEF;AACE;AA4CE;AAGA;AACE;AACE;AAC+C;AAEjD;AAGF;AACE;AACE;AAEM;AAAA;AAIA;AAEJ;AAiBJ;AAAOC;AAGT;AACE;AAA2B;AACzB;AACA;AACG;AACJ;AAGH;AAAO;AAGT;AAcE;AACA;AACA;AAqCA;AAAyD;AAG3D;AAIE;AACA;AACA;AACA;AAmEA;AACE;AACE;AAAO;AACY;AACE;AACnB;AACA;AAAA;AAGJ;AAEA;AAAsE;AACxE;AAGF;AAAO;AACL;AACA;AACA;AAEJ;;;;;"}
|
package/dist/esm/useField.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, useRef, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n AnyFieldApi,\n AnyFieldMeta,\n DeepKeys,\n DeepValue,\n FieldAsyncValidateOrFn,\n FieldValidateOrFn,\n FieldValidators,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, ReactElement, ReactNode } from 'react'\nimport type { UseFieldOptions, UseFieldOptionsBound } from './types'\n\ninterface ReactFieldApi<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> {\n /**\n * A pre-bound and type-safe sub-field component using this field as a root.\n */\n Field: FieldComponent<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >\n}\n\n/**\n * A type representing a hook for using a field in a form with the given form data type.\n *\n * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.\n */\nexport type UseField<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> = <\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>(\n opts: UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n >,\n) => FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>\n\n/**\n * A hook for managing a field in a form.\n * @param opts An object with field options.\n *\n * @returns The `FieldApi` instance for the specified field.\n */\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >,\n) {\n // Keep a snapshot of options so that React Compiler doesn't\n // wrongly optimize fieldApi.\n const [prevOptions, setPrevOptions] = useState(() => ({\n form: opts.form,\n name: opts.name,\n }))\n\n const [fieldApi, setFieldApi] = useState(() => {\n return new FieldApi({\n ...opts,\n })\n })\n\n // We only want to\n // update on name changes since those are at risk of becoming stale. The field\n // state must be up to date for the internal JSX render.\n // The other options can freely be in `fieldApi.update`\n if (prevOptions.form !== opts.form || prevOptions.name !== opts.name) {\n setFieldApi(\n new FieldApi({\n ...opts,\n }),\n )\n setPrevOptions({ form: opts.form, name: opts.name })\n }\n\n const reactiveStateValue = useStore(fieldApi.store, (state) => state.value)\n const reactiveMetaIsTouched = useStore(\n fieldApi.store,\n (state) => state.meta.isTouched,\n )\n const reactiveMetaIsBlurred = useStore(\n fieldApi.store,\n (state) => state.meta.isBlurred,\n )\n const reactiveMetaIsDirty = useStore(\n fieldApi.store,\n (state) => state.meta.isDirty,\n )\n const reactiveMetaErrorMap = useStore(\n fieldApi.store,\n (state) => state.meta.errorMap,\n )\n const reactiveMetaErrorSourceMap = useStore(\n fieldApi.store,\n (state) => state.meta.errorSourceMap,\n )\n const reactiveMetaIsValidating = useStore(\n fieldApi.store,\n (state) => state.meta.isValidating,\n )\n\n // This makes me sad, but if I understand correctly, this is what we have to do for reactivity to work properly with React compiler.\n const extendedFieldApi = useMemo(() => {\n const reactiveFieldApi = {\n ...fieldApi,\n get state() {\n return {\n value: reactiveStateValue,\n get meta() {\n return {\n ...fieldApi.state.meta,\n isTouched: reactiveMetaIsTouched,\n isBlurred: reactiveMetaIsBlurred,\n isDirty: reactiveMetaIsDirty,\n errorMap: reactiveMetaErrorMap,\n errorSourceMap: reactiveMetaErrorSourceMap,\n isValidating: reactiveMetaIsValidating,\n } satisfies AnyFieldMeta\n },\n } satisfies AnyFieldApi['state']\n },\n }\n\n const extendedApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ReactFieldApi<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > = reactiveFieldApi as never\n\n extendedApi.Field = Field as never\n\n return extendedApi\n }, [\n fieldApi,\n reactiveStateValue,\n reactiveMetaIsTouched,\n reactiveMetaIsBlurred,\n reactiveMetaIsDirty,\n reactiveMetaErrorMap,\n reactiveMetaErrorSourceMap,\n reactiveMetaIsValidating,\n ])\n\n useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])\n\n /**\n * fieldApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n fieldApi.update(opts)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [\n state.meta,\n Object.keys((state.value as unknown) ?? []).length,\n ]\n }\n : undefined,\n )\n\n return extendedFieldApi\n}\n\n/**\n * @param children A render function that takes a field API instance and returns a React element.\n */\ninterface FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\ninterface FieldComponentBoundProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n > {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\n/**\n * A type alias representing a field component for a specific form data type.\n */\nexport type FieldComponent<\n in out TParentData,\n in out TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChangeAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnBlurAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnSubmitAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnDynamicAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n in out TPatentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentBoundProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta,\n ExtendedApi\n>) => ReturnType<FunctionComponent>\n\n/**\n * A type alias representing a field component for a form lens data type.\n */\nexport type LensFieldComponent<\n in out TLensData,\n in out TParentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TLensData>,\n TData extends DeepValue<TLensData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChange extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentBoundProps<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n TParentSubmitMeta,\n ExtendedApi\n >,\n 'name' | 'validators'\n> & {\n name: TName\n validators?: Omit<\n FieldValidators<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n >,\n 'onChangeListenTo' | 'onBlurListenTo'\n > & {\n /**\n * An optional list of field names that should trigger this field's `onChange` and `onChangeAsync` events when its value changes\n */\n onChangeListenTo?: DeepKeys<TLensData>[]\n /**\n * An optional list of field names that should trigger this field's `onBlur` and `onBlurAsync` events when its value changes\n */\n onBlurListenTo?: DeepKeys<TLensData>[]\n }\n}) => ReturnType<FunctionComponent>\n\n/**\n * A function component that takes field options and a render function as children and returns a React component.\n *\n * The `Field` component uses the `useField` hook internally to manage the field instance.\n */\nexport const Field = (<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>): ReturnType<FunctionComponent> => {\n const fieldApi = useField(fieldOptions as any)\n\n const jsxToDisplay = useMemo(\n () => functionalUpdate(children, fieldApi as any),\n [children, fieldApi],\n )\n return (<>{jsxToDisplay}</>) as never\n}) satisfies FunctionComponent<\n FieldComponentProps<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n>\n"],"names":[],"mappings":";;;;;;AA0IO;AA6DL;AAAsD;AACzC;AACA;AAGb;AACE;AAAoB;AACf;AACJ;AAOH;AACE;AAAA;AACe;AACR;AACJ;AAEH;AAAmD;AAGrD;AACA;AAA8B;AACnB;AACa;AAExB;AAA8B;AACnB;AACa;AAExB;AAA4B;AACjB;AACa;AAExB;AAA6B;AAClB;AACa;AAExB;AAAmC;AACxB;AACa;AAExB;AAAiC;AACtB;AACa;AAIxB;AACE;AAAyB;AACpB;AAED;AAAO;AACE;AAEL;AAAO;AACa;AACP;AACA;AACF;AACC;AACM;AACF;AAAA;AAElB;AAAA;AAEJ;AAGF;AAwCA;AAEA;AAAO;AACN;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGF;AAMA;AACE;AAAoB;AAGtB;AAAA;AACW;AAGH;AAAO;AACC;AACsC;AAAA;AAGhD;AAGN;AACF;AAkVO;AAgCL;AACA;AAEF;AAyBE;AAEA;AAAqB;AAC6B;AAC7B;AAErB;AACF;;;;;"}
|
|
1
|
+
{"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, useRef, useState } from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type {\n AnyFieldApi,\n AnyFieldMeta,\n DeepKeys,\n DeepValue,\n FieldAsyncValidateOrFn,\n FieldValidateOrFn,\n FieldValidators,\n FormAsyncValidateOrFn,\n FormValidateOrFn,\n} from '@tanstack/form-core'\nimport type { FunctionComponent, ReactElement, ReactNode } from 'react'\nimport type { UseFieldOptions, UseFieldOptionsBound } from './types'\n\ninterface ReactFieldApi<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> {\n /**\n * A pre-bound and type-safe sub-field component using this field as a root.\n */\n Field: FieldComponent<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >\n}\n\n/**\n * A type representing a hook for using a field in a form with the given form data type.\n *\n * A function that takes an optional object with a `name` property and field options, and returns a `FieldApi` instance for the specified field.\n */\nexport type UseField<\n TParentData,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n> = <\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>(\n opts: UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n >,\n) => FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>\n\n/**\n * A hook for managing a field in a form.\n * @param opts An object with field options.\n *\n * @returns The `FieldApi` instance for the specified field.\n */\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n >,\n) {\n // Keep a snapshot of options so that React Compiler doesn't\n // wrongly optimize fieldApi.\n const [prevOptions, setPrevOptions] = useState(() => ({\n form: opts.form,\n name: opts.name,\n }))\n\n const [fieldApi, setFieldApi] = useState(() => {\n return new FieldApi({\n ...opts,\n })\n })\n\n // We only want to\n // update on name changes since those are at risk of becoming stale. The field\n // state must be up to date for the internal JSX render.\n // The other options can freely be in `fieldApi.update`\n if (prevOptions.form !== opts.form || prevOptions.name !== opts.name) {\n setFieldApi(\n new FieldApi({\n ...opts,\n }),\n )\n setPrevOptions({ form: opts.form, name: opts.name })\n }\n\n const reactiveStateValue = useStore(fieldApi.store, (state) => state.value)\n const reactiveMetaIsTouched = useStore(\n fieldApi.store,\n (state) => state.meta.isTouched,\n )\n const reactiveMetaIsBlurred = useStore(\n fieldApi.store,\n (state) => state.meta.isBlurred,\n )\n const reactiveMetaIsDirty = useStore(\n fieldApi.store,\n (state) => state.meta.isDirty,\n )\n const reactiveMetaErrorMap = useStore(\n fieldApi.store,\n (state) => state.meta.errorMap,\n )\n const reactiveMetaErrorSourceMap = useStore(\n fieldApi.store,\n (state) => state.meta.errorSourceMap,\n )\n const reactiveMetaIsValidating = useStore(\n fieldApi.store,\n (state) => state.meta.isValidating,\n )\n\n // This makes me sad, but if I understand correctly, this is what we have to do for reactivity to work properly with React compiler.\n const extendedFieldApi = useMemo(() => {\n const reactiveFieldApi = {\n ...fieldApi,\n get state() {\n return {\n value: reactiveStateValue,\n get meta() {\n return {\n ...fieldApi.state.meta,\n isTouched: reactiveMetaIsTouched,\n isBlurred: reactiveMetaIsBlurred,\n isDirty: reactiveMetaIsDirty,\n errorMap: reactiveMetaErrorMap,\n errorSourceMap: reactiveMetaErrorSourceMap,\n isValidating: reactiveMetaIsValidating,\n } satisfies AnyFieldMeta\n },\n } satisfies AnyFieldApi['state']\n },\n }\n\n const extendedApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ReactFieldApi<\n TParentData,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > = reactiveFieldApi as never\n\n extendedApi.Field = Field as never\n\n return extendedApi\n }, [\n fieldApi,\n reactiveStateValue,\n reactiveMetaIsTouched,\n reactiveMetaIsBlurred,\n reactiveMetaIsDirty,\n reactiveMetaErrorMap,\n reactiveMetaErrorSourceMap,\n reactiveMetaIsValidating,\n ])\n\n useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])\n\n /**\n * fieldApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n fieldApi.update(opts)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [\n state.meta,\n Object.keys((state.value as unknown) ?? []).length,\n ]\n }\n : undefined,\n )\n\n return extendedFieldApi\n}\n\n/**\n * @param children A render function that takes a field API instance and returns a React element.\n */\ninterface FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptions<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n> {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\ninterface FieldComponentBoundProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n ExtendedApi = {},\n> extends UseFieldOptionsBound<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n> {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n > &\n ExtendedApi,\n ) => ReactNode\n}\n\n/**\n * A type alias representing a field component for a specific form data type.\n */\nexport type FieldComponent<\n in out TParentData,\n in out TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnChangeAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnBlurAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnSubmitAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n in out TFormOnDynamicAsync extends\n | undefined\n | FormAsyncValidateOrFn<TParentData>,\n in out TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n in out TPatentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n>({\n children,\n ...fieldOptions\n}: FieldComponentBoundProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta,\n ExtendedApi\n>) => ReturnType<FunctionComponent>\n\n/**\n * A type alias representing a field component for a form lens data type.\n */\nexport type LensFieldComponent<\n in out TLensData,\n in out TParentSubmitMeta,\n in out ExtendedApi = {},\n> = <\n const TName extends DeepKeys<TLensData>,\n TData extends DeepValue<TLensData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChange extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<unknown, string, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<unknown, string, TData>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentBoundProps<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n undefined | FormAsyncValidateOrFn<unknown>,\n TParentSubmitMeta,\n ExtendedApi\n >,\n 'name' | 'validators'\n> & {\n name: TName\n validators?: Omit<\n FieldValidators<\n unknown,\n string,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync\n >,\n 'onChangeListenTo' | 'onBlurListenTo'\n > & {\n /**\n * An optional list of field names that should trigger this field's `onChange` and `onChangeAsync` events when its value changes\n */\n onChangeListenTo?: DeepKeys<TLensData>[]\n /**\n * An optional list of field names that should trigger this field's `onBlur` and `onBlurAsync` events when its value changes\n */\n onBlurListenTo?: DeepKeys<TLensData>[]\n }\n}) => ReturnType<FunctionComponent>\n\n/**\n * A function component that takes field options and a render function as children and returns a React component.\n *\n * The `Field` component uses the `useField` hook internally to manage the field instance.\n */\nexport const Field = (<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData extends DeepValue<TParentData, TName>,\n TOnMount extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChange extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnChangeAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnBlur extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnBlurAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnSubmit extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnSubmitAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TOnDynamic extends undefined | FieldValidateOrFn<TParentData, TName, TData>,\n TOnDynamicAsync extends\n | undefined\n | FieldAsyncValidateOrFn<TParentData, TName, TData>,\n TFormOnMount extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChange extends undefined | FormValidateOrFn<TParentData>,\n TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnBlur extends undefined | FormValidateOrFn<TParentData>,\n TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnSubmit extends undefined | FormValidateOrFn<TParentData>,\n TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnDynamic extends undefined | FormValidateOrFn<TParentData>,\n TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,\n TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,\n TPatentSubmitMeta,\n>({\n children,\n ...fieldOptions\n}: FieldComponentProps<\n TParentData,\n TName,\n TData,\n TOnMount,\n TOnChange,\n TOnChangeAsync,\n TOnBlur,\n TOnBlurAsync,\n TOnSubmit,\n TOnSubmitAsync,\n TOnDynamic,\n TOnDynamicAsync,\n TFormOnMount,\n TFormOnChange,\n TFormOnChangeAsync,\n TFormOnBlur,\n TFormOnBlurAsync,\n TFormOnSubmit,\n TFormOnSubmitAsync,\n TFormOnDynamic,\n TFormOnDynamicAsync,\n TFormOnServer,\n TPatentSubmitMeta\n>): ReturnType<FunctionComponent> => {\n const fieldApi = useField(fieldOptions as any)\n\n const jsxToDisplay = useMemo(\n () => functionalUpdate(children, fieldApi as any),\n [children, fieldApi],\n )\n return (<>{jsxToDisplay}</>) as never\n}) satisfies FunctionComponent<\n FieldComponentProps<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n any\n >\n>\n"],"names":[],"mappings":";;;;;;AA0IO;AA6DL;AAAsD;AACzC;AACA;AAGb;AACE;AAAoB;AACf;AACJ;AAOH;AACE;AAAA;AACe;AACR;AACJ;AAEH;AAAmD;AAGrD;AACA;AAA8B;AACnB;AACa;AAExB;AAA8B;AACnB;AACa;AAExB;AAA4B;AACjB;AACa;AAExB;AAA6B;AAClB;AACa;AAExB;AAAmC;AACxB;AACa;AAExB;AAAiC;AACtB;AACa;AAIxB;AACE;AAAyB;AACpB;AAED;AAAO;AACE;AAEL;AAAO;AACa;AACP;AACA;AACF;AACC;AACM;AACF;AAAA;AAElB;AAAA;AAEJ;AAGF;AAwCA;AAEA;AAAO;AACN;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGF;AAMA;AACE;AAAoB;AAGtB;AAAA;AACW;AAGH;AAAO;AACC;AACsC;AAAA;AAGhD;AAGN;AACF;AAkVO;AAgCL;AACA;AAEF;AAyBE;AAEA;AAAqB;AAC6B;AAC7B;AAErB;AACF;;;;;"}
|
package/dist/esm/useForm.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, Fragment } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { FormApi, functionalUpdate } from "@tanstack/form-core";
|
|
4
4
|
import { useStore } from "@tanstack/react-store";
|
|
5
5
|
import { useState, useMemo } from "react";
|
|
6
6
|
import { Field } from "./useField.js";
|
|
7
7
|
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
8
|
+
import { useFormId } from "./useFormId.js";
|
|
8
9
|
function LocalSubscribe({
|
|
9
10
|
form,
|
|
10
11
|
selector,
|
|
@@ -14,7 +15,7 @@ function LocalSubscribe({
|
|
|
14
15
|
return /* @__PURE__ */ jsx(Fragment, { children: functionalUpdate(children, data) });
|
|
15
16
|
}
|
|
16
17
|
function useForm(opts) {
|
|
17
|
-
const fallbackFormId =
|
|
18
|
+
const fallbackFormId = useFormId();
|
|
18
19
|
const [prevFormId, setPrevFormId] = useState(opts?.formId);
|
|
19
20
|
const [formApi, setFormApi] = useState(() => {
|
|
20
21
|
return new FormApi({ ...opts, formId: opts?.formId ?? fallbackFormId });
|
|
@@ -27,6 +28,9 @@ function useForm(opts) {
|
|
|
27
28
|
const extendedFormApi = useMemo(() => {
|
|
28
29
|
const extendedApi = {
|
|
29
30
|
...formApi,
|
|
31
|
+
handleSubmit: ((...props) => {
|
|
32
|
+
return formApi._handleSubmit(...props);
|
|
33
|
+
}),
|
|
30
34
|
// We must add all `get`ters from `core`'s `FormApi` here, as otherwise the spread operator won't catch those
|
|
31
35
|
get formId() {
|
|
32
36
|
return formApi._formId;
|
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
|
|
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;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFormId.js","sources":["../../src/useFormId.ts"],"sourcesContent":["import * as React from 'react'\nimport { useUUID } from './useUUID'\n\n/** React 17 does not have the useId hook, so we use a random uuid as a fallback. */\nexport const useFormId =\n React.version.split('.')[0] === '17' ? useUUID : React.useId\n"],"names":[],"mappings":";;AAIO,MAAM,YACX,MAAM,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM,OAAO,UAAU,MAAM;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUUID.js","sources":["../../src/useUUID.ts"],"sourcesContent":["import { useState } from 'react'\nimport { uuid } from '@tanstack/form-core'\n\n/** Generates a random UUID. and returns a stable reference to it. */\nexport function useUUID() {\n return useState<string>(() => uuid())[0]\n}\n"],"names":[],"mappings":";;AAIO,SAAS,UAAU;AACxB,SAAO,SAAiB,MAAM,KAAA,CAAM,EAAE,CAAC;AACzC;"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-form",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.2",
|
|
4
4
|
"description": "Powerful, type-safe forms for React.",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/TanStack/form.git",
|
|
9
|
+
"url": "git+https://github.com/TanStack/form.git",
|
|
10
10
|
"directory": "packages/react-form"
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://tanstack.com/form",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@tanstack/react-store": "^0.8.0",
|
|
41
|
-
"@tanstack/form-core": "1.27.
|
|
41
|
+
"@tanstack/form-core": "1.27.2"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/react": "^19.0.7",
|
package/src/createFormHook.tsx
CHANGED
|
@@ -214,19 +214,19 @@ export interface WithFormProps<
|
|
|
214
214
|
TFormComponents extends Record<string, ComponentType<any>>,
|
|
215
215
|
TRenderProps extends object = Record<string, never>,
|
|
216
216
|
> extends FormOptions<
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
217
|
+
TFormData,
|
|
218
|
+
TOnMount,
|
|
219
|
+
TOnChange,
|
|
220
|
+
TOnChangeAsync,
|
|
221
|
+
TOnBlur,
|
|
222
|
+
TOnBlurAsync,
|
|
223
|
+
TOnSubmit,
|
|
224
|
+
TOnSubmitAsync,
|
|
225
|
+
TOnDynamic,
|
|
226
|
+
TOnDynamicAsync,
|
|
227
|
+
TOnServer,
|
|
228
|
+
TSubmitMeta
|
|
229
|
+
> {
|
|
230
230
|
// Optional, but adds props to the `render` function outside of `form`
|
|
231
231
|
props?: TRenderProps
|
|
232
232
|
render: FunctionComponent<
|
package/src/types.ts
CHANGED
|
@@ -49,7 +49,9 @@ export interface UseFieldOptions<
|
|
|
49
49
|
TFormOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TParentData>,
|
|
50
50
|
TFormOnServer extends undefined | FormAsyncValidateOrFn<TParentData>,
|
|
51
51
|
TSubmitMeta,
|
|
52
|
-
>
|
|
52
|
+
>
|
|
53
|
+
extends
|
|
54
|
+
FieldApiOptions<
|
|
53
55
|
TParentData,
|
|
54
56
|
TName,
|
|
55
57
|
TData,
|
|
@@ -97,7 +99,9 @@ export interface UseFieldOptionsBound<
|
|
|
97
99
|
TOnDynamicAsync extends
|
|
98
100
|
| undefined
|
|
99
101
|
| FieldAsyncValidateOrFn<TParentData, TName, TData>,
|
|
100
|
-
>
|
|
102
|
+
>
|
|
103
|
+
extends
|
|
104
|
+
FieldOptions<
|
|
101
105
|
TParentData,
|
|
102
106
|
TName,
|
|
103
107
|
TData,
|
package/src/useField.tsx
CHANGED
|
@@ -385,30 +385,30 @@ interface FieldComponentProps<
|
|
|
385
385
|
TPatentSubmitMeta,
|
|
386
386
|
ExtendedApi = {},
|
|
387
387
|
> extends UseFieldOptions<
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
388
|
+
TParentData,
|
|
389
|
+
TName,
|
|
390
|
+
TData,
|
|
391
|
+
TOnMount,
|
|
392
|
+
TOnChange,
|
|
393
|
+
TOnChangeAsync,
|
|
394
|
+
TOnBlur,
|
|
395
|
+
TOnBlurAsync,
|
|
396
|
+
TOnSubmit,
|
|
397
|
+
TOnSubmitAsync,
|
|
398
|
+
TOnDynamic,
|
|
399
|
+
TOnDynamicAsync,
|
|
400
|
+
TFormOnMount,
|
|
401
|
+
TFormOnChange,
|
|
402
|
+
TFormOnChangeAsync,
|
|
403
|
+
TFormOnBlur,
|
|
404
|
+
TFormOnBlurAsync,
|
|
405
|
+
TFormOnSubmit,
|
|
406
|
+
TFormOnSubmitAsync,
|
|
407
|
+
TFormOnDynamic,
|
|
408
|
+
TFormOnDynamicAsync,
|
|
409
|
+
TFormOnServer,
|
|
410
|
+
TPatentSubmitMeta
|
|
411
|
+
> {
|
|
412
412
|
children: (
|
|
413
413
|
fieldApi: FieldApi<
|
|
414
414
|
TParentData,
|
|
@@ -473,19 +473,19 @@ interface FieldComponentBoundProps<
|
|
|
473
473
|
TPatentSubmitMeta,
|
|
474
474
|
ExtendedApi = {},
|
|
475
475
|
> extends UseFieldOptionsBound<
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
476
|
+
TParentData,
|
|
477
|
+
TName,
|
|
478
|
+
TData,
|
|
479
|
+
TOnMount,
|
|
480
|
+
TOnChange,
|
|
481
|
+
TOnChangeAsync,
|
|
482
|
+
TOnBlur,
|
|
483
|
+
TOnBlurAsync,
|
|
484
|
+
TOnSubmit,
|
|
485
|
+
TOnSubmitAsync,
|
|
486
|
+
TOnDynamic,
|
|
487
|
+
TOnDynamicAsync
|
|
488
|
+
> {
|
|
489
489
|
children: (
|
|
490
490
|
fieldApi: FieldApi<
|
|
491
491
|
TParentData,
|
package/src/useForm.tsx
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { FormApi, functionalUpdate
|
|
3
|
+
import { FormApi, functionalUpdate } from '@tanstack/form-core'
|
|
4
4
|
import { useStore } from '@tanstack/react-store'
|
|
5
5
|
import { useMemo, useState } from 'react'
|
|
6
6
|
import { Field } from './useField'
|
|
7
7
|
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
|
|
8
|
+
import { useFormId } from './useFormId'
|
|
8
9
|
import type {
|
|
9
10
|
AnyFormApi,
|
|
10
11
|
AnyFormState,
|
|
@@ -184,7 +185,7 @@ export function useForm<
|
|
|
184
185
|
TSubmitMeta
|
|
185
186
|
>,
|
|
186
187
|
) {
|
|
187
|
-
const fallbackFormId =
|
|
188
|
+
const fallbackFormId = useFormId()
|
|
188
189
|
const [prevFormId, setPrevFormId] = useState<string>(opts?.formId as never)
|
|
189
190
|
|
|
190
191
|
const [formApi, setFormApi] = useState(() => {
|
|
@@ -226,6 +227,9 @@ export function useForm<
|
|
|
226
227
|
TSubmitMeta
|
|
227
228
|
> = {
|
|
228
229
|
...formApi,
|
|
230
|
+
handleSubmit: ((...props: never[]) => {
|
|
231
|
+
return formApi._handleSubmit(...props)
|
|
232
|
+
}) as typeof formApi.handleSubmit,
|
|
229
233
|
// We must add all `get`ters from `core`'s `FormApi` here, as otherwise the spread operator won't catch those
|
|
230
234
|
get formId(): string {
|
|
231
235
|
return formApi._formId
|
package/src/useFormId.ts
ADDED