@tanstack/react-form 0.16.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/useField.cjs.map +1 -1
- package/dist/cjs/useField.d.cts +6 -6
- package/dist/cjs/useForm.cjs.map +1 -1
- package/dist/cjs/validateFormData.d.cts +1 -1
- package/dist/esm/useField.d.ts +6 -6
- package/dist/esm/useField.js.map +1 -1
- package/dist/esm/useForm.js.map +1 -1
- package/dist/esm/validateFormData.d.ts +1 -1
- package/package.json +2 -2
- package/src/tests/useField.test-d.tsx +41 -0
- package/src/useField.tsx +29 -14
- package/src/useForm.tsx +1 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useField.cjs","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'rehackt'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { UseFieldOptions } from './types'\nimport type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TParentData, TFormValidator>\n }\n}\n\nexport type UseField<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n 'form'\n >,\n) => FieldApi
|
|
1
|
+
{"version":3,"file":"useField.cjs","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'rehackt'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { UseFieldOptions } from './types'\nimport type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TParentData, TFormValidator>\n }\n}\n\nexport type UseField<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>,\n 'form'\n >,\n) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData> {\n const [fieldApi] = useState(() => {\n const api = new FieldApi({\n ...opts,\n form: opts.form,\n name: opts.name,\n })\n\n api.Field = Field as never\n\n return api\n })\n\n useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])\n\n /**\n * fieldApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n fieldApi.update(opts)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [state.meta, Object.keys(state.value as never).length]\n }\n : undefined,\n )\n\n return fieldApi as never\n}\n\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => any\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\nexport type FieldComponent<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n 'form'\n>) => any\n\nexport function Field<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => any\n} & UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n>) {\n const fieldApi = useField(fieldOptions as any)\n\n return <>{functionalUpdate(children, fieldApi as any)}</>\n}\n"],"names":["useState","FieldApi","useIsomorphicLayoutEffect","useStore","jsx","Fragment","functionalUpdate"],"mappings":";;;;;;;AA+CO,SAAS,SAWd,MAOsE;AACtE,QAAM,CAAC,QAAQ,IAAIA,QAAAA,SAAS,MAAM;AAC1B,UAAA,MAAM,IAAIC,kBAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IAAA,CACZ;AAED,QAAI,QAAQ;AAEL,WAAA;AAAA,EAAA,CACR;AAEDC,4BAAAA,0BAA0B,SAAS,OAAO,CAAC,QAAQ,CAAC;AAMpDA,4BAAAA,0BAA0B,MAAM;AAC9B,aAAS,OAAO,IAAI;AAAA,EAAA,CACrB;AAEDC,aAAA;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACF,aAAA,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAc,EAAE,MAAM;AAAA,IAE9D,IAAA;AAAA,EAAA;AAGC,SAAA;AACT;AAiDO,SAAS,MAUd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAgBG;AACK,QAAA,WAAW,SAAS,YAAmB;AAE7C,SAAUC,2BAAA,IAAAC,WAAA,UAAA,EAAA,UAAAC,SAAA,iBAAiB,UAAU,QAAe,EAAE,CAAA;AACxD;;;"}
|
package/dist/cjs/useField.d.cts
CHANGED
|
@@ -8,13 +8,13 @@ declare module '@tanstack/form-core' {
|
|
|
8
8
|
Field: FieldComponent<TParentData, TFormValidator>;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
export type UseField<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined>(opts: Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>, 'form'>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator,
|
|
12
|
-
export declare function useField<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>(opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): FieldApi<TParentData, TName, TFieldValidator, TFormValidator>;
|
|
11
|
+
export type UseField<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>, 'form'>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
12
|
+
export declare function useField<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
13
13
|
type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = {
|
|
14
14
|
children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>) => any;
|
|
15
|
-
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>;
|
|
15
|
+
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
16
16
|
export type FieldComponent<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: Omit<FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator, TData>, 'form'>) => any;
|
|
17
|
-
export declare function Field<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>({ children, ...fieldOptions }: {
|
|
18
|
-
children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>) => any;
|
|
19
|
-
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): React.JSX.Element;
|
|
17
|
+
export declare function Field<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: {
|
|
18
|
+
children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>) => any;
|
|
19
|
+
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>): React.JSX.Element;
|
|
20
20
|
export {};
|
package/dist/cjs/useForm.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useForm.cjs","sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport React, {
|
|
1
|
+
{"version":3,"file":"useForm.cjs","sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport React, { type ReactNode, useState } from 'rehackt'\nimport { Field, type FieldComponent, type UseField, useField } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NoInfer } from '@tanstack/react-store'\nimport type { FormOptions, FormState, Validator } from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n Field: FieldComponent<TFormData, TFormValidator>\n useField: UseField<TFormData, TFormValidator>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {\n /**\n TypeScript versions <=5.0.4 have a bug that prevents\n the type of the `TSelected` generic from being inferred\n from the return type of this method.\n\n In these versions, `TSelected` will fall back to the default\n type (or `unknown` if that's not defined).\n\n @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}\n @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}\n */\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => JSX.Element\n }\n}\n\nexport function useForm<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n opts?: FormOptions<TFormData, TFormValidator>,\n): FormApi<TFormData, TFormValidator> {\n const [formApi] = useState(() => {\n const api = new FormApi<TFormData, TFormValidator>(opts)\n api.Field = function APIField(props) {\n return <Field {...props} form={api} />\n }\n // eslint-disable-next-line react-hooks/rules-of-hooks\n api.useField = (props) => useField({ ...props, form: api })\n api.useStore = (\n // @ts-ignore\n selector,\n ) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useStore(api.store as any, selector as any) as any\n }\n api.Subscribe = (\n // @ts-ignore\n props,\n ) => {\n return functionalUpdate(\n props.children,\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(api.store as any, props.selector as any),\n ) as any\n }\n\n return api\n })\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n formApi.useStore((state) => state.isSubmitting)\n\n /**\n * formApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n formApi.update(opts)\n })\n\n return formApi as any\n}\n"],"names":["useState","FormApi","jsx","Field","useField","useStore","functionalUpdate","useIsomorphicLayoutEffect"],"mappings":";;;;;;;;AAkCO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAIA,QAAAA,SAAS,MAAM;AACzB,UAAA,MAAM,IAAIC,iBAAmC,IAAI;AACnD,QAAA,QAAQ,SAAS,SAAS,OAAO;AACnC,aAAQC,2BAAAA,IAAAC,SAAAA,OAAA,EAAO,GAAG,OAAO,MAAM,IAAK,CAAA;AAAA,IAAA;AAGlC,QAAA,WAAW,CAAC,UAAUC,SAAA,SAAS,EAAE,GAAG,OAAO,MAAM,IAAA,CAAK;AACtD,QAAA,WAAW,CAEb,aACG;AAEI,aAAAC,oBAAS,IAAI,OAAc,QAAe;AAAA,IAAA;AAE/C,QAAA,YAAY,CAEd,UACG;AACI,aAAAC,SAAA;AAAA,QACL,MAAM;AAAA;AAAA,QAEND,WAAAA,SAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAAA;AAAA,IAClD;AAGK,WAAA;AAAA,EAAA,CACR;AAEyBE,4BAAAA,0BAAA,QAAQ,OAAO,CAAA,CAAE;AAE3C,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9CA,4BAAAA,0BAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EAAA,CACpB;AAEM,SAAA;AACT;;"}
|
|
@@ -10,5 +10,5 @@ declare module '@tanstack/form-core' {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
export type ValidateFormData<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined> = (formData: FormData, info?: Parameters<typeof decode>[1]) => Promise<Partial<FormApi<TFormData, TFormValidator>['state']>>;
|
|
13
|
-
export declare const getValidateFormData: <TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined>(defaultOpts?: FormOptions<TFormData, TFormValidator>
|
|
13
|
+
export declare const getValidateFormData: <TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined>(defaultOpts?: FormOptions<TFormData, TFormValidator>) => ValidateFormData<TFormData, TFormValidator>;
|
|
14
14
|
export {};
|
package/dist/esm/useField.d.ts
CHANGED
|
@@ -8,13 +8,13 @@ declare module '@tanstack/form-core' {
|
|
|
8
8
|
Field: FieldComponent<TParentData, TFormValidator>;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
export type UseField<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined>(opts: Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>, 'form'>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator,
|
|
12
|
-
export declare function useField<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>(opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): FieldApi<TParentData, TName, TFieldValidator, TFormValidator>;
|
|
11
|
+
export type UseField<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>, 'form'>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
12
|
+
export declare function useField<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
13
13
|
type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = {
|
|
14
14
|
children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>) => any;
|
|
15
|
-
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>;
|
|
15
|
+
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
|
16
16
|
export type FieldComponent<TParentData, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = <TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: Omit<FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator, TData>, 'form'>) => any;
|
|
17
|
-
export declare function Field<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>({ children, ...fieldOptions }: {
|
|
18
|
-
children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator>) => any;
|
|
19
|
-
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>): React.JSX.Element;
|
|
17
|
+
export declare function Field<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>({ children, ...fieldOptions }: {
|
|
18
|
+
children: (fieldApi: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>) => any;
|
|
19
|
+
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>): React.JSX.Element;
|
|
20
20
|
export {};
|
package/dist/esm/useField.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'rehackt'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { UseFieldOptions } from './types'\nimport type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TParentData, TFormValidator>\n }\n}\n\nexport type UseField<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n 'form'\n >,\n) => FieldApi
|
|
1
|
+
{"version":3,"file":"useField.js","sources":["../../src/useField.tsx"],"sourcesContent":["import React, { useState } from 'rehackt'\nimport { useStore } from '@tanstack/react-store'\nimport { FieldApi, functionalUpdate } from '@tanstack/form-core'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { UseFieldOptions } from './types'\nimport type {\n DeepKeys,\n DeepValue,\n Narrow,\n Validator,\n} from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FieldApi<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TParentData, TFormValidator>\n }\n}\n\nexport type UseField<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>,\n 'form'\n >,\n) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData> {\n const [fieldApi] = useState(() => {\n const api = new FieldApi({\n ...opts,\n form: opts.form,\n name: opts.name,\n })\n\n api.Field = Field as never\n\n return api\n })\n\n useIsomorphicLayoutEffect(fieldApi.mount, [fieldApi])\n\n /**\n * fieldApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n fieldApi.update(opts)\n })\n\n useStore(\n fieldApi.store,\n opts.mode === 'array'\n ? (state) => {\n return [state.meta, Object.keys(state.value as never).length]\n }\n : undefined,\n )\n\n return fieldApi as never\n}\n\ntype FieldComponentProps<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n> = {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => any\n} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>\n\nexport type FieldComponent<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: Omit<\n FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n 'form'\n>) => any\n\nexport function Field<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>({\n children,\n ...fieldOptions\n}: {\n children: (\n fieldApi: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n ) => any\n} & UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n>) {\n const fieldApi = useField(fieldOptions as any)\n\n return <>{functionalUpdate(children, fieldApi as any)}</>\n}\n"],"names":[],"mappings":";;;;;AA+CO,SAAS,SAWd,MAOsE;AACtE,QAAM,CAAC,QAAQ,IAAI,SAAS,MAAM;AAC1B,UAAA,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IAAA,CACZ;AAED,QAAI,QAAQ;AAEL,WAAA;AAAA,EAAA,CACR;AAED,4BAA0B,SAAS,OAAO,CAAC,QAAQ,CAAC;AAMpD,4BAA0B,MAAM;AAC9B,aAAS,OAAO,IAAI;AAAA,EAAA,CACrB;AAED;AAAA,IACE,SAAS;AAAA,IACT,KAAK,SAAS,UACV,CAAC,UAAU;AACF,aAAA,CAAC,MAAM,MAAM,OAAO,KAAK,MAAM,KAAc,EAAE,MAAM;AAAA,IAE9D,IAAA;AAAA,EAAA;AAGC,SAAA;AACT;AAiDO,SAAS,MAUd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAgBG;AACK,QAAA,WAAW,SAAS,YAAmB;AAE7C,SAAU,oBAAA,UAAA,EAAA,UAAA,iBAAiB,UAAU,QAAe,EAAE,CAAA;AACxD;"}
|
package/dist/esm/useForm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useForm.js","sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport React, {
|
|
1
|
+
{"version":3,"file":"useForm.js","sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, functionalUpdate } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/react-store'\nimport React, { type ReactNode, useState } from 'rehackt'\nimport { Field, type FieldComponent, type UseField, useField } from './useField'\nimport { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'\nimport type { NoInfer } from '@tanstack/react-store'\nimport type { FormOptions, FormState, Validator } from '@tanstack/form-core'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n Field: FieldComponent<TFormData, TFormValidator>\n useField: UseField<TFormData, TFormValidator>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {\n /**\n TypeScript versions <=5.0.4 have a bug that prevents\n the type of the `TSelected` generic from being inferred\n from the return type of this method.\n\n In these versions, `TSelected` will fall back to the default\n type (or `unknown` if that's not defined).\n\n @see {@link https://github.com/TanStack/form/pull/606/files#r1506715714 | This discussion on GitHub for the details}\n @see {@link https://github.com/microsoft/TypeScript/issues/52786 | The bug report in `microsoft/TypeScript`}\n */\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode\n }) => JSX.Element\n }\n}\n\nexport function useForm<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n opts?: FormOptions<TFormData, TFormValidator>,\n): FormApi<TFormData, TFormValidator> {\n const [formApi] = useState(() => {\n const api = new FormApi<TFormData, TFormValidator>(opts)\n api.Field = function APIField(props) {\n return <Field {...props} form={api} />\n }\n // eslint-disable-next-line react-hooks/rules-of-hooks\n api.useField = (props) => useField({ ...props, form: api })\n api.useStore = (\n // @ts-ignore\n selector,\n ) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useStore(api.store as any, selector as any) as any\n }\n api.Subscribe = (\n // @ts-ignore\n props,\n ) => {\n return functionalUpdate(\n props.children,\n // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(api.store as any, props.selector as any),\n ) as any\n }\n\n return api\n })\n\n useIsomorphicLayoutEffect(formApi.mount, [])\n\n formApi.useStore((state) => state.isSubmitting)\n\n /**\n * formApi.update should not have any side effects. Think of it like a `useRef`\n * that we need to keep updated every render with the most up-to-date information.\n */\n useIsomorphicLayoutEffect(() => {\n formApi.update(opts)\n })\n\n return formApi as any\n}\n"],"names":[],"mappings":";;;;;;AAkCO,SAAS,QAId,MACoC;AACpC,QAAM,CAAC,OAAO,IAAI,SAAS,MAAM;AACzB,UAAA,MAAM,IAAI,QAAmC,IAAI;AACnD,QAAA,QAAQ,SAAS,SAAS,OAAO;AACnC,aAAQ,oBAAA,OAAA,EAAO,GAAG,OAAO,MAAM,IAAK,CAAA;AAAA,IAAA;AAGlC,QAAA,WAAW,CAAC,UAAU,SAAS,EAAE,GAAG,OAAO,MAAM,IAAA,CAAK;AACtD,QAAA,WAAW,CAEb,aACG;AAEI,aAAA,SAAS,IAAI,OAAc,QAAe;AAAA,IAAA;AAE/C,QAAA,YAAY,CAEd,UACG;AACI,aAAA;AAAA,QACL,MAAM;AAAA;AAAA,QAEN,SAAS,IAAI,OAAc,MAAM,QAAe;AAAA,MAAA;AAAA,IAClD;AAGK,WAAA;AAAA,EAAA,CACR;AAEyB,4BAAA,QAAQ,OAAO,CAAA,CAAE;AAE3C,UAAQ,SAAS,CAAC,UAAU,MAAM,YAAY;AAM9C,4BAA0B,MAAM;AAC9B,YAAQ,OAAO,IAAI;AAAA,EAAA,CACpB;AAEM,SAAA;AACT;"}
|
|
@@ -10,5 +10,5 @@ declare module '@tanstack/form-core' {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
export type ValidateFormData<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined> = (formData: FormData, info?: Parameters<typeof decode>[1]) => Promise<Partial<FormApi<TFormData, TFormValidator>['state']>>;
|
|
13
|
-
export declare const getValidateFormData: <TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined>(defaultOpts?: FormOptions<TFormData, TFormValidator>
|
|
13
|
+
export declare const getValidateFormData: <TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined>(defaultOpts?: FormOptions<TFormData, TFormValidator>) => ValidateFormData<TFormData, TFormValidator>;
|
|
14
14
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-form",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "Powerful, type-safe forms for React.",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@tanstack/react-store": "^0.3.1",
|
|
44
44
|
"decode-formdata": "^0.4.0",
|
|
45
45
|
"rehackt": "^0.0.3",
|
|
46
|
-
"@tanstack/form-core": "0.16.
|
|
46
|
+
"@tanstack/form-core": "0.16.1"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"react": "^17.0.0 || ^18.0.0"
|
|
@@ -65,3 +65,44 @@ it('should type onChange properly', () => {
|
|
|
65
65
|
)
|
|
66
66
|
}
|
|
67
67
|
})
|
|
68
|
+
|
|
69
|
+
it('should type array subfields', () => {
|
|
70
|
+
type FormDefinition = {
|
|
71
|
+
nested: {
|
|
72
|
+
people: {
|
|
73
|
+
name: string
|
|
74
|
+
age: number
|
|
75
|
+
}[]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function App() {
|
|
80
|
+
const form = useForm({
|
|
81
|
+
defaultValues: {
|
|
82
|
+
nested: {
|
|
83
|
+
people: [],
|
|
84
|
+
},
|
|
85
|
+
} as FormDefinition,
|
|
86
|
+
onSubmit({ value }) {
|
|
87
|
+
alert(JSON.stringify(value))
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<form.Field name="nested.people" mode="array">
|
|
93
|
+
{(field) =>
|
|
94
|
+
field.state.value.map((_, i) => (
|
|
95
|
+
<form.Field key={i} name={`nested.people[${i}].name`}>
|
|
96
|
+
{(subField) => (
|
|
97
|
+
<input
|
|
98
|
+
value={subField.state.value}
|
|
99
|
+
onChange={(e) => subField.handleChange(e.target.value)}
|
|
100
|
+
/>
|
|
101
|
+
)}
|
|
102
|
+
</form.Field>
|
|
103
|
+
))
|
|
104
|
+
}
|
|
105
|
+
</form.Field>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
})
|
package/src/useField.tsx
CHANGED
|
@@ -37,18 +37,13 @@ export type UseField<
|
|
|
37
37
|
TFieldValidator extends
|
|
38
38
|
| Validator<DeepValue<TParentData, TName>, unknown>
|
|
39
39
|
| undefined = undefined,
|
|
40
|
+
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
|
40
41
|
>(
|
|
41
42
|
opts: Omit<
|
|
42
|
-
UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,
|
|
43
|
+
UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>,
|
|
43
44
|
'form'
|
|
44
45
|
>,
|
|
45
|
-
) => FieldApi<
|
|
46
|
-
TParentData,
|
|
47
|
-
TName,
|
|
48
|
-
TFieldValidator,
|
|
49
|
-
TFormValidator,
|
|
50
|
-
DeepValue<TParentData, TName>
|
|
51
|
-
>
|
|
46
|
+
) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>
|
|
52
47
|
|
|
53
48
|
export function useField<
|
|
54
49
|
TParentData,
|
|
@@ -59,9 +54,16 @@ export function useField<
|
|
|
59
54
|
TFormValidator extends
|
|
60
55
|
| Validator<TParentData, unknown>
|
|
61
56
|
| undefined = undefined,
|
|
57
|
+
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
|
62
58
|
>(
|
|
63
|
-
opts: UseFieldOptions<
|
|
64
|
-
|
|
59
|
+
opts: UseFieldOptions<
|
|
60
|
+
TParentData,
|
|
61
|
+
TName,
|
|
62
|
+
TFieldValidator,
|
|
63
|
+
TFormValidator,
|
|
64
|
+
TData
|
|
65
|
+
>,
|
|
66
|
+
): FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData> {
|
|
65
67
|
const [fieldApi] = useState(() => {
|
|
66
68
|
const api = new FieldApi({
|
|
67
69
|
...opts,
|
|
@@ -88,7 +90,7 @@ export function useField<
|
|
|
88
90
|
fieldApi.store,
|
|
89
91
|
opts.mode === 'array'
|
|
90
92
|
? (state) => {
|
|
91
|
-
return [state.meta, Object.keys(state.value).length]
|
|
93
|
+
return [state.meta, Object.keys(state.value as never).length]
|
|
92
94
|
}
|
|
93
95
|
: undefined,
|
|
94
96
|
)
|
|
@@ -116,7 +118,7 @@ type FieldComponentProps<
|
|
|
116
118
|
TData
|
|
117
119
|
>,
|
|
118
120
|
) => any
|
|
119
|
-
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>
|
|
121
|
+
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData>
|
|
120
122
|
|
|
121
123
|
export type FieldComponent<
|
|
122
124
|
TParentData,
|
|
@@ -152,14 +154,27 @@ export function Field<
|
|
|
152
154
|
TFormValidator extends
|
|
153
155
|
| Validator<TParentData, unknown>
|
|
154
156
|
| undefined = undefined,
|
|
157
|
+
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
|
155
158
|
>({
|
|
156
159
|
children,
|
|
157
160
|
...fieldOptions
|
|
158
161
|
}: {
|
|
159
162
|
children: (
|
|
160
|
-
fieldApi: FieldApi<
|
|
163
|
+
fieldApi: FieldApi<
|
|
164
|
+
TParentData,
|
|
165
|
+
TName,
|
|
166
|
+
TFieldValidator,
|
|
167
|
+
TFormValidator,
|
|
168
|
+
TData
|
|
169
|
+
>,
|
|
161
170
|
) => any
|
|
162
|
-
} & UseFieldOptions<
|
|
171
|
+
} & UseFieldOptions<
|
|
172
|
+
TParentData,
|
|
173
|
+
TName,
|
|
174
|
+
TFieldValidator,
|
|
175
|
+
TFormValidator,
|
|
176
|
+
TData
|
|
177
|
+
>) {
|
|
163
178
|
const fieldApi = useField(fieldOptions as any)
|
|
164
179
|
|
|
165
180
|
return <>{functionalUpdate(children, fieldApi as any)}</>
|
package/src/useForm.tsx
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { FormApi, functionalUpdate } from '@tanstack/form-core'
|
|
2
2
|
import { useStore } from '@tanstack/react-store'
|
|
3
|
-
import React, {
|
|
4
|
-
type PropsWithChildren,
|
|
5
|
-
type ReactNode,
|
|
6
|
-
useState,
|
|
7
|
-
} from 'rehackt'
|
|
3
|
+
import React, { type ReactNode, useState } from 'rehackt'
|
|
8
4
|
import { Field, type FieldComponent, type UseField, useField } from './useField'
|
|
9
5
|
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
|
|
10
6
|
import type { NoInfer } from '@tanstack/react-store'
|