@tanstack/vue-form 0.3.7 → 0.4.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.
Files changed (46) hide show
  1. package/build/legacy/createFormFactory.cjs.map +1 -1
  2. package/build/legacy/createFormFactory.d.cts +5 -5
  3. package/build/legacy/createFormFactory.d.ts +5 -5
  4. package/build/legacy/createFormFactory.js.map +1 -1
  5. package/build/legacy/formContext.cjs.map +1 -1
  6. package/build/legacy/formContext.d.cts +2 -2
  7. package/build/legacy/formContext.d.ts +2 -2
  8. package/build/legacy/formContext.js.map +1 -1
  9. package/build/legacy/types.cjs.map +1 -1
  10. package/build/legacy/types.d.cts +1 -1
  11. package/build/legacy/types.d.ts +1 -1
  12. package/build/legacy/useField.cjs.map +1 -1
  13. package/build/legacy/useField.d.cts +13 -13
  14. package/build/legacy/useField.d.ts +13 -13
  15. package/build/legacy/useField.js.map +1 -1
  16. package/build/legacy/useForm.cjs.map +1 -1
  17. package/build/legacy/useForm.d.cts +4 -4
  18. package/build/legacy/useForm.d.ts +4 -4
  19. package/build/legacy/useForm.js.map +1 -1
  20. package/build/modern/createFormFactory.cjs.map +1 -1
  21. package/build/modern/createFormFactory.d.cts +5 -5
  22. package/build/modern/createFormFactory.d.ts +5 -5
  23. package/build/modern/createFormFactory.js.map +1 -1
  24. package/build/modern/formContext.cjs.map +1 -1
  25. package/build/modern/formContext.d.cts +2 -2
  26. package/build/modern/formContext.d.ts +2 -2
  27. package/build/modern/formContext.js.map +1 -1
  28. package/build/modern/types.cjs.map +1 -1
  29. package/build/modern/types.d.cts +1 -1
  30. package/build/modern/types.d.ts +1 -1
  31. package/build/modern/useField.cjs.map +1 -1
  32. package/build/modern/useField.d.cts +13 -13
  33. package/build/modern/useField.d.ts +13 -13
  34. package/build/modern/useField.js.map +1 -1
  35. package/build/modern/useForm.cjs.map +1 -1
  36. package/build/modern/useForm.d.cts +4 -4
  37. package/build/modern/useForm.d.ts +4 -4
  38. package/build/modern/useForm.js.map +1 -1
  39. package/package.json +2 -2
  40. package/src/createFormFactory.ts +10 -8
  41. package/src/formContext.ts +1 -1
  42. package/src/tests/useField.test.tsx +30 -10
  43. package/src/tests/useForm.test.tsx +13 -38
  44. package/src/types.ts +4 -2
  45. package/src/useField.tsx +67 -14
  46. package/src/useForm.tsx +9 -7
@@ -4,32 +4,32 @@ import { SetupContext, SlotsType, Ref } from 'vue-demi';
4
4
  import { UseFieldOptions } from './types.js';
5
5
 
6
6
  declare module '@tanstack/form-core' {
7
- interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>> {
8
- Field: FieldComponent<TData>;
7
+ interface FieldApi<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData = DeepValue<TParentData, TName>> {
8
+ Field: FieldComponent<TData, FormValidator>;
9
9
  }
10
10
  }
11
- type UseField<TParentData> = <TName extends DeepKeys<TParentData>>(opts?: {
11
+ type UseField<TParentData, FormValidator> = <TName extends DeepKeys<TParentData>, ValidatorType>(opts?: {
12
12
  name: Narrow<TName>;
13
- } & UseFieldOptions<TParentData, TName, DeepValue<TParentData, TName>>) => FieldApi<TParentData, TName, DeepValue<TParentData, TName>>;
14
- declare function useField<TParentData, TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>>(opts: UseFieldOptions<TParentData, TName>): {
15
- api: FieldApi<TParentData, TName>;
16
- state: Readonly<Ref<FieldApi<TParentData, TName, TData>['state']>>;
13
+ } & UseFieldOptions<TParentData, TName, ValidatorType, FormValidator, DeepValue<TParentData, TName>>) => FieldApi<TParentData, TName, ValidatorType, FormValidator, DeepValue<TParentData, TName>>;
14
+ declare function useField<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(opts: UseFieldOptions<TParentData, TName, ValidatorType, FormValidator, TData>): {
15
+ api: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>;
16
+ state: Readonly<Ref<FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>['state']>>;
17
17
  };
18
18
  type FieldValue<TParentData, TName> = TParentData extends any[] ? unknown extends TName ? TParentData[number] : DeepValue<TParentData[number], TName> : DeepValue<TParentData, TName>;
19
- type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>> = (TParentData extends any[] ? {
19
+ type FieldComponentProps<TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator> = (TParentData extends any[] ? {
20
20
  name?: TName;
21
21
  index: number;
22
22
  } : {
23
23
  name: TName;
24
24
  index?: never;
25
- }) & Omit<UseFieldOptions<TParentData, TName>, 'name' | 'index'>;
26
- type FieldComponent<TParentData> = <TName extends DeepKeys<TParentData>, TData = DeepValue<TParentData, TName>>(fieldOptions: FieldComponentProps<TParentData, TName>, context: SetupContext<{}, SlotsType<{
25
+ }) & Omit<UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>, 'name' | 'index'>;
26
+ type FieldComponent<TParentData, FormValidator> = <TName extends DeepKeys<TParentData>, ValidatorType, TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>>(fieldOptions: FieldComponentProps<TParentData, TName, ValidatorType, FormValidator>, context: SetupContext<{}, SlotsType<{
27
27
  default: {
28
- field: FieldApi<TParentData, TName, TData>;
29
- state: FieldApi<TParentData, TName, TData>['state'];
28
+ field: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>;
29
+ state: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>['state'];
30
30
  };
31
31
  }>>) => any;
32
- declare const Field: <TParentData, TName extends DeepKeys<TParentData>>(props: _tanstack_form_core.FieldOptions<TParentData, TName, DeepValue<TParentData, TName>> & {
32
+ declare const Field: <TParentData, TName extends DeepKeys<TParentData>, ValidatorType, FormValidator>(props: _tanstack_form_core.FieldOptions<TParentData, TName, ValidatorType, FormValidator, DeepValue<TParentData, TName>> & {
33
33
  mode?: "value" | "array" | undefined;
34
34
  } & ({
35
35
  [x: `on${Capitalize<string>}`]: ((...args: never) => any) | undefined;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useField.tsx"],"sourcesContent":["import { FieldApi } 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-demi'\nimport type { SlotsType, SetupContext, Ref } from 'vue-demi'\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 TData = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TData>\n }\n}\n\nexport type UseField<TParentData> = <TName extends DeepKeys<TParentData>>(\n opts?: { name: Narrow<TName> } & UseFieldOptions<\n TParentData,\n TName,\n DeepValue<TParentData, TName>\n >,\n) => FieldApi<TParentData, TName, DeepValue<TParentData, TName>>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<TParentData, TName>,\n): {\n api: FieldApi<\n TParentData,\n TName\n // Omit<typeof opts, 'onMount'> & {\n // form: FormApi<TParentData>\n // }\n >\n state: Readonly<\n Ref<\n FieldApi<\n TParentData,\n TName,\n TData\n // Omit<typeof opts, 'onMount'> & {\n // form: FormApi<TParentData>\n // }\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> = (TParentData extends any[]\n ? {\n name?: TName\n index: number\n }\n : {\n name: TName\n index?: never\n }) &\n Omit<UseFieldOptions<TParentData, TName>, 'name' | 'index'>\n\nexport type FieldComponent<TParentData> = <\n TName extends DeepKeys<TParentData>,\n TData = DeepValue<TParentData, TName>,\n>(\n fieldOptions: FieldComponentProps<TParentData, TName>,\n context: SetupContext<\n {},\n SlotsType<{\n default: {\n field: FieldApi<TParentData, TName, TData>\n state: FieldApi<TParentData, TName, TData>['state']\n }\n }>\n >,\n) => any\n\nexport const Field = defineComponent(\n <TParentData, TName extends DeepKeys<TParentData>>(\n fieldOptions: UseFieldOptions<TParentData, TName>,\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"],"mappings":";AAAA,SAAS,gBAAgB;AAEzB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB,WAAW,aAAa,aAAa;AAE/D,SAAS,oBAAoB,sBAAsB;AAsB5C,SAAS,SAKd,MAqBA;AAEA,QAAM,EAAE,SAAS,gBAAgB,IAAI,eAAe;AAEpD,QAAM,YAAY,MAAM;AACtB,UAAM,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,IACb,CAAU;AAEV,QAAI,QAAQ;AAEZ,WAAO;AAAA,EACT,GAAG;AAEH,QAAM,aAAa,SAAS,SAAS,OAAO,CAAC,UAAU,KAAK;AAE5D,MAAI;AACJ,YAAU,MAAM;AACd,cAAU,SAAS,MAAM;AAAA,EAC3B,CAAC;AAED,cAAY,MAAM;AAChB,YAAQ;AAAA,EACV,CAAC;AAED;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAEJ,eAAS,OAAO,EAAE,GAAG,MAAM,MAAM,QAAQ,CAAU;AAAA,IACrD;AAAA,EACF;AAEA,SAAO,EAAE,KAAK,UAAU,OAAO,WAAW;AAC5C;AAsCO,IAAM,QAAQ;AAAA,EACnB,CACE,cACA,YACG;AACH,UAAM,WAAW,SAAS,EAAE,GAAG,cAAc,GAAG,QAAQ,MAAM,CAAQ;AAEtE,uBAAmB;AAAA,MACjB,SAAS,SAAS,IAAI;AAAA,MACtB,iBAAiB,SAAS,IAAI;AAAA,IAChC,CAAU;AAEV,WAAO,MACL,QAAQ,MAAM,QAAS;AAAA,MACrB,OAAO,SAAS;AAAA,MAChB,OAAO,SAAS,MAAM;AAAA,IACxB,CAAC;AAAA,EACL;AAAA,EACA,EAAE,MAAM,SAAS,cAAc,MAAM;AACvC;","names":[]}
1
+ {"version":3,"sources":["../../src/useField.tsx"],"sourcesContent":["import { FieldApi } 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-demi'\nimport type { SlotsType, SetupContext, Ref } from 'vue-demi'\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 ValidatorType,\n FormValidator,\n TData = DeepValue<TParentData, TName>,\n > {\n Field: FieldComponent<TData, FormValidator>\n }\n}\n\nexport type UseField<TParentData, FormValidator> = <\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n>(\n opts?: { name: Narrow<TName> } & UseFieldOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n DeepValue<TParentData, TName>\n >,\n) => FieldApi<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n DeepValue<TParentData, TName>\n>\n\nexport function useField<\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n opts: UseFieldOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >,\n): {\n api: FieldApi<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\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 ValidatorType,\n FormValidator,\n TData\n // Omit<typeof opts, 'onMount'> & {\n // form: FormApi<TParentData>\n // }\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 ValidatorType,\n FormValidator,\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, ValidatorType, FormValidator>,\n 'name' | 'index'\n >\n\nexport type FieldComponent<TParentData, FormValidator> = <\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,\n>(\n fieldOptions: FieldComponentProps<\n TParentData,\n TName,\n ValidatorType,\n FormValidator\n >,\n context: SetupContext<\n {},\n SlotsType<{\n default: {\n field: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>\n state: FieldApi<\n TParentData,\n TName,\n ValidatorType,\n FormValidator,\n TData\n >['state']\n }\n }>\n >,\n) => any\n\nexport const Field = defineComponent(\n <\n TParentData,\n TName extends DeepKeys<TParentData>,\n ValidatorType,\n FormValidator,\n >(\n fieldOptions: UseFieldOptions<\n TParentData,\n TName,\n ValidatorType,\n FormValidator\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"],"mappings":";AAAA,SAAS,gBAAgB;AAEzB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB,WAAW,aAAa,aAAa;AAE/D,SAAS,oBAAoB,sBAAsB;AAmC5C,SAAS,SAOd,MAgCA;AAEA,QAAM,EAAE,SAAS,gBAAgB,IAAI,eAAe;AAEpD,QAAM,YAAY,MAAM;AACtB,UAAM,MAAM,IAAI,SAAS;AAAA,MACvB,GAAG;AAAA,MACH,MAAM;AAAA,MACN,MAAM,KAAK;AAAA,IACb,CAAU;AAEV,QAAI,QAAQ;AAEZ,WAAO;AAAA,EACT,GAAG;AAEH,QAAM,aAAa,SAAS,SAAS,OAAO,CAAC,UAAU,KAAK;AAE5D,MAAI;AACJ,YAAU,MAAM;AACd,cAAU,SAAS,MAAM;AAAA,EAC3B,CAAC;AAED,cAAY,MAAM;AAChB,YAAQ;AAAA,EACV,CAAC;AAED;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAEJ,eAAS,OAAO,EAAE,GAAG,MAAM,MAAM,QAAQ,CAAU;AAAA,IACrD;AAAA,EACF;AAEA,SAAO,EAAE,KAAK,UAAU,OAAO,WAAW;AAC5C;AAuDO,IAAM,QAAQ;AAAA,EACnB,CAME,cAMA,YACG;AACH,UAAM,WAAW,SAAS,EAAE,GAAG,cAAc,GAAG,QAAQ,MAAM,CAAQ;AAEtE,uBAAmB;AAAA,MACjB,SAAS,SAAS,IAAI;AAAA,MACtB,iBAAiB,SAAS,IAAI;AAAA,IAChC,CAAU;AAEV,WAAO,MACL,QAAQ,MAAM,QAAS;AAAA,MACrB,OAAO,SAAS;AAAA,MAChB,OAAO,SAAS,MAAM;AAAA,IACxB,CAAC;AAAA,EACL;AAAA,EACA,EAAE,MAAM,SAAS,cAAc,MAAM;AACvC;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, type FormState, type FormOptions } 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 defineComponent,\n} from 'vue-demi'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData> {\n Provider: (props: Record<string, any> & {}) => any\n provideFormContext: () => void\n Field: FieldComponent<TFormData>\n useField: UseField<TFormData>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(\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<TData>(opts?: FormOptions<TData>): FormApi<TData> {\n const formApi = (() => {\n const api = new FormApi<TData>(opts)\n\n api.Provider = defineComponent(\n (_, context) => {\n provideFormContext({ formApi })\n return () => context.slots.default!()\n },\n { name: 'Provider' },\n )\n api.provideFormContext = () => {\n provideFormContext({ formApi })\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAA0D;AAC1D,uBAAuC;AACvC,sBAAoE;AACpE,yBAAmC;AACnC,sBAKO;AAwBA,SAAS,QAAe,MAA2C;AACxE,QAAM,WAAW,MAAM;AACrB,UAAM,MAAM,IAAI,yBAAe,IAAI;AAEnC,QAAI,eAAW;AAAA,MACb,CAAC,GAAG,YAAY;AACd,mDAAmB,EAAE,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,MAAM,QAAS;AAAA,MACtC;AAAA,MACA,EAAE,MAAM,WAAW;AAAA,IACrB;AACA,QAAI,qBAAqB,MAAM;AAC7B,iDAAmB,EAAE,QAAQ,CAAC;AAAA,IAChC;AACA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,WAAW,CAAC,aAAa;AAC3B,iBAAO,2BAAS,IAAI,OAAgB,QAAiB;AAAA,IACvD;AACA,QAAI,gBAAY;AAAA,MACd,CAAC,OAAO,YAAY;AAClB,cAAM,WAAW,EAAE,GAAG,OAAO,GAAG,QAAQ,MAAM;AAC9C,cAAM,WAAW,SAAS,aAAa,CAAC,UAAU;AAClD,cAAM,WAAO,2BAAS,IAAI,OAAgB,QAAiB;AAC3D,eAAO,MAAM,QAAQ,MAAM,QAAS,KAAK,KAAK;AAAA,MAChD;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,cAAc;AAAA,MAChB;AAAA,IACF;AAEA,WAAO;AAAA,EACT,GAAG;AAGH,UAAQ,OAAO,IAAI;AAEnB,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, type FormState, type FormOptions } 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 defineComponent,\n} from 'vue-demi'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, ValidatorType> {\n Provider: (props: Record<string, any> & {}) => any\n provideFormContext: () => void\n Field: FieldComponent<TFormData, ValidatorType>\n useField: UseField<TFormData, ValidatorType>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => 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<TData, FormValidator>(\n opts?: FormOptions<TData, FormValidator>,\n): FormApi<TData, FormValidator> {\n const formApi = (() => {\n const api = new FormApi<TData, FormValidator>(opts)\n\n api.Provider = defineComponent(\n (_, context) => {\n provideFormContext({ formApi: formApi as never })\n return () => context.slots.default!()\n },\n { name: 'Provider' },\n )\n api.provideFormContext = () => {\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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAA0D;AAC1D,uBAAuC;AACvC,sBAAoE;AACpE,yBAAmC;AACnC,sBAKO;AAwBA,SAAS,QACd,MAC+B;AAC/B,QAAM,WAAW,MAAM;AACrB,UAAM,MAAM,IAAI,yBAA8B,IAAI;AAElD,QAAI,eAAW;AAAA,MACb,CAAC,GAAG,YAAY;AACd,mDAAmB,EAAE,QAA0B,CAAC;AAChD,eAAO,MAAM,QAAQ,MAAM,QAAS;AAAA,MACtC;AAAA,MACA,EAAE,MAAM,WAAW;AAAA,IACrB;AACA,QAAI,qBAAqB,MAAM;AAC7B,iDAAmB,EAAE,QAA0B,CAAC;AAAA,IAClD;AACA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,WAAW,CAAC,aAAa;AAC3B,iBAAO,2BAAS,IAAI,OAAgB,QAAiB;AAAA,IACvD;AACA,QAAI,gBAAY;AAAA,MACd,CAAC,OAAO,YAAY;AAClB,cAAM,WAAW,EAAE,GAAG,OAAO,GAAG,QAAQ,MAAM;AAC9C,cAAM,WAAW,SAAS,aAAa,CAAC,UAAU;AAClD,cAAM,WAAO,2BAAS,IAAI,OAAgB,QAAiB;AAC3D,eAAO,MAAM,QAAQ,MAAM,QAAS,KAAK,KAAK;AAAA,MAChD;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,cAAc;AAAA,MAChB;AAAA,IACF;AAEA,WAAO;AAAA,EACT,GAAG;AAGH,UAAQ,OAAO,IAAI;AAEnB,SAAO;AACT;","names":[]}
@@ -5,11 +5,11 @@ import { SetupContext, EmitsOptions, SlotsType } from 'vue-demi';
5
5
  import './types.cjs';
6
6
 
7
7
  declare module '@tanstack/form-core' {
8
- interface FormApi<TFormData> {
8
+ interface FormApi<TFormData, ValidatorType> {
9
9
  Provider: (props: Record<string, any> & {}) => any;
10
10
  provideFormContext: () => void;
11
- Field: FieldComponent<TFormData>;
12
- useField: UseField<TFormData>;
11
+ Field: FieldComponent<TFormData, ValidatorType>;
12
+ useField: UseField<TFormData, ValidatorType>;
13
13
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
14
14
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
15
15
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected;
@@ -18,6 +18,6 @@ declare module '@tanstack/form-core' {
18
18
  }>>) => any;
19
19
  }
20
20
  }
21
- declare function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData>;
21
+ declare function useForm<TData, FormValidator>(opts?: FormOptions<TData, FormValidator>): FormApi<TData, FormValidator>;
22
22
 
23
23
  export { useForm };
@@ -5,11 +5,11 @@ import { SetupContext, EmitsOptions, SlotsType } from 'vue-demi';
5
5
  import './types.js';
6
6
 
7
7
  declare module '@tanstack/form-core' {
8
- interface FormApi<TFormData> {
8
+ interface FormApi<TFormData, ValidatorType> {
9
9
  Provider: (props: Record<string, any> & {}) => any;
10
10
  provideFormContext: () => void;
11
- Field: FieldComponent<TFormData>;
12
- useField: UseField<TFormData>;
11
+ Field: FieldComponent<TFormData, ValidatorType>;
12
+ useField: UseField<TFormData, ValidatorType>;
13
13
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(selector?: (state: NoInfer<FormState<TFormData>>) => TSelected) => TSelected;
14
14
  Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(props: {
15
15
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected;
@@ -18,6 +18,6 @@ declare module '@tanstack/form-core' {
18
18
  }>>) => any;
19
19
  }
20
20
  }
21
- declare function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData>;
21
+ declare function useForm<TData, FormValidator>(opts?: FormOptions<TData, FormValidator>): FormApi<TData, FormValidator>;
22
22
 
23
23
  export { useForm };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, type FormState, type FormOptions } 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 defineComponent,\n} from 'vue-demi'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData> {\n Provider: (props: Record<string, any> & {}) => any\n provideFormContext: () => void\n Field: FieldComponent<TFormData>\n useField: UseField<TFormData>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => TSelected\n Subscribe: <TSelected = NoInfer<FormState<TFormData>>>(\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<TData>(opts?: FormOptions<TData>): FormApi<TData> {\n const formApi = (() => {\n const api = new FormApi<TData>(opts)\n\n api.Provider = defineComponent(\n (_, context) => {\n provideFormContext({ formApi })\n return () => context.slots.default!()\n },\n { name: 'Provider' },\n )\n api.provideFormContext = () => {\n provideFormContext({ formApi })\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"],"mappings":";AAAA,SAAS,eAAiD;AAC1D,SAAuB,gBAAgB;AACvC,SAA6C,OAAO,gBAAgB;AACpE,SAAS,0BAA0B;AACnC;AAAA,EAIE;AAAA,OACK;AAwBA,SAAS,QAAe,MAA2C;AACxE,QAAM,WAAW,MAAM;AACrB,UAAM,MAAM,IAAI,QAAe,IAAI;AAEnC,QAAI,WAAW;AAAA,MACb,CAAC,GAAG,YAAY;AACd,2BAAmB,EAAE,QAAQ,CAAC;AAC9B,eAAO,MAAM,QAAQ,MAAM,QAAS;AAAA,MACtC;AAAA,MACA,EAAE,MAAM,WAAW;AAAA,IACrB;AACA,QAAI,qBAAqB,MAAM;AAC7B,yBAAmB,EAAE,QAAQ,CAAC;AAAA,IAChC;AACA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,WAAW,CAAC,aAAa;AAC3B,aAAO,SAAS,IAAI,OAAgB,QAAiB;AAAA,IACvD;AACA,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,IACF;AAEA,WAAO;AAAA,EACT,GAAG;AAGH,UAAQ,OAAO,IAAI;AAEnB,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/useForm.tsx"],"sourcesContent":["import { FormApi, type FormState, type FormOptions } 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 defineComponent,\n} from 'vue-demi'\n\ndeclare module '@tanstack/form-core' {\n // eslint-disable-next-line no-shadow\n interface FormApi<TFormData, ValidatorType> {\n Provider: (props: Record<string, any> & {}) => any\n provideFormContext: () => void\n Field: FieldComponent<TFormData, ValidatorType>\n useField: UseField<TFormData, ValidatorType>\n useStore: <TSelected = NoInfer<FormState<TFormData>>>(\n selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,\n ) => 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<TData, FormValidator>(\n opts?: FormOptions<TData, FormValidator>,\n): FormApi<TData, FormValidator> {\n const formApi = (() => {\n const api = new FormApi<TData, FormValidator>(opts)\n\n api.Provider = defineComponent(\n (_, context) => {\n provideFormContext({ formApi: formApi as never })\n return () => context.slots.default!()\n },\n { name: 'Provider' },\n )\n api.provideFormContext = () => {\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"],"mappings":";AAAA,SAAS,eAAiD;AAC1D,SAAuB,gBAAgB;AACvC,SAA6C,OAAO,gBAAgB;AACpE,SAAS,0BAA0B;AACnC;AAAA,EAIE;AAAA,OACK;AAwBA,SAAS,QACd,MAC+B;AAC/B,QAAM,WAAW,MAAM;AACrB,UAAM,MAAM,IAAI,QAA8B,IAAI;AAElD,QAAI,WAAW;AAAA,MACb,CAAC,GAAG,YAAY;AACd,2BAAmB,EAAE,QAA0B,CAAC;AAChD,eAAO,MAAM,QAAQ,MAAM,QAAS;AAAA,MACtC;AAAA,MACA,EAAE,MAAM,WAAW;AAAA,IACrB;AACA,QAAI,qBAAqB,MAAM;AAC7B,yBAAmB,EAAE,QAA0B,CAAC;AAAA,IAClD;AACA,QAAI,QAAQ;AACZ,QAAI,WAAW;AACf,QAAI,WAAW,CAAC,aAAa;AAC3B,aAAO,SAAS,IAAI,OAAgB,QAAiB;AAAA,IACvD;AACA,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,IACF;AAEA,WAAO;AAAA,EACT,GAAG;AAGH,UAAQ,OAAO,IAAI;AAEnB,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/vue-form",
3
- "version": "0.3.7",
3
+ "version": "0.4.1",
4
4
  "description": "Powerful, type-safe forms for Vue.",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -45,7 +45,7 @@
45
45
  "@tanstack/store": "0.1.3",
46
46
  "@tanstack/vue-store": "0.1.3",
47
47
  "vue-demi": "^0.14.6",
48
- "@tanstack/form-core": "0.3.7"
48
+ "@tanstack/form-core": "0.4.1"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@vue/composition-api": "1.7.2",
@@ -3,19 +3,21 @@ import type { FormApi, FormOptions } from '@tanstack/form-core'
3
3
  import { type UseField, type FieldComponent, Field, useField } from './useField'
4
4
  import { useForm } from './useForm'
5
5
 
6
- export type FormFactory<TFormData> = {
7
- useForm: (opts?: FormOptions<TFormData>) => FormApi<TFormData>
8
- useField: UseField<TFormData>
9
- Field: FieldComponent<TFormData>
6
+ export type FormFactory<TFormData, FormValidator> = {
7
+ useForm: (
8
+ opts?: FormOptions<TFormData, FormValidator>,
9
+ ) => FormApi<TFormData, FormValidator>
10
+ useField: UseField<TFormData, FormValidator>
11
+ Field: FieldComponent<TFormData, FormValidator>
10
12
  }
11
13
 
12
- export function createFormFactory<TFormData>(
13
- defaultOpts?: FormOptions<TFormData>,
14
- ): FormFactory<TFormData> {
14
+ export function createFormFactory<TFormData, FormValidator>(
15
+ defaultOpts?: FormOptions<TFormData, FormValidator>,
16
+ ): FormFactory<TFormData, FormValidator> {
15
17
  return {
16
18
  useForm: (opts) => {
17
19
  const formOptions = Object.assign({}, defaultOpts, opts)
18
- return useForm<TFormData>(formOptions)
20
+ return useForm<TFormData, FormValidator>(formOptions)
19
21
  },
20
22
  useField: useField as any,
21
23
  Field: Field as any,
@@ -2,7 +2,7 @@ import type { FormApi } from '@tanstack/form-core'
2
2
  import { inject, provide } from 'vue-demi'
3
3
 
4
4
  export type FormContext = {
5
- formApi: FormApi<any>
5
+ formApi: FormApi<any, unknown>
6
6
  parentFieldName?: string
7
7
  } | null
8
8
 
@@ -21,7 +21,7 @@ describe('useField', () => {
21
21
  lastName: string
22
22
  }
23
23
 
24
- const formFactory = createFormFactory<Person>()
24
+ const formFactory = createFormFactory<Person, unknown>()
25
25
 
26
26
  const Comp = defineComponent(() => {
27
27
  const form = formFactory.useForm()
@@ -30,7 +30,11 @@ describe('useField', () => {
30
30
 
31
31
  return () => (
32
32
  <form.Field name="firstName" defaultValue="FirstName">
33
- {({ field }: { field: FieldApi<Person, 'firstName'> }) => (
33
+ {({
34
+ field,
35
+ }: {
36
+ field: FieldApi<Person, 'firstName', never, never>
37
+ }) => (
34
38
  <input
35
39
  data-testid={'fieldinput'}
36
40
  value={field.state.value}
@@ -56,7 +60,7 @@ describe('useField', () => {
56
60
  }
57
61
  const error = 'Please enter a different value'
58
62
 
59
- const formFactory = createFormFactory<Person>()
63
+ const formFactory = createFormFactory<Person, unknown>()
60
64
 
61
65
  const Comp = defineComponent(() => {
62
66
  const form = formFactory.useForm()
@@ -68,7 +72,11 @@ describe('useField', () => {
68
72
  name="firstName"
69
73
  onChange={(value) => (value === 'other' ? error : undefined)}
70
74
  >
71
- {({ field }: { field: FieldApi<Person, 'firstName'> }) => (
75
+ {({
76
+ field,
77
+ }: {
78
+ field: FieldApi<Person, 'firstName', never, never>
79
+ }) => (
72
80
  <div>
73
81
  <input
74
82
  data-testid="fieldinput"
@@ -99,7 +107,7 @@ describe('useField', () => {
99
107
  }
100
108
  const error = 'Please enter a different value'
101
109
 
102
- const formFactory = createFormFactory<Person>()
110
+ const formFactory = createFormFactory<Person, unknown>()
103
111
 
104
112
  const Comp = defineComponent(() => {
105
113
  const form = formFactory.useForm()
@@ -111,7 +119,11 @@ describe('useField', () => {
111
119
  name="firstName"
112
120
  onChange={(value) => (value === 'other' ? error : undefined)}
113
121
  >
114
- {({ field }: { field: FieldApi<Person, 'firstName'> }) => (
122
+ {({
123
+ field,
124
+ }: {
125
+ field: FieldApi<Person, 'firstName', never, never>
126
+ }) => (
115
127
  <div>
116
128
  <input
117
129
  data-testid="fieldinput"
@@ -143,7 +155,7 @@ describe('useField', () => {
143
155
  }
144
156
  const error = 'Please enter a different value'
145
157
 
146
- const formFactory = createFormFactory<Person>()
158
+ const formFactory = createFormFactory<Person, unknown>()
147
159
 
148
160
  const Comp = defineComponent(() => {
149
161
  const form = formFactory.useForm()
@@ -159,7 +171,11 @@ describe('useField', () => {
159
171
  return error
160
172
  }}
161
173
  >
162
- {({ field }: { field: FieldApi<Person, 'firstName'> }) => (
174
+ {({
175
+ field,
176
+ }: {
177
+ field: FieldApi<Person, 'firstName', never, never>
178
+ }) => (
163
179
  <div>
164
180
  <input
165
181
  data-testid="fieldinput"
@@ -193,7 +209,7 @@ describe('useField', () => {
193
209
 
194
210
  const mockFn = vi.fn()
195
211
  const error = 'Please enter a different value'
196
- const formFactory = createFormFactory<Person>()
212
+ const formFactory = createFormFactory<Person, unknown>()
197
213
 
198
214
  const Comp = defineComponent(() => {
199
215
  const form = formFactory.useForm()
@@ -211,7 +227,11 @@ describe('useField', () => {
211
227
  return error
212
228
  }}
213
229
  >
214
- {({ field }: { field: FieldApi<Person, 'firstName'> }) => (
230
+ {({
231
+ field,
232
+ }: {
233
+ field: FieldApi<Person, 'firstName', never, never>
234
+ }) => (
215
235
  <div>
216
236
  <input
217
237
  data-testid="fieldinput"
@@ -20,7 +20,7 @@ describe('useForm', () => {
20
20
  lastName: string
21
21
  }
22
22
 
23
- const formFactory = createFormFactory<Person>()
23
+ const formFactory = createFormFactory<Person, unknown>()
24
24
 
25
25
  const Comp = defineComponent(() => {
26
26
  const form = formFactory.useForm()
@@ -29,7 +29,11 @@ describe('useForm', () => {
29
29
 
30
30
  return () => (
31
31
  <form.Field name="firstName" defaultValue="">
32
- {({ field }: { field: FieldApi<Person, 'firstName'> }) => (
32
+ {({
33
+ field,
34
+ }: {
35
+ field: FieldApi<Person, 'firstName', never, never>
36
+ }) => (
33
37
  <input
34
38
  data-testid={'fieldinput'}
35
39
  value={field.state.value}
@@ -56,7 +60,7 @@ describe('useForm', () => {
56
60
  lastName: string
57
61
  }
58
62
 
59
- const formFactory = createFormFactory<Person>()
63
+ const formFactory = createFormFactory<Person, unknown>()
60
64
 
61
65
  const Comp = defineComponent(() => {
62
66
  const form = formFactory.useForm({
@@ -69,9 +73,11 @@ describe('useForm', () => {
69
73
 
70
74
  return () => (
71
75
  <form.Field name="firstName">
72
- {({ field }: { field: FieldApi<Person, 'firstName'> }) => (
73
- <p>{field.state.value}</p>
74
- )}
76
+ {({
77
+ field,
78
+ }: {
79
+ field: FieldApi<Person, 'firstName', never, never>
80
+ }) => <p>{field.state.value}</p>}
75
81
  </form.Field>
76
82
  )
77
83
  })
@@ -81,37 +87,6 @@ describe('useForm', () => {
81
87
  expect(queryByText('LastName')).not.toBeInTheDocument()
82
88
  })
83
89
 
84
- it('should use field default value first', async () => {
85
- type Person = {
86
- firstName: string
87
- lastName: string
88
- }
89
-
90
- const formFactory = createFormFactory<Person>()
91
-
92
- const Comp = defineComponent(() => {
93
- const form = formFactory.useForm({
94
- defaultValues: {
95
- firstName: 'FirstName',
96
- lastName: 'LastName',
97
- },
98
- })
99
- form.provideFormContext()
100
-
101
- return () => (
102
- <form.Field name="firstName" defaultValue="otherName">
103
- {({ field }: { field: FieldApi<Person, 'firstName'> }) => (
104
- <p>{field.state.value}</p>
105
- )}
106
- </form.Field>
107
- )
108
- })
109
-
110
- const { findByText, queryByText } = render(Comp)
111
- expect(await findByText('otherName')).toBeInTheDocument()
112
- expect(queryByText('LastName')).not.toBeInTheDocument()
113
- })
114
-
115
90
  it('should handle submitting properly', async () => {
116
91
  const Comp = defineComponent(() => {
117
92
  const submittedData = ref<{ firstName: string }>()
@@ -132,7 +107,7 @@ describe('useForm', () => {
132
107
  {({
133
108
  field,
134
109
  }: {
135
- field: FieldApi<{ firstName: string }, 'firstName'>
110
+ field: FieldApi<{ firstName: string }, 'firstName', never, never>
136
111
  }) => {
137
112
  return (
138
113
  <input
package/src/types.ts CHANGED
@@ -3,7 +3,9 @@ import type { FieldOptions, DeepKeys, DeepValue } from '@tanstack/form-core'
3
3
  export type UseFieldOptions<
4
4
  TParentData,
5
5
  TName extends DeepKeys<TParentData>,
6
- TData = DeepValue<TParentData, TName>,
7
- > = FieldOptions<TParentData, TName, TData> & {
6
+ ValidatorType,
7
+ FormValidator,
8
+ TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
9
+ > = FieldOptions<TParentData, TName, ValidatorType, FormValidator, TData> & {
8
10
  mode?: 'value' | 'array'
9
11
  }
package/src/useField.tsx CHANGED
@@ -11,30 +11,54 @@ declare module '@tanstack/form-core' {
11
11
  interface FieldApi<
12
12
  TParentData,
13
13
  TName extends DeepKeys<TParentData>,
14
+ ValidatorType,
15
+ FormValidator,
14
16
  TData = DeepValue<TParentData, TName>,
15
17
  > {
16
- Field: FieldComponent<TData>
18
+ Field: FieldComponent<TData, FormValidator>
17
19
  }
18
20
  }
19
21
 
20
- export type UseField<TParentData> = <TName extends DeepKeys<TParentData>>(
22
+ export type UseField<TParentData, FormValidator> = <
23
+ TName extends DeepKeys<TParentData>,
24
+ ValidatorType,
25
+ >(
21
26
  opts?: { name: Narrow<TName> } & UseFieldOptions<
22
27
  TParentData,
23
28
  TName,
29
+ ValidatorType,
30
+ FormValidator,
24
31
  DeepValue<TParentData, TName>
25
32
  >,
26
- ) => FieldApi<TParentData, TName, DeepValue<TParentData, TName>>
33
+ ) => FieldApi<
34
+ TParentData,
35
+ TName,
36
+ ValidatorType,
37
+ FormValidator,
38
+ DeepValue<TParentData, TName>
39
+ >
27
40
 
28
41
  export function useField<
29
42
  TParentData,
30
43
  TName extends DeepKeys<TParentData>,
31
- TData = DeepValue<TParentData, TName>,
44
+ ValidatorType,
45
+ FormValidator,
46
+ TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
32
47
  >(
33
- opts: UseFieldOptions<TParentData, TName>,
48
+ opts: UseFieldOptions<
49
+ TParentData,
50
+ TName,
51
+ ValidatorType,
52
+ FormValidator,
53
+ TData
54
+ >,
34
55
  ): {
35
56
  api: FieldApi<
36
57
  TParentData,
37
- TName
58
+ TName,
59
+ ValidatorType,
60
+ FormValidator,
61
+ TData
38
62
  // Omit<typeof opts, 'onMount'> & {
39
63
  // form: FormApi<TParentData>
40
64
  // }
@@ -44,6 +68,8 @@ export function useField<
44
68
  FieldApi<
45
69
  TParentData,
46
70
  TName,
71
+ ValidatorType,
72
+ FormValidator,
47
73
  TData
48
74
  // Omit<typeof opts, 'onMount'> & {
49
75
  // form: FormApi<TParentData>
@@ -98,6 +124,8 @@ export type FieldValue<TParentData, TName> = TParentData extends any[]
98
124
  type FieldComponentProps<
99
125
  TParentData,
100
126
  TName extends DeepKeys<TParentData>,
127
+ ValidatorType,
128
+ FormValidator,
101
129
  > = (TParentData extends any[]
102
130
  ? {
103
131
  name?: TName
@@ -107,27 +135,52 @@ type FieldComponentProps<
107
135
  name: TName
108
136
  index?: never
109
137
  }) &
110
- Omit<UseFieldOptions<TParentData, TName>, 'name' | 'index'>
138
+ Omit<
139
+ UseFieldOptions<TParentData, TName, ValidatorType, FormValidator>,
140
+ 'name' | 'index'
141
+ >
111
142
 
112
- export type FieldComponent<TParentData> = <
143
+ export type FieldComponent<TParentData, FormValidator> = <
113
144
  TName extends DeepKeys<TParentData>,
114
- TData = DeepValue<TParentData, TName>,
145
+ ValidatorType,
146
+ TData extends DeepValue<TParentData, TName> = DeepValue<TParentData, TName>,
115
147
  >(
116
- fieldOptions: FieldComponentProps<TParentData, TName>,
148
+ fieldOptions: FieldComponentProps<
149
+ TParentData,
150
+ TName,
151
+ ValidatorType,
152
+ FormValidator
153
+ >,
117
154
  context: SetupContext<
118
155
  {},
119
156
  SlotsType<{
120
157
  default: {
121
- field: FieldApi<TParentData, TName, TData>
122
- state: FieldApi<TParentData, TName, TData>['state']
158
+ field: FieldApi<TParentData, TName, ValidatorType, FormValidator, TData>
159
+ state: FieldApi<
160
+ TParentData,
161
+ TName,
162
+ ValidatorType,
163
+ FormValidator,
164
+ TData
165
+ >['state']
123
166
  }
124
167
  }>
125
168
  >,
126
169
  ) => any
127
170
 
128
171
  export const Field = defineComponent(
129
- <TParentData, TName extends DeepKeys<TParentData>>(
130
- fieldOptions: UseFieldOptions<TParentData, TName>,
172
+ <
173
+ TParentData,
174
+ TName extends DeepKeys<TParentData>,
175
+ ValidatorType,
176
+ FormValidator,
177
+ >(
178
+ fieldOptions: UseFieldOptions<
179
+ TParentData,
180
+ TName,
181
+ ValidatorType,
182
+ FormValidator
183
+ >,
131
184
  context: SetupContext,
132
185
  ) => {
133
186
  const fieldApi = useField({ ...fieldOptions, ...context.attrs } as any)
package/src/useForm.tsx CHANGED
@@ -11,11 +11,11 @@ import {
11
11
 
12
12
  declare module '@tanstack/form-core' {
13
13
  // eslint-disable-next-line no-shadow
14
- interface FormApi<TFormData> {
14
+ interface FormApi<TFormData, ValidatorType> {
15
15
  Provider: (props: Record<string, any> & {}) => any
16
16
  provideFormContext: () => void
17
- Field: FieldComponent<TFormData>
18
- useField: UseField<TFormData>
17
+ Field: FieldComponent<TFormData, ValidatorType>
18
+ useField: UseField<TFormData, ValidatorType>
19
19
  useStore: <TSelected = NoInfer<FormState<TFormData>>>(
20
20
  selector?: (state: NoInfer<FormState<TFormData>>) => TSelected,
21
21
  ) => TSelected
@@ -31,19 +31,21 @@ declare module '@tanstack/form-core' {
31
31
  }
32
32
  }
33
33
 
34
- export function useForm<TData>(opts?: FormOptions<TData>): FormApi<TData> {
34
+ export function useForm<TData, FormValidator>(
35
+ opts?: FormOptions<TData, FormValidator>,
36
+ ): FormApi<TData, FormValidator> {
35
37
  const formApi = (() => {
36
- const api = new FormApi<TData>(opts)
38
+ const api = new FormApi<TData, FormValidator>(opts)
37
39
 
38
40
  api.Provider = defineComponent(
39
41
  (_, context) => {
40
- provideFormContext({ formApi })
42
+ provideFormContext({ formApi: formApi as never })
41
43
  return () => context.slots.default!()
42
44
  },
43
45
  { name: 'Provider' },
44
46
  )
45
47
  api.provideFormContext = () => {
46
- provideFormContext({ formApi })
48
+ provideFormContext({ formApi: formApi as never })
47
49
  }
48
50
  api.Field = Field as never
49
51
  api.useField = useField as never