@tanstack/vue-form 0.10.3 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/createFormFactory.d.ts +8 -0
- package/dist/cjs/formContext.d.ts +11 -0
- package/dist/cjs/index.cjs +119 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +5 -0
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.js +119 -0
- package/dist/cjs/tests/useField.test.d.ts +1 -0
- package/dist/cjs/tests/useForm.test.d.ts +1 -0
- package/dist/cjs/tests/utils.d.ts +1 -0
- package/dist/cjs/types.d.ts +4 -0
- package/dist/cjs/useField.d.ts +38 -0
- package/dist/cjs/useForm.d.ts +19 -0
- package/dist/mjs/createFormFactory.d.ts +8 -0
- package/dist/mjs/formContext.d.ts +11 -0
- package/dist/mjs/index.d.mts +5 -0
- package/dist/mjs/index.d.ts +5 -0
- package/dist/mjs/index.js +113 -0
- package/dist/mjs/index.mjs +113 -0
- package/dist/mjs/index.mjs.map +1 -0
- package/dist/mjs/tests/useField.test.d.ts +1 -0
- package/dist/mjs/tests/useForm.test.d.ts +1 -0
- package/dist/mjs/tests/utils.d.ts +1 -0
- package/dist/mjs/types.d.ts +4 -0
- package/dist/mjs/useField.d.ts +38 -0
- package/dist/mjs/useForm.d.ts +19 -0
- package/package.json +17 -22
- package/src/createFormFactory.ts +16 -10
- package/src/formContext.ts +10 -4
- package/src/tests/useField.test.tsx +23 -15
- package/src/tests/useForm.test.tsx +57 -39
- package/src/types.ts +13 -4
- package/src/useField.tsx +68 -35
- package/src/useForm.tsx +16 -8
- package/build/legacy/createFormFactory.cjs +0 -42
- package/build/legacy/createFormFactory.cjs.map +0 -1
- package/build/legacy/createFormFactory.d.cts +0 -13
- package/build/legacy/createFormFactory.d.ts +0 -13
- package/build/legacy/createFormFactory.js +0 -17
- package/build/legacy/createFormFactory.js.map +0 -1
- package/build/legacy/formContext.cjs +0 -46
- package/build/legacy/formContext.cjs.map +0 -1
- package/build/legacy/formContext.d.cts +0 -14
- package/build/legacy/formContext.d.ts +0 -14
- package/build/legacy/formContext.js +0 -19
- package/build/legacy/formContext.js.map +0 -1
- package/build/legacy/index.cjs +0 -33
- package/build/legacy/index.cjs.map +0 -1
- package/build/legacy/index.d.cts +0 -8
- package/build/legacy/index.d.ts +0 -8
- package/build/legacy/index.js +0 -7
- package/build/legacy/index.js.map +0 -1
- package/build/legacy/types.cjs +0 -19
- package/build/legacy/types.cjs.map +0 -1
- package/build/legacy/types.d.cts +0 -7
- package/build/legacy/types.d.ts +0 -7
- package/build/legacy/types.js +0 -1
- package/build/legacy/types.js.map +0 -1
- package/build/legacy/useField.cjs +0 -77
- package/build/legacy/useField.cjs.map +0 -1
- package/build/legacy/useField.d.cts +0 -40
- package/build/legacy/useField.d.ts +0 -40
- package/build/legacy/useField.js +0 -51
- package/build/legacy/useField.js.map +0 -1
- package/build/legacy/useForm.cjs +0 -72
- package/build/legacy/useForm.cjs.map +0 -1
- package/build/legacy/useForm.d.cts +0 -23
- package/build/legacy/useForm.d.ts +0 -23
- package/build/legacy/useForm.js +0 -50
- package/build/legacy/useForm.js.map +0 -1
- package/build/modern/createFormFactory.cjs +0 -42
- package/build/modern/createFormFactory.cjs.map +0 -1
- package/build/modern/createFormFactory.d.cts +0 -13
- package/build/modern/createFormFactory.d.ts +0 -13
- package/build/modern/createFormFactory.js +0 -17
- package/build/modern/createFormFactory.js.map +0 -1
- package/build/modern/formContext.cjs +0 -46
- package/build/modern/formContext.cjs.map +0 -1
- package/build/modern/formContext.d.cts +0 -14
- package/build/modern/formContext.d.ts +0 -14
- package/build/modern/formContext.js +0 -19
- package/build/modern/formContext.js.map +0 -1
- package/build/modern/index.cjs +0 -33
- package/build/modern/index.cjs.map +0 -1
- package/build/modern/index.d.cts +0 -8
- package/build/modern/index.d.ts +0 -8
- package/build/modern/index.js +0 -7
- package/build/modern/index.js.map +0 -1
- package/build/modern/types.cjs +0 -19
- package/build/modern/types.cjs.map +0 -1
- package/build/modern/types.d.cts +0 -7
- package/build/modern/types.d.ts +0 -7
- package/build/modern/types.js +0 -1
- package/build/modern/types.js.map +0 -1
- package/build/modern/useField.cjs +0 -77
- package/build/modern/useField.cjs.map +0 -1
- package/build/modern/useField.d.cts +0 -40
- package/build/modern/useField.d.ts +0 -40
- package/build/modern/useField.js +0 -51
- package/build/modern/useField.js.map +0 -1
- package/build/modern/useForm.cjs +0 -72
- package/build/modern/useForm.cjs.map +0 -1
- package/build/modern/useForm.d.cts +0 -23
- package/build/modern/useForm.d.ts +0 -23
- package/build/modern/useForm.js +0 -50
- package/build/modern/useForm.js.map +0 -1
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/formContext.ts","../../src/useField.tsx","../../src/useForm.tsx","../../src/createFormFactory.ts"],"sourcesContent":["import type { FormApi, Validator } from '@tanstack/form-core'\nimport { inject, provide } from 'vue'\n\nexport type FormContext<\n TFormData = any,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n formApi: FormApi<TFormData, TFormValidator>\n parentFieldName?: string\n} | null\n\nexport const formContext = Symbol('FormContext')\n\nexport function provideFormContext<\n TFormData = any,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(val: FormContext<TFormData, TFormValidator>) {\n provide(formContext, val)\n}\n\nexport function useFormContext() {\n const formApi = inject(formContext) as FormContext\n\n if (!formApi) {\n throw new Error(`You are trying to use the form API outside of a form!`)\n }\n\n return formApi\n}\n","import { FieldApi, type Validator } from '@tanstack/form-core'\nimport type { DeepKeys, DeepValue, Narrow } from '@tanstack/form-core'\nimport { useStore } from '@tanstack/vue-store'\nimport { defineComponent, onMounted, onUnmounted, watch } from 'vue'\nimport type { SlotsType, SetupContext, Ref } from 'vue'\nimport { provideFormContext, useFormContext } from './formContext'\nimport type { UseFieldOptions } from './types'\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 = 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?: { name: Narrow<TName> } & UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n DeepValue<TParentData, TName>\n >,\n) => FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n DeepValue<TParentData, TName>\n>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >,\n): {\n api: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n // Omit<typeof opts, 'onMount'> & {\n // form: FormApi<TParentData>\n // }\n >\n state: Readonly<\n Ref<\n FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >['state']\n >\n >\n} {\n // Get the form API either manually or from context\n const { formApi, parentFieldName } = useFormContext()\n\n const fieldApi = (() => {\n const api = new FieldApi({\n ...opts,\n form: formApi,\n name: opts.name,\n } as never)\n\n api.Field = Field as never\n\n return api\n })()\n\n const fieldState = useStore(fieldApi.store, (state) => state)\n\n let cleanup!: () => void\n onMounted(() => {\n cleanup = fieldApi.mount()\n })\n\n onUnmounted(() => {\n cleanup()\n })\n\n watch(\n () => opts,\n () => {\n // Keep options up to date as they are rendered\n fieldApi.update({ ...opts, form: formApi } as never)\n },\n )\n\n return { api: fieldApi, state: fieldState } as never\n}\n\nexport type FieldValue<TParentData, TName> = TParentData extends any[]\n ? unknown extends TName\n ? TParentData[number]\n : DeepValue<TParentData[number], TName>\n : DeepValue<TParentData, TName>\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> = (TParentData extends any[]\n ? {\n name?: TName\n index: number\n }\n : {\n name: TName\n index?: never\n }) &\n Omit<\n UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>,\n 'name' | 'index'\n >\n\nexport type FieldComponent<\n TParentData,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n> = <\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n fieldOptions: FieldComponentProps<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator\n >,\n context: SetupContext<\n {},\n SlotsType<{\n default: {\n field: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >\n state: FieldApi<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator,\n TData\n >['state']\n }\n }>\n >,\n) => any\n\nexport const Field = defineComponent(\n <\n TParentData,\n TName extends DeepKeys<TParentData>,\n TFieldValidator extends\n | Validator<DeepValue<TParentData, TName>, unknown>\n | undefined = undefined,\n TFormValidator extends\n | Validator<TParentData, unknown>\n | undefined = undefined,\n >(\n fieldOptions: UseFieldOptions<\n TParentData,\n TName,\n TFieldValidator,\n TFormValidator\n >,\n context: SetupContext,\n ) => {\n const fieldApi = useField({ ...fieldOptions, ...context.attrs } as any)\n\n provideFormContext({\n formApi: fieldApi.api.form,\n parentFieldName: fieldApi.api.name,\n } as never)\n\n return () =>\n context.slots.default!({\n field: fieldApi.api,\n state: fieldApi.state.value,\n })\n },\n { name: 'Field', inheritAttrs: false },\n)\n","import {\n FormApi,\n type FormState,\n type FormOptions,\n type Validator,\n} from '@tanstack/form-core'\nimport { type NoInfer, useStore } from '@tanstack/vue-store'\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { provideFormContext } from './formContext'\nimport {\n type EmitsOptions,\n type SlotsType,\n type SetupContext,\n type Ref,\n defineComponent,\n onMounted,\n} from 'vue'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, TFormValidator> {\n Provider: (props: Record<string, any> & {}) => any\n provideFormContext: () => void\n Field: FieldComponent<TFormData, TFormValidator>\n useField: UseField<TFormData, TFormValidator>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => Readonly<Ref<TSelected>>\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(\n props: {\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected\n },\n context: SetupContext<\n EmitsOptions,\n SlotsType<{ default: NoInfer<FormState<TFormData>> }>\n >,\n ) => any\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 = (() => {\n const api = new FormApi<TFormData, TFormValidator>(opts)\n\n api.Provider = defineComponent(\n (_, context) => {\n onMounted(api.mount)\n provideFormContext({ formApi: formApi as never })\n return () => context.slots.default!()\n },\n { name: 'Provider' },\n )\n api.provideFormContext = () => {\n onMounted(api.mount)\n provideFormContext({ formApi: formApi as never })\n }\n api.Field = Field as never\n api.useField = useField as never\n api.useStore = (selector) => {\n return useStore(api.store as never, selector as never) as never\n }\n api.Subscribe = defineComponent(\n (props, context) => {\n const allProps = { ...props, ...context.attrs }\n const selector = allProps.selector ?? ((state) => state)\n const data = useStore(api.store as never, selector as never)\n return () => context.slots.default!(data.value)\n },\n {\n name: 'Subscribe',\n inheritAttrs: false,\n },\n )\n\n return api\n })()\n\n // formApi.useStore((state) => state.isSubmitting)\n formApi.update(opts)\n\n return formApi as never\n}\n","import type { FormApi, FormOptions, Validator } from '@tanstack/form-core'\n\nimport { type UseField, type FieldComponent, Field, useField } from './useField'\nimport { useForm } from './useForm'\n\nexport type FormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n> = {\n useForm: (\n opts?: FormOptions<TFormData, TFormValidator>,\n ) => FormApi<TFormData, TFormValidator>\n useField: UseField<TFormData, TFormValidator>\n Field: FieldComponent<TFormData, TFormValidator>\n}\n\nexport function createFormFactory<\n TFormData,\n TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,\n>(\n defaultOpts?: FormOptions<TFormData, TFormValidator>,\n): FormFactory<TFormData, TFormValidator> {\n return {\n useForm: (opts) => {\n const formOptions = Object.assign({}, defaultOpts, opts)\n return useForm<TFormData, TFormValidator>(formOptions)\n },\n useField: useField as any,\n Field: Field as any,\n }\n}\n"],"names":[],"mappings":";;;;AAWa,MAAA,cAAc,OAAO,aAAa;AAExC,SAAS,mBAGd,KAA6C;AAC7C,UAAQ,aAAa,GAAG;AAC1B;AAEO,SAAS,iBAAiB;AACzB,QAAA,UAAU,OAAO,WAAW;AAElC,MAAI,CAAC,SAAS;AACN,UAAA,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEO,SAAA;AACT;ACuBO,SAAS,SAWd,MA6BA;AAEA,QAAM,EAAE,SAAS,gBAAgB,IAAI,eAAe;AAEpD,QAAM,YAAY,MAAM;AAChB,UAAA,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,IAAA,CACH;AAEV,QAAI,QAAQ;AAEL,WAAA;AAAA,EAAA;AAGT,QAAM,aAAa,SAAS,SAAS,OAAO,CAAC,UAAU,KAAK;AAExD,MAAA;AACJ,YAAU,MAAM;AACd,cAAU,SAAS;EAAM,CAC1B;AAED,cAAY,MAAM;AACR;EAAA,CACT;AAED;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAEJ,eAAS,OAAO,EAAE,GAAG,MAAM,MAAM,SAAkB;AAAA,IACrD;AAAA,EAAA;AAGF,SAAO,EAAE,KAAK,UAAU,OAAO,WAAW;AAC5C;AAwEO,MAAM,QAAQ;AAAA,EACnB,CAUE,cAMA,YACG;AACG,UAAA,WAAW,SAAS,EAAE,GAAG,cAAc,GAAG,QAAQ,OAAc;AAEnD,uBAAA;AAAA,MACjB,SAAS,SAAS,IAAI;AAAA,MACtB,iBAAiB,SAAS,IAAI;AAAA,IAAA,CACtB;AAEH,WAAA,MACL,QAAQ,MAAM,QAAS;AAAA,MACrB,OAAO,SAAS;AAAA,MAChB,OAAO,SAAS,MAAM;AAAA,IAAA,CACvB;AAAA,EACL;AAAA,EACA,EAAE,MAAM,SAAS,cAAc,MAAM;AACvC;AChMO,SAAS,QAId,MACoC;AACpC,QAAM,WAAW,MAAM;AACf,UAAA,MAAM,IAAI,QAAmC,IAAI;AAEvD,QAAI,WAAW;AAAA,MACb,CAAC,GAAG,YAAY;AACd,kBAAU,IAAI,KAAK;AACA,2BAAA,EAAE,SAA2B;AACzC,eAAA,MAAM,QAAQ,MAAM;MAC7B;AAAA,MACA,EAAE,MAAM,WAAW;AAAA,IAAA;AAErB,QAAI,qBAAqB,MAAM;AAC7B,gBAAU,IAAI,KAAK;AACA,yBAAA,EAAE,SAA2B;AAAA,IAAA;AAElD,QAAI,QAAQ;AACZ,QAAI,WAAW;AACX,QAAA,WAAW,CAAC,aAAa;AACpB,aAAA,SAAS,IAAI,OAAgB,QAAiB;AAAA,IAAA;AAEvD,QAAI,YAAY;AAAA,MACd,CAAC,OAAO,YAAY;AAClB,cAAM,WAAW,EAAE,GAAG,OAAO,GAAG,QAAQ,MAAM;AAC9C,cAAM,WAAW,SAAS,aAAa,CAAC,UAAU;AAClD,cAAM,OAAO,SAAS,IAAI,OAAgB,QAAiB;AAC3D,eAAO,MAAM,QAAQ,MAAM,QAAS,KAAK,KAAK;AAAA,MAChD;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,cAAc;AAAA,MAChB;AAAA,IAAA;AAGK,WAAA;AAAA,EAAA;AAIT,UAAQ,OAAO,IAAI;AAEZ,SAAA;AACT;ACtEO,SAAS,kBAId,aACwC;AACjC,SAAA;AAAA,IACL,SAAS,CAAC,SAAS;AACjB,YAAM,cAAc,OAAO,OAAO,CAAA,GAAI,aAAa,IAAI;AACvD,aAAO,QAAmC,WAAW;AAAA,IACvD;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;"}
|
@@ -0,0 +1 @@
|
|
1
|
+
/// <reference lib="dom" />
|
@@ -0,0 +1 @@
|
|
1
|
+
/// <reference lib="dom" />
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function sleep(timeout: number): Promise<void>;
|
@@ -0,0 +1,4 @@
|
|
1
|
+
import type { FieldOptions, DeepKeys, DeepValue, Validator } from '@tanstack/form-core';
|
2
|
+
export type UseFieldOptions<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>> = FieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData> & {
|
3
|
+
mode?: 'value' | 'array';
|
4
|
+
};
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import { FieldApi, type Validator } from '@tanstack/form-core';
|
2
|
+
import type { DeepKeys, DeepValue, Narrow } from '@tanstack/form-core';
|
3
|
+
import type { SlotsType, SetupContext, Ref } from 'vue';
|
4
|
+
import type { UseFieldOptions } from './types';
|
5
|
+
declare module '@tanstack/form-core' {
|
6
|
+
interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined, TData = DeepValue<TParentData, TName>> {
|
7
|
+
Field: FieldComponent<TParentData, TFormValidator>;
|
8
|
+
}
|
9
|
+
}
|
10
|
+
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?: {
|
11
|
+
name: Narrow<TName>;
|
12
|
+
} & UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator, DeepValue<TParentData, TName>>) => FieldApi<TParentData, TName, TFieldValidator, TFormValidator, DeepValue<TParentData, TName>>;
|
13
|
+
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>): {
|
14
|
+
api: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
15
|
+
state: Readonly<Ref<FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>['state']>>;
|
16
|
+
};
|
17
|
+
export type FieldValue<TParentData, TName> = TParentData extends any[] ? unknown extends TName ? TParentData[number] : DeepValue<TParentData[number], TName> : DeepValue<TParentData, TName>;
|
18
|
+
type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined> = (TParentData extends any[] ? {
|
19
|
+
name?: TName;
|
20
|
+
index: number;
|
21
|
+
} : {
|
22
|
+
name: TName;
|
23
|
+
index?: never;
|
24
|
+
}) & Omit<UseFieldOptions<TParentData, TName, TFieldValidator, TFormValidator>, 'name' | 'index'>;
|
25
|
+
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>>(fieldOptions: FieldComponentProps<TParentData, TName, TFieldValidator, TFormValidator>, context: SetupContext<{}, SlotsType<{
|
26
|
+
default: {
|
27
|
+
field: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>;
|
28
|
+
state: FieldApi<TParentData, TName, TFieldValidator, TFormValidator, TData>['state'];
|
29
|
+
};
|
30
|
+
}>>) => any;
|
31
|
+
export declare const Field: <TParentData, TName extends DeepKeys<TParentData>, TFieldValidator extends Validator<DeepValue<TParentData, TName>, unknown> | undefined = undefined, TFormValidator extends Validator<TParentData, unknown> | undefined = undefined>(props: import("@tanstack/form-core").FieldOptions<TParentData, TName, TFieldValidator, TFormValidator, DeepValue<TParentData, TName>> & {
|
32
|
+
mode?: "value" | "array" | undefined;
|
33
|
+
} & ({
|
34
|
+
[x: `on${Capitalize<string>}`]: ((...args: never) => any) | undefined;
|
35
|
+
} | {
|
36
|
+
[x: `on${Capitalize<string>}`]: ((...args: any[]) => any) | undefined;
|
37
|
+
})) => any;
|
38
|
+
export {};
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { FormApi, type FormState, type FormOptions, type Validator } from '@tanstack/form-core';
|
2
|
+
import { type NoInfer } from '@tanstack/vue-store';
|
3
|
+
import { type UseField, type FieldComponent } from './useField';
|
4
|
+
import { type EmitsOptions, type SlotsType, type SetupContext, type Ref } from 'vue';
|
5
|
+
declare module '@tanstack/form-core' {
|
6
|
+
interface FormApi<TFormData, TFormValidator> {
|
7
|
+
Provider: (props: Record<string, any> & {}) => any;
|
8
|
+
provideFormContext: () => void;
|
9
|
+
Field: FieldComponent<TFormData, TFormValidator>;
|
10
|
+
useField: UseField<TFormData, TFormValidator>;
|
11
|
+
useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => Readonly<Ref<TSelected>>;
|
12
|
+
Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
|
13
|
+
selector?: (state: NoInfer<FormState<TFormData>>) => TSelected;
|
14
|
+
}, context: SetupContext<EmitsOptions, SlotsType<{
|
15
|
+
default: NoInfer<FormState<TFormData>>;
|
16
|
+
}>>) => any;
|
17
|
+
}
|
18
|
+
}
|
19
|
+
export declare function useForm<TFormData, TFormValidator extends Validator<TFormData, unknown> | undefined = undefined>(opts?: FormOptions<TFormData, TFormValidator>): FormApi<TFormData, TFormValidator>;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@tanstack/vue-form",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.12.0",
|
4
4
|
"description": "Powerful, type-safe forms for Vue.",
|
5
5
|
"author": "tannerlinsley",
|
6
6
|
"license": "MIT",
|
@@ -11,40 +11,31 @@
|
|
11
11
|
"url": "https://github.com/sponsors/tannerlinsley"
|
12
12
|
},
|
13
13
|
"type": "module",
|
14
|
-
"types": "
|
15
|
-
"main": "
|
16
|
-
"module": "
|
14
|
+
"types": "dist/mjs/index.d.mts",
|
15
|
+
"main": "dist/cjs/index.cjs",
|
16
|
+
"module": "dist/mjs/index.mjs",
|
17
17
|
"exports": {
|
18
18
|
".": {
|
19
19
|
"import": {
|
20
|
-
"types": "./
|
21
|
-
"default": "./
|
20
|
+
"types": "./dist/mjs/index.d.mts",
|
21
|
+
"default": "./dist/mjs/index.mjs"
|
22
22
|
},
|
23
23
|
"require": {
|
24
|
-
"types": "./
|
25
|
-
"default": "./
|
24
|
+
"types": "./dist/cjs/index.d.cts",
|
25
|
+
"default": "./dist/cjs/index.cjs"
|
26
26
|
}
|
27
27
|
},
|
28
28
|
"./package.json": "./package.json"
|
29
29
|
},
|
30
30
|
"sideEffects": false,
|
31
|
-
"nx": {
|
32
|
-
"targets": {
|
33
|
-
"test:build": {
|
34
|
-
"dependsOn": [
|
35
|
-
"build"
|
36
|
-
]
|
37
|
-
}
|
38
|
-
}
|
39
|
-
},
|
40
31
|
"files": [
|
41
|
-
"
|
32
|
+
"dist",
|
42
33
|
"src"
|
43
34
|
],
|
44
35
|
"dependencies": {
|
45
36
|
"@tanstack/store": "0.1.3",
|
46
37
|
"@tanstack/vue-store": "0.1.3",
|
47
|
-
"@tanstack/form-core": "0.
|
38
|
+
"@tanstack/form-core": "0.12.0"
|
48
39
|
},
|
49
40
|
"devDependencies": {
|
50
41
|
"vue": "^3.3.4"
|
@@ -53,13 +44,17 @@
|
|
53
44
|
"vue": "^3.3.0"
|
54
45
|
},
|
55
46
|
"scripts": {
|
56
|
-
"clean": "rimraf ./
|
47
|
+
"clean": "rimraf ./dist && rimraf ./coverage",
|
57
48
|
"test:eslint": "eslint --ext .ts,.tsx ./src",
|
58
|
-
"test:types": "tsc",
|
49
|
+
"test:types:versions49": "../../node_modules/typescript49/bin/tsc --noEmit",
|
50
|
+
"test:types:versions50": "../../node_modules/typescript50/bin/tsc --noEmit",
|
51
|
+
"test:types:versions51": "../../node_modules/typescript51/bin/tsc --noEmit",
|
52
|
+
"test:types:versions52": "tsc --noEmit",
|
53
|
+
"test:types": "pnpm run \"/^test:types:versions.*/\"",
|
59
54
|
"fixme:test:lib": "pnpm run test:2 && pnpm run test:2.7 && pnpm run test:3",
|
60
55
|
"test:lib": "vitest",
|
61
56
|
"test:lib:dev": "pnpm run test:lib --watch",
|
62
57
|
"test:build": "publint --strict",
|
63
|
-
"build": "
|
58
|
+
"build": "vite build"
|
64
59
|
}
|
65
60
|
}
|
package/src/createFormFactory.ts
CHANGED
@@ -1,23 +1,29 @@
|
|
1
|
-
import type { FormApi, FormOptions } from '@tanstack/form-core'
|
1
|
+
import type { FormApi, FormOptions, Validator } from '@tanstack/form-core'
|
2
2
|
|
3
3
|
import { type UseField, type FieldComponent, Field, useField } from './useField'
|
4
4
|
import { useForm } from './useForm'
|
5
5
|
|
6
|
-
export type FormFactory<
|
6
|
+
export type FormFactory<
|
7
|
+
TFormData,
|
8
|
+
TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
|
9
|
+
> = {
|
7
10
|
useForm: (
|
8
|
-
opts?: FormOptions<TFormData,
|
9
|
-
) => FormApi<TFormData,
|
10
|
-
useField: UseField<TFormData,
|
11
|
-
Field: FieldComponent<TFormData,
|
11
|
+
opts?: FormOptions<TFormData, TFormValidator>,
|
12
|
+
) => FormApi<TFormData, TFormValidator>
|
13
|
+
useField: UseField<TFormData, TFormValidator>
|
14
|
+
Field: FieldComponent<TFormData, TFormValidator>
|
12
15
|
}
|
13
16
|
|
14
|
-
export function createFormFactory<
|
15
|
-
|
16
|
-
|
17
|
+
export function createFormFactory<
|
18
|
+
TFormData,
|
19
|
+
TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
|
20
|
+
>(
|
21
|
+
defaultOpts?: FormOptions<TFormData, TFormValidator>,
|
22
|
+
): FormFactory<TFormData, TFormValidator> {
|
17
23
|
return {
|
18
24
|
useForm: (opts) => {
|
19
25
|
const formOptions = Object.assign({}, defaultOpts, opts)
|
20
|
-
return useForm<TFormData,
|
26
|
+
return useForm<TFormData, TFormValidator>(formOptions)
|
21
27
|
},
|
22
28
|
useField: useField as any,
|
23
29
|
Field: Field as any,
|
package/src/formContext.ts
CHANGED
@@ -1,14 +1,20 @@
|
|
1
|
-
import type { FormApi } from '@tanstack/form-core'
|
1
|
+
import type { FormApi, Validator } from '@tanstack/form-core'
|
2
2
|
import { inject, provide } from 'vue'
|
3
3
|
|
4
|
-
export type FormContext
|
5
|
-
|
4
|
+
export type FormContext<
|
5
|
+
TFormData = any,
|
6
|
+
TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
|
7
|
+
> = {
|
8
|
+
formApi: FormApi<TFormData, TFormValidator>
|
6
9
|
parentFieldName?: string
|
7
10
|
} | null
|
8
11
|
|
9
12
|
export const formContext = Symbol('FormContext')
|
10
13
|
|
11
|
-
export function provideFormContext
|
14
|
+
export function provideFormContext<
|
15
|
+
TFormData = any,
|
16
|
+
TFormValidator extends Validator<TFormData, unknown> | undefined = undefined,
|
17
|
+
>(val: FormContext<TFormData, TFormValidator>) {
|
12
18
|
provide(formContext, val)
|
13
19
|
}
|
14
20
|
|
@@ -15,7 +15,7 @@ describe('useField', () => {
|
|
15
15
|
lastName: string
|
16
16
|
}
|
17
17
|
|
18
|
-
const formFactory = createFormFactory<Person
|
18
|
+
const formFactory = createFormFactory<Person>()
|
19
19
|
|
20
20
|
const Comp = defineComponent(() => {
|
21
21
|
const form = formFactory.useForm()
|
@@ -54,7 +54,7 @@ describe('useField', () => {
|
|
54
54
|
}
|
55
55
|
const error = 'Please enter a different value'
|
56
56
|
|
57
|
-
const formFactory = createFormFactory<Person
|
57
|
+
const formFactory = createFormFactory<Person>()
|
58
58
|
|
59
59
|
const Comp = defineComponent(() => {
|
60
60
|
const form = formFactory.useForm()
|
@@ -64,7 +64,9 @@ describe('useField', () => {
|
|
64
64
|
return () => (
|
65
65
|
<form.Field
|
66
66
|
name="firstName"
|
67
|
-
|
67
|
+
validators={{
|
68
|
+
onChange: ({ value }) => (value === 'other' ? error : undefined),
|
69
|
+
}}
|
68
70
|
>
|
69
71
|
{({
|
70
72
|
field,
|
@@ -101,7 +103,7 @@ describe('useField', () => {
|
|
101
103
|
}
|
102
104
|
const error = 'Please enter a different value'
|
103
105
|
|
104
|
-
const formFactory = createFormFactory<Person
|
106
|
+
const formFactory = createFormFactory<Person>()
|
105
107
|
|
106
108
|
const Comp = defineComponent(() => {
|
107
109
|
const form = formFactory.useForm()
|
@@ -111,7 +113,9 @@ describe('useField', () => {
|
|
111
113
|
return () => (
|
112
114
|
<form.Field
|
113
115
|
name="firstName"
|
114
|
-
|
116
|
+
validators={{
|
117
|
+
onChange: ({ value }) => (value === 'other' ? error : undefined),
|
118
|
+
}}
|
115
119
|
>
|
116
120
|
{({
|
117
121
|
field,
|
@@ -149,7 +153,7 @@ describe('useField', () => {
|
|
149
153
|
}
|
150
154
|
const error = 'Please enter a different value'
|
151
155
|
|
152
|
-
const formFactory = createFormFactory<Person
|
156
|
+
const formFactory = createFormFactory<Person>()
|
153
157
|
|
154
158
|
const Comp = defineComponent(() => {
|
155
159
|
const form = formFactory.useForm()
|
@@ -160,9 +164,11 @@ describe('useField', () => {
|
|
160
164
|
<form.Field
|
161
165
|
name="firstName"
|
162
166
|
defaultMeta={{ isTouched: true }}
|
163
|
-
|
164
|
-
|
165
|
-
|
167
|
+
validators={{
|
168
|
+
onChangeAsync: async () => {
|
169
|
+
await sleep(10)
|
170
|
+
return error
|
171
|
+
},
|
166
172
|
}}
|
167
173
|
>
|
168
174
|
{({
|
@@ -203,7 +209,7 @@ describe('useField', () => {
|
|
203
209
|
|
204
210
|
const mockFn = vi.fn()
|
205
211
|
const error = 'Please enter a different value'
|
206
|
-
const formFactory = createFormFactory<Person
|
212
|
+
const formFactory = createFormFactory<Person>()
|
207
213
|
|
208
214
|
const Comp = defineComponent(() => {
|
209
215
|
const form = formFactory.useForm()
|
@@ -214,11 +220,13 @@ describe('useField', () => {
|
|
214
220
|
<form.Field
|
215
221
|
name="firstName"
|
216
222
|
defaultMeta={{ isTouched: true }}
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
223
|
+
validators={{
|
224
|
+
onChangeAsyncDebounceMs: 100,
|
225
|
+
onChangeAsync: async () => {
|
226
|
+
mockFn()
|
227
|
+
await sleep(10)
|
228
|
+
return error
|
229
|
+
},
|
222
230
|
}}
|
223
231
|
>
|
224
232
|
{({
|
@@ -22,7 +22,7 @@ type Person = {
|
|
22
22
|
|
23
23
|
describe('useForm', () => {
|
24
24
|
it('preserved field state', async () => {
|
25
|
-
const formFactory = createFormFactory<Person
|
25
|
+
const formFactory = createFormFactory<Person>()
|
26
26
|
|
27
27
|
const Comp = defineComponent(() => {
|
28
28
|
const form = formFactory.useForm()
|
@@ -57,7 +57,7 @@ describe('useForm', () => {
|
|
57
57
|
})
|
58
58
|
|
59
59
|
it('should allow default values to be set', async () => {
|
60
|
-
const formFactory = createFormFactory<Person
|
60
|
+
const formFactory = createFormFactory<Person>()
|
61
61
|
|
62
62
|
const Comp = defineComponent(() => {
|
63
63
|
const form = formFactory.useForm({
|
@@ -92,8 +92,8 @@ describe('useForm', () => {
|
|
92
92
|
defaultValues: {
|
93
93
|
firstName: 'FirstName',
|
94
94
|
},
|
95
|
-
onSubmit: (
|
96
|
-
submittedData.value =
|
95
|
+
onSubmit: ({ value }) => {
|
96
|
+
submittedData.value = value
|
97
97
|
},
|
98
98
|
})
|
99
99
|
form.provideFormContext()
|
@@ -145,9 +145,11 @@ describe('useForm', () => {
|
|
145
145
|
defaultValues: {
|
146
146
|
firstName: 'FirstName',
|
147
147
|
},
|
148
|
-
|
149
|
-
|
150
|
-
|
148
|
+
validators: {
|
149
|
+
onMount: () => {
|
150
|
+
formMounted.value = true
|
151
|
+
return undefined
|
152
|
+
},
|
151
153
|
},
|
152
154
|
})
|
153
155
|
|
@@ -171,12 +173,14 @@ describe('useForm', () => {
|
|
171
173
|
it('should validate async on change for the form', async () => {
|
172
174
|
const error = 'Please enter a different value'
|
173
175
|
|
174
|
-
const formFactory = createFormFactory<Person
|
176
|
+
const formFactory = createFormFactory<Person>()
|
175
177
|
|
176
178
|
const Comp = defineComponent(() => {
|
177
179
|
const form = formFactory.useForm({
|
178
|
-
|
179
|
-
|
180
|
+
validators: {
|
181
|
+
onChange() {
|
182
|
+
return error
|
183
|
+
},
|
180
184
|
},
|
181
185
|
})
|
182
186
|
|
@@ -218,11 +222,14 @@ describe('useForm', () => {
|
|
218
222
|
it('should not validate on change if isTouched is false', async () => {
|
219
223
|
const error = 'Please enter a different value'
|
220
224
|
|
221
|
-
const formFactory = createFormFactory<Person
|
225
|
+
const formFactory = createFormFactory<Person>()
|
222
226
|
|
223
227
|
const Comp = defineComponent(() => {
|
224
228
|
const form = formFactory.useForm({
|
225
|
-
|
229
|
+
validators: {
|
230
|
+
onChange: ({ value }) =>
|
231
|
+
value.firstName === 'other' ? error : undefined,
|
232
|
+
},
|
226
233
|
})
|
227
234
|
|
228
235
|
const errors = form.useStore((s) => s.errors)
|
@@ -264,11 +271,14 @@ describe('useForm', () => {
|
|
264
271
|
it('should validate on change if isTouched is true', async () => {
|
265
272
|
const error = 'Please enter a different value'
|
266
273
|
|
267
|
-
const formFactory = createFormFactory<Person
|
274
|
+
const formFactory = createFormFactory<Person>()
|
268
275
|
|
269
276
|
const Comp = defineComponent(() => {
|
270
277
|
const form = formFactory.useForm({
|
271
|
-
|
278
|
+
validators: {
|
279
|
+
onChange: ({ value }) =>
|
280
|
+
value.firstName === 'other' ? error : undefined,
|
281
|
+
},
|
272
282
|
})
|
273
283
|
|
274
284
|
const errors = form.useStore((s) => s.errorMap)
|
@@ -317,13 +327,15 @@ describe('useForm', () => {
|
|
317
327
|
defaultValues: {
|
318
328
|
firstName: '',
|
319
329
|
},
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
330
|
+
validators: {
|
331
|
+
onChange: ({ value }) => {
|
332
|
+
if (value.firstName === 'other') return onChangeError
|
333
|
+
return undefined
|
334
|
+
},
|
335
|
+
onBlur: ({ value }) => {
|
336
|
+
if (value.firstName === 'other') return onBlurError
|
337
|
+
return undefined
|
338
|
+
},
|
327
339
|
},
|
328
340
|
})
|
329
341
|
|
@@ -370,13 +382,15 @@ describe('useForm', () => {
|
|
370
382
|
it('should validate async on change', async () => {
|
371
383
|
const error = 'Please enter a different value'
|
372
384
|
|
373
|
-
const formFactory = createFormFactory<Person
|
385
|
+
const formFactory = createFormFactory<Person>()
|
374
386
|
|
375
387
|
const Comp = defineComponent(() => {
|
376
388
|
const form = formFactory.useForm({
|
377
|
-
|
378
|
-
|
379
|
-
|
389
|
+
validators: {
|
390
|
+
onChangeAsync: async () => {
|
391
|
+
await sleep(10)
|
392
|
+
return error
|
393
|
+
},
|
380
394
|
},
|
381
395
|
})
|
382
396
|
|
@@ -422,17 +436,19 @@ describe('useForm', () => {
|
|
422
436
|
const onChangeError = 'Please enter a different value (onChangeError)'
|
423
437
|
const onBlurError = 'Please enter a different value (onBlurError)'
|
424
438
|
|
425
|
-
const formFactory = createFormFactory<Person
|
439
|
+
const formFactory = createFormFactory<Person>()
|
426
440
|
|
427
441
|
const Comp = defineComponent(() => {
|
428
442
|
const form = formFactory.useForm({
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
443
|
+
validators: {
|
444
|
+
onChangeAsync: async () => {
|
445
|
+
await sleep(10)
|
446
|
+
return onChangeError
|
447
|
+
},
|
448
|
+
onBlurAsync: async () => {
|
449
|
+
await sleep(10)
|
450
|
+
return onBlurError
|
451
|
+
},
|
436
452
|
},
|
437
453
|
})
|
438
454
|
const errors = form.useStore((s) => s.errorMap)
|
@@ -482,15 +498,17 @@ describe('useForm', () => {
|
|
482
498
|
it('should validate async on change with debounce', async () => {
|
483
499
|
const mockFn = vi.fn()
|
484
500
|
const error = 'Please enter a different value'
|
485
|
-
const formFactory = createFormFactory<Person
|
501
|
+
const formFactory = createFormFactory<Person>()
|
486
502
|
|
487
503
|
const Comp = defineComponent(() => {
|
488
504
|
const form = formFactory.useForm({
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
505
|
+
validators: {
|
506
|
+
onChangeAsyncDebounceMs: 100,
|
507
|
+
onChangeAsync: async () => {
|
508
|
+
mockFn()
|
509
|
+
await sleep(10)
|
510
|
+
return error
|
511
|
+
},
|
494
512
|
},
|
495
513
|
})
|
496
514
|
const errors = form.useStore((s) => s.errors)
|
package/src/types.ts
CHANGED
@@ -1,11 +1,20 @@
|
|
1
|
-
import type {
|
1
|
+
import type {
|
2
|
+
FieldOptions,
|
3
|
+
DeepKeys,
|
4
|
+
DeepValue,
|
5
|
+
Validator,
|
6
|
+
} from '@tanstack/form-core'
|
2
7
|
|
3
8
|
export type UseFieldOptions<
|
4
9
|
TParentData,
|
5
10
|
TName extends DeepKeys<TParentData>,
|
6
|
-
|
7
|
-
|
11
|
+
TFieldValidator extends
|
12
|
+
| Validator<DeepValue<TParentData, TName>, unknown>
|
13
|
+
| undefined = undefined,
|
14
|
+
TFormValidator extends
|
15
|
+
| Validator<TParentData, unknown>
|
16
|
+
| undefined = undefined,
|
8
17
|
TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
|
9
|
-
> = FieldOptions<TParentData, TName,
|
18
|
+
> = FieldOptions<TParentData, TName, TFieldValidator, TFormValidator, TData> & {
|
10
19
|
mode?: 'value' | 'array'
|
11
20
|
}
|