diff --git a/docs/framework/angular/guides/basic-concepts.md b/docs/framework/angular/guides/basic-concepts.md index 1b3da15b8..5b219d5f2 100644 --- a/docs/framework/angular/guides/basic-concepts.md +++ b/docs/framework/angular/guides/basic-concepts.md @@ -88,7 +88,7 @@ Example: `, }) export class AppComponent { - firstNameValidator: FieldValidateFn = ({ + firstNameValidator: FieldValidateFn = ({ value, }) => !value @@ -97,7 +97,7 @@ export class AppComponent { ? 'First name must be at least 3 characters' : undefined - firstNameAsyncValidator: FieldValidateAsyncFn = + firstNameAsyncValidator: FieldValidateAsyncFn = async ({ value }) => { await new Promise((resolve) => setTimeout(resolve, 1000)) return value.includes('error') && 'No "error" allowed in first name' diff --git a/docs/framework/angular/guides/validation.md b/docs/framework/angular/guides/validation.md index d9d72352a..5a084066c 100644 --- a/docs/framework/angular/guides/validation.md +++ b/docs/framework/angular/guides/validation.md @@ -204,6 +204,42 @@ export class AppComponent { } ``` +It's worth mentioning that our `errors` array and the `errorMap` matches the types returned by the validators. This means that: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + + @if (!age.api.state.meta.errorMap['onChange']?.isOldEnough) { + The user is not old enough + } + + `, +}) +export class AppComponent { + ageValidator: FieldValidateFn = ({ value }) => + value < 13 ? 'You must be 13 to make an account' : undefined + + // ... +} +``` + + + + ## Validation at field level vs at form level As shown above, each `[tanstackField]` accepts its own validation rules via the `onChange`, `onBlur` etc... callbacks. It is also possible to define validation rules at the form level (as opposed to field by field) by passing similar callbacks to the `injectForm()` function. @@ -288,7 +324,7 @@ To do this, we have dedicated `onChangeAsync`, `onBlurAsync`, and other methods `, }) export class AppComponent { - ageValidator: FieldValidateAsyncFn = async ({ + ageValidator: FieldValidateAsyncFn = async ({ value, }) => { await new Promise((resolve) => setTimeout(resolve, 1000)) @@ -332,7 +368,7 @@ export class AppComponent { ensureAge13: FieldValidateFn = ({ value }) => value < 13 ? 'You must be at least 13' : undefined - ensureOlderAge: FieldValidateAsyncFn = async ({ + ensureOlderAge: FieldValidateAsyncFn = async ({ value, }) => { const currentAge = await fetchCurrentAgeOnProfile() @@ -418,7 +454,7 @@ import { z } from 'zod' `, }) export class AppComponent { - form = injectForm({ + form = injectForm({ // ... }) @@ -466,51 +502,6 @@ export class AppComponent { } ``` -### Other Schema Libraries - -We also support [Yup](https://github.com/jquense/yup) through an official adapter: - -```bash -$ npm install @tanstack/yup-form-adapter yup -``` - -Once done, we can add the adapter to the `validator` property on the form or field: - -```angular-ts -import { yupValidator } from '@tanstack/yup-form-adapter' -import * as yup from 'yup' - -@Component({ - selector: 'app-root', - standalone: true, - imports: [TanStackField], - template: ` - - - - `, -}) -export class AppComponent { - form = injectForm({ - // Either add the validator here or on `Field` - validatorAdapter: yupValidator(), - // ... - }) - - yup = yup - - // ... -} -``` - - ## Preventing invalid forms from being submitted The `onChange`, `onBlur` etc... callbacks are also run when the form is submitted and the submission is blocked if the form is invalid. diff --git a/docs/framework/angular/reference/classes/tanstackfield.md b/docs/framework/angular/reference/classes/tanstackfield.md index 8d8f6dbaa..1f82a06b4 100644 --- a/docs/framework/angular/reference/classes/tanstackfield.md +++ b/docs/framework/angular/reference/classes/tanstackfield.md @@ -3,9 +3,9 @@ id: TanStackField title: TanStackField --- -# Class: TanStackField\ +# Class: TanStackField\ -Defined in: [tanstack-field.directive.ts:25](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L25) +Defined in: [tanstack-field.directive.ts:32](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L32) ## Type Parameters @@ -13,42 +13,66 @@ Defined in: [tanstack-field.directive.ts:25](https://github.com/TanStack/form/bl • **TName** *extends* `DeepKeys`\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> = `DeepValue`\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Implements - `OnInit` - `OnChanges` - `OnDestroy` -- `FieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +- `FieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> ## Constructors ### new TanStackField() ```ts -new TanStackField(): TanStackField +new TanStackField(): TanStackField ``` #### Returns -[`TanStackField`](tanstackfield.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +[`TanStackField`](tanstackfield.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> ## Properties ### api ```ts -api: FieldApi; +api: FieldApi; ``` -Defined in: [tanstack-field.directive.ts:62](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L62) +Defined in: [tanstack-field.directive.ts:131](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L131) *** @@ -58,7 +82,7 @@ Defined in: [tanstack-field.directive.ts:62](https://github.com/TanStack/form/bl optional asyncAlways: boolean; ``` -Defined in: [tanstack-field.directive.ts:48](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L48) +Defined in: [tanstack-field.directive.ts:81](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L81) If `true`, always run async validation, even if there are errors emitted during synchronous validation. @@ -76,7 +100,7 @@ FieldOptions.asyncAlways optional asyncDebounceMs: number; ``` -Defined in: [tanstack-field.directive.ts:47](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L47) +Defined in: [tanstack-field.directive.ts:80](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L80) The default time to debounce async validation if there is not a more specific debounce time passed. @@ -91,10 +115,10 @@ FieldOptions.asyncDebounceMs ### defaultMeta? ```ts -optional defaultMeta: Partial; +optional defaultMeta: Partial>; ``` -Defined in: [tanstack-field.directive.ts:60](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L60) +Defined in: [tanstack-field.directive.ts:108](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L108) An optional object with default metadata for the field. @@ -112,7 +136,7 @@ FieldOptions.defaultMeta optional defaultValue: NoInfer; ``` -Defined in: [tanstack-field.directive.ts:46](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L46) +Defined in: [tanstack-field.directive.ts:79](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L79) An optional default value for the field. @@ -124,13 +148,31 @@ FieldOptions.defaultValue *** +### disableErrorFlat? + +```ts +optional disableErrorFlat: boolean; +``` + +Defined in: [tanstack-field.directive.ts:129](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L129) + +Disable the `flat(1)` operation on `field.errors`. This is useful if you want to keep the error structure as is. Not suggested for most use-cases. + +#### Implementation of + +```ts +FieldOptions.disableErrorFlat +``` + +*** + ### listeners? ```ts -optional listeners: NoInfer>; +optional listeners: NoInfer>; ``` -Defined in: [tanstack-field.directive.ts:57](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L57) +Defined in: [tanstack-field.directive.ts:107](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L107) A list of listeners which attach to the corresponding events @@ -148,7 +190,7 @@ FieldOptions.listeners name: TName; ``` -Defined in: [tanstack-field.directive.ts:42](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L42) +Defined in: [tanstack-field.directive.ts:75](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L75) The field name. The type will be `DeepKeys` to ensure your name is a deep key of the parent dataset. @@ -163,10 +205,10 @@ FieldOptions.name ### tanstackField ```ts -tanstackField: FormApi; +tanstackField: FormApi; ``` -Defined in: [tanstack-field.directive.ts:50](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L50) +Defined in: [tanstack-field.directive.ts:82](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L82) *** @@ -176,7 +218,7 @@ Defined in: [tanstack-field.directive.ts:50](https://github.com/TanStack/form/bl optional unmount: () => void; ``` -Defined in: [tanstack-field.directive.ts:78](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L78) +Defined in: [tanstack-field.directive.ts:185](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L185) #### Returns @@ -184,31 +226,13 @@ Defined in: [tanstack-field.directive.ts:78](https://github.com/TanStack/form/bl *** -### validatorAdapter? - -```ts -optional validatorAdapter: TFieldValidator; -``` - -Defined in: [tanstack-field.directive.ts:49](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L49) - -A validator provided by an extension, like `yupValidator` from `@tanstack/yup-form-adapter` - -#### Implementation of - -```ts -FieldOptions.validatorAdapter -``` - -*** - ### validators? ```ts -optional validators: NoInfer>; +optional validators: NoInfer>; ``` -Defined in: [tanstack-field.directive.ts:54](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L54) +Defined in: [tanstack-field.directive.ts:93](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L93) A list of validators to pass to the field @@ -226,7 +250,7 @@ FieldOptions.validators ngOnChanges(): void ``` -Defined in: [tanstack-field.directive.ts:90](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L90) +Defined in: [tanstack-field.directive.ts:197](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L197) A callback method that is invoked immediately after the default change detector has checked data-bound properties @@ -251,7 +275,7 @@ OnChanges.ngOnChanges ngOnDestroy(): void ``` -Defined in: [tanstack-field.directive.ts:86](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L86) +Defined in: [tanstack-field.directive.ts:193](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L193) A callback method that performs custom clean-up, invoked immediately before a directive, pipe, or service instance is destroyed. @@ -274,7 +298,7 @@ OnDestroy.ngOnDestroy ngOnInit(): void ``` -Defined in: [tanstack-field.directive.ts:80](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L80) +Defined in: [tanstack-field.directive.ts:187](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L187) A callback method that is invoked immediately after the default change detector has checked the directive's diff --git a/docs/framework/angular/reference/functions/injectform.md b/docs/framework/angular/reference/functions/injectform.md index 05b89cd61..2d1390639 100644 --- a/docs/framework/angular/reference/functions/injectform.md +++ b/docs/framework/angular/reference/functions/injectform.md @@ -6,23 +6,37 @@ title: injectForm # Function: injectForm() ```ts -function injectForm(opts?): FormApi +function injectForm(opts?): FormApi ``` -Defined in: [inject-form.ts:5](https://github.com/TanStack/form/blob/main/packages/angular-form/src/inject-form.ts#L5) +Defined in: [inject-form.ts:9](https://github.com/TanStack/form/blob/main/packages/angular-form/src/inject-form.ts#L9) ## Type Parameters • **TFormData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TFormData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> ## Parameters ### opts? -`FormOptions`\<`TFormData`, `TFormValidator`\> +`FormOptions`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ## Returns -`FormApi`\<`TFormData`, `TFormValidator`\> +`FormApi`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> diff --git a/docs/framework/angular/reference/functions/injectstore.md b/docs/framework/angular/reference/functions/injectstore.md index d66d6302a..0d19fc8de 100644 --- a/docs/framework/angular/reference/functions/injectstore.md +++ b/docs/framework/angular/reference/functions/injectstore.md @@ -6,24 +6,38 @@ title: injectStore # Function: injectStore() ```ts -function injectStore(form, selector?): Signal +function injectStore(form, selector?): Signal ``` -Defined in: [inject-store.ts:4](https://github.com/TanStack/form/blob/main/packages/angular-form/src/inject-store.ts#L4) +Defined in: [inject-store.ts:9](https://github.com/TanStack/form/blob/main/packages/angular-form/src/inject-store.ts#L9) ## Type Parameters • **TFormData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TFormData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> -• **TSelected** = `NoInfer`\<`FormState`\<`TFormData`\>\> +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TSelected** = `NoInfer`\<`FormState`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\>\> ## Parameters ### form -`FormApi`\<`TFormData`, `TFormValidator`\> +`FormApi`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ### selector? diff --git a/docs/framework/lit/reference/classes/tanstackformcontroller.md b/docs/framework/lit/reference/classes/tanstackformcontroller.md index b5be60c77..8523a2715 100644 --- a/docs/framework/lit/reference/classes/tanstackformcontroller.md +++ b/docs/framework/lit/reference/classes/tanstackformcontroller.md @@ -3,15 +3,29 @@ id: TanStackFormController title: TanStackFormController --- -# Class: TanStackFormController\ +# Class: TanStackFormController\ -Defined in: [tanstack-form-controller.ts:81](https://github.com/TanStack/form/blob/main/packages/lit-form/src/tanstack-form-controller.ts#L81) +Defined in: [tanstack-form-controller.ts:183](https://github.com/TanStack/form/blob/main/packages/lit-form/src/tanstack-form-controller.ts#L183) ## Type Parameters • **TParentData** -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Implements @@ -22,10 +36,10 @@ Defined in: [tanstack-form-controller.ts:81](https://github.com/TanStack/form/bl ### new TanStackFormController() ```ts -new TanStackFormController(host, config?): TanStackFormController +new TanStackFormController(host, config?): TanStackFormController ``` -Defined in: [tanstack-form-controller.ts:93](https://github.com/TanStack/form/blob/main/packages/lit-form/src/tanstack-form-controller.ts#L93) +Defined in: [tanstack-form-controller.ts:210](https://github.com/TanStack/form/blob/main/packages/lit-form/src/tanstack-form-controller.ts#L210) #### Parameters @@ -35,51 +49,61 @@ Defined in: [tanstack-form-controller.ts:93](https://github.com/TanStack/form/bl ##### config? -`FormOptions`\<`TParentData`, `TFormValidator`\> +`FormOptions`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> #### Returns -[`TanStackFormController`](tanstackformcontroller.md)\<`TParentData`, `TFormValidator`\> +[`TanStackFormController`](tanstackformcontroller.md)\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> ## Properties ### api ```ts -api: FormApi; +api: FormApi; ``` -Defined in: [tanstack-form-controller.ts:91](https://github.com/TanStack/form/blob/main/packages/lit-form/src/tanstack-form-controller.ts#L91) +Defined in: [tanstack-form-controller.ts:198](https://github.com/TanStack/form/blob/main/packages/lit-form/src/tanstack-form-controller.ts#L198) ## Methods ### field() ```ts -field(fieldConfig, render): object +field(fieldConfig, render): object ``` -Defined in: [tanstack-form-controller.ts:112](https://github.com/TanStack/form/blob/main/packages/lit-form/src/tanstack-form-controller.ts#L112) +Defined in: [tanstack-form-controller.ts:249](https://github.com/TanStack/form/blob/main/packages/lit-form/src/tanstack-form-controller.ts#L249) #### Type Parameters • **TName** *extends* `string` \| `number` -• **TFieldValidator** *extends* - \| `undefined` - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`, `IsNullable`\<`TParentData`\>\>, `unknown`\> = `undefined` +• **TData** + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** = `DeepValue`\<`TParentData`, `TName`, `IsNullable`\<`TParentData`\>\> +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> #### Parameters ##### fieldConfig -`FieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +`FieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> ##### render -`renderCallback`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +`renderCallback`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> #### Returns @@ -94,19 +118,19 @@ values: object; ###### values.form ```ts -form: FormApi; +form: FormApi; ``` ###### values.options ```ts -options: FieldOptions; +options: FieldOptions; ``` ###### values.render ```ts -render: renderCallback; +render: renderCallback; ``` *** @@ -117,7 +141,7 @@ render: renderCallback({ +const form = useForm({ onSubmit: async ({ value }) => { // Do something with form data console.log(value) @@ -47,7 +47,7 @@ const form = useForm({ firstName: '', lastName: '', hobbies: [], - }, + } as Person, }) ``` diff --git a/docs/framework/react/guides/ssr.md b/docs/framework/react/guides/ssr.md index f584a792c..74e63d7d2 100644 --- a/docs/framework/react/guides/ssr.md +++ b/docs/framework/react/guides/ssr.md @@ -20,7 +20,6 @@ This section focuses on integrating TanStack Form with TanStack Start. - Start a new `TanStack Start` project, following the steps in the [TanStack Start Quickstart Guide](https://tanstack.com/router/latest/docs/framework/react/guide/tanstack-start) - Install `@tanstack/react-form` -- Install any [form validator](/form/latest/docs/framework/react/guides/validation#validation-through-schema-libraries) of your choice. [Optional] ### Start integration @@ -31,7 +30,7 @@ Let's start by creating a `formOption` that we'll use to share the form's shape // Notice the import path is different from the typical import location import { formOptions } from '@tanstack/react-form/start' -// You can pass other form options here, like `validatorAdapter` +// You can pass other form options here export const formOpts = formOptions({ defaultValues: { firstName: '', @@ -40,7 +39,7 @@ export const formOpts = formOptions({ }) ``` -Next, we can create [a Start Server Action](https://tanstack.com/router/latest/docs/framework/react/guide/server-functions) that will handle the form submission on the server. +Next, we can create [a Start Server Action](https://tanstack.com/start/latest/docs/framework/react/server-functions) that will handle the form submission on the server. ```typescript // app/routes/index.tsx, but can be extracted to any other path @@ -58,28 +57,32 @@ const serverValidate = createServerValidate({ }, }) -export const handleForm = createServerFn( - 'POST', - async (formData: FormData, ctx) => { +export const handleForm = createServerFn({ + method: 'POST', +}) + .validator((data: unknown) => { + if (!(data instanceof FormData)) { + throw new Error('Invalid form data') + } + return data + }) + .handler(async (ctx) => { try { - await serverValidate(ctx, formData) + await serverValidate(ctx.data) } catch (e) { if (e instanceof ServerValidateError) { + // Log form errors or do any other logic here return e.response } // Some other error occurred when parsing the form console.error(e) - return new Response('There was an internal error', { - status: 500, - }) + setResponseStatus(500) + return 'There was an internal error' } - return new Response('Form has validated successfully', { - status: 200, - }) - }, -) + return 'Form has validated successfully' + }) ``` Then we need to establish a way to grab the form data from `serverValidate`'s `response` using another server action: @@ -88,9 +91,11 @@ Then we need to establish a way to grab the form data from `serverValidate`'s `r // app/routes/index.tsx, but can be extracted to any other path import { getFormData } from '@tanstack/react-form/start' -export const getFormDataFromServer = createServerFn('GET', async (_, ctx) => { - return getFormData(ctx) -}) +export const getFormDataFromServer = createServerFn({ method: 'GET' }).handler( + async () => { + return getFormData() + }, +) ``` Finally, we'll use `getFormDataFromServer` in our loader to get the state from our server into our client and `handleForm` in our client-side form component. @@ -161,7 +166,7 @@ function Home() { ## Using TanStack Form in a Next.js App Router -> Before reading this section, it's suggested you understand how React Server Components and React Server Actions work. [Check out this blog series for more information](https://unicorn-utterances.com/collections/react-beyond-the-render) +> Before reading this section, it's suggested you understand how React Server Components and React Server Actions work. [Check out this blog series for more information](https://playfulprogramming.com/collections/react-beyond-the-render) This section focuses on integrating TanStack Form with `Next.js`, particularly using the `App Router` and `Server Actions`. @@ -180,7 +185,7 @@ Let's start by creating a `formOption` that we'll use to share the form's shape // Notice the import path is different from the client import { formOptions } from '@tanstack/react-form/nextjs' -// You can pass other form options here, like `validatorAdapter` +// You can pass other form options here export const formOpts = formOptions({ defaultValues: { firstName: '', @@ -189,7 +194,7 @@ export const formOpts = formOptions({ }) ``` -Next, we can create [a React Server Action](https://unicorn-utterances.com/posts/what-are-react-server-components) that will handle the form submission on the server. +Next, we can create [a React Server Action](https://playfulprogramming.com/posts/what-are-react-server-components) that will handle the form submission on the server. ```typescript // action.ts @@ -294,7 +299,7 @@ export const ClientComp = () => { } ``` -Here, we're using [React's `useActionState` hook](https://unicorn-utterances.com/posts/what-is-use-action-state-and-form-status) and TanStack Form's `useTransform` hook to merge state returned from the server action with the form state. +Here, we're using [React's `useActionState` hook](https://playfulprogramming.com/posts/what-is-use-action-state-and-form-status) and TanStack Form's `useTransform` hook to merge state returned from the server action with the form state. > If you get the following error in your Next.js application: > @@ -326,7 +331,7 @@ Let's start by creating a `formOption` that we'll use to share the form's shape // routes/_index/route.tsx import { formOptions } from '@tanstack/react-form/remix' -// You can pass other form options here, like `validatorAdapter` +// You can pass other form options here export const formOpts = formOptions({ defaultValues: { firstName: '', diff --git a/docs/framework/react/guides/validation.md b/docs/framework/react/guides/validation.md index e8a9ff26f..46c00eb34 100644 --- a/docs/framework/react/guides/validation.md +++ b/docs/framework/react/guides/validation.md @@ -150,6 +150,31 @@ Or use the `errorMap` property to access the specific error you're looking for: ``` +It's worth mentioning that our `errors` array and the `errorMap` matches the types returned by the validators. This means that: + +```tsx + + value < 13 ? {isOldEnough: false} : undefined, + }} +> + {(field) => ( + <> + {/* ... */} + {/* errorMap.onChange is type `{isOldEnough: false} | undefined` */} + {/* meta.errors is type `Array<{isOldEnough: false} | undefined>` */} + {!field.state.meta.errorMap['onChange']?.isOldEnough ? ( + The user is not old enough + ) : null} + + )} + +``` + + + ## Validation at field level vs at form level As shown above, each `` accepts its own validation rules via the `onChange`, `onBlur` etc... callbacks. It is also possible to define validation rules at the form level (as opposed to field by field) by passing similar callbacks to the `useForm()` hook. @@ -479,40 +504,6 @@ Async validations on form and field level are supported as well: /> ``` -### Other Schema Libraries - -We also support [Yup](https://github.com/jquense/yup) through an official adapter: - -```bash -$ npm install @tanstack/yup-form-adapter yup -``` - -Once done, we can add the adapter to the `validator` property on the form or field: - -```tsx -import { yupValidator } from '@tanstack/yup-form-adapter' -import * as yup from 'yup' - -// ... - -const form = useForm({ - // Either add the validator here or on `Field` - validatorAdapter: yupValidator(), - // ... -}) - - { - return <>{/* ... */} - }} -/> -``` - ## Preventing invalid forms from being submitted The `onChange`, `onBlur` etc... callbacks are also run when the form is submitted and the submission is blocked if the form is invalid. diff --git a/docs/framework/react/reference/functions/field.md b/docs/framework/react/reference/functions/field.md index 908bd0d99..4bdf6c2ef 100644 --- a/docs/framework/react/reference/functions/field.md +++ b/docs/framework/react/reference/functions/field.md @@ -6,10 +6,10 @@ title: Field # Function: Field() ```ts -function Field(__namedParameters): ReactNode +function Field(__namedParameters): ReactNode ``` -Defined in: [packages/react-form/src/useField.tsx:164](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L164) +Defined in: [packages/react-form/src/useField.tsx:352](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L352) A function component that takes field options and a render function as children and returns a React component. @@ -21,19 +21,43 @@ The `Field` component uses the `useField` hook internally to manage the field in • **TName** *extends* `string` \| `number` -• **TFieldValidator** *extends* - \| `undefined` - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> = `undefined` +• **TData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TParentData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** = `DeepValue`\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Parameters ### \_\_namedParameters -`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +`FieldComponentProps`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> ## Returns diff --git a/docs/framework/react/reference/functions/usefield.md b/docs/framework/react/reference/functions/usefield.md index 72bc66835..f2e75d646 100644 --- a/docs/framework/react/reference/functions/usefield.md +++ b/docs/framework/react/reference/functions/usefield.md @@ -6,10 +6,10 @@ title: useField # Function: useField() ```ts -function useField(opts): FieldApi & ReactFieldApi +function useField(opts): FieldApi & ReactFieldApi ``` -Defined in: [packages/react-form/src/useField.tsx:50](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L50) +Defined in: [packages/react-form/src/useField.tsx:125](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L125) A hook for managing a field in a form. @@ -19,24 +19,48 @@ A hook for managing a field in a form. • **TName** *extends* `string` \| `number` -• **TFieldValidator** *extends* - \| `undefined` - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> = `undefined` +• **TData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TParentData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** = `DeepValue`\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Parameters ### opts -`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +`UseFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> An object with field options. ## Returns -`FieldApi`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> & `ReactFieldApi`\<`TParentData`, `TFormValidator`\> +`FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> & `ReactFieldApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> The `FieldApi` instance for the specified field. diff --git a/docs/framework/react/reference/functions/useform.md b/docs/framework/react/reference/functions/useform.md index 826335c33..a8dd55524 100644 --- a/docs/framework/react/reference/functions/useform.md +++ b/docs/framework/react/reference/functions/useform.md @@ -6,10 +6,10 @@ title: useForm # Function: useForm() ```ts -function useForm(opts?): ReactFormExtendedApi +function useForm(opts?): ReactFormExtendedApi ``` -Defined in: [packages/react-form/src/useForm.tsx:57](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L57) +Defined in: [packages/react-form/src/useForm.tsx:137](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L137) A custom React Hook that returns an extended instance of the `FormApi` class. @@ -19,14 +19,28 @@ This API encapsulates all the necessary functionalities related to the form. It • **TFormData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TFormData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> ## Parameters ### opts? -`FormOptions`\<`TFormData`, `TFormValidator`\> +`FormOptions`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ## Returns -[`ReactFormExtendedApi`](../type-aliases/reactformextendedapi.md)\<`TFormData`, `TFormValidator`\> +[`ReactFormExtendedApi`](../type-aliases/reactformextendedapi.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> diff --git a/docs/framework/react/reference/functions/usetransform.md b/docs/framework/react/reference/functions/usetransform.md index 737c8c8af..52b6a6f58 100644 --- a/docs/framework/react/reference/functions/usetransform.md +++ b/docs/framework/react/reference/functions/usetransform.md @@ -6,22 +6,36 @@ title: useTransform # Function: useTransform() ```ts -function useTransform(fn, deps): FormTransform +function useTransform(fn, deps): FormTransform ``` -Defined in: [packages/react-form/src/useTransform.ts:3](https://github.com/TanStack/form/blob/main/packages/react-form/src/useTransform.ts#L3) +Defined in: [packages/react-form/src/useTransform.ts:8](https://github.com/TanStack/form/blob/main/packages/react-form/src/useTransform.ts#L8) ## Type Parameters • **TFormData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TFormData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> ## Parameters ### fn -(`formBase`) => `FormApi`\<`TFormData`, `TFormValidator`\> +(`formBase`) => `FormApi`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ### deps @@ -29,4 +43,4 @@ Defined in: [packages/react-form/src/useTransform.ts:3](https://github.com/TanSt ## Returns -`FormTransform`\<`TFormData`, `TFormValidator`\> +`FormTransform`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> diff --git a/docs/framework/react/reference/interfaces/reactformapi.md b/docs/framework/react/reference/interfaces/reactformapi.md index b53804b8d..c11deb9c7 100644 --- a/docs/framework/react/reference/interfaces/reactformapi.md +++ b/docs/framework/react/reference/interfaces/reactformapi.md @@ -3,9 +3,9 @@ id: ReactFormApi title: ReactFormApi --- -# Interface: ReactFormApi\ +# Interface: ReactFormApi\ -Defined in: [packages/react-form/src/useForm.tsx:14](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L14) +Defined in: [packages/react-form/src/useForm.tsx:21](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L21) Fields that are added onto the `FormAPI` from `@tanstack/form-core` and returned from `useForm` @@ -13,17 +13,31 @@ Fields that are added onto the `FormAPI` from `@tanstack/form-core` and returned • **TFormData** -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> ## Properties ### Field ```ts -Field: FieldComponent; +Field: FieldComponent; ``` -Defined in: [packages/react-form/src/useForm.tsx:21](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L21) +Defined in: [packages/react-form/src/useForm.tsx:35](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L35) A React component to render form fields. With this, you can render and manage individual form fields. @@ -35,13 +49,13 @@ A React component to render form fields. With this, you can render and manage in Subscribe: (props) => ReactNode; ``` -Defined in: [packages/react-form/src/useForm.tsx:25](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L25) +Defined in: [packages/react-form/src/useForm.tsx:49](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L49) A `Subscribe` function that allows you to listen and react to changes in the form's state. It's especially useful when you need to execute side effects or render specific components in response to state updates. #### Type Parameters -• **TSelected** = `FormState`\<`TFormData`\> +• **TSelected** = `FormState`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> #### Parameters @@ -51,7 +65,7 @@ A `Subscribe` function that allows you to listen and react to changes in the for `ReactNode` \| (`state`) => `ReactNode` -###### selector +###### selector? (`state`) => `TSelected` diff --git a/docs/framework/react/reference/type-aliases/fieldcomponent.md b/docs/framework/react/reference/type-aliases/fieldcomponent.md index 00fc39ca7..f7d1388c0 100644 --- a/docs/framework/react/reference/type-aliases/fieldcomponent.md +++ b/docs/framework/react/reference/type-aliases/fieldcomponent.md @@ -3,16 +3,16 @@ id: FieldComponent title: FieldComponent --- -# Type Alias: FieldComponent()\ +# Type Alias: FieldComponent()\ ```ts -type FieldComponent = ({ +type FieldComponent = ({ children, ...fieldOptions }) => ReactNode; ``` -Defined in: [packages/react-form/src/useField.tsx:134](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L134) +Defined in: [packages/react-form/src/useField.tsx:294](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L294) A type alias representing a field component for a specific form data type. @@ -20,17 +20,41 @@ A type alias representing a field component for a specific form data type. • **TParentData** -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Type Parameters • **TName** *extends* `DeepKeys`\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> = `DeepValue`\<`TParentData`, `TName`\> +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> ## Parameters @@ -39,7 +63,7 @@ A type alias representing a field component for a specific form data type. ...fieldOptions \} -`Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +`Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>, `"form"`\> ## Returns diff --git a/docs/framework/react/reference/type-aliases/reactformextendedapi.md b/docs/framework/react/reference/type-aliases/reactformextendedapi.md index ec56e7c0d..66ca3973e 100644 --- a/docs/framework/react/reference/type-aliases/reactformextendedapi.md +++ b/docs/framework/react/reference/type-aliases/reactformextendedapi.md @@ -3,13 +3,13 @@ id: ReactFormExtendedApi title: ReactFormExtendedApi --- -# Type Alias: ReactFormExtendedApi\ +# Type Alias: ReactFormExtendedApi\ ```ts -type ReactFormExtendedApi = FormApi & ReactFormApi; +type ReactFormExtendedApi = FormApi & ReactFormApi; ``` -Defined in: [packages/react-form/src/useForm.tsx:34](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L34) +Defined in: [packages/react-form/src/useForm.tsx:86](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L86) An extended version of the `FormApi` class that includes React-specific functionalities from `ReactFormApi` @@ -17,4 +17,18 @@ An extended version of the `FormApi` class that includes React-specific function • **TFormData** -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> diff --git a/docs/framework/react/reference/type-aliases/usefield.md b/docs/framework/react/reference/type-aliases/usefield.md index 6ebd1f268..2fdea33cb 100644 --- a/docs/framework/react/reference/type-aliases/usefield.md +++ b/docs/framework/react/reference/type-aliases/usefield.md @@ -3,13 +3,13 @@ id: UseField title: UseField --- -# Type Alias: UseField()\ +# Type Alias: UseField()\ ```ts -type UseField = (opts) => FieldApi; +type UseField = (opts) => FieldApi; ``` -Defined in: [packages/react-form/src/useField.tsx:26](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L26) +Defined in: [packages/react-form/src/useField.tsx:48](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L48) A type representing a hook for using a field in a form with the given form data type. @@ -19,24 +19,48 @@ A function that takes an optional object with a `name` property and field option • **TParentData** -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Type Parameters • **TName** *extends* `DeepKeys`\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> = `DeepValue`\<`TParentData`, `TName`\> +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> ## Parameters ### opts -`Omit`\<`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +`Omit`\<`UseFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>, `"form"`\> ## Returns -`FieldApi`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +`FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> diff --git a/docs/framework/solid/guides/validation.md b/docs/framework/solid/guides/validation.md index 08c60857b..40a2e6218 100644 --- a/docs/framework/solid/guides/validation.md +++ b/docs/framework/solid/guides/validation.md @@ -152,6 +152,32 @@ Or use the `errorMap` property to access the specific error you're looking for: ``` + +It's worth mentioning that our `errors` array and the `errorMap` matches the types returned by the validators. This means that: + +```tsx + + value < 13 ? {isOldEnough: false} : undefined, + }} +> + {(field) => ( + <> + {/* ... */} + {/* errorMap.onChange is type `{isOldEnough: false} | undefined` */} + {/* meta.errors is type `Array<{isOldEnough: false} | undefined>` */} + {!field().state.meta.errorMap['onChange']?.isOldEnough ? ( + The user is not old enough + ) : null} + + )} + +``` + + + ## Validation at field level vs at form level As shown above, each `` accepts its own validation rules via the `onChange`, `onBlur` etc... callbacks. It is also possible to define validation rules at the form level (as opposed to field by field) by passing similar callbacks to the `createForm()` hook. @@ -371,41 +397,6 @@ Async validations on form and field level are supported as well: /> ``` -### Other Schema Libraries - -We also support [Yup](https://github.com/jquense/yup) through an official adapter: - -```bash -$ npm install @tanstack/yup-form-adapter yup -``` - -Once done, we can add the adapter to the `validator` property on the form or field: - - -```tsx -import { yupValidator } from '@tanstack/yup-form-adapter' -import * as yup from 'yup' - -// ... - -const form = createForm(() => ({ - // Either add the validator here or on `Field` - validatorAdapter: yupValidator(), - // ... -})); - - { - return <>{/* ... */} - }} -/> -``` - ## Preventing invalid forms from being submitted The `onChange`, `onBlur` etc... callbacks are also run when the form is submitted and the submission is blocked if the form is invalid. diff --git a/docs/framework/solid/reference/functions/createfield.md b/docs/framework/solid/reference/functions/createfield.md index 6befedc54..bb7a449ee 100644 --- a/docs/framework/solid/reference/functions/createfield.md +++ b/docs/framework/solid/reference/functions/createfield.md @@ -6,10 +6,10 @@ title: createField # Function: createField() ```ts -function createField(opts): () => never +function createField(opts): () => FieldApi & SolidFieldApi ``` -Defined in: [packages/solid-form/src/createField.tsx:87](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L87) +Defined in: [packages/solid-form/src/createField.tsx:225](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L225) ## Type Parameters @@ -17,19 +17,43 @@ Defined in: [packages/solid-form/src/createField.tsx:87](https://github.com/TanS • **TName** *extends* `string` \| `number` -• **TFieldValidator** *extends* - \| `undefined` - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> = `undefined` +• **TData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TParentData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** = `DeepValue`\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Parameters ### opts -() => `CreateFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +() => `CreateFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> ## Returns @@ -37,4 +61,4 @@ Defined in: [packages/solid-form/src/createField.tsx:87](https://github.com/TanS ### Returns -`never` +`FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> & `SolidFieldApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> diff --git a/docs/framework/solid/reference/functions/createform.md b/docs/framework/solid/reference/functions/createform.md index 4408204c0..eccd2d43d 100644 --- a/docs/framework/solid/reference/functions/createform.md +++ b/docs/framework/solid/reference/functions/createform.md @@ -6,23 +6,37 @@ title: createForm # Function: createForm() ```ts -function createForm(opts?): FormApi & SolidFormApi +function createForm(opts?): FormApi & SolidFormApi ``` -Defined in: [packages/solid-form/src/createForm.tsx:26](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L26) +Defined in: [packages/solid-form/src/createForm.tsx:114](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L114) ## Type Parameters • **TParentData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TParentData`, `unknown`\> = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Parameters ### opts? -() => `FormOptions`\<`TParentData`, `TFormValidator`\> +() => `FormOptions`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> ## Returns -`FormApi`\<`TParentData`, `TFormValidator`\> & [`SolidFormApi`](../interfaces/solidformapi.md)\<`TParentData`, `TFormValidator`\> +`FormApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> & [`SolidFormApi`](../interfaces/solidformapi.md)\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> diff --git a/docs/framework/solid/reference/functions/field.md b/docs/framework/solid/reference/functions/field.md index 7cb6956d1..7c4edc74e 100644 --- a/docs/framework/solid/reference/functions/field.md +++ b/docs/framework/solid/reference/functions/field.md @@ -6,10 +6,10 @@ title: Field # Function: Field() ```ts -function Field(props): Element +function Field(props): Element ``` -Defined in: [packages/solid-form/src/createField.tsx:196](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L196) +Defined in: [packages/solid-form/src/createField.tsx:460](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L460) ## Type Parameters @@ -17,19 +17,43 @@ Defined in: [packages/solid-form/src/createField.tsx:196](https://github.com/Tan • **TName** *extends* `string` \| `number` -• **TFieldValidator** *extends* - \| `undefined` - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> = `undefined` +• **TData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TParentData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** = `DeepValue`\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Parameters ### props -`object` & `FieldApiOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> & `object` +`object` & `FieldApiOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> & `object` ## Returns diff --git a/docs/framework/solid/reference/functions/usestore.md b/docs/framework/solid/reference/functions/usestore.md index b1251110e..bf10af9e4 100644 --- a/docs/framework/solid/reference/functions/usestore.md +++ b/docs/framework/solid/reference/functions/usestore.md @@ -11,7 +11,7 @@ title: useStore function useStore(store, selector?): Accessor ``` -Defined in: node\_modules/.pnpm/@tanstack+solid-store@0.7.0\_solid-js@1.9.3/node\_modules/@tanstack/solid-store/dist/esm/index.d.ts:8 +Defined in: node\_modules/.pnpm/@tanstack+solid-store@0.7.0\_solid-js@1.9.4/node\_modules/@tanstack/solid-store/dist/esm/index.d.ts:8 ### Type Parameters @@ -39,7 +39,7 @@ Defined in: node\_modules/.pnpm/@tanstack+solid-store@0.7.0\_solid-js@1.9.3/node function useStore(store, selector?): Accessor ``` -Defined in: node\_modules/.pnpm/@tanstack+solid-store@0.7.0\_solid-js@1.9.3/node\_modules/@tanstack/solid-store/dist/esm/index.d.ts:9 +Defined in: node\_modules/.pnpm/@tanstack+solid-store@0.7.0\_solid-js@1.9.4/node\_modules/@tanstack/solid-store/dist/esm/index.d.ts:9 ### Type Parameters diff --git a/docs/framework/solid/reference/interfaces/solidformapi.md b/docs/framework/solid/reference/interfaces/solidformapi.md index a0ae50053..4a13b7506 100644 --- a/docs/framework/solid/reference/interfaces/solidformapi.md +++ b/docs/framework/solid/reference/interfaces/solidformapi.md @@ -3,35 +3,49 @@ id: SolidFormApi title: SolidFormApi --- -# Interface: SolidFormApi\ +# Interface: SolidFormApi\ -Defined in: [packages/solid-form/src/createForm.tsx:11](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L11) +Defined in: [packages/solid-form/src/createForm.tsx:16](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L16) ## Type Parameters -• **TFormData** +• **TParentData** + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Properties ### createField ```ts -createField: CreateField; +createField: CreateField; ``` -Defined in: [packages/solid-form/src/createForm.tsx:16](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L16) +Defined in: [packages/solid-form/src/createForm.tsx:38](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L38) *** ### Field ```ts -Field: FieldComponent; +Field: FieldComponent; ``` -Defined in: [packages/solid-form/src/createForm.tsx:15](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L15) +Defined in: [packages/solid-form/src/createForm.tsx:27](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L27) *** @@ -41,11 +55,11 @@ Defined in: [packages/solid-form/src/createForm.tsx:15](https://github.com/TanSt Subscribe: (props) => Element; ``` -Defined in: [packages/solid-form/src/createForm.tsx:20](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L20) +Defined in: [packages/solid-form/src/createForm.tsx:80](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L80) #### Type Parameters -• **TSelected** = `FormState`\<`TFormData`\> +• **TSelected** = `FormState`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> #### Parameters @@ -55,7 +69,7 @@ Defined in: [packages/solid-form/src/createForm.tsx:20](https://github.com/TanSt `Element` \| (`state`) => `Element` -###### selector +###### selector? (`state`) => `TSelected` @@ -71,11 +85,11 @@ Defined in: [packages/solid-form/src/createForm.tsx:20](https://github.com/TanSt useStore: (selector?) => () => TSelected; ``` -Defined in: [packages/solid-form/src/createForm.tsx:17](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L17) +Defined in: [packages/solid-form/src/createForm.tsx:49](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L49) #### Type Parameters -• **TSelected** = `FormState`\<`TFormData`\> +• **TSelected** = `FormState`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> #### Parameters diff --git a/docs/framework/solid/reference/type-aliases/createfield.md b/docs/framework/solid/reference/type-aliases/createfield.md index 3c91dcf69..6ee4c533f 100644 --- a/docs/framework/solid/reference/type-aliases/createfield.md +++ b/docs/framework/solid/reference/type-aliases/createfield.md @@ -3,35 +3,59 @@ id: CreateField title: CreateField --- -# Type Alias: CreateField()\ +# Type Alias: CreateField()\ ```ts -type CreateField = (opts) => () => FieldApi & SolidFieldApi; +type CreateField = (opts) => () => FieldApi & SolidFieldApi; ``` -Defined in: [packages/solid-form/src/createField.tsx:29](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L29) +Defined in: [packages/solid-form/src/createField.tsx:47](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L47) ## Type Parameters • **TParentData** -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Type Parameters • **TName** *extends* `DeepKeys`\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> = `DeepValue`\<`TParentData`, `TName`\> +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> ## Parameters ### opts -() => `object` & `Omit`\<`CreateFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +() => `object` & `Omit`\<`CreateFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>, `"form"`\> ## Returns @@ -39,4 +63,4 @@ Defined in: [packages/solid-form/src/createField.tsx:29](https://github.com/TanS ### Returns -`FieldApi`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> & `SolidFieldApi`\<`TParentData`, `TFormValidator`\> +`FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> & `SolidFieldApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> diff --git a/docs/framework/solid/reference/type-aliases/fieldcomponent.md b/docs/framework/solid/reference/type-aliases/fieldcomponent.md index d0464a4ea..0199395e6 100644 --- a/docs/framework/solid/reference/type-aliases/fieldcomponent.md +++ b/docs/framework/solid/reference/type-aliases/fieldcomponent.md @@ -3,32 +3,56 @@ id: FieldComponent title: FieldComponent --- -# Type Alias: FieldComponent()\ +# Type Alias: FieldComponent()\ ```ts -type FieldComponent = ({ +type FieldComponent = ({ children, ...fieldOptions }) => JSXElement; ``` -Defined in: [packages/solid-form/src/createField.tsx:171](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L171) +Defined in: [packages/solid-form/src/createField.tsx:407](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L407) ## Type Parameters • **TParentData** -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Type Parameters • **TName** *extends* `DeepKeys`\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> = `DeepValue`\<`TParentData`, `TName`\> +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> ## Parameters @@ -37,7 +61,7 @@ Defined in: [packages/solid-form/src/createField.tsx:171](https://github.com/Tan ...fieldOptions \} -`Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +`Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>, `"form"`\> ## Returns diff --git a/docs/framework/vue/guides/basic-concepts.md b/docs/framework/vue/guides/basic-concepts.md index 86a8a90f9..1dc101e30 100644 --- a/docs/framework/vue/guides/basic-concepts.md +++ b/docs/framework/vue/guides/basic-concepts.md @@ -12,12 +12,12 @@ You can create options for your form so that it can be shared between multiple f Example: ```ts -const formOpts = formOptions({ +const formOpts = formOptions({ defaultValues: { firstName: '', lastName: '', hobbies: [], - }, + } as Person, }) ``` @@ -38,7 +38,7 @@ const form = useForm({ You may also create a form instance without using `formOptions` by using the standalone `useForm` API: ```ts -const form = useForm({ +const form = useForm({ onSubmit: async ({ value }) => { // Do something with form data console.log(value) @@ -47,7 +47,7 @@ const form = useForm({ firstName: '', lastName: '', hobbies: [], - }, + } as Person, }) ``` diff --git a/docs/framework/vue/guides/validation.md b/docs/framework/vue/guides/validation.md index beb3f7504..9de37e064 100644 --- a/docs/framework/vue/guides/validation.md +++ b/docs/framework/vue/guides/validation.md @@ -143,6 +143,26 @@ Or use the `errorMap` property to access the specific error you're looking for: ``` +It's worth mentioning that our `errors` array and the `errorMap` matches the types returned by the validators. This means that: + +```vue + + + +``` + + ## Validation at field level vs at form level As shown above, each `` accepts its own validation rules via the `onChange`, `onBlur` etc... callbacks. It is also possible to define validation rules at the form level (as opposed to field by field) by passing similar callbacks to the `useForm()` function. @@ -392,47 +412,6 @@ Async validations on form and field level are supported as well: ``` -### Other Schema Libraries - -We also support [Yup](https://github.com/jquense/yup) through an official adapter: - -```bash -$ npm install @tanstack/yup-form-adapter yup -``` - -Once done, we can add the adapter to the `validator` property on the form or field: - -```vue - - - -``` - ## Preventing invalid forms from being submitted The `onChange`, `onBlur` etc... callbacks are also run when the form is submitted and the submission is blocked if the form is invalid. diff --git a/docs/framework/vue/quick-start.md b/docs/framework/vue/quick-start.md index 5b3648d85..5b719ddd2 100644 --- a/docs/framework/vue/quick-start.md +++ b/docs/framework/vue/quick-start.md @@ -3,12 +3,6 @@ id: quick-start title: Quick Start --- -> There is a bug in Vue's TypeScript support that's impacting our types that you'll likely run into: -> -> https://github.com/vuejs/language-tools/issues/3782 -> -> Please give it a thumbs up, but _do not reply with comments such as "+1" or "When will this be fixed?", as such comments are unhelpful and rude_. - The bare minimum to get started with TanStack Form is to create a form and add a field. Keep in mind that this example does not include any validation or error handling... yet. ```vue diff --git a/docs/framework/vue/reference/functions/usefield.md b/docs/framework/vue/reference/functions/usefield.md index 2f06fddb5..ebb68ccfd 100644 --- a/docs/framework/vue/reference/functions/usefield.md +++ b/docs/framework/vue/reference/functions/usefield.md @@ -6,10 +6,10 @@ title: useField # Function: useField() ```ts -function useField(opts): object +function useField(opts): object ``` -Defined in: [packages/vue-form/src/useField.tsx:49](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L49) +Defined in: [packages/vue-form/src/useField.tsx:291](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L291) ## Type Parameters @@ -17,19 +17,43 @@ Defined in: [packages/vue-form/src/useField.tsx:49](https://github.com/TanStack/ • **TName** *extends* `string` \| `number` -• **TFieldValidator** *extends* - \| `undefined` - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> = `undefined` +• **TData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TParentData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** = `DeepValue`\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Parameters ### opts -`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +`UseFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> ## Returns @@ -38,11 +62,11 @@ Defined in: [packages/vue-form/src/useField.tsx:49](https://github.com/TanStack/ ### api ```ts -readonly api: FieldApi & VueFieldApi = fieldApi; +readonly api: FieldApi & VueFieldApi = fieldApi; ``` ### state ```ts -readonly state: Readonly, FieldState>> = fieldState; +readonly state: Readonly, FieldState>> = fieldState; ``` diff --git a/docs/framework/vue/reference/functions/useform.md b/docs/framework/vue/reference/functions/useform.md index 2d67b6719..a061b613f 100644 --- a/docs/framework/vue/reference/functions/useform.md +++ b/docs/framework/vue/reference/functions/useform.md @@ -6,23 +6,37 @@ title: useForm # Function: useForm() ```ts -function useForm(opts?): FormApi & VueFormApi +function useForm(opts?): FormApi & VueFormApi ``` -Defined in: [packages/vue-form/src/useForm.tsx:30](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L30) +Defined in: [packages/vue-form/src/useForm.tsx:192](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L192) ## Type Parameters -• **TFormData** +• **TParentData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TFormData`, `unknown`\> = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Parameters ### opts? -`FormOptions`\<`TFormData`, `TFormValidator`\> +`FormOptions`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> ## Returns -`FormApi`\<`TFormData`, `TFormValidator`\> & [`VueFormApi`](../interfaces/vueformapi.md)\<`TFormData`, `TFormValidator`\> +`FormApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> & [`VueFormApi`](../interfaces/vueformapi.md)\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> diff --git a/docs/framework/vue/reference/functions/usestore.md b/docs/framework/vue/reference/functions/usestore.md index 60c4f752a..2967ed2cc 100644 --- a/docs/framework/vue/reference/functions/usestore.md +++ b/docs/framework/vue/reference/functions/usestore.md @@ -8,10 +8,10 @@ title: useStore ## Call Signature ```ts -function useStore(store, selector?): Readonly> +function useStore(store, selector?): Readonly> ``` -Defined in: node\_modules/.pnpm/@tanstack+vue-store@0.7.0\_vue@3.5.12\_typescript@5.7.2\_/node\_modules/@tanstack/vue-store/dist/esm/index.d.ts:8 +Defined in: node\_modules/.pnpm/@tanstack+vue-store@0.7.0\_vue@3.5.13\_typescript@5.7.2\_/node\_modules/@tanstack/vue-store/dist/esm/index.d.ts:8 ### Type Parameters @@ -31,15 +31,15 @@ Defined in: node\_modules/.pnpm/@tanstack+vue-store@0.7.0\_vue@3.5.12\_typescrip ### Returns -`Readonly`\<`Ref`\<`TSelected`\>\> +`Readonly`\<`Ref`\<`TSelected`, `TSelected`\>\> ## Call Signature ```ts -function useStore(store, selector?): Readonly> +function useStore(store, selector?): Readonly> ``` -Defined in: node\_modules/.pnpm/@tanstack+vue-store@0.7.0\_vue@3.5.12\_typescript@5.7.2\_/node\_modules/@tanstack/vue-store/dist/esm/index.d.ts:9 +Defined in: node\_modules/.pnpm/@tanstack+vue-store@0.7.0\_vue@3.5.13\_typescript@5.7.2\_/node\_modules/@tanstack/vue-store/dist/esm/index.d.ts:9 ### Type Parameters @@ -59,4 +59,4 @@ Defined in: node\_modules/.pnpm/@tanstack+vue-store@0.7.0\_vue@3.5.12\_typescrip ### Returns -`Readonly`\<`Ref`\<`TSelected`\>\> +`Readonly`\<`Ref`\<`TSelected`, `TSelected`\>\> diff --git a/docs/framework/vue/reference/index.md b/docs/framework/vue/reference/index.md index 27abe16df..a265548af 100644 --- a/docs/framework/vue/reference/index.md +++ b/docs/framework/vue/reference/index.md @@ -13,6 +13,7 @@ title: "@tanstack/vue-form" ## Type Aliases - [FieldComponent](type-aliases/fieldcomponent.md) +- [FieldComponentProps](type-aliases/fieldcomponentprops.md) - [UseField](type-aliases/usefield.md) ## Variables diff --git a/docs/framework/vue/reference/interfaces/vuefieldapi.md b/docs/framework/vue/reference/interfaces/vuefieldapi.md index 5b638938c..7ac1e82d8 100644 --- a/docs/framework/vue/reference/interfaces/vuefieldapi.md +++ b/docs/framework/vue/reference/interfaces/vuefieldapi.md @@ -3,22 +3,36 @@ id: VueFieldApi title: VueFieldApi --- -# Interface: VueFieldApi\ +# Interface: VueFieldApi\ -Defined in: [packages/vue-form/src/useField.tsx:8](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L8) +Defined in: [packages/vue-form/src/useField.tsx:159](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L159) ## Type Parameters • **TParentData** -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Properties ### Field ```ts -Field: FieldComponent; +Field: FieldComponent; ``` -Defined in: [packages/vue-form/src/useField.tsx:14](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L14) +Defined in: [packages/vue-form/src/useField.tsx:170](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L170) diff --git a/docs/framework/vue/reference/interfaces/vueformapi.md b/docs/framework/vue/reference/interfaces/vueformapi.md index 9cd097244..ad948871f 100644 --- a/docs/framework/vue/reference/interfaces/vueformapi.md +++ b/docs/framework/vue/reference/interfaces/vueformapi.md @@ -3,67 +3,59 @@ id: VueFormApi title: VueFormApi --- -# Interface: VueFormApi\ +# Interface: VueFormApi\ -Defined in: [packages/vue-form/src/useForm.tsx:10](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L10) +Defined in: [packages/vue-form/src/useForm.tsx:115](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L115) ## Type Parameters -• **TFormData** +• **TParentData** -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> -## Properties - -### Field +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> -```ts -Field: FieldComponent; -``` +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> -Defined in: [packages/vue-form/src/useForm.tsx:14](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L14) +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> -*** +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> -### Subscribe() +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> -```ts -Subscribe: (props, context) => any; -``` - -Defined in: [packages/vue-form/src/useForm.tsx:19](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L19) - -#### Type Parameters +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> -• **TSelected** = `FormState`\<`TFormData`\> +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> -#### Parameters +## Properties -##### props +### Field -###### selector +```ts +Field: FieldComponent; +``` -(`state`) => `TSelected` +Defined in: [packages/vue-form/src/useForm.tsx:126](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L126) -##### context +*** -`SetupContext`\<`EmitsOptions`, `SlotsType`\<\{ - `default`: `FormState`\<`TFormData`\>; - \}\>\> +### Subscribe -#### Returns +```ts +Subscribe: SubscribeComponent; +``` -`any` +Defined in: [packages/vue-form/src/useForm.tsx:179](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L179) *** ### useField ```ts -useField: UseField; +useField: UseField; ``` -Defined in: [packages/vue-form/src/useForm.tsx:15](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L15) +Defined in: [packages/vue-form/src/useForm.tsx:137](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L137) *** @@ -73,11 +65,11 @@ Defined in: [packages/vue-form/src/useForm.tsx:15](https://github.com/TanStack/f useStore: (selector?) => Readonly>; ``` -Defined in: [packages/vue-form/src/useForm.tsx:16](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L16) +Defined in: [packages/vue-form/src/useForm.tsx:148](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L148) #### Type Parameters -• **TSelected** = `FormState`\<`TFormData`\> +• **TSelected** = `FormState`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> #### Parameters diff --git a/docs/framework/vue/reference/type-aliases/fieldcomponent.md b/docs/framework/vue/reference/type-aliases/fieldcomponent.md index 15179546d..ec31cb22f 100644 --- a/docs/framework/vue/reference/type-aliases/fieldcomponent.md +++ b/docs/framework/vue/reference/type-aliases/fieldcomponent.md @@ -3,45 +3,50 @@ id: FieldComponent title: FieldComponent --- -# Type Alias: FieldComponent()\ +# Type Alias: FieldComponent()\ ```ts -type FieldComponent = (fieldOptions, context) => any; +type FieldComponent = (props) => CreateComponentPublicInstanceWithMixins, "form">, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, PublicProps, {}, false, {}, SlotsType<{ + default: { + field: FieldApi; + state: FieldApi["state"]; + }; +}>>; ``` -Defined in: [packages/vue-form/src/useField.tsx:117](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L117) +Defined in: [packages/vue-form/src/useField.tsx:24](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L24) ## Type Parameters • **TParentData** -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> -## Type Parameters +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> -• **TName** *extends* `DeepKeys`\<`TParentData`\> +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> -• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> = `DeepValue`\<`TParentData`, `TName`\> +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Parameters -### fieldOptions +### props -`Omit`\<`FieldComponentProps`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +`Omit`\<[`FieldComponentProps`](fieldcomponentprops.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>, `"form"`\> & `EmitsToProps`\<`EmitsOptions`\> & `PublicProps` -### context +## Returns -`SetupContext`\<\{\}, `SlotsType`\<\{ +`CreateComponentPublicInstanceWithMixins`\<`Omit`\<[`FieldComponentProps`](fieldcomponentprops.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>, `"form"`\>, \{\}, \{\}, \{\}, \{\}, `ComponentOptionsMixin`, `ComponentOptionsMixin`, `EmitsOptions`, `PublicProps`, \{\}, `false`, \{\}, `SlotsType`\<\{ `default`: \{ - `field`: `FieldApi`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>; - `state`: `FieldApi`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>\[`"state"`\]; + `field`: `FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>; + `state`: `FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>\[`"state"`\]; \}; \}\>\> - -## Returns - -`any` diff --git a/docs/framework/vue/reference/type-aliases/fieldcomponentprops.md b/docs/framework/vue/reference/type-aliases/fieldcomponentprops.md new file mode 100644 index 000000000..54c77f8a9 --- /dev/null +++ b/docs/framework/vue/reference/type-aliases/fieldcomponentprops.md @@ -0,0 +1,50 @@ +--- +id: FieldComponentProps +title: FieldComponentProps +--- + +# Type Alias: FieldComponentProps\ + +```ts +type FieldComponentProps = UseFieldOptions; +``` + +Defined in: [packages/vue-form/src/useField.tsx:385](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L385) + +## Type Parameters + +• **TParentData** + +• **TName** *extends* `DeepKeys`\<`TParentData`\> + +• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> diff --git a/docs/framework/vue/reference/type-aliases/usefield.md b/docs/framework/vue/reference/type-aliases/usefield.md index 5fb33846e..f54c91d46 100644 --- a/docs/framework/vue/reference/type-aliases/usefield.md +++ b/docs/framework/vue/reference/type-aliases/usefield.md @@ -3,35 +3,59 @@ id: UseField title: UseField --- -# Type Alias: UseField()\ +# Type Alias: UseField()\ ```ts -type UseField = (opts) => object; +type UseField = (opts) => object; ``` -Defined in: [packages/vue-form/src/useField.tsx:17](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L17) +Defined in: [packages/vue-form/src/useField.tsx:183](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L183) ## Type Parameters • **TParentData** -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Type Parameters • **TName** *extends* `DeepKeys`\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<`DeepValue`\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* `DeepValue`\<`TParentData`, `TName`\> = `DeepValue`\<`TParentData`, `TName`\> +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> ## Parameters ### opts -`Omit`\<`UseFieldOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\>, `"form"`\> +`Omit`\<`UseFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\>, `"form"`\> ## Returns @@ -40,11 +64,11 @@ Defined in: [packages/vue-form/src/useField.tsx:17](https://github.com/TanStack/ ### api ```ts -api: FieldApi & VueFieldApi; +api: FieldApi & VueFieldApi; ``` ### state ```ts -state: Readonly["state"]>>; +state: Readonly["state"]>>; ``` diff --git a/docs/framework/vue/reference/variables/field.md b/docs/framework/vue/reference/variables/field.md index 8b9c3092d..99d3585ad 100644 --- a/docs/framework/vue/reference/variables/field.md +++ b/docs/framework/vue/reference/variables/field.md @@ -6,17 +6,17 @@ title: Field # Variable: Field() ```ts -const Field: (props) => CreateComponentPublicInstanceWithMixins & object & {} | {}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, PublicProps, {}, false, {}, {}, {}, {}, string, {}, any, ComponentProvideOptions, OptionTypesType<{}, {}, {}, {}, {}, {}>, object & FieldApiOptions & { mode?: "value" | ... 1 more ... | undefined; } & ({ ...; } | { ...; }), {}, {}, {}, {}, {}>; +const Field: (props) => CreateComponentPublicInstanceWithMixins & object & {} | {}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, PublicProps, {}, false, {}, {}>; ``` -Defined in: [packages/vue-form/src/useField.tsx:162](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L162) +Defined in: [packages/vue-form/src/useField.tsx:431](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L431) ## Parameters ### props -FieldApiOptions\ & \{ mode?: "value" \| ... 1 more ... \| undefined; \} & (\{ ...; \} \| \{ ...; \}) & `VNodeProps` & `AllowedComponentProps` & `ComponentCustomProps` +FieldApiOptions\ & \{ ...; \} & (\{ ...; \} \| \{ ...; \}) & `VNodeProps` & `AllowedComponentProps` & `ComponentCustomProps` ## Returns -`CreateComponentPublicInstanceWithMixins`\<`FieldApiOptions`\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> & `object` & \{\} \| \{\}, \{\}, \{\}, \{\}, \{\}, `ComponentOptionsMixin`, `ComponentOptionsMixin`, `EmitsOptions`, `PublicProps`, \{\}, `false`, \{\}, \{\}, \{\}, \{\}, `string`, \{\}, `any`, `ComponentProvideOptions`, `OptionTypesType`\<\{\}, \{\}, \{\}, \{\}, \{\}, \{\}\>, `object` & FieldApiOptions\ & \{ mode?: "value" \| ... 1 more ... \| undefined; \} & (\{ ...; \} \| \{ ...; \}), \{\}, \{\}, \{\}, \{\}, \{\}\> +`CreateComponentPublicInstanceWithMixins`\<`FieldApiOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> & `object` & \{\} \| \{\}, \{\}, \{\}, \{\}, \{\}, `ComponentOptionsMixin`, `ComponentOptionsMixin`, `EmitsOptions`, `PublicProps`, \{\}, `false`, \{\}, \{\}\> diff --git a/docs/overview.md b/docs/overview.md index a0506af9d..a5620be86 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -33,9 +33,9 @@ In the example below, you can see TanStack Form in action with the React framewo import * as React from 'react' import { createRoot } from 'react-dom/client' import { useForm } from '@tanstack/react-form' -import type { FieldApi } from '@tanstack/react-form' +import type { AnyFieldApi } from '@tanstack/react-form' -function FieldInfo({ field }: { field: FieldApi }) { +function FieldInfo({ field }: { field: AnyFieldApi }) { return ( <> {field.state.meta.isTouched && field.state.meta.errors.length ? ( diff --git a/docs/reference/classes/fieldapi.md b/docs/reference/classes/fieldapi.md index b20740351..034c060a4 100644 --- a/docs/reference/classes/fieldapi.md +++ b/docs/reference/classes/fieldapi.md @@ -3,9 +3,9 @@ id: FieldApi title: FieldApi --- -# Class: FieldApi\ +# Class: FieldApi\ -Defined in: [packages/form-core/src/FieldApi.ts:427](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L427) +Defined in: [packages/form-core/src/FieldApi.ts:832](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L832) A class representing the API for managing a form field. @@ -21,23 +21,47 @@ the `new FieldApi` constructor. • **TName** *extends* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<[`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> = [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Constructors ### new FieldApi() ```ts -new FieldApi(opts): FieldApi +new FieldApi(opts): FieldApi ``` -Defined in: [packages/form-core/src/FieldApi.ts:477](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L477) +Defined in: [packages/form-core/src/FieldApi.ts:943](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L943) Initializes a new `FieldApi` instance. @@ -45,21 +69,21 @@ Initializes a new `FieldApi` instance. ##### opts -[`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +[`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> #### Returns -[`FieldApi`](fieldapi.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +[`FieldApi`](fieldapi.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> ## Properties ### form ```ts -form: FormApi; +form: FormApi; ``` -Defined in: [packages/form-core/src/FieldApi.ts:441](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L441) +Defined in: [packages/form-core/src/FieldApi.ts:861](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L861) A reference to the form API instance. @@ -71,7 +95,7 @@ A reference to the form API instance. name: unknown extends TParentData ? string : TParentData extends readonly any[] & IsTuple ? PrefixTupleAccessor, AllowedIndexes, never>, []> : TParentData extends any[] ? PrefixArrayAccessor, [any]> : TParentData extends Date ? never : TParentData extends object ? PrefixObjectAccessor, []> : TParentData extends string | number | bigint | boolean ? "" : never; ``` -Defined in: [packages/form-core/src/FieldApi.ts:451](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L451) +Defined in: [packages/form-core/src/FieldApi.ts:884](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L884) The field name. @@ -80,10 +104,10 @@ The field name. ### options ```ts -options: FieldApiOptions; +options: FieldApiOptions; ``` -Defined in: [packages/form-core/src/FieldApi.ts:455](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L455) +Defined in: [packages/form-core/src/FieldApi.ts:888](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L888) The field options. @@ -92,10 +116,10 @@ The field options. ### store ```ts -store: Derived>; +store: Derived>; ``` -Defined in: [packages/form-core/src/FieldApi.ts:465](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L465) +Defined in: [packages/form-core/src/FieldApi.ts:911](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L911) The field state store. @@ -107,7 +131,7 @@ The field state store. timeoutIds: Record; ``` -Defined in: [packages/form-core/src/FieldApi.ts:472](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L472) +Defined in: [packages/form-core/src/FieldApi.ts:938](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L938) ## Accessors @@ -116,46 +140,46 @@ Defined in: [packages/form-core/src/FieldApi.ts:472](https://github.com/TanStack #### Get Signature ```ts -get state(): FieldState +get state(): FieldState ``` -Defined in: [packages/form-core/src/FieldApi.ts:469](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L469) +Defined in: [packages/form-core/src/FieldApi.ts:935](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L935) The current field state. ##### Returns -[`FieldState`](../type-aliases/fieldstate.md)\<`TData`\> +[`FieldState`](../type-aliases/fieldstate.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`\> ## Methods ### getInfo() ```ts -getInfo(): FieldInfo +getInfo(): FieldInfo ``` -Defined in: [packages/form-core/src/FieldApi.ts:673](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L673) +Defined in: [packages/form-core/src/FieldApi.ts:1189](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1189) Gets the field information object. #### Returns -[`FieldInfo`](../type-aliases/fieldinfo.md)\<`TParentData`, `TFormValidator`\> +[`FieldInfo`](../type-aliases/fieldinfo.md)\<`TParentData`\> *** ### getMeta() ```ts -getMeta(): FieldMeta +getMeta(): FieldMeta ``` -Defined in: [packages/form-core/src/FieldApi.ts:662](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L662) +Defined in: [packages/form-core/src/FieldApi.ts:1157](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1157) #### Returns -[`FieldMeta`](../type-aliases/fieldmeta.md) +[`FieldMeta`](../type-aliases/fieldmeta.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`\> *** @@ -165,7 +189,7 @@ Defined in: [packages/form-core/src/FieldApi.ts:662](https://github.com/TanStack getValue(): TData ``` -Defined in: [packages/form-core/src/FieldApi.ts:644](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L644) +Defined in: [packages/form-core/src/FieldApi.ts:1139](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1139) Gets the current field value. @@ -185,7 +209,7 @@ Use `field.state.value` instead. handleBlur(): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1030](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1030) +Defined in: [packages/form-core/src/FieldApi.ts:1561](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1561) Handles the blur event. @@ -201,7 +225,7 @@ Handles the blur event. handleChange(updater): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1023](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1023) +Defined in: [packages/form-core/src/FieldApi.ts:1554](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1554) Handles the change event. @@ -226,7 +250,7 @@ insertValue( opts?): Promise ``` -Defined in: [packages/form-core/src/FieldApi.ts:686](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L686) +Defined in: [packages/form-core/src/FieldApi.ts:1202](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1202) Inserts a value at the specified index, shifting the subsequent values to the right. @@ -256,7 +280,7 @@ Inserts a value at the specified index, shifting the subsequent values to the ri mount(): () => void ``` -Defined in: [packages/form-core/src/FieldApi.ts:567](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L567) +Defined in: [packages/form-core/src/FieldApi.ts:1046](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1046) Mounts the field instance to the form. @@ -279,7 +303,7 @@ moveValue( opts?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:716](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L716) +Defined in: [packages/form-core/src/FieldApi.ts:1232](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1232) Moves the value at the first specified index to the second specified index. @@ -309,7 +333,7 @@ Moves the value at the first specified index to the second specified index. pushValue(value, opts?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:678](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L678) +Defined in: [packages/form-core/src/FieldApi.ts:1194](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1194) Pushes a new value to the field. @@ -335,7 +359,7 @@ Pushes a new value to the field. removeValue(index, opts?): Promise ``` -Defined in: [packages/form-core/src/FieldApi.ts:704](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L704) +Defined in: [packages/form-core/src/FieldApi.ts:1220](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1220) Removes a value at the specified index. @@ -364,7 +388,7 @@ replaceValue( opts?): Promise ``` -Defined in: [packages/form-core/src/FieldApi.ts:695](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L695) +Defined in: [packages/form-core/src/FieldApi.ts:1211](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1211) Replaces a value at the specified index. @@ -394,7 +418,7 @@ Replaces a value at the specified index. setErrorMap(errorMap): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:1050](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1050) +Defined in: [packages/form-core/src/FieldApi.ts:1581](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1581) Updates the field's errorMap @@ -416,7 +440,7 @@ Updates the field's errorMap setMeta(updater): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:667](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L667) +Defined in: [packages/form-core/src/FieldApi.ts:1162](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1162) Sets the field metadata. @@ -424,7 +448,7 @@ Sets the field metadata. ##### updater -[`Updater`](../type-aliases/updater.md)\<[`FieldMeta`](../type-aliases/fieldmeta.md)\> +[`Updater`](../type-aliases/updater.md)\<[`FieldMeta`](../type-aliases/fieldmeta.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`\>\> #### Returns @@ -438,7 +462,7 @@ Sets the field metadata. setValue(updater, options?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:651](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L651) +Defined in: [packages/form-core/src/FieldApi.ts:1146](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1146) Sets the field value and run the `change` validator. @@ -467,7 +491,7 @@ swapValues( opts?): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:710](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L710) +Defined in: [packages/form-core/src/FieldApi.ts:1226](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1226) Swaps the values at the specified indices. @@ -497,7 +521,7 @@ Swaps the values at the specified indices. update(opts): void ``` -Defined in: [packages/form-core/src/FieldApi.ts:606](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L606) +Defined in: [packages/form-core/src/FieldApi.ts:1088](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1088) Updates the field instance with new options. @@ -505,7 +529,7 @@ Updates the field instance with new options. ##### opts -[`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +[`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`\> #### Returns @@ -516,12 +540,10 @@ Updates the field instance with new options. ### validate() ```ts -validate(cause, opts?): - | ValidationError[] -| Promise +validate(cause, opts?): unknown[] | Promise ``` -Defined in: [packages/form-core/src/FieldApi.ts:990](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L990) +Defined in: [packages/form-core/src/FieldApi.ts:1521](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1521) Validates the field value. @@ -533,11 +555,10 @@ Validates the field value. ##### opts? -###### skipFormValidation +###### skipFormValidation? `boolean` #### Returns - \| [`ValidationError`](../type-aliases/validationerror.md)[] - \| `Promise`\<[`ValidationError`](../type-aliases/validationerror.md)[]\> +`unknown`[] \| `Promise`\<`unknown`[]\> diff --git a/docs/reference/classes/formapi.md b/docs/reference/classes/formapi.md index 2b6275dba..f0b3bec34 100644 --- a/docs/reference/classes/formapi.md +++ b/docs/reference/classes/formapi.md @@ -3,9 +3,9 @@ id: FormApi title: FormApi --- -# Class: FormApi\ +# Class: FormApi\ -Defined in: [packages/form-core/src/FormApi.ts:362](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L362) +Defined in: [packages/form-core/src/FormApi.ts:622](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L622) A class representing the Form API. It handles the logic and interactions with the form state. @@ -17,17 +17,31 @@ However, if you need to create a new instance manually, you can do so by calling • **TFormData** -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> ## Constructors ### new FormApi() ```ts -new FormApi(opts?): FormApi +new FormApi(opts?): FormApi ``` -Defined in: [packages/form-core/src/FormApi.ts:391](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L391) +Defined in: [packages/form-core/src/FormApi.ts:691](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L691) Constructs a new `FormApi` instance with the given form options. @@ -35,31 +49,31 @@ Constructs a new `FormApi` instance with the given form options. ##### opts? -[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> +[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> #### Returns -[`FormApi`](formapi.md)\<`TFormData`, `TFormValidator`\> +[`FormApi`](formapi.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ## Properties ### baseStore ```ts -baseStore: Store, (cb) => BaseFormState>; +baseStore: Store>; ``` -Defined in: [packages/form-core/src/FormApi.ts:370](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L370) +Defined in: [packages/form-core/src/FormApi.ts:647](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L647) *** ### fieldInfo ```ts -fieldInfo: Record ? PrefixTupleAccessor, AllowedIndexes, never>, []> : TFormData extends any[] ? PrefixArrayAccessor, [any]> : TFormData extends Date ? never : TFormData extends object ? PrefixObjectAccessor, []> : TFormData extends string | number | bigint | boolean ? "" : never, FieldInfo>; +fieldInfo: Record ? PrefixTupleAccessor, AllowedIndexes, never>, []> : TFormData extends any[] ? PrefixArrayAccessor, [any]> : TFormData extends Date ? never : TFormData extends object ? PrefixObjectAccessor, []> : TFormData extends string | number | bigint | boolean ? "" : never, FieldInfo>; ``` -Defined in: [packages/form-core/src/FormApi.ts:376](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L376) +Defined in: [packages/form-core/src/FormApi.ts:677](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L677) A record of field information for each field in the form. @@ -68,20 +82,20 @@ A record of field information for each field in the form. ### fieldMetaDerived ```ts -fieldMetaDerived: Derived ? PrefixTupleAccessor, AllowedIndexes, never>, []> : TFormData extends any[] ? PrefixArrayAccessor, [any]> : TFormData extends Date ? never : TFormData extends object ? PrefixObjectAccessor, []> : TFormData extends string | number | bigint | boolean ? "" : never, FieldMeta>>; +fieldMetaDerived: Derived ? PrefixTupleAccessor, AllowedIndexes, never>, []> : TFormData extends any[] ? PrefixArrayAccessor, [any]> : TFormData extends Date ? never : TFormData extends object ? PrefixObjectAccessor, []> : TFormData extends string | number | bigint | boolean ? "" : never, AnyFieldMeta>>; ``` -Defined in: [packages/form-core/src/FormApi.ts:371](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L371) +Defined in: [packages/form-core/src/FormApi.ts:660](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L660) *** ### options ```ts -options: FormOptions = {}; +options: FormOptions = {}; ``` -Defined in: [packages/form-core/src/FormApi.ts:369](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L369) +Defined in: [packages/form-core/src/FormApi.ts:636](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L636) The options for the form. @@ -90,10 +104,10 @@ The options for the form. ### store ```ts -store: Derived>; +store: Derived>; ``` -Defined in: [packages/form-core/src/FormApi.ts:372](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L372) +Defined in: [packages/form-core/src/FormApi.ts:661](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L661) ## Accessors @@ -102,14 +116,14 @@ Defined in: [packages/form-core/src/FormApi.ts:372](https://github.com/TanStack/ #### Get Signature ```ts -get state(): FormState +get state(): FormState ``` -Defined in: [packages/form-core/src/FormApi.ts:379](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L379) +Defined in: [packages/form-core/src/FormApi.ts:679](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L679) ##### Returns -[`FormState`](../type-aliases/formstate.md)\<`TFormData`\> +[`FormState`](../type-aliases/formstate.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ## Methods @@ -119,7 +133,7 @@ Defined in: [packages/form-core/src/FormApi.ts:379](https://github.com/TanStack/ deleteField(field): void ``` -Defined in: [packages/form-core/src/FormApi.ts:1240](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1240) +Defined in: [packages/form-core/src/FormApi.ts:1661](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1661) #### Type Parameters @@ -140,10 +154,10 @@ Defined in: [packages/form-core/src/FormApi.ts:1240](https://github.com/TanStack ### getFieldInfo() ```ts -getFieldInfo(field): FieldInfo +getFieldInfo(field): FieldInfo ``` -Defined in: [packages/form-core/src/FormApi.ts:1149](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1149) +Defined in: [packages/form-core/src/FormApi.ts:1570](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1570) Gets the field info of the specified field. @@ -159,17 +173,17 @@ Gets the field info of the specified field. #### Returns -[`FieldInfo`](../type-aliases/fieldinfo.md)\<`TFormData`, `TFormValidator`\> +[`FieldInfo`](../type-aliases/fieldinfo.md)\<`TFormData`\> *** ### getFieldMeta() ```ts -getFieldMeta(field): undefined | FieldMeta +getFieldMeta(field): undefined | AnyFieldMeta ``` -Defined in: [packages/form-core/src/FormApi.ts:1140](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1140) +Defined in: [packages/form-core/src/FormApi.ts:1561](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1561) Gets the metadata of the specified field. @@ -185,17 +199,17 @@ Gets the metadata of the specified field. #### Returns -`undefined` \| [`FieldMeta`](../type-aliases/fieldmeta.md) +`undefined` \| [`AnyFieldMeta`](../type-aliases/anyfieldmeta.md) *** ### getFieldValue() ```ts -getFieldValue(field): DeepValue> +getFieldValue(field): DeepValue ``` -Defined in: [packages/form-core/src/FormApi.ts:1133](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1133) +Defined in: [packages/form-core/src/FormApi.ts:1554](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1554) Gets the value of the specified field. @@ -211,7 +225,7 @@ Gets the value of the specified field. #### Returns -[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`, `IsNullable`\<`TFormData`\>\> +[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`\> *** @@ -221,7 +235,7 @@ Gets the value of the specified field. handleSubmit(): Promise ``` -Defined in: [packages/form-core/src/FormApi.ts:1064](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1064) +Defined in: [packages/form-core/src/FormApi.ts:1485](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1485) Handles the form submission, performs validation, and calls the appropriate onSubmit or onInvalidSubmit callbacks. @@ -241,7 +255,7 @@ insertFieldValue( opts?): Promise ``` -Defined in: [packages/form-core/src/FormApi.ts:1269](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1269) +Defined in: [packages/form-core/src/FormApi.ts:1690](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1690) #### Type Parameters @@ -277,7 +291,7 @@ Defined in: [packages/form-core/src/FormApi.ts:1269](https://github.com/TanStack mount(): () => void ``` -Defined in: [packages/form-core/src/FormApi.ts:639](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L639) +Defined in: [packages/form-core/src/FormApi.ts:989](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L989) #### Returns @@ -299,7 +313,7 @@ moveFieldValues( opts?): void ``` -Defined in: [packages/form-core/src/FormApi.ts:1398](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1398) +Defined in: [packages/form-core/src/FormApi.ts:1819](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1819) Moves the value at the first specified index to the second specified index within an array field. @@ -340,7 +354,7 @@ pushFieldValue( opts?): void ``` -Defined in: [packages/form-core/src/FormApi.ts:1254](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1254) +Defined in: [packages/form-core/src/FormApi.ts:1675](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1675) Pushes a value into an array field. @@ -377,7 +391,7 @@ removeFieldValue( opts?): Promise ``` -Defined in: [packages/form-core/src/FormApi.ts:1327](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1327) +Defined in: [packages/form-core/src/FormApi.ts:1748](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1748) Removes a value from an array field at the specified index. @@ -415,7 +429,7 @@ replaceFieldValue( opts?): Promise ``` -Defined in: [packages/form-core/src/FormApi.ts:1301](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1301) +Defined in: [packages/form-core/src/FormApi.ts:1722](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1722) Replaces a value into an array field at the specified index. @@ -453,7 +467,7 @@ Replaces a value into an array field at the specified index. reset(values?, opts?): void ``` -Defined in: [packages/form-core/src/FormApi.ts:702](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L702) +Defined in: [packages/form-core/src/FormApi.ts:1064](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1064) Resets the form state to the default values. If values are provided, the form will be reset to those values instead and the default values will be updated. @@ -470,7 +484,7 @@ Optional values to reset the form to. Optional options to control the reset behavior. -###### keepDefaultValues +###### keepDefaultValues? `boolean` @@ -483,10 +497,10 @@ Optional options to control the reset behavior. ### resetFieldMeta() ```ts -resetFieldMeta(fieldMeta): Record +resetFieldMeta(fieldMeta): Record ``` -Defined in: [packages/form-core/src/FormApi.ts:1186](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1186) +Defined in: [packages/form-core/src/FormApi.ts:1607](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1607) #### Type Parameters @@ -496,11 +510,11 @@ Defined in: [packages/form-core/src/FormApi.ts:1186](https://github.com/TanStack ##### fieldMeta -`Record`\<`TField`, [`FieldMeta`](../type-aliases/fieldmeta.md)\> +`Record`\<`TField`, [`AnyFieldMeta`](../type-aliases/anyfieldmeta.md)\> #### Returns -`Record`\<`TField`, [`FieldMeta`](../type-aliases/fieldmeta.md)\> +`Record`\<`TField`, [`AnyFieldMeta`](../type-aliases/anyfieldmeta.md)\> *** @@ -510,7 +524,7 @@ Defined in: [packages/form-core/src/FormApi.ts:1186](https://github.com/TanStack setErrorMap(errorMap): void ``` -Defined in: [packages/form-core/src/FormApi.ts:1425](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1425) +Defined in: [packages/form-core/src/FormApi.ts:1846](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1846) Updates the form's errorMap @@ -518,7 +532,7 @@ Updates the form's errorMap ##### errorMap -`ValidationErrorMap` +`ValidationErrorMap`\<`TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> #### Returns @@ -532,7 +546,7 @@ Updates the form's errorMap setFieldMeta(field, updater): void ``` -Defined in: [packages/form-core/src/FormApi.ts:1168](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1168) +Defined in: [packages/form-core/src/FormApi.ts:1589](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1589) Updates the metadata of the specified field. @@ -548,7 +562,7 @@ Updates the metadata of the specified field. ##### updater -[`Updater`](../type-aliases/updater.md)\<[`FieldMeta`](../type-aliases/fieldmeta.md)\> +[`Updater`](../type-aliases/updater.md)\<[`AnyFieldMeta`](../type-aliases/anyfieldmeta.md)\> #### Returns @@ -565,7 +579,7 @@ setFieldValue( opts?): void ``` -Defined in: [packages/form-core/src/FormApi.ts:1210](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1210) +Defined in: [packages/form-core/src/FormApi.ts:1631](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1631) Sets the value of the specified field and optionally updates the touched state. @@ -603,7 +617,7 @@ swapFieldValues( opts?): void ``` -Defined in: [packages/form-core/src/FormApi.ts:1369](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1369) +Defined in: [packages/form-core/src/FormApi.ts:1790](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1790) Swaps the values at the specified indices within an array field. @@ -641,7 +655,7 @@ Swaps the values at the specified indices within an array field. update(options?): void ``` -Defined in: [packages/form-core/src/FormApi.ts:656](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L656) +Defined in: [packages/form-core/src/FormApi.ts:1006](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1006) Updates the form options and form state. @@ -649,7 +663,7 @@ Updates the form options and form state. ##### options? -[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> +[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> #### Returns @@ -660,10 +674,10 @@ Updates the form options and form state. ### validateAllFields() ```ts -validateAllFields(cause): Promise +validateAllFields(cause): Promise ``` -Defined in: [packages/form-core/src/FormApi.ts:728](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L728) +Defined in: [packages/form-core/src/FormApi.ts:1090](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1090) Validates all fields using the correct handlers for a given validation cause. @@ -675,7 +689,7 @@ Validates all fields using the correct handlers for a given validation cause. #### Returns -`Promise`\<[`ValidationError`](../type-aliases/validationerror.md)[]\> +`Promise`\<`unknown`[]\> *** @@ -685,10 +699,10 @@ Validates all fields using the correct handlers for a given validation cause. validateArrayFieldsStartingFrom( field, index, -cause): Promise +cause): Promise ``` -Defined in: [packages/form-core/src/FormApi.ts:758](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L758) +Defined in: [packages/form-core/src/FormApi.ts:1120](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1120) Validates the children of a specified array in the form starting from a given index until the end using the correct handlers for a given validation type. @@ -712,19 +726,17 @@ Validates the children of a specified array in the form starting from a given in #### Returns -`Promise`\<[`ValidationError`](../type-aliases/validationerror.md)[]\> +`Promise`\<`unknown`[]\> *** ### validateField() ```ts -validateField(field, cause): - | ValidationError[] -| Promise +validateField(field, cause): unknown[] | Promise ``` -Defined in: [packages/form-core/src/FormApi.ts:797](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L797) +Defined in: [packages/form-core/src/FormApi.ts:1159](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1159) Validates a specified field in the form using the correct handlers for a given validation type. @@ -744,5 +756,4 @@ Validates a specified field in the form using the correct handlers for a given v #### Returns - \| [`ValidationError`](../type-aliases/validationerror.md)[] - \| `Promise`\<[`ValidationError`](../type-aliases/validationerror.md)[]\> +`unknown`[] \| `Promise`\<`unknown`[]\> diff --git a/docs/reference/functions/formoptions.md b/docs/reference/functions/formoptions.md index 9b3ff5ea1..606254e44 100644 --- a/docs/reference/functions/formoptions.md +++ b/docs/reference/functions/formoptions.md @@ -6,26 +6,40 @@ title: formOptions # Function: formOptions() ```ts -function formOptions(defaultOpts?): +function formOptions(defaultOpts?): | undefined -| FormOptions +| FormOptions ``` -Defined in: [packages/form-core/src/formOptions.ts:4](https://github.com/TanStack/form/blob/main/packages/form-core/src/formOptions.ts#L4) +Defined in: [packages/form-core/src/formOptions.ts:7](https://github.com/TanStack/form/blob/main/packages/form-core/src/formOptions.ts#L7) ## Type Parameters • **TFormData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TFormData`, `unknown`\> = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> ## Parameters ### defaultOpts? -[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> +[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ## Returns \| `undefined` - \| [`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TFormValidator`\> + \| [`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> diff --git a/docs/reference/functions/isglobalformvalidationerror.md b/docs/reference/functions/isglobalformvalidationerror.md new file mode 100644 index 000000000..a771692c4 --- /dev/null +++ b/docs/reference/functions/isglobalformvalidationerror.md @@ -0,0 +1,22 @@ +--- +id: isGlobalFormValidationError +title: isGlobalFormValidationError +--- + +# Function: isGlobalFormValidationError() + +```ts +function isGlobalFormValidationError(error): error is GlobalFormValidationError +``` + +Defined in: [packages/form-core/src/utils.ts:328](https://github.com/TanStack/form/blob/main/packages/form-core/src/utils.ts#L328) + +## Parameters + +### error + +`unknown` + +## Returns + +`error is GlobalFormValidationError` diff --git a/docs/reference/functions/isstandardschemavalidator.md b/docs/reference/functions/isstandardschemavalidator.md index b3f4a6001..4aeab95bd 100644 --- a/docs/reference/functions/isstandardschemavalidator.md +++ b/docs/reference/functions/isstandardschemavalidator.md @@ -9,7 +9,7 @@ title: isStandardSchemaValidator function isStandardSchemaValidator(validator): validator is StandardSchemaV1 ``` -Defined in: [packages/form-core/src/standardSchemaValidator.ts:86](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L86) +Defined in: [packages/form-core/src/standardSchemaValidator.ts:75](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L75) ## Parameters diff --git a/docs/reference/functions/mergeform.md b/docs/reference/functions/mergeform.md index ca5facccc..f5bbb1858 100644 --- a/docs/reference/functions/mergeform.md +++ b/docs/reference/functions/mergeform.md @@ -6,27 +6,25 @@ title: mergeForm # Function: mergeForm() ```ts -function mergeForm(baseForm, state): FormApi, NoInfer> +function mergeForm(baseForm, state): FormApi, any, any, any, any, any, any, any, any> ``` -Defined in: [packages/form-core/src/mergeForm.ts:75](https://github.com/TanStack/form/blob/main/packages/form-core/src/mergeForm.ts#L75) +Defined in: [packages/form-core/src/mergeForm.ts:74](https://github.com/TanStack/form/blob/main/packages/form-core/src/mergeForm.ts#L74) ## Type Parameters • **TFormData** -• **TFormValidator** *extends* `undefined` \| `Validator`\<`TFormData`, `unknown`\> = `undefined` - ## Parameters ### baseForm -[`FormApi`](../classes/formapi.md)\<`NoInfer`\<`TFormData`\>, `NoInfer`\<`TFormValidator`\>\> +[`FormApi`](../classes/formapi.md)\<`NoInfer`\<`TFormData`\>, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\> ### state -`Partial`\<[`FormState`](../type-aliases/formstate.md)\<`TFormData`\>\> +`Partial`\<[`FormState`](../type-aliases/formstate.md)\<`TFormData`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\>\> ## Returns -[`FormApi`](../classes/formapi.md)\<`NoInfer`\<`TFormData`\>, `NoInfer`\<`TFormValidator`\>\> +[`FormApi`](../classes/formapi.md)\<`NoInfer`\<`TFormData`\>, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\> diff --git a/docs/reference/functions/shallow.md b/docs/reference/functions/shallow.md index 344e80850..34c641189 100644 --- a/docs/reference/functions/shallow.md +++ b/docs/reference/functions/shallow.md @@ -9,7 +9,7 @@ title: shallow function shallow(objA, objB): boolean ``` -Defined in: [packages/form-core/src/utils.ts:328](https://github.com/TanStack/form/blob/main/packages/form-core/src/utils.ts#L328) +Defined in: [packages/form-core/src/utils.ts:334](https://github.com/TanStack/form/blob/main/packages/form-core/src/utils.ts#L334) ## Type Parameters diff --git a/docs/reference/functions/standardschemavalidator.md b/docs/reference/functions/standardschemavalidator.md deleted file mode 100644 index 22c05433c..000000000 --- a/docs/reference/functions/standardschemavalidator.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -id: standardSchemaValidator -title: standardSchemaValidator ---- - -# Function: standardSchemaValidator() - -```ts -function standardSchemaValidator(params): Validator> -``` - -Defined in: [packages/form-core/src/standardSchemaValidator.ts:48](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L48) - -## Parameters - -### params - -`Params` = `{}` - -## Returns - -`Validator`\<`unknown`, [`StandardSchemaV1`](../type-aliases/standardschemav1.md)\<`any`, `any`\>\> diff --git a/docs/reference/index.md b/docs/reference/index.md index 5f9cb9ddf..545c5b5b0 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -18,9 +18,16 @@ title: "@tanstack/form-core" - [FieldValidators](interfaces/fieldvalidators.md) - [FormOptions](interfaces/formoptions.md) - [FormValidators](interfaces/formvalidators.md) +- [StandardSchemaV1Issue](interfaces/standardschemav1issue.md) ## Type Aliases +- [AnyFieldApi](type-aliases/anyfieldapi.md) +- [AnyFieldMeta](type-aliases/anyfieldmeta.md) +- [AnyFieldMetaBase](type-aliases/anyfieldmetabase.md) +- [AnyFieldMetaDerived](type-aliases/anyfieldmetaderived.md) +- [AnyFormApi](type-aliases/anyformapi.md) +- [AnyFormState](type-aliases/anyformstate.md) - [BaseFormState](type-aliases/baseformstate.md) - [DeepKeys](type-aliases/deepkeys.md) - [DeepValue](type-aliases/deepvalue.md) @@ -29,22 +36,32 @@ title: "@tanstack/form-core" - [FieldMeta](type-aliases/fieldmeta.md) - [FieldMetaBase](type-aliases/fieldmetabase.md) - [FieldMetaDerived](type-aliases/fieldmetaderived.md) -- [FieldsErrorMapFromValidator](type-aliases/fieldserrormapfromvalidator.md) - [FieldState](type-aliases/fieldstate.md) - [FormState](type-aliases/formstate.md) - [FormValidateFn](type-aliases/formvalidatefn.md) +- [FormValidationError](type-aliases/formvalidationerror.md) - [FormValidator](type-aliases/formvalidator.md) - [StandardSchemaV1](type-aliases/standardschemav1.md) +- [TStandardSchemaValidatorValue](type-aliases/tstandardschemavalidatorvalue.md) +- [UnwrapFieldAsyncValidateOrFn](type-aliases/unwrapfieldasyncvalidateorfn.md) +- [UnwrapFieldValidateOrFn](type-aliases/unwrapfieldvalidateorfn.md) +- [UnwrapFormAsyncValidateOrFn](type-aliases/unwrapformasyncvalidateorfn.md) +- [UnwrapFormValidateOrFn](type-aliases/unwrapformvalidateorfn.md) +- [UnwrapOneLevelOfArray](type-aliases/unwraponelevelofarray.md) - [Updater](type-aliases/updater.md) - [UpdaterFn](type-aliases/updaterfn.md) - [ValidationError](type-aliases/validationerror.md) - [ValidationMeta](type-aliases/validationmeta.md) - [ValidationSource](type-aliases/validationsource.md) +## Variables + +- [standardSchemaValidators](variables/standardschemavalidators.md) + ## Functions - [formOptions](functions/formoptions.md) +- [isGlobalFormValidationError](functions/isglobalformvalidationerror.md) - [isStandardSchemaValidator](functions/isstandardschemavalidator.md) - [mergeForm](functions/mergeform.md) - [shallow](functions/shallow.md) -- [standardSchemaValidator](functions/standardschemavalidator.md) diff --git a/docs/reference/interfaces/fieldapioptions.md b/docs/reference/interfaces/fieldapioptions.md index 842ab2292..51e00a278 100644 --- a/docs/reference/interfaces/fieldapioptions.md +++ b/docs/reference/interfaces/fieldapioptions.md @@ -3,15 +3,15 @@ id: FieldApiOptions title: FieldApiOptions --- -# Interface: FieldApiOptions\ +# Interface: FieldApiOptions\ -Defined in: [packages/form-core/src/FieldApi.ts:345](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L345) +Defined in: [packages/form-core/src/FieldApi.ts:423](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L423) An object type representing the required options for the FieldApi class. ## Extends -- [`FieldOptions`](fieldoptions.md)\<`TParentData`, `TName`, `TFieldValidator`, `TFormValidator`, `TData`\> +- [`FieldOptions`](fieldoptions.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> ## Type Parameters @@ -19,13 +19,37 @@ An object type representing the required options for the FieldApi class. • **TName** *extends* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<[`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> = [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Properties @@ -35,7 +59,7 @@ An object type representing the required options for the FieldApi class. optional asyncAlways: boolean; ``` -Defined in: [packages/form-core/src/FieldApi.ts:311](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L311) +Defined in: [packages/form-core/src/FieldApi.ts:370](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L370) If `true`, always run async validation, even if there are errors emitted during synchronous validation. @@ -51,7 +75,7 @@ If `true`, always run async validation, even if there are errors emitted during optional asyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FieldApi.ts:307](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L307) +Defined in: [packages/form-core/src/FieldApi.ts:366](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L366) The default time to debounce async validation if there is not a more specific debounce time passed. @@ -64,10 +88,10 @@ The default time to debounce async validation if there is not a more specific de ### defaultMeta? ```ts -optional defaultMeta: Partial; +optional defaultMeta: Partial>; ``` -Defined in: [packages/form-core/src/FieldApi.ts:329](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L329) +Defined in: [packages/form-core/src/FieldApi.ts:389](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L389) An optional object with default metadata for the field. @@ -83,7 +107,7 @@ An optional object with default metadata for the field. optional defaultValue: NoInfer; ``` -Defined in: [packages/form-core/src/FieldApi.ts:303](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L303) +Defined in: [packages/form-core/src/FieldApi.ts:362](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L362) An optional default value for the field. @@ -93,23 +117,39 @@ An optional default value for the field. *** +### disableErrorFlat? + +```ts +optional disableErrorFlat: boolean; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:417](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L417) + +Disable the `flat(1)` operation on `field.errors`. This is useful if you want to keep the error structure as is. Not suggested for most use-cases. + +#### Inherited from + +[`FieldOptions`](fieldoptions.md).[`disableErrorFlat`](FieldOptions.md#disableerrorflat) + +*** + ### form ```ts -form: FormApi; +form: FormApi; ``` -Defined in: [packages/form-core/src/FieldApi.ts:362](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L362) +Defined in: [packages/form-core/src/FieldApi.ts:460](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L460) *** ### listeners? ```ts -optional listeners: FieldListeners; +optional listeners: FieldListeners; ``` -Defined in: [packages/form-core/src/FieldApi.ts:333](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L333) +Defined in: [packages/form-core/src/FieldApi.ts:413](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L413) A list of listeners which attach to the corresponding events @@ -125,7 +165,7 @@ A list of listeners which attach to the corresponding events name: TName; ``` -Defined in: [packages/form-core/src/FieldApi.ts:299](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L299) +Defined in: [packages/form-core/src/FieldApi.ts:358](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L358) The field name. The type will be `DeepKeys` to ensure your name is a deep key of the parent dataset. @@ -135,29 +175,13 @@ The field name. The type will be `DeepKeys` to ensure your name is *** -### validatorAdapter? - -```ts -optional validatorAdapter: TFieldValidator; -``` - -Defined in: [packages/form-core/src/FieldApi.ts:315](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L315) - -A validator provided by an extension, like `yupValidator` from `@tanstack/yup-form-adapter` - -#### Inherited from - -[`FieldOptions`](fieldoptions.md).[`validatorAdapter`](FieldOptions.md#validatoradapter) - -*** - ### validators? ```ts -optional validators: FieldValidators; +optional validators: FieldValidators; ``` -Defined in: [packages/form-core/src/FieldApi.ts:319](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L319) +Defined in: [packages/form-core/src/FieldApi.ts:374](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L374) A list of validators to pass to the field diff --git a/docs/reference/interfaces/fieldlisteners.md b/docs/reference/interfaces/fieldlisteners.md index c72b78d03..d2a6a3a7e 100644 --- a/docs/reference/interfaces/fieldlisteners.md +++ b/docs/reference/interfaces/fieldlisteners.md @@ -3,9 +3,9 @@ id: FieldListeners title: FieldListeners --- -# Interface: FieldListeners\ +# Interface: FieldListeners\ -Defined in: [packages/form-core/src/FieldApi.ts:241](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L241) +Defined in: [packages/form-core/src/FieldApi.ts:323](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L323) ## Type Parameters @@ -13,12 +13,6 @@ Defined in: [packages/form-core/src/FieldApi.ts:241](https://github.com/TanStack • **TName** *extends* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<[`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` - -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` - • **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> = [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> ## Properties @@ -26,37 +20,37 @@ Defined in: [packages/form-core/src/FieldApi.ts:241](https://github.com/TanStack ### onBlur? ```ts -optional onBlur: FieldListenerFn; +optional onBlur: FieldListenerFn; ``` -Defined in: [packages/form-core/src/FieldApi.ts:259](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L259) +Defined in: [packages/form-core/src/FieldApi.ts:329](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L329) *** ### onChange? ```ts -optional onChange: FieldListenerFn; +optional onChange: FieldListenerFn; ``` -Defined in: [packages/form-core/src/FieldApi.ts:252](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L252) +Defined in: [packages/form-core/src/FieldApi.ts:328](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L328) *** ### onMount? ```ts -optional onMount: FieldListenerFn; +optional onMount: FieldListenerFn; ``` -Defined in: [packages/form-core/src/FieldApi.ts:266](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L266) +Defined in: [packages/form-core/src/FieldApi.ts:330](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L330) *** ### onSubmit? ```ts -optional onSubmit: FieldListenerFn; +optional onSubmit: FieldListenerFn; ``` -Defined in: [packages/form-core/src/FieldApi.ts:273](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L273) +Defined in: [packages/form-core/src/FieldApi.ts:331](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L331) diff --git a/docs/reference/interfaces/fieldoptions.md b/docs/reference/interfaces/fieldoptions.md index cdcdaaa80..12300fc75 100644 --- a/docs/reference/interfaces/fieldoptions.md +++ b/docs/reference/interfaces/fieldoptions.md @@ -3,9 +3,9 @@ id: FieldOptions title: FieldOptions --- -# Interface: FieldOptions\ +# Interface: FieldOptions\ -Defined in: [packages/form-core/src/FieldApi.ts:285](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L285) +Defined in: [packages/form-core/src/FieldApi.ts:337](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L337) An object type representing the options for a field in a form. @@ -19,13 +19,21 @@ An object type representing the options for a field in a form. • **TName** *extends* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<[`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> = [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> ## Properties @@ -35,7 +43,7 @@ An object type representing the options for a field in a form. optional asyncAlways: boolean; ``` -Defined in: [packages/form-core/src/FieldApi.ts:311](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L311) +Defined in: [packages/form-core/src/FieldApi.ts:370](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L370) If `true`, always run async validation, even if there are errors emitted during synchronous validation. @@ -47,7 +55,7 @@ If `true`, always run async validation, even if there are errors emitted during optional asyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FieldApi.ts:307](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L307) +Defined in: [packages/form-core/src/FieldApi.ts:366](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L366) The default time to debounce async validation if there is not a more specific debounce time passed. @@ -56,10 +64,10 @@ The default time to debounce async validation if there is not a more specific de ### defaultMeta? ```ts -optional defaultMeta: Partial; +optional defaultMeta: Partial>; ``` -Defined in: [packages/form-core/src/FieldApi.ts:329](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L329) +Defined in: [packages/form-core/src/FieldApi.ts:389](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L389) An optional object with default metadata for the field. @@ -71,54 +79,54 @@ An optional object with default metadata for the field. optional defaultValue: NoInfer; ``` -Defined in: [packages/form-core/src/FieldApi.ts:303](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L303) +Defined in: [packages/form-core/src/FieldApi.ts:362](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L362) An optional default value for the field. *** -### listeners? +### disableErrorFlat? ```ts -optional listeners: FieldListeners; +optional disableErrorFlat: boolean; ``` -Defined in: [packages/form-core/src/FieldApi.ts:333](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L333) +Defined in: [packages/form-core/src/FieldApi.ts:417](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L417) -A list of listeners which attach to the corresponding events +Disable the `flat(1)` operation on `field.errors`. This is useful if you want to keep the error structure as is. Not suggested for most use-cases. *** -### name +### listeners? ```ts -name: TName; +optional listeners: FieldListeners; ``` -Defined in: [packages/form-core/src/FieldApi.ts:299](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L299) +Defined in: [packages/form-core/src/FieldApi.ts:413](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L413) -The field name. The type will be `DeepKeys` to ensure your name is a deep key of the parent dataset. +A list of listeners which attach to the corresponding events *** -### validatorAdapter? +### name ```ts -optional validatorAdapter: TFieldValidator; +name: TName; ``` -Defined in: [packages/form-core/src/FieldApi.ts:315](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L315) +Defined in: [packages/form-core/src/FieldApi.ts:358](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L358) -A validator provided by an extension, like `yupValidator` from `@tanstack/yup-form-adapter` +The field name. The type will be `DeepKeys` to ensure your name is a deep key of the parent dataset. *** ### validators? ```ts -optional validators: FieldValidators; +optional validators: FieldValidators; ``` -Defined in: [packages/form-core/src/FieldApi.ts:319](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L319) +Defined in: [packages/form-core/src/FieldApi.ts:374](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L374) A list of validators to pass to the field diff --git a/docs/reference/interfaces/fieldvalidators.md b/docs/reference/interfaces/fieldvalidators.md index 2f34e46a9..1bce2beb9 100644 --- a/docs/reference/interfaces/fieldvalidators.md +++ b/docs/reference/interfaces/fieldvalidators.md @@ -3,9 +3,9 @@ id: FieldValidators title: FieldValidators --- -# Interface: FieldValidators\ +# Interface: FieldValidators\ -Defined in: [packages/form-core/src/FieldApi.ts:119](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L119) +Defined in: [packages/form-core/src/FieldApi.ts:242](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L242) ## Type Parameters @@ -13,31 +13,38 @@ Defined in: [packages/form-core/src/FieldApi.ts:119](https://github.com/TanStack • **TName** *extends* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> -• **TFieldValidator** *extends* - \| `Validator`\<[`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\>, `unknown`\> - \| `undefined` = `undefined` +• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> -• **TFormValidator** *extends* `Validator`\<`TParentData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> -• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> = [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> ## Properties ### onBlur? ```ts -optional onBlur: FieldValidateOrFn; +optional onBlur: TOnBlur; ``` -Defined in: [packages/form-core/src/FieldApi.ts:182](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L182) +Defined in: [packages/form-core/src/FieldApi.ts:291](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L291) An optional function, that runs on the blur event of input. -If `validatorAdapter` is passed, this may also accept a property from the respective adapter #### Example ```ts -z.string().min(1) // if `zodAdapter` is passed +z.string().min(1) ``` *** @@ -45,18 +52,17 @@ z.string().min(1) // if `zodAdapter` is passed ### onBlurAsync? ```ts -optional onBlurAsync: FieldAsyncValidateOrFn; +optional onBlurAsync: TOnBlurAsync; ``` -Defined in: [packages/form-core/src/FieldApi.ts:195](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L195) +Defined in: [packages/form-core/src/FieldApi.ts:297](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L297) -An optional property similar to `onBlur` but async validation. If `validatorAdapter` -is passed, this may also accept a property from the respective adapter +An optional property similar to `onBlur` but async validation. #### Example ```ts -z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // if `zodAdapter` is passed +z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) ``` *** @@ -67,7 +73,7 @@ z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // optional onBlurAsyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FieldApi.ts:208](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L208) +Defined in: [packages/form-core/src/FieldApi.ts:304](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L304) An optional number to represent how long the `onBlurAsync` should wait before running @@ -81,7 +87,7 @@ If set to a number larger than 0, will debounce the async validation event by th optional onBlurListenTo: unknown extends TParentData ? string : TParentData extends readonly any[] & IsTuple ? PrefixTupleAccessor, AllowedIndexes, never>, []> : TParentData extends any[] ? PrefixArrayAccessor, [any]> : TParentData extends Date ? never : TParentData extends object ? PrefixObjectAccessor, []> : TParentData extends string | number | bigint | boolean ? "" : never[]; ``` -Defined in: [packages/form-core/src/FieldApi.ts:212](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L212) +Defined in: [packages/form-core/src/FieldApi.ts:308](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L308) An optional list of field names that should trigger this field's `onBlur` and `onBlurAsync` events when its value changes @@ -90,18 +96,17 @@ An optional list of field names that should trigger this field's `onBlur` and `o ### onChange? ```ts -optional onChange: FieldValidateOrFn; +optional onChange: TOnChange; ``` -Defined in: [packages/form-core/src/FieldApi.ts:146](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L146) +Defined in: [packages/form-core/src/FieldApi.ts:269](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L269) -An optional property that takes a `ValidateFn` which is a generic of `TData` and `TParentData`. -If `validatorAdapter` is passed, this may also accept a property from the respective adapter +An optional function, that runs on the change event of input. #### Example ```ts -z.string().min(1) // if `zodAdapter` is passed +z.string().min(1) ``` *** @@ -109,18 +114,17 @@ z.string().min(1) // if `zodAdapter` is passed ### onChangeAsync? ```ts -optional onChangeAsync: FieldAsyncValidateOrFn; +optional onChangeAsync: TOnChangeAsync; ``` -Defined in: [packages/form-core/src/FieldApi.ts:159](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L159) +Defined in: [packages/form-core/src/FieldApi.ts:275](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L275) -An optional property similar to `onChange` but async validation. If `validatorAdapter` -is passed, this may also accept a property from the respective adapter +An optional property similar to `onChange` but async validation #### Example ```ts -z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // if `zodAdapter` is passed +z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) ``` *** @@ -131,7 +135,7 @@ z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // optional onChangeAsyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FieldApi.ts:171](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L171) +Defined in: [packages/form-core/src/FieldApi.ts:281](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L281) An optional number to represent how long the `onChangeAsync` should wait before running @@ -145,7 +149,7 @@ If set to a number larger than 0, will debounce the async validation event by th optional onChangeListenTo: unknown extends TParentData ? string : TParentData extends readonly any[] & IsTuple ? PrefixTupleAccessor, AllowedIndexes, never>, []> : TParentData extends any[] ? PrefixArrayAccessor, [any]> : TParentData extends Date ? never : TParentData extends object ? PrefixObjectAccessor, []> : TParentData extends string | number | bigint | boolean ? "" : never[]; ``` -Defined in: [packages/form-core/src/FieldApi.ts:175](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L175) +Defined in: [packages/form-core/src/FieldApi.ts:285](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L285) An optional list of field names that should trigger this field's `onChange` and `onChangeAsync` events when its value changes @@ -154,30 +158,29 @@ An optional list of field names that should trigger this field's `onChange` and ### onMount? ```ts -optional onMount: FieldValidateOrFn; +optional onMount: TOnMount; ``` -Defined in: [packages/form-core/src/FieldApi.ts:133](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L133) +Defined in: [packages/form-core/src/FieldApi.ts:263](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L263) -An optional function that takes a param of `formApi` which is a generic type of `TData` and `TParentData` +An optional function, that runs on the mount event of input. *** ### onSubmit? ```ts -optional onSubmit: FieldValidateOrFn; +optional onSubmit: TOnSubmit; ``` -Defined in: [packages/form-core/src/FieldApi.ts:219](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L219) +Defined in: [packages/form-core/src/FieldApi.ts:314](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L314) An optional function, that runs on the submit event of form. -If `validatorAdapter` is passed, this may also accept a property from the respective adapter #### Example ```ts -z.string().min(1) // if `zodAdapter` is passed +z.string().min(1) ``` *** @@ -185,16 +188,15 @@ z.string().min(1) // if `zodAdapter` is passed ### onSubmitAsync? ```ts -optional onSubmitAsync: FieldAsyncValidateOrFn; +optional onSubmitAsync: TOnSubmitAsync; ``` -Defined in: [packages/form-core/src/FieldApi.ts:232](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L232) +Defined in: [packages/form-core/src/FieldApi.ts:320](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L320) -An optional property similar to `onSubmit` but async validation. If `validatorAdapter` -is passed, this may also accept a property from the respective adapter +An optional property similar to `onSubmit` but async validation. #### Example ```ts -z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // if `zodAdapter` is passed +z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) ``` diff --git a/docs/reference/interfaces/formoptions.md b/docs/reference/interfaces/formoptions.md index 20b0eb248..70ddb79eb 100644 --- a/docs/reference/interfaces/formoptions.md +++ b/docs/reference/interfaces/formoptions.md @@ -3,9 +3,9 @@ id: FormOptions title: FormOptions --- -# Interface: FormOptions\ +# Interface: FormOptions\ -Defined in: [packages/form-core/src/FormApi.ts:150](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L150) +Defined in: [packages/form-core/src/FormApi.ts:232](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L232) An object representing the options for a form. @@ -13,7 +13,21 @@ An object representing the options for a form. • **TFormData** -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> ## Properties @@ -23,7 +37,7 @@ An object representing the options for a form. optional asyncAlways: boolean; ``` -Defined in: [packages/form-core/src/FormApi.ts:165](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L165) +Defined in: [packages/form-core/src/FormApi.ts:266](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L266) If true, always run async validation, even when sync validation has produced an error. Defaults to undefined. @@ -35,7 +49,7 @@ If true, always run async validation, even when sync validation has produced an optional asyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FormApi.ts:169](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L169) +Defined in: [packages/form-core/src/FormApi.ts:270](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L270) Optional time in milliseconds if you want to introduce a delay before firing off an async action. @@ -44,10 +58,10 @@ Optional time in milliseconds if you want to introduce a delay before firing off ### defaultState? ```ts -optional defaultState: Partial>; +optional defaultState: Partial>; ``` -Defined in: [packages/form-core/src/FormApi.ts:161](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L161) +Defined in: [packages/form-core/src/FormApi.ts:250](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L250) The default state for the form. @@ -59,7 +73,7 @@ The default state for the form. optional defaultValues: TFormData; ``` -Defined in: [packages/form-core/src/FormApi.ts:157](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L157) +Defined in: [packages/form-core/src/FormApi.ts:246](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L246) Set initial values for your form. @@ -71,7 +85,7 @@ Set initial values for your form. optional onSubmit: (props) => any; ``` -Defined in: [packages/form-core/src/FormApi.ts:181](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L181) +Defined in: [packages/form-core/src/FormApi.ts:287](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L287) A function to be called when the form is submitted, what should happen once the user submits a valid form returns `any` or a promise `Promise` @@ -81,7 +95,7 @@ A function to be called when the form is submitted, what should happen once the ###### formApi -[`FormApi`](../classes/formapi.md)\<`TFormData`, `TFormValidator`\> +[`FormApi`](../classes/formapi.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ###### value @@ -99,7 +113,7 @@ A function to be called when the form is submitted, what should happen once the optional onSubmitInvalid: (props) => void; ``` -Defined in: [packages/form-core/src/FormApi.ts:188](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L188) +Defined in: [packages/form-core/src/FormApi.ts:304](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L304) Specify an action for scenarios where the user tries to submit an invalid form. @@ -109,7 +123,7 @@ Specify an action for scenarios where the user tries to submit an invalid form. ###### formApi -[`FormApi`](../classes/formapi.md)\<`TFormData`, `TFormValidator`\> +[`FormApi`](../classes/formapi.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> ###### value @@ -124,31 +138,19 @@ Specify an action for scenarios where the user tries to submit an invalid form. ### transform? ```ts -optional transform: FormTransform; +optional transform: FormTransform; ``` -Defined in: [packages/form-core/src/FormApi.ts:192](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L192) - -*** - -### validatorAdapter? - -```ts -optional validatorAdapter: TFormValidator; -``` - -Defined in: [packages/form-core/src/FormApi.ts:173](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L173) - -A validator adapter to support usage of extra validation types (IE: Zod, Yup, or Valibot usage) +Defined in: [packages/form-core/src/FormApi.ts:318](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L318) *** ### validators? ```ts -optional validators: FormValidators; +optional validators: FormValidators; ``` -Defined in: [packages/form-core/src/FormApi.ts:177](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L177) +Defined in: [packages/form-core/src/FormApi.ts:274](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L274) A list of validators to pass to the form diff --git a/docs/reference/interfaces/formvalidators.md b/docs/reference/interfaces/formvalidators.md index 04842e036..41b1c336f 100644 --- a/docs/reference/interfaces/formvalidators.md +++ b/docs/reference/interfaces/formvalidators.md @@ -3,25 +3,37 @@ id: FormValidators title: FormValidators --- -# Interface: FormValidators\ +# Interface: FormValidators\ -Defined in: [packages/form-core/src/FormApi.ts:98](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L98) +Defined in: [packages/form-core/src/FormApi.ts:147](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L147) ## Type Parameters • **TFormData** -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> ## Properties ### onBlur? ```ts -optional onBlur: FormValidateOrFn; +optional onBlur: TOnBlur; ``` -Defined in: [packages/form-core/src/FormApi.ts:121](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L121) +Defined in: [packages/form-core/src/FormApi.ts:176](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L176) Optional function that validates the form data when a field loses focus, returns a `FormValidationError` @@ -30,10 +42,10 @@ Optional function that validates the form data when a field loses focus, returns ### onBlurAsync? ```ts -optional onBlurAsync: FormAsyncValidateOrFn; +optional onBlurAsync: TOnBlurAsync; ``` -Defined in: [packages/form-core/src/FormApi.ts:125](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L125) +Defined in: [packages/form-core/src/FormApi.ts:180](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L180) Optional onBlur asynchronous validation method for when a field loses focus returns a ` FormValidationError` or a promise of `Promise` @@ -45,7 +57,7 @@ Optional onBlur asynchronous validation method for when a field loses focus retu optional onBlurAsyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FormApi.ts:129](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L129) +Defined in: [packages/form-core/src/FormApi.ts:184](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L184) The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds. @@ -54,10 +66,10 @@ The default time in milliseconds that if set to a number larger than 0, will deb ### onChange? ```ts -optional onChange: FormValidateOrFn; +optional onChange: TOnChange; ``` -Defined in: [packages/form-core/src/FormApi.ts:109](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L109) +Defined in: [packages/form-core/src/FormApi.ts:164](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L164) Optional function that checks the validity of your data whenever a value changes @@ -66,10 +78,10 @@ Optional function that checks the validity of your data whenever a value changes ### onChangeAsync? ```ts -optional onChangeAsync: FormAsyncValidateOrFn; +optional onChangeAsync: TOnChangeAsync; ``` -Defined in: [packages/form-core/src/FormApi.ts:113](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L113) +Defined in: [packages/form-core/src/FormApi.ts:168](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L168) Optional onChange asynchronous counterpart to onChange. Useful for more complex validation logic that might involve server requests. @@ -81,7 +93,7 @@ Optional onChange asynchronous counterpart to onChange. Useful for more complex optional onChangeAsyncDebounceMs: number; ``` -Defined in: [packages/form-core/src/FormApi.ts:117](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L117) +Defined in: [packages/form-core/src/FormApi.ts:172](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L172) The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds. @@ -90,10 +102,10 @@ The default time in milliseconds that if set to a number larger than 0, will deb ### onMount? ```ts -optional onMount: FormValidateOrFn; +optional onMount: TOnMount; ``` -Defined in: [packages/form-core/src/FormApi.ts:105](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L105) +Defined in: [packages/form-core/src/FormApi.ts:160](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L160) Optional function that fires as soon as the component mounts. @@ -102,17 +114,17 @@ Optional function that fires as soon as the component mounts. ### onSubmit? ```ts -optional onSubmit: FormValidateOrFn; +optional onSubmit: TOnSubmit; ``` -Defined in: [packages/form-core/src/FormApi.ts:130](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L130) +Defined in: [packages/form-core/src/FormApi.ts:185](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L185) *** ### onSubmitAsync? ```ts -optional onSubmitAsync: FormAsyncValidateOrFn; +optional onSubmitAsync: TOnSubmitAsync; ``` -Defined in: [packages/form-core/src/FormApi.ts:131](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L131) +Defined in: [packages/form-core/src/FormApi.ts:186](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L186) diff --git a/docs/reference/interfaces/standardschemav1issue.md b/docs/reference/interfaces/standardschemav1issue.md new file mode 100644 index 000000000..d8a5f5140 --- /dev/null +++ b/docs/reference/interfaces/standardschemav1issue.md @@ -0,0 +1,34 @@ +--- +id: StandardSchemaV1Issue +title: StandardSchemaV1Issue +--- + +# Interface: StandardSchemaV1Issue + +Defined in: [packages/form-core/src/standardSchemaValidator.ts:144](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L144) + +The issue interface of the failure output. + +## Properties + +### message + +```ts +readonly message: string; +``` + +Defined in: [packages/form-core/src/standardSchemaValidator.ts:148](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L148) + +The error message of the issue. + +*** + +### path? + +```ts +readonly optional path: readonly (PropertyKey | StandardSchemaV1PathSegment)[]; +``` + +Defined in: [packages/form-core/src/standardSchemaValidator.ts:152](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L152) + +The path of the issue, if any. diff --git a/docs/reference/type-aliases/anyfieldapi.md b/docs/reference/type-aliases/anyfieldapi.md new file mode 100644 index 000000000..b1023743a --- /dev/null +++ b/docs/reference/type-aliases/anyfieldapi.md @@ -0,0 +1,14 @@ +--- +id: AnyFieldApi +title: AnyFieldApi +--- + +# Type Alias: AnyFieldApi + +```ts +type AnyFieldApi = FieldApi; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:802](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L802) + +A type representing the Field API with all generics set to `any` for convenience. diff --git a/docs/reference/type-aliases/anyfieldmeta.md b/docs/reference/type-aliases/anyfieldmeta.md new file mode 100644 index 000000000..e6af8d671 --- /dev/null +++ b/docs/reference/type-aliases/anyfieldmeta.md @@ -0,0 +1,12 @@ +--- +id: AnyFieldMeta +title: AnyFieldMeta +--- + +# Type Alias: AnyFieldMeta + +```ts +type AnyFieldMeta = FieldMeta; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:721](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L721) diff --git a/docs/reference/type-aliases/anyfieldmetabase.md b/docs/reference/type-aliases/anyfieldmetabase.md new file mode 100644 index 000000000..2ecf5cd42 --- /dev/null +++ b/docs/reference/type-aliases/anyfieldmetabase.md @@ -0,0 +1,12 @@ +--- +id: AnyFieldMetaBase +title: AnyFieldMetaBase +--- + +# Type Alias: AnyFieldMetaBase + +```ts +type AnyFieldMetaBase = FieldMetaBase; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:543](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L543) diff --git a/docs/reference/type-aliases/anyfieldmetaderived.md b/docs/reference/type-aliases/anyfieldmetaderived.md new file mode 100644 index 000000000..11ab936fa --- /dev/null +++ b/docs/reference/type-aliases/anyfieldmetaderived.md @@ -0,0 +1,12 @@ +--- +id: AnyFieldMetaDerived +title: AnyFieldMetaDerived +--- + +# Type Alias: AnyFieldMetaDerived + +```ts +type AnyFieldMetaDerived = FieldMetaDerived; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:635](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L635) diff --git a/docs/reference/type-aliases/anyformapi.md b/docs/reference/type-aliases/anyformapi.md new file mode 100644 index 000000000..2e3e5e04d --- /dev/null +++ b/docs/reference/type-aliases/anyformapi.md @@ -0,0 +1,14 @@ +--- +id: AnyFormApi +title: AnyFormApi +--- + +# Type Alias: AnyFormApi + +```ts +type AnyFormApi = FormApi; +``` + +Defined in: [packages/form-core/src/FormApi.ts:613](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L613) + +A type representing the Form API with all generics set to `any` for convenience. diff --git a/docs/reference/type-aliases/anyformstate.md b/docs/reference/type-aliases/anyformstate.md new file mode 100644 index 000000000..4ff923f5f --- /dev/null +++ b/docs/reference/type-aliases/anyformstate.md @@ -0,0 +1,12 @@ +--- +id: AnyFormState +title: AnyFormState +--- + +# Type Alias: AnyFormState + +```ts +type AnyFormState = FormState; +``` + +Defined in: [packages/form-core/src/FormApi.ts:543](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L543) diff --git a/docs/reference/type-aliases/baseformstate.md b/docs/reference/type-aliases/baseformstate.md index 6b32748a0..6ff1511eb 100644 --- a/docs/reference/type-aliases/baseformstate.md +++ b/docs/reference/type-aliases/baseformstate.md @@ -3,13 +3,13 @@ id: BaseFormState title: BaseFormState --- -# Type Alias: BaseFormState\ +# Type Alias: BaseFormState\ ```ts -type BaseFormState = object; +type BaseFormState = object; ``` -Defined in: [packages/form-core/src/FormApi.ts:230](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L230) +Defined in: [packages/form-core/src/FormApi.ts:377](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L377) An object representing the current state of the form. @@ -17,12 +17,28 @@ An object representing the current state of the form. • **TFormData** +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + ## Type declaration ### errorMap ```ts -errorMap: FormValidationErrorMap; +errorMap: FormValidationErrorMap, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormAsyncValidateOrFn>; ``` The error map for the form itself. @@ -30,7 +46,7 @@ The error map for the form itself. ### fieldMetaBase ```ts -fieldMetaBase: Record, FieldMetaBase>; +fieldMetaBase: Record, AnyFieldMetaBase>; ``` A record of field metadata for each field in the form, not including the derived properties, like `errors` and such diff --git a/docs/reference/type-aliases/deepkeys.md b/docs/reference/type-aliases/deepkeys.md index 974a0dd32..d3535e3b8 100644 --- a/docs/reference/type-aliases/deepkeys.md +++ b/docs/reference/type-aliases/deepkeys.md @@ -9,7 +9,7 @@ title: DeepKeys type DeepKeys = TDepth["length"] extends 5 ? never : unknown extends T ? PrefixFromDepth : T extends readonly any[] & IsTuple ? PrefixTupleAccessor, TDepth> : T extends any[] ? PrefixArrayAccessor : T extends Date ? never : T extends object ? PrefixObjectAccessor : T extends string | number | boolean | bigint ? "" : never; ``` -Defined in: [packages/form-core/src/util-types.ts:85](https://github.com/TanStack/form/blob/main/packages/form-core/src/util-types.ts#L85) +Defined in: [packages/form-core/src/util-types.ts:87](https://github.com/TanStack/form/blob/main/packages/form-core/src/util-types.ts#L87) The keys of an object or array, deeply nested. diff --git a/docs/reference/type-aliases/deepvalue.md b/docs/reference/type-aliases/deepvalue.md index 405c68661..9cc682ab6 100644 --- a/docs/reference/type-aliases/deepvalue.md +++ b/docs/reference/type-aliases/deepvalue.md @@ -9,7 +9,7 @@ title: DeepValue type DeepValue = unknown extends TValue ? TValue : TValue extends ReadonlyArray ? TAccessor extends `[${infer TBrackets}].${infer TAfter}` ? DeepValue, TAfter> : TAccessor extends `[${infer TBrackets}]` ? DeepValue : TAccessor extends keyof TValue ? TValue[TAccessor] : TValue[TAccessor & number] : TValue extends Record ? TAccessor extends `${infer TBefore}[${infer TEverythingElse}` ? DeepValue, `[${TEverythingElse}`> : TAccessor extends `[${infer TBrackets}]` ? DeepValue : TAccessor extends `${infer TBefore}.${infer TAfter}` ? DeepValue, TAfter> : TAccessor extends string ? TNullable extends true ? Nullable : TValue[TAccessor] : never : never; ``` -Defined in: [packages/form-core/src/util-types.ts:109](https://github.com/TanStack/form/blob/main/packages/form-core/src/util-types.ts#L109) +Defined in: [packages/form-core/src/util-types.ts:111](https://github.com/TanStack/form/blob/main/packages/form-core/src/util-types.ts#L111) Infer the type of a deeply nested property within an object or an array. diff --git a/docs/reference/type-aliases/derivedformstate.md b/docs/reference/type-aliases/derivedformstate.md index 61d22cb56..fe6fe33c8 100644 --- a/docs/reference/type-aliases/derivedformstate.md +++ b/docs/reference/type-aliases/derivedformstate.md @@ -3,18 +3,34 @@ id: DerivedFormState title: DerivedFormState --- -# Type Alias: DerivedFormState\ +# Type Alias: DerivedFormState\ ```ts -type DerivedFormState = object; +type DerivedFormState = object; ``` -Defined in: [packages/form-core/src/FormApi.ts:274](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L274) +Defined in: [packages/form-core/src/FormApi.ts:440](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L440) ## Type Parameters • **TFormData** +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + ## Type declaration ### canSubmit @@ -28,7 +44,15 @@ A boolean indicating if the form can be submitted based on its current state. ### errors ```ts -errors: ValidationError[]; +errors: ( + | UnwrapFormValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormAsyncValidateOrFn)[]; ``` The error array for the form itself. @@ -36,7 +60,7 @@ The error array for the form itself. ### fieldMeta ```ts -fieldMeta: Record, FieldMeta>; +fieldMeta: Record, AnyFieldMeta>; ``` A record of field metadata for each field in the form. diff --git a/docs/reference/type-aliases/fieldinfo.md b/docs/reference/type-aliases/fieldinfo.md index 6b566a853..8e3427cb6 100644 --- a/docs/reference/type-aliases/fieldinfo.md +++ b/docs/reference/type-aliases/fieldinfo.md @@ -3,13 +3,13 @@ id: FieldInfo title: FieldInfo --- -# Type Alias: FieldInfo\ +# Type Alias: FieldInfo\ ```ts -type FieldInfo = object; +type FieldInfo = object; ``` -Defined in: [packages/form-core/src/FormApi.ts:208](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L208) +Defined in: [packages/form-core/src/FormApi.ts:344](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L344) An object representing the field information for a specific field within the form. @@ -17,15 +17,13 @@ An object representing the field information for a specific field within the for • **TFormData** -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` - ## Type declaration ### instance ```ts instance: - | FieldApi | undefined, TFormValidator> + | FieldApi | null; ``` diff --git a/docs/reference/type-aliases/fieldmeta.md b/docs/reference/type-aliases/fieldmeta.md index 92d188bea..f5d85f842 100644 --- a/docs/reference/type-aliases/fieldmeta.md +++ b/docs/reference/type-aliases/fieldmeta.md @@ -3,12 +3,48 @@ id: FieldMeta title: FieldMeta --- -# Type Alias: FieldMeta +# Type Alias: FieldMeta\ ```ts -type FieldMeta = FieldMetaBase & FieldMetaDerived; +type FieldMeta = FieldMetaBase & FieldMetaDerived; ``` -Defined in: [packages/form-core/src/FieldApi.ts:402](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L402) +Defined in: [packages/form-core/src/FieldApi.ts:658](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L658) An object type representing the metadata of a field in a form. + +## Type Parameters + +• **TParentData** + +• **TName** *extends* [`DeepKeys`](deepkeys.md)\<`TParentData`\> + +• **TData** *extends* [`DeepValue`](deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> diff --git a/docs/reference/type-aliases/fieldmetabase.md b/docs/reference/type-aliases/fieldmetabase.md index a09bbb5cf..f7b3c10d9 100644 --- a/docs/reference/type-aliases/fieldmetabase.md +++ b/docs/reference/type-aliases/fieldmetabase.md @@ -3,20 +3,56 @@ id: FieldMetaBase title: FieldMetaBase --- -# Type Alias: FieldMetaBase +# Type Alias: FieldMetaBase\ ```ts -type FieldMetaBase = object; +type FieldMetaBase = object; ``` -Defined in: [packages/form-core/src/FieldApi.ts:365](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L365) +Defined in: [packages/form-core/src/FieldApi.ts:473](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L473) + +## Type Parameters + +• **TParentData** + +• **TName** *extends* [`DeepKeys`](deepkeys.md)\<`TParentData`\> + +• **TData** *extends* [`DeepValue`](deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Type declaration ### errorMap ```ts -errorMap: ValidationErrorMap; +errorMap: ValidationErrorMap, UnwrapFieldValidateOrFn, UnwrapFieldAsyncValidateOrFn, UnwrapFieldValidateOrFn, UnwrapFieldAsyncValidateOrFn, UnwrapFieldValidateOrFn, UnwrapFieldAsyncValidateOrFn>; ``` A map of errors related to the field value. diff --git a/docs/reference/type-aliases/fieldmetaderived.md b/docs/reference/type-aliases/fieldmetaderived.md index 1228a198f..7f7251eac 100644 --- a/docs/reference/type-aliases/fieldmetaderived.md +++ b/docs/reference/type-aliases/fieldmetaderived.md @@ -3,20 +3,63 @@ id: FieldMetaDerived title: FieldMetaDerived --- -# Type Alias: FieldMetaDerived +# Type Alias: FieldMetaDerived\ ```ts -type FieldMetaDerived = object; +type FieldMetaDerived = object; ``` -Defined in: [packages/form-core/src/FieldApi.ts:388](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L388) +Defined in: [packages/form-core/src/FieldApi.ts:563](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L563) + +## Type Parameters + +• **TParentData** + +• **TName** *extends* [`DeepKeys`](deepkeys.md)\<`TParentData`\> + +• **TData** *extends* [`DeepValue`](deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Type declaration ### errors ```ts -errors: ValidationError[]; +errors: ( + | UnwrapOneLevelOfArray> + | UnwrapOneLevelOfArray> + | UnwrapOneLevelOfArray> + | UnwrapOneLevelOfArray> + | UnwrapOneLevelOfArray> + | UnwrapOneLevelOfArray> + | UnwrapOneLevelOfArray>)[]; ``` An array of errors related to the field value. diff --git a/docs/reference/type-aliases/fieldserrormapfromvalidator.md b/docs/reference/type-aliases/fieldserrormapfromvalidator.md deleted file mode 100644 index 588ac78ab..000000000 --- a/docs/reference/type-aliases/fieldserrormapfromvalidator.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -id: FieldsErrorMapFromValidator -title: FieldsErrorMapFromValidator ---- - -# Type Alias: FieldsErrorMapFromValidator\ - -```ts -type FieldsErrorMapFromValidator = Partial, ValidationErrorMap>>; -``` - -Defined in: [packages/form-core/src/FormApi.ts:33](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L33) - -## Type Parameters - -• **TFormData** diff --git a/docs/reference/type-aliases/fieldstate.md b/docs/reference/type-aliases/fieldstate.md index 30edf86ef..096794d1b 100644 --- a/docs/reference/type-aliases/fieldstate.md +++ b/docs/reference/type-aliases/fieldstate.md @@ -3,26 +3,58 @@ id: FieldState title: FieldState --- -# Type Alias: FieldState\ +# Type Alias: FieldState\ ```ts -type FieldState = object; +type FieldState = object; ``` -Defined in: [packages/form-core/src/FieldApi.ts:407](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L407) +Defined in: [packages/form-core/src/FieldApi.ts:744](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L744) An object type representing the state of a field. ## Type Parameters -• **TData** +• **TParentData** + +• **TName** *extends* [`DeepKeys`](deepkeys.md)\<`TParentData`\> + +• **TData** *extends* [`DeepValue`](deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> ## Type declaration ### meta ```ts -meta: FieldMeta; +meta: FieldMeta; ``` The current metadata of the field. diff --git a/docs/reference/type-aliases/formstate.md b/docs/reference/type-aliases/formstate.md index 84c777763..6b146bdc4 100644 --- a/docs/reference/type-aliases/formstate.md +++ b/docs/reference/type-aliases/formstate.md @@ -3,14 +3,30 @@ id: FormState title: FormState --- -# Type Alias: FormState\ +# Type Alias: FormState\ ```ts -type FormState = BaseFormState & DerivedFormState; +type FormState = BaseFormState & DerivedFormState; ``` -Defined in: [packages/form-core/src/FormApi.ts:325](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L325) +Defined in: [packages/form-core/src/FormApi.ts:510](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L510) ## Type Parameters • **TFormData** + +• **TOnMount** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *extends* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> diff --git a/docs/reference/type-aliases/formvalidatefn.md b/docs/reference/type-aliases/formvalidatefn.md index 7c9c2dd68..4d3e91f02 100644 --- a/docs/reference/type-aliases/formvalidatefn.md +++ b/docs/reference/type-aliases/formvalidatefn.md @@ -3,27 +3,25 @@ id: FormValidateFn title: FormValidateFn --- -# Type Alias: FormValidateFn()\ +# Type Alias: FormValidateFn()\ ```ts -type FormValidateFn = (props) => FormValidationError; +type FormValidateFn = (props) => unknown; ``` -Defined in: [packages/form-core/src/FormApi.ts:37](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L37) +Defined in: [packages/form-core/src/FormApi.ts:64](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L64) ## Type Parameters • **TFormData** -• **TFormValidator** *extends* `Validator`\<`TFormData`, `unknown`\> \| `undefined` = `undefined` - ## Parameters ### props #### formApi -[`FormApi`](../classes/formapi.md)\<`TFormData`, `TFormValidator`\> +[`FormApi`](../classes/formapi.md)\<`TFormData`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\> #### value @@ -31,4 +29,4 @@ Defined in: [packages/form-core/src/FormApi.ts:37](https://github.com/TanStack/f ## Returns -`FormValidationError`\<`TFormData`\> +`unknown` diff --git a/docs/reference/type-aliases/formvalidationerror.md b/docs/reference/type-aliases/formvalidationerror.md new file mode 100644 index 000000000..4b455b416 --- /dev/null +++ b/docs/reference/type-aliases/formvalidationerror.md @@ -0,0 +1,18 @@ +--- +id: FormValidationError +title: FormValidationError +--- + +# Type Alias: FormValidationError\ + +```ts +type FormValidationError = + | ValidationError +| GlobalFormValidationError; +``` + +Defined in: [packages/form-core/src/types.ts:58](https://github.com/TanStack/form/blob/main/packages/form-core/src/types.ts#L58) + +## Type Parameters + +• **TFormData** diff --git a/docs/reference/type-aliases/formvalidator.md b/docs/reference/type-aliases/formvalidator.md index 843136e59..6929439e2 100644 --- a/docs/reference/type-aliases/formvalidator.md +++ b/docs/reference/type-aliases/formvalidator.md @@ -9,7 +9,7 @@ title: FormValidator type FormValidator = object; ``` -Defined in: [packages/form-core/src/FormApi.ts:70](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L70) +Defined in: [packages/form-core/src/FormApi.ts:117](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L117) ## Type Parameters @@ -37,7 +37,7 @@ Defined in: [packages/form-core/src/FormApi.ts:70](https://github.com/TanStack/f #### Returns -[`ValidationError`](validationerror.md) +`unknown` ### validateAsync() @@ -55,4 +55,4 @@ Defined in: [packages/form-core/src/FormApi.ts:70](https://github.com/TanStack/f #### Returns -`Promise`\<`FormValidationError`\<`TFormData`\>\> +`Promise`\<`unknown`\> diff --git a/docs/reference/type-aliases/standardschemav1.md b/docs/reference/type-aliases/standardschemav1.md index 041725a53..fe75351bf 100644 --- a/docs/reference/type-aliases/standardschemav1.md +++ b/docs/reference/type-aliases/standardschemav1.md @@ -9,7 +9,7 @@ title: StandardSchemaV1 type StandardSchemaV1 = object; ``` -Defined in: [packages/form-core/src/standardSchemaValidator.ts:94](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L94) +Defined in: [packages/form-core/src/standardSchemaValidator.ts:83](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L83) The Standard Schema interface. diff --git a/docs/reference/type-aliases/tstandardschemavalidatorvalue.md b/docs/reference/type-aliases/tstandardschemavalidatorvalue.md new file mode 100644 index 000000000..b984ed7e0 --- /dev/null +++ b/docs/reference/type-aliases/tstandardschemavalidatorvalue.md @@ -0,0 +1,30 @@ +--- +id: TStandardSchemaValidatorValue +title: TStandardSchemaValidatorValue +--- + +# Type Alias: TStandardSchemaValidatorValue\ + +```ts +type TStandardSchemaValidatorValue = object; +``` + +Defined in: [packages/form-core/src/standardSchemaValidator.ts:3](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L3) + +## Type Parameters + +• **TData** + +## Type declaration + +### validationSource + +```ts +validationSource: ValidationSource; +``` + +### value + +```ts +value: TData; +``` diff --git a/docs/reference/type-aliases/unwrapfieldasyncvalidateorfn.md b/docs/reference/type-aliases/unwrapfieldasyncvalidateorfn.md new file mode 100644 index 000000000..500eb59bb --- /dev/null +++ b/docs/reference/type-aliases/unwrapfieldasyncvalidateorfn.md @@ -0,0 +1,25 @@ +--- +id: UnwrapFieldAsyncValidateOrFn +title: UnwrapFieldAsyncValidateOrFn +--- + +# Type Alias: UnwrapFieldAsyncValidateOrFn\ + +```ts +type UnwrapFieldAsyncValidateOrFn = + | [TFormValidateOrFn] extends [StandardSchemaV1] ? TName extends keyof TStandardOut ? StandardSchemaV1Issue[] : undefined : undefined + | UnwrapFormAsyncValidateOrFn extends infer TFormValidateVal ? TFormValidateVal extends object ? TName extends keyof TFormValidateVal["fields"] ? TFormValidateVal["fields"][TName] : undefined : undefined : never + | [TValidateOrFn] extends [FieldValidateAsyncFn] ? Awaited> : [TValidateOrFn] extends [StandardSchemaV1] ? StandardSchemaV1Issue[] : undefined; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:184](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L184) + +## Type Parameters + +• **TParentData** + +• **TName** *extends* [`DeepKeys`](deepkeys.md)\<`TParentData`\> + +• **TValidateOrFn** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`any`, `any`, `any`\> + +• **TFormValidateOrFn** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`any`\> diff --git a/docs/reference/type-aliases/unwrapfieldvalidateorfn.md b/docs/reference/type-aliases/unwrapfieldvalidateorfn.md new file mode 100644 index 000000000..7f8133881 --- /dev/null +++ b/docs/reference/type-aliases/unwrapfieldvalidateorfn.md @@ -0,0 +1,25 @@ +--- +id: UnwrapFieldValidateOrFn +title: UnwrapFieldValidateOrFn +--- + +# Type Alias: UnwrapFieldValidateOrFn\ + +```ts +type UnwrapFieldValidateOrFn = + | [TFormValidateOrFn] extends [StandardSchemaV1] ? TName extends keyof TStandardOut ? StandardSchemaV1Issue[] : undefined : undefined + | UnwrapFormValidateOrFn extends infer TFormValidateVal ? TFormValidateVal extends object ? TName extends keyof TFormValidateVal["fields"] ? TFormValidateVal["fields"][TName] : undefined : undefined : never + | [TValidateOrFn] extends [FieldValidateFn] ? ReturnType : [TValidateOrFn] extends [StandardSchemaV1] ? StandardSchemaV1Issue[] : undefined; +``` + +Defined in: [packages/form-core/src/FieldApi.ts:114](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L114) + +## Type Parameters + +• **TParentData** + +• **TName** *extends* [`DeepKeys`](deepkeys.md)\<`TParentData`\> + +• **TValidateOrFn** *extends* `undefined` \| `FieldValidateOrFn`\<`any`, `any`, `any`\> + +• **TFormValidateOrFn** *extends* `undefined` \| `FormValidateOrFn`\<`any`\> diff --git a/docs/reference/type-aliases/unwrapformasyncvalidateorfn.md b/docs/reference/type-aliases/unwrapformasyncvalidateorfn.md new file mode 100644 index 000000000..f0c6a404c --- /dev/null +++ b/docs/reference/type-aliases/unwrapformasyncvalidateorfn.md @@ -0,0 +1,16 @@ +--- +id: UnwrapFormAsyncValidateOrFn +title: UnwrapFormAsyncValidateOrFn +--- + +# Type Alias: UnwrapFormAsyncValidateOrFn\ + +```ts +type UnwrapFormAsyncValidateOrFn = [TValidateOrFn] extends [FormValidateAsyncFn] ? Awaited> : [TValidateOrFn] extends [StandardSchemaV1] ? Record : undefined; +``` + +Defined in: [packages/form-core/src/FormApi.ts:139](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L139) + +## Type Parameters + +• **TValidateOrFn** *extends* `undefined` \| `FormAsyncValidateOrFn`\<`any`\> diff --git a/docs/reference/type-aliases/unwrapformvalidateorfn.md b/docs/reference/type-aliases/unwrapformvalidateorfn.md new file mode 100644 index 000000000..f74081dfd --- /dev/null +++ b/docs/reference/type-aliases/unwrapformvalidateorfn.md @@ -0,0 +1,16 @@ +--- +id: UnwrapFormValidateOrFn +title: UnwrapFormValidateOrFn +--- + +# Type Alias: UnwrapFormValidateOrFn\ + +```ts +type UnwrapFormValidateOrFn = [TValidateOrFn] extends [FormValidateFn] ? ReturnType : [TValidateOrFn] extends [StandardSchemaV1] ? Record : undefined; +``` + +Defined in: [packages/form-core/src/FormApi.ts:88](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L88) + +## Type Parameters + +• **TValidateOrFn** *extends* `undefined` \| `FormValidateOrFn`\<`any`\> diff --git a/docs/reference/type-aliases/unwraponelevelofarray.md b/docs/reference/type-aliases/unwraponelevelofarray.md new file mode 100644 index 000000000..1c24252b1 --- /dev/null +++ b/docs/reference/type-aliases/unwraponelevelofarray.md @@ -0,0 +1,16 @@ +--- +id: UnwrapOneLevelOfArray +title: UnwrapOneLevelOfArray +--- + +# Type Alias: UnwrapOneLevelOfArray\ + +```ts +type UnwrapOneLevelOfArray = T extends infer U[] ? U : T; +``` + +Defined in: [packages/form-core/src/util-types.ts:4](https://github.com/TanStack/form/blob/main/packages/form-core/src/util-types.ts#L4) + +## Type Parameters + +• **T** diff --git a/docs/reference/type-aliases/validationerror.md b/docs/reference/type-aliases/validationerror.md index 774c3fc0c..5421ef7ba 100644 --- a/docs/reference/type-aliases/validationerror.md +++ b/docs/reference/type-aliases/validationerror.md @@ -6,7 +6,7 @@ title: ValidationError # Type Alias: ValidationError ```ts -type ValidationError = undefined | false | null | string; +type ValidationError = unknown; ``` Defined in: [packages/form-core/src/types.ts:3](https://github.com/TanStack/form/blob/main/packages/form-core/src/types.ts#L3) diff --git a/docs/reference/type-aliases/validationmeta.md b/docs/reference/type-aliases/validationmeta.md index 550e0ab74..c2616fbae 100644 --- a/docs/reference/type-aliases/validationmeta.md +++ b/docs/reference/type-aliases/validationmeta.md @@ -9,7 +9,7 @@ title: ValidationMeta type ValidationMeta = object; ``` -Defined in: [packages/form-core/src/FormApi.ts:198](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L198) +Defined in: [packages/form-core/src/FormApi.ts:334](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L334) An object representing the validation metadata for a field. Not intended for public usage. diff --git a/docs/reference/variables/standardschemavalidators.md b/docs/reference/variables/standardschemavalidators.md new file mode 100644 index 000000000..e94b3e430 --- /dev/null +++ b/docs/reference/variables/standardschemavalidators.md @@ -0,0 +1,57 @@ +--- +id: standardSchemaValidators +title: standardSchemaValidators +--- + +# Variable: standardSchemaValidators + +```ts +const standardSchemaValidators: object; +``` + +Defined in: [packages/form-core/src/standardSchemaValidator.ts:48](https://github.com/TanStack/form/blob/main/packages/form-core/src/standardSchemaValidator.ts#L48) + +## Type declaration + +### validate() + +#### Parameters + +##### \_\_namedParameters + +[`TStandardSchemaValidatorValue`](../type-aliases/tstandardschemavalidatorvalue.md)\<`unknown`\> + +##### schema + +[`StandardSchemaV1`](../type-aliases/standardschemav1.md) + +#### Returns + + \| `undefined` + \| readonly [`StandardSchemaV1Issue`](../interfaces/standardschemav1issue.md)[] + \| \{ + `fields`: \{\}; + `form`: \{\}; + \} + +### validateAsync() + +#### Parameters + +##### \_\_namedParameters + +[`TStandardSchemaValidatorValue`](../type-aliases/tstandardschemavalidatorvalue.md)\<`unknown`\> + +##### schema + +[`StandardSchemaV1`](../type-aliases/standardschemav1.md) + +#### Returns + +`Promise`\< + \| `undefined` + \| readonly [`StandardSchemaV1Issue`](../interfaces/standardschemav1issue.md)[] + \| \{ + `fields`: \{\}; + `form`: \{\}; + \}\> diff --git a/examples/angular/simple/src/app/app.component.ts b/examples/angular/simple/src/app/app.component.ts index 8a7b7909c..ce3706f64 100644 --- a/examples/angular/simple/src/app/app.component.ts +++ b/examples/angular/simple/src/app/app.component.ts @@ -62,20 +62,19 @@ import type { `, }) export class AppComponent { - firstNameValidator: FieldValidateFn = ({ - value, - }) => + firstNameValidator: FieldValidateFn = ({ value }) => !value ? 'A first name is required' : value.length < 3 ? 'First name must be at least 3 characters' : undefined - firstNameAsyncValidator: FieldValidateAsyncFn = - async ({ value }) => { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return value.includes('error') && 'No "error" allowed in first name' - } + firstNameAsyncValidator: FieldValidateAsyncFn = async ({ + value, + }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return value.includes('error') && 'No "error" allowed in first name' + } form = injectForm({ defaultValues: { diff --git a/examples/angular/valibot/.editorconfig b/examples/angular/valibot/.editorconfig deleted file mode 100644 index 59d9a3a3e..000000000 --- a/examples/angular/valibot/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/examples/angular/valibot/.gitignore b/examples/angular/valibot/.gitignore deleted file mode 100644 index 0711527ef..000000000 --- a/examples/angular/valibot/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# Compiled output -/dist -/tmp -/out-tsc -/bazel-out - -# Node -/node_modules -npm-debug.log -yarn-error.log - -# IDEs and editors -.idea/ -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# Visual Studio Code -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.history/* - -# Miscellaneous -/.angular/cache -.sass-cache/ -/connect.lock -/coverage -/libpeerconnection.log -testem.log -/typings - -# System files -.DS_Store -Thumbs.db diff --git a/examples/angular/valibot/README.md b/examples/angular/valibot/README.md deleted file mode 100644 index 3e87f4c6d..000000000 --- a/examples/angular/valibot/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Simple - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.1. - -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/examples/angular/valibot/angular.json b/examples/angular/valibot/angular.json deleted file mode 100644 index 27a423bce..000000000 --- a/examples/angular/valibot/angular.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "simple": { - "projectType": "application", - "schematics": {}, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:application", - "options": { - "outputPath": "dist/simple", - "index": "src/index.html", - "browser": "src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "tsconfig.app.json", - "assets": ["src/favicon.ico", "src/assets"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "simple:build:production" - }, - "development": { - "buildTarget": "simple:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "buildTarget": "simple:build" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "polyfills": ["zone.js", "zone.js/testing"], - "tsConfig": "tsconfig.spec.json", - "assets": ["src/favicon.ico", "src/assets"], - "scripts": [] - } - } - } - } - }, - "cli": { - "analytics": false - } -} diff --git a/examples/angular/valibot/package.json b/examples/angular/valibot/package.json deleted file mode 100644 index 38d7d15ef..000000000 --- a/examples/angular/valibot/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "@tanstack/form-example-angular-valibot", - "private": true, - "type": "module", - "scripts": { - "ng": "ng", - "start": "ng cache clean && ng serve", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test" - }, - "dependencies": { - "@angular/animations": "^19.0.0", - "@angular/common": "^19.0.0", - "@angular/compiler": "^19.0.0", - "@angular/core": "^19.0.0", - "@angular/forms": "^19.0.0", - "@angular/platform-browser": "^19.0.0", - "@angular/platform-browser-dynamic": "^19.0.0", - "@angular/router": "^19.0.0", - "@tanstack/angular-form": "^0.42.1", - "@tanstack/valibot-form-adapter": "^0.42.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.1", - "valibot": "^1.0.0-beta.9", - "zone.js": "^0.15.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.0.0", - "@angular/cli": "^19.0.0", - "@angular/compiler-cli": "^19.0.0", - "typescript": "5.6.3" - } -} diff --git a/examples/angular/valibot/src/app/app.component.ts b/examples/angular/valibot/src/app/app.component.ts deleted file mode 100644 index 34e343efa..000000000 --- a/examples/angular/valibot/src/app/app.component.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { Component } from '@angular/core' -import { TanStackField, injectForm, injectStore } from '@tanstack/angular-form' -import { valibotValidator } from '@tanstack/valibot-form-adapter' -import * as v from 'valibot' - -@Component({ - selector: 'app-root', - standalone: true, - imports: [TanStackField], - template: ` -
-
- - - - @if (firstName.api.state.meta.isTouched) { - @for (error of firstName.api.state.meta.errors; track $index) { -
- {{ error }} -
- } - } - @if (firstName.api.state.meta.isValidating) { -

Validating...

- } -
-
-
- - - - -
- -
- `, -}) -export class AppComponent { - firstNameValidator = v.pipe( - v.string(), - v.minLength(3, 'You must have a length of at least 3'), - ) - - firstNameAsyncValidator = v.pipeAsync( - v.string(), - v.checkAsync(async (value) => { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value.includes('error') - }, "No 'error' allowed in first name"), - ) - - form = injectForm({ - defaultValues: { - firstName: '', - lastName: '', - }, - onSubmit({ value }) { - // Do something with form data - console.log(value) - }, - // Add a validator to support Zod usage in Form and Field (no longer needed with valibot@1.0.0 or higher) - validatorAdapter: valibotValidator(), - }) - - canSubmit = injectStore(this.form, (state) => state.canSubmit) - isSubmitting = injectStore(this.form, (state) => state.isSubmitting) - - handleSubmit(event: SubmitEvent) { - event.preventDefault() - event.stopPropagation() - this.form.handleSubmit() - } -} diff --git a/examples/angular/valibot/src/favicon.ico b/examples/angular/valibot/src/favicon.ico deleted file mode 100644 index 57614f9c9..000000000 Binary files a/examples/angular/valibot/src/favicon.ico and /dev/null differ diff --git a/examples/angular/valibot/src/index.html b/examples/angular/valibot/src/index.html deleted file mode 100644 index c3c6fbbdd..000000000 --- a/examples/angular/valibot/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Simple - - - - - - - - diff --git a/examples/angular/valibot/src/main.ts b/examples/angular/valibot/src/main.ts deleted file mode 100644 index 56773910e..000000000 --- a/examples/angular/valibot/src/main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser' -import { AppComponent } from './app/app.component' - -bootstrapApplication(AppComponent).catch((err) => console.error(err)) diff --git a/examples/angular/valibot/tsconfig.app.json b/examples/angular/valibot/tsconfig.app.json deleted file mode 100644 index 84f1f992d..000000000 --- a/examples/angular/valibot/tsconfig.app.json +++ /dev/null @@ -1,10 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "files": ["src/main.ts"], - "include": ["src/**/*.d.ts"] -} diff --git a/examples/angular/valibot/tsconfig.json b/examples/angular/valibot/tsconfig.json deleted file mode 100644 index 8ecd81899..000000000 --- a/examples/angular/valibot/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "compileOnSave": false, - "compilerOptions": { - "outDir": "./dist/out-tsc", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "esModuleInterop": true, - "sourceMap": true, - "declaration": false, - "experimentalDecorators": true, - "moduleResolution": "node", - "importHelpers": true, - "target": "ES2022", - "module": "ES2022", - "useDefineForClassFields": false, - "skipLibCheck": true, - "lib": ["ES2022", "dom"] - }, - "angularCompilerOptions": { - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/examples/angular/valibot/tsconfig.spec.json b/examples/angular/valibot/tsconfig.spec.json deleted file mode 100644 index 47e3dd755..000000000 --- a/examples/angular/valibot/tsconfig.spec.json +++ /dev/null @@ -1,9 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "types": ["jasmine"] - }, - "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] -} diff --git a/examples/angular/yup/.editorconfig b/examples/angular/yup/.editorconfig deleted file mode 100644 index 59d9a3a3e..000000000 --- a/examples/angular/yup/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/examples/angular/yup/.gitignore b/examples/angular/yup/.gitignore deleted file mode 100644 index 0711527ef..000000000 --- a/examples/angular/yup/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# Compiled output -/dist -/tmp -/out-tsc -/bazel-out - -# Node -/node_modules -npm-debug.log -yarn-error.log - -# IDEs and editors -.idea/ -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# Visual Studio Code -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.history/* - -# Miscellaneous -/.angular/cache -.sass-cache/ -/connect.lock -/coverage -/libpeerconnection.log -testem.log -/typings - -# System files -.DS_Store -Thumbs.db diff --git a/examples/angular/yup/README.md b/examples/angular/yup/README.md deleted file mode 100644 index 3e87f4c6d..000000000 --- a/examples/angular/yup/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Simple - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.1. - -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/examples/angular/yup/angular.json b/examples/angular/yup/angular.json deleted file mode 100644 index 0cc433f7f..000000000 --- a/examples/angular/yup/angular.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "simple": { - "projectType": "application", - "schematics": {}, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:application", - "options": { - "outputPath": "dist/simple", - "index": "src/index.html", - "browser": "src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "tsconfig.app.json", - "assets": ["src/favicon.ico", "src/assets"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "simple:build:production" - }, - "development": { - "buildTarget": "simple:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "buildTarget": "simple:build" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "polyfills": ["zone.js", "zone.js/testing"], - "tsConfig": "tsconfig.spec.json", - "assets": ["src/favicon.ico", "src/assets"], - "scripts": [] - } - } - } - } - } -} diff --git a/examples/angular/yup/package.json b/examples/angular/yup/package.json deleted file mode 100644 index 163b66c2a..000000000 --- a/examples/angular/yup/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "@tanstack/form-example-angular-yup", - "private": true, - "type": "module", - "scripts": { - "ng": "ng", - "start": "ng cache clean && ng serve", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test" - }, - "dependencies": { - "@angular/animations": "^19.0.0", - "@angular/common": "^19.0.0", - "@angular/compiler": "^19.0.0", - "@angular/core": "^19.0.0", - "@angular/forms": "^19.0.0", - "@angular/platform-browser": "^19.0.0", - "@angular/platform-browser-dynamic": "^19.0.0", - "@angular/router": "^19.0.0", - "@tanstack/angular-form": "^0.42.1", - "@tanstack/yup-form-adapter": "^0.42.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.1", - "yup": "^1.5.0", - "zone.js": "^0.15.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.0.0", - "@angular/cli": "^19.0.0", - "@angular/compiler-cli": "^19.0.0", - "typescript": "5.6.3" - } -} diff --git a/examples/angular/yup/src/app/app.component.ts b/examples/angular/yup/src/app/app.component.ts deleted file mode 100644 index 58434ae3b..000000000 --- a/examples/angular/yup/src/app/app.component.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Component } from '@angular/core' -import { TanStackField, injectForm, injectStore } from '@tanstack/angular-form' -import { yupValidator } from '@tanstack/yup-form-adapter' -import * as yup from 'yup' - -@Component({ - selector: 'app-root', - standalone: true, - imports: [TanStackField], - template: ` -
-
- - - - @if (firstName.api.state.meta.isTouched) { - @for (error of firstName.api.state.meta.errors; track $index) { -
- {{ error }} -
- } - } - @if (firstName.api.state.meta.isValidating) { -

Validating...

- } -
-
-
- - - - -
- -
- `, -}) -export class AppComponent { - firstNameAsyncValidator = yup - .string() - .test('no-error', "No 'error' allowed in first name", async (value) => { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value?.includes('error') - }) - - form = injectForm({ - defaultValues: { - firstName: '', - lastName: '', - }, - onSubmit({ value }) { - // Do something with form data - console.log(value) - }, - // Add a validator to support Zod usage in Form and Field - validatorAdapter: yupValidator(), - }) - - yup = yup - - canSubmit = injectStore(this.form, (state) => state.canSubmit) - isSubmitting = injectStore(this.form, (state) => state.isSubmitting) - - handleSubmit(event: SubmitEvent) { - event.preventDefault() - event.stopPropagation() - this.form.handleSubmit() - } -} diff --git a/examples/angular/yup/src/favicon.ico b/examples/angular/yup/src/favicon.ico deleted file mode 100644 index 57614f9c9..000000000 Binary files a/examples/angular/yup/src/favicon.ico and /dev/null differ diff --git a/examples/angular/yup/src/index.html b/examples/angular/yup/src/index.html deleted file mode 100644 index c3c6fbbdd..000000000 --- a/examples/angular/yup/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Simple - - - - - - - - diff --git a/examples/angular/yup/src/main.ts b/examples/angular/yup/src/main.ts deleted file mode 100644 index 56773910e..000000000 --- a/examples/angular/yup/src/main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser' -import { AppComponent } from './app/app.component' - -bootstrapApplication(AppComponent).catch((err) => console.error(err)) diff --git a/examples/angular/yup/tsconfig.app.json b/examples/angular/yup/tsconfig.app.json deleted file mode 100644 index 84f1f992d..000000000 --- a/examples/angular/yup/tsconfig.app.json +++ /dev/null @@ -1,10 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "files": ["src/main.ts"], - "include": ["src/**/*.d.ts"] -} diff --git a/examples/angular/yup/tsconfig.json b/examples/angular/yup/tsconfig.json deleted file mode 100644 index f077510cd..000000000 --- a/examples/angular/yup/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "compileOnSave": false, - "compilerOptions": { - "outDir": "./dist/out-tsc", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "esModuleInterop": true, - "sourceMap": true, - "declaration": false, - "experimentalDecorators": true, - "moduleResolution": "node", - "importHelpers": true, - "target": "ES2022", - "module": "ES2022", - "useDefineForClassFields": false, - "lib": ["ES2022", "dom"] - }, - "angularCompilerOptions": { - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/examples/angular/yup/tsconfig.spec.json b/examples/angular/yup/tsconfig.spec.json deleted file mode 100644 index 47e3dd755..000000000 --- a/examples/angular/yup/tsconfig.spec.json +++ /dev/null @@ -1,9 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "types": ["jasmine"] - }, - "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] -} diff --git a/examples/angular/zod/.editorconfig b/examples/angular/zod/.editorconfig deleted file mode 100644 index 59d9a3a3e..000000000 --- a/examples/angular/zod/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Editor configuration, see https://editorconfig.org -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 2 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.ts] -quote_type = single - -[*.md] -max_line_length = off -trim_trailing_whitespace = false diff --git a/examples/angular/zod/.gitignore b/examples/angular/zod/.gitignore deleted file mode 100644 index 0711527ef..000000000 --- a/examples/angular/zod/.gitignore +++ /dev/null @@ -1,42 +0,0 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# Compiled output -/dist -/tmp -/out-tsc -/bazel-out - -# Node -/node_modules -npm-debug.log -yarn-error.log - -# IDEs and editors -.idea/ -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# Visual Studio Code -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -.history/* - -# Miscellaneous -/.angular/cache -.sass-cache/ -/connect.lock -/coverage -/libpeerconnection.log -testem.log -/typings - -# System files -.DS_Store -Thumbs.db diff --git a/examples/angular/zod/README.md b/examples/angular/zod/README.md deleted file mode 100644 index 3e87f4c6d..000000000 --- a/examples/angular/zod/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Simple - -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.1. - -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/examples/angular/zod/angular.json b/examples/angular/zod/angular.json deleted file mode 100644 index 0cc433f7f..000000000 --- a/examples/angular/zod/angular.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "$schema": "./node_modules/@angular/cli/lib/config/schema.json", - "version": 1, - "newProjectRoot": "projects", - "projects": { - "simple": { - "projectType": "application", - "schematics": {}, - "root": "", - "sourceRoot": "src", - "prefix": "app", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:application", - "options": { - "outputPath": "dist/simple", - "index": "src/index.html", - "browser": "src/main.ts", - "polyfills": ["zone.js"], - "tsConfig": "tsconfig.app.json", - "assets": ["src/favicon.ico", "src/assets"], - "scripts": [] - }, - "configurations": { - "production": { - "budgets": [ - { - "type": "initial", - "maximumWarning": "500kb", - "maximumError": "1mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "2kb", - "maximumError": "4kb" - } - ], - "outputHashing": "all" - }, - "development": { - "optimization": false, - "extractLicenses": false, - "sourceMap": true - } - }, - "defaultConfiguration": "production" - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "configurations": { - "production": { - "buildTarget": "simple:build:production" - }, - "development": { - "buildTarget": "simple:build:development" - } - }, - "defaultConfiguration": "development" - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "buildTarget": "simple:build" - } - }, - "test": { - "builder": "@angular-devkit/build-angular:karma", - "options": { - "polyfills": ["zone.js", "zone.js/testing"], - "tsConfig": "tsconfig.spec.json", - "assets": ["src/favicon.ico", "src/assets"], - "scripts": [] - } - } - } - } - } -} diff --git a/examples/angular/zod/package.json b/examples/angular/zod/package.json deleted file mode 100644 index f9c5509a4..000000000 --- a/examples/angular/zod/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "@tanstack/form-example-angular-zod", - "private": true, - "type": "module", - "scripts": { - "ng": "ng", - "start": "ng cache clean && ng serve", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test" - }, - "dependencies": { - "@angular/animations": "^19.0.0", - "@angular/common": "^19.0.0", - "@angular/compiler": "^19.0.0", - "@angular/core": "^19.0.0", - "@angular/forms": "^19.0.0", - "@angular/platform-browser": "^19.0.0", - "@angular/platform-browser-dynamic": "^19.0.0", - "@angular/router": "^19.0.0", - "@tanstack/angular-form": "^0.42.1", - "@tanstack/zod-form-adapter": "^0.42.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.1", - "zod": "^3.24.0", - "zone.js": "^0.15.0" - }, - "devDependencies": { - "@angular-devkit/build-angular": "^19.0.0", - "@angular/cli": "^19.0.0", - "@angular/compiler-cli": "^19.0.0", - "typescript": "5.6.3" - } -} diff --git a/examples/angular/zod/src/app/app.component.ts b/examples/angular/zod/src/app/app.component.ts deleted file mode 100644 index 4644c892b..000000000 --- a/examples/angular/zod/src/app/app.component.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Component } from '@angular/core' -import { TanStackField, injectForm, injectStore } from '@tanstack/angular-form' -import { zodValidator } from '@tanstack/zod-form-adapter' -import { z } from 'zod' - -@Component({ - selector: 'app-root', - standalone: true, - imports: [TanStackField], - template: ` -
-
- - - - @if (firstName.api.state.meta.isTouched) { - @for (error of firstName.api.state.meta.errors; track $index) { -
- {{ error }} -
- } - } - @if (firstName.api.state.meta.isValidating) { -

Validating...

- } -
-
-
- - - - -
- -
- `, -}) -export class AppComponent { - firstNameAsyncValidator = z.string().refine( - async (value) => { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value.includes('error') - }, - { - message: "No 'error' allowed in first name", - }, - ) - - form = injectForm({ - defaultValues: { - firstName: '', - lastName: '', - }, - onSubmit({ value }) { - // Do something with form data - console.log(value) - }, - // Add a validator to support Zod usage in Form and Field (no longer needed with zod@3.24.0 or higher) - validatorAdapter: zodValidator(), - }) - - z = z - - canSubmit = injectStore(this.form, (state) => state.canSubmit) - isSubmitting = injectStore(this.form, (state) => state.isSubmitting) - - handleSubmit(event: SubmitEvent) { - event.preventDefault() - event.stopPropagation() - this.form.handleSubmit() - } -} diff --git a/examples/angular/zod/src/favicon.ico b/examples/angular/zod/src/favicon.ico deleted file mode 100644 index 57614f9c9..000000000 Binary files a/examples/angular/zod/src/favicon.ico and /dev/null differ diff --git a/examples/angular/zod/src/index.html b/examples/angular/zod/src/index.html deleted file mode 100644 index c3c6fbbdd..000000000 --- a/examples/angular/zod/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - Simple - - - - - - - - diff --git a/examples/angular/zod/src/main.ts b/examples/angular/zod/src/main.ts deleted file mode 100644 index 56773910e..000000000 --- a/examples/angular/zod/src/main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { bootstrapApplication } from '@angular/platform-browser' -import { AppComponent } from './app/app.component' - -bootstrapApplication(AppComponent).catch((err) => console.error(err)) diff --git a/examples/angular/zod/tsconfig.app.json b/examples/angular/zod/tsconfig.app.json deleted file mode 100644 index 84f1f992d..000000000 --- a/examples/angular/zod/tsconfig.app.json +++ /dev/null @@ -1,10 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/app", - "types": [] - }, - "files": ["src/main.ts"], - "include": ["src/**/*.d.ts"] -} diff --git a/examples/angular/zod/tsconfig.json b/examples/angular/zod/tsconfig.json deleted file mode 100644 index f077510cd..000000000 --- a/examples/angular/zod/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "compileOnSave": false, - "compilerOptions": { - "outDir": "./dist/out-tsc", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "esModuleInterop": true, - "sourceMap": true, - "declaration": false, - "experimentalDecorators": true, - "moduleResolution": "node", - "importHelpers": true, - "target": "ES2022", - "module": "ES2022", - "useDefineForClassFields": false, - "lib": ["ES2022", "dom"] - }, - "angularCompilerOptions": { - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } -} diff --git a/examples/angular/zod/tsconfig.spec.json b/examples/angular/zod/tsconfig.spec.json deleted file mode 100644 index 47e3dd755..000000000 --- a/examples/angular/zod/tsconfig.spec.json +++ /dev/null @@ -1,9 +0,0 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "./out-tsc/spec", - "types": ["jasmine"] - }, - "include": ["src/**/*.spec.ts", "src/**/*.d.ts"] -} diff --git a/examples/lit/simple/package.json b/examples/lit/simple/package.json index d7d7b70ca..e12d448dc 100644 --- a/examples/lit/simple/package.json +++ b/examples/lit/simple/package.json @@ -13,7 +13,7 @@ "lit": "^3.2.1" }, "devDependencies": { - "vite": "^5.4.11" + "vite": "^6.1.1" }, "browserslist": { "production": [ diff --git a/examples/lit/simple/src/index.ts b/examples/lit/simple/src/index.ts index ab5d2628f..08c585db0 100644 --- a/examples/lit/simple/src/index.ts +++ b/examples/lit/simple/src/index.ts @@ -140,12 +140,8 @@ export class TanStackFormDemo extends LitElement { name: `employees[${index}].jobTitle`, defaultValue: '', validators: { - onChange: ({ - value, - }: { - value: string - }) => { - return value.length === 0 + onChange: ({ value }) => { + return value?.length === 0 ? 'Needs to have a job here' : null }, diff --git a/examples/lit/ui-libraries/package.json b/examples/lit/ui-libraries/package.json index 9844a2213..a82a0756f 100644 --- a/examples/lit/ui-libraries/package.json +++ b/examples/lit/ui-libraries/package.json @@ -14,7 +14,7 @@ "lit": "^3.2.1" }, "devDependencies": { - "vite": "^5.4.11" + "vite": "^6.1.1" }, "browserslist": { "production": [ diff --git a/examples/lit/ui-libraries/src/index.ts b/examples/lit/ui-libraries/src/index.ts index c4ac0f93d..d5e9b48fa 100644 --- a/examples/lit/ui-libraries/src/index.ts +++ b/examples/lit/ui-libraries/src/index.ts @@ -126,12 +126,8 @@ export class TanStackFormDemo extends LitElement { name: `employees[${index}].jobTitle`, defaultValue: '', validators: { - onChange: ({ - value, - }: { - value: string - }) => { - return value.length === 0 + onChange: ({ value }) => { + return value?.length === 0 ? 'Needs to have a job here' : null }, diff --git a/examples/react/array/package.json b/examples/react/array/package.json index 1c23a147a..629504d0a 100644 --- a/examples/react/array/package.json +++ b/examples/react/array/package.json @@ -14,10 +14,10 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "vite": "^5.4.11" + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "vite": "^6.1.1" }, "browserslist": { "production": [ diff --git a/examples/react/compiler/package.json b/examples/react/compiler/package.json index 8da4c74a3..5e2b0f926 100644 --- a/examples/react/compiler/package.json +++ b/examples/react/compiler/package.json @@ -14,12 +14,12 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "babel-plugin-react-compiler": "^19.0.0-beta-0dec889-20241115", - "eslint-plugin-react-compiler": "^19.0.0-beta-0dec889-20241115", - "vite": "^5.4.11" + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "babel-plugin-react-compiler": "19.0.0-beta-e552027-20250112", + "eslint-plugin-react-compiler": "19.0.0-beta-e552027-20250112", + "vite": "^6.1.1" }, "browserslist": { "production": [ diff --git a/examples/react/compiler/src/index.tsx b/examples/react/compiler/src/index.tsx index 67cfca1d3..79c72b804 100644 --- a/examples/react/compiler/src/index.tsx +++ b/examples/react/compiler/src/index.tsx @@ -1,9 +1,9 @@ import { useForm } from '@tanstack/react-form' import * as React from 'react' import { createRoot } from 'react-dom/client' -import type { FieldApi } from '@tanstack/react-form' +import type { AnyFieldApi } from '@tanstack/react-form' -function FieldInfo({ field }: { field: FieldApi }) { +function FieldInfo({ field }: { field: AnyFieldApi }) { return ( <> {field.state.meta.isTouched && field.state.meta.errors.length ? ( diff --git a/examples/react/field-errors-from-form-validators/package.json b/examples/react/field-errors-from-form-validators/package.json index 54c9e28d1..564b42421 100644 --- a/examples/react/field-errors-from-form-validators/package.json +++ b/examples/react/field-errors-from-form-validators/package.json @@ -14,10 +14,10 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "vite": "^5.4.11" + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "vite": "^6.1.1" }, "browserslist": { "production": [ diff --git a/examples/react/next-server-actions/package.json b/examples/react/next-server-actions/package.json index ce4541b7b..aa966b342 100644 --- a/examples/react/next-server-actions/package.json +++ b/examples/react/next-server-actions/package.json @@ -10,14 +10,14 @@ "dependencies": { "@tanstack/react-form": "^0.42.1", "@tanstack/react-store": "^0.7.0", - "next": "15.0.3", + "next": "15.1.7", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { - "@types/node": "^22.10.1", - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", + "@types/node": "^22.10.6", + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", "typescript": "5.6.3" } } diff --git a/examples/react/next-server-actions/src/app/client-component.tsx b/examples/react/next-server-actions/src/app/client-component.tsx index 8942b7477..b7e62909c 100644 --- a/examples/react/next-server-actions/src/app/client-component.tsx +++ b/examples/react/next-server-actions/src/app/client-component.tsx @@ -23,7 +23,7 @@ export const ClientComp = () => { return (
form.handleSubmit()}> {formErrors.map((error) => ( -

{error}

+

{error}

))} }) { +function FieldInfo({ field }: { field: AnyFieldApi }) { return ( <> {field.state.meta.isTouched && field.state.meta.errors.length ? ( diff --git a/examples/react/remix/package.json b/examples/react/remix/package.json index d1757c786..f1f522e01 100644 --- a/examples/react/remix/package.json +++ b/examples/react/remix/package.json @@ -9,8 +9,8 @@ }, "dependencies": { "@remix-run/node": "^2.15.3", - "@remix-run/react": "^2.15.0", - "@remix-run/serve": "^2.15.0", + "@remix-run/react": "^2.15.3", + "@remix-run/serve": "^2.15.3", "@tanstack/react-form": "^0.42.1", "@tanstack/react-store": "^0.7.0", "isbot": "^5.1.17", @@ -19,10 +19,10 @@ }, "devDependencies": { "@remix-run/dev": "^2.15.0", - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", "typescript": "5.6.3", - "vite": "^5.4.11", + "vite": "^6.1.1", "vite-tsconfig-paths": "^5.1.2" }, "engines": { diff --git a/examples/react/simple/package.json b/examples/react/simple/package.json index f6d219ee9..70d041175 100644 --- a/examples/react/simple/package.json +++ b/examples/react/simple/package.json @@ -14,10 +14,10 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "vite": "^5.4.11" + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "vite": "^6.1.1" }, "browserslist": { "production": [ diff --git a/examples/react/simple/src/index.tsx b/examples/react/simple/src/index.tsx index 8e57f3352..79c72b804 100644 --- a/examples/react/simple/src/index.tsx +++ b/examples/react/simple/src/index.tsx @@ -1,9 +1,9 @@ -import type { FieldApi } from '@tanstack/react-form' import { useForm } from '@tanstack/react-form' import * as React from 'react' import { createRoot } from 'react-dom/client' +import type { AnyFieldApi } from '@tanstack/react-form' -function FieldInfo({ field }: { field: FieldApi }) { +function FieldInfo({ field }: { field: AnyFieldApi }) { return ( <> {field.state.meta.isTouched && field.state.meta.errors.length ? ( diff --git a/examples/react/standard-schema/package.json b/examples/react/standard-schema/package.json index da70ee0aa..85e616fa2 100644 --- a/examples/react/standard-schema/package.json +++ b/examples/react/standard-schema/package.json @@ -10,17 +10,17 @@ }, "dependencies": { "@tanstack/react-form": "^0.42.1", - "arktype": "2.0.0-rc.23", + "arktype": "^2.0.0", "react": "^19.0.0", "react-dom": "^19.0.0", "valibot": "^1.0.0-beta.9", "zod": "^3.24.0" }, "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "vite": "^5.4.11" + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "vite": "^6.1.1" }, "browserslist": { "production": [ diff --git a/examples/react/standard-schema/src/index.tsx b/examples/react/standard-schema/src/index.tsx index 6e463526f..2a114f31b 100644 --- a/examples/react/standard-schema/src/index.tsx +++ b/examples/react/standard-schema/src/index.tsx @@ -4,9 +4,9 @@ import * as React from 'react' import { createRoot } from 'react-dom/client' import * as v from 'valibot' import { z } from 'zod' -import type { FieldApi } from '@tanstack/react-form' +import type { AnyFieldApi } from '@tanstack/react-form' -function FieldInfo({ field }: { field: FieldApi }) { +function FieldInfo({ field }: { field: AnyFieldApi }) { return ( <> {field.state.meta.isTouched && field.state.meta.errors.length ? ( diff --git a/examples/react/tanstack-start/app.config.ts b/examples/react/tanstack-start/app.config.ts index f2cde2c11..36b964528 100644 --- a/examples/react/tanstack-start/app.config.ts +++ b/examples/react/tanstack-start/app.config.ts @@ -3,7 +3,7 @@ import tsConfigPaths from 'vite-tsconfig-paths' export default defineConfig({ vite: { - plugins: () => [ + plugins: [ tsConfigPaths({ projects: ['./tsconfig.json'], }), diff --git a/examples/react/tanstack-start/app/client.tsx b/examples/react/tanstack-start/app/client.tsx index f16ba73f6..ffee5f382 100644 --- a/examples/react/tanstack-start/app/client.tsx +++ b/examples/react/tanstack-start/app/client.tsx @@ -4,4 +4,4 @@ import { createRouter } from './router' const router = createRouter() -hydrateRoot(document.getElementById('root')!, ) +hydrateRoot(document, ) diff --git a/examples/react/tanstack-start/app/routeTree.gen.ts b/examples/react/tanstack-start/app/routeTree.gen.ts index 5ecc21f20..5e682936b 100644 --- a/examples/react/tanstack-start/app/routeTree.gen.ts +++ b/examples/react/tanstack-start/app/routeTree.gen.ts @@ -1,12 +1,12 @@ -/* prettier-ignore-start */ - /* eslint-disable */ // @ts-nocheck // noinspection JSUnusedGlobalSymbols -// This file is auto-generated by TanStack Router +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. // Import Routes @@ -16,6 +16,7 @@ import { Route as IndexImport } from './routes/index' // Create/Update Routes const IndexRoute = IndexImport.update({ + id: '/', path: '/', getParentRoute: () => rootRoute, } as any) @@ -36,9 +37,39 @@ declare module '@tanstack/react-router' { // Create and export the route tree -export const routeTree = rootRoute.addChildren({ IndexRoute }) +export interface FileRoutesByFullPath { + '/': typeof IndexRoute +} + +export interface FileRoutesByTo { + '/': typeof IndexRoute +} + +export interface FileRoutesById { + __root__: typeof rootRoute + '/': typeof IndexRoute +} + +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' + fileRoutesByTo: FileRoutesByTo + to: '/' + id: '__root__' | '/' + fileRoutesById: FileRoutesById +} + +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, +} -/* prettier-ignore-end */ +export const routeTree = rootRoute + ._addFileChildren(rootRouteChildren) + ._addFileTypes() /* ROUTE_MANIFEST_START { diff --git a/examples/react/tanstack-start/app/routes/__root.tsx b/examples/react/tanstack-start/app/routes/__root.tsx index 9e824c828..0d2d6abc7 100644 --- a/examples/react/tanstack-start/app/routes/__root.tsx +++ b/examples/react/tanstack-start/app/routes/__root.tsx @@ -1,21 +1,26 @@ -import { createRootRoute } from '@tanstack/react-router' -import { Outlet, ScrollRestoration } from '@tanstack/react-router' -import { Body, Head, Html, Meta, Scripts } from '@tanstack/start' +import { + Outlet, + ScrollRestoration, + createRootRoute, +} from '@tanstack/react-router' +import { Meta, Scripts } from '@tanstack/start' import * as React from 'react' export const Route = createRootRoute({ - meta: () => [ - { - charSet: 'utf-8', - }, - { - name: 'viewport', - content: 'width=device-width, initial-scale=1', - }, - { - title: 'TanStack Form + Start', - }, - ], + head: () => ({ + meta: [ + { + charSet: 'utf-8', + }, + { + name: 'viewport', + content: 'width=device-width, initial-scale=1', + }, + { + title: 'TanStack Form + Start', + }, + ], + }), component: RootComponent, }) @@ -29,15 +34,15 @@ function RootComponent() { function RootDocument({ children }: { children: React.ReactNode }) { return ( - - + + - - + + {children} - - + + ) } diff --git a/examples/react/tanstack-start/app/routes/index.tsx b/examples/react/tanstack-start/app/routes/index.tsx index 0b8e8bb87..3fbc56f67 100644 --- a/examples/react/tanstack-start/app/routes/index.tsx +++ b/examples/react/tanstack-start/app/routes/index.tsx @@ -12,6 +12,7 @@ export const Route = createFileRoute('/')({ function Home() { const { state } = Route.useLoaderData() + const form = useForm({ ...formOpts, transform: useTransform((baseForm) => mergeForm(baseForm, state), [state]), @@ -22,7 +23,7 @@ function Home() { return ( {formErrors.map((error) => ( -

{error}

+

{error}

))} { +export const handleForm = createServerFn({ + method: 'POST', +}) + .validator((data: unknown) => { + if (!(data instanceof FormData)) { + throw new Error('Invalid form data') + } + return data + }) + .handler(async (ctx) => { try { - await serverValidate(ctx, formData) + await serverValidate(ctx.data) } catch (e) { if (e instanceof ServerValidateError) { + // Log form errors or do any other logic here return e.response } // Some other error occurred when parsing the form console.error(e) - return new Response('There was an internal error', { - status: 500, - }) + setResponseStatus(500) + return 'There was an internal error' } - return new Response('Form has validated successfully', { - status: 200, - }) + return 'Form has validated successfully' + }) + +export const getFormDataFromServer = createServerFn({ method: 'GET' }).handler( + async () => { + return getFormData() }, ) - -export const getFormDataFromServer = createServerFn('GET', async (_, ctx) => { - return getFormData(ctx) -}) diff --git a/examples/react/tanstack-start/package.json b/examples/react/tanstack-start/package.json index 72767a6f2..fe2e13683 100644 --- a/examples/react/tanstack-start/package.json +++ b/examples/react/tanstack-start/package.json @@ -11,20 +11,20 @@ "dependencies": { "@tanstack/form-core": "^0.42.1", "@tanstack/react-form": "^0.42.1", - "@tanstack/react-router": "^1.81.1", + "@tanstack/react-router": "^1.95.6", "@tanstack/react-store": "^0.7.0", - "@tanstack/start": "^1.81.1", + "@tanstack/start": "^1.95.7", "react": "^19.0.0", "react-dom": "^19.0.0", - "vinxi": "^0.4.3" + "vinxi": "^0.5.1" }, "devDependencies": { - "@types/node": "^22.10.1", - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", + "@types/node": "^22.10.6", + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", "typescript": "5.6.3", - "vite": "^5.4.11", + "vite": "^6.1.1", "vite-tsconfig-paths": "^5.1.2" } } diff --git a/examples/react/ui-libraries/package.json b/examples/react/ui-libraries/package.json index 37bee77f3..d878e7528 100644 --- a/examples/react/ui-libraries/package.json +++ b/examples/react/ui-libraries/package.json @@ -9,26 +9,26 @@ "test:types": "tsc --noEmit" }, "dependencies": { - "@emotion/react": "11.13.3", - "@emotion/styled": "11.13.0", - "@mantine/core": "7.13.5", - "@mantine/hooks": "7.13.5", - "@mui/material": "5.16.7", + "@emotion/react": "11.14.0", + "@emotion/styled": "11.14.0", + "@mantine/core": "7.16.0", + "@mantine/hooks": "7.16.0", + "@mui/material": "6.4.0", "@tanstack/react-form": "^0.42.1", "@yme/lay-postcss": "0.1.0", - "postcss": "8.4.48", + "postcss": "8.5.1", "postcss-preset-mantine": "1.17.0", "postcss-simple-vars": "7.0.1", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "@vitejs/plugin-react-swc": "^3.7.1", + "@types/react": "^19.0.7", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "@vitejs/plugin-react-swc": "^3.8.0", "typescript": "5.6.3", - "vite": "^5.4.11" + "vite": "^6.1.1" }, "browserslist": { "production": [ diff --git a/examples/react/valibot/.eslintrc.cjs b/examples/react/valibot/.eslintrc.cjs deleted file mode 100644 index 35853b617..000000000 --- a/examples/react/valibot/.eslintrc.cjs +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-check - -/** @type {import('eslint').Linter.Config} */ -const config = { - extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], - rules: { - 'react/no-children-prop': 'off', - }, -} - -module.exports = config diff --git a/examples/react/valibot/.gitignore b/examples/react/valibot/.gitignore deleted file mode 100644 index 4673b022e..000000000 --- a/examples/react/valibot/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -pnpm-lock.yaml -yarn.lock -package-lock.json - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/examples/react/valibot/README.md b/examples/react/valibot/README.md deleted file mode 100644 index 1cf889265..000000000 --- a/examples/react/valibot/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Example - -To run this example: - -- `npm install` -- `npm run dev` diff --git a/examples/react/valibot/index.html b/examples/react/valibot/index.html deleted file mode 100644 index 7415713d8..000000000 --- a/examples/react/valibot/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - TanStack Form React Valibot Example App - - - -
- - - diff --git a/examples/react/valibot/package.json b/examples/react/valibot/package.json deleted file mode 100644 index f45e25e9f..000000000 --- a/examples/react/valibot/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@tanstack/form-example-react-valibot", - "private": true, - "type": "module", - "scripts": { - "dev": "vite --port=3001", - "build": "vite build", - "preview": "vite preview", - "test:types": "tsc" - }, - "dependencies": { - "@tanstack/react-form": "^0.42.1", - "@tanstack/valibot-form-adapter": "^0.42.1", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "valibot": "^1.0.0-beta.9" - }, - "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "vite": "^5.4.11" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/examples/react/valibot/public/emblem-light.svg b/examples/react/valibot/public/emblem-light.svg deleted file mode 100644 index a58e69ad5..000000000 --- a/examples/react/valibot/public/emblem-light.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - emblem-light - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/examples/react/valibot/src/index.tsx b/examples/react/valibot/src/index.tsx deleted file mode 100644 index 7236e82ed..000000000 --- a/examples/react/valibot/src/index.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import * as React from 'react' -import { createRoot } from 'react-dom/client' -import { useForm } from '@tanstack/react-form' -import { valibotValidator } from '@tanstack/valibot-form-adapter' -import * as v from 'valibot' -import type { FieldApi } from '@tanstack/react-form' - -function FieldInfo({ field }: { field: FieldApi }) { - return ( - <> - {field.state.meta.isTouched && field.state.meta.errors.length ? ( - {field.state.meta.errors.join(',')} - ) : null} - {field.state.meta.isValidating ? 'Validating...' : null} - - ) -} - -export default function App() { - const form = useForm({ - defaultValues: { - firstName: '', - lastName: '', - }, - onSubmit: async ({ value }) => { - // Do something with form data - console.log(value) - }, - // Add a validator to support Valibot usage in Form and Field (no longer needed with valibot@1.0.0 or higher) - validatorAdapter: valibotValidator(), - }) - - return ( -
-

Valibot Form Example

- { - e.preventDefault() - e.stopPropagation() - form.handleSubmit() - }} - > -
- {/* A type-safe field component*/} - { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value.includes('error') - }, "No 'error' allowed in first name"), - ), - }} - children={(field) => { - // Avoid hasty abstractions. Render props are great! - return ( - <> - - field.handleChange(e.target.value)} - /> - - - ) - }} - /> -
-
- ( - <> - - field.handleChange(e.target.value)} - /> - - - )} - /> -
- [state.canSubmit, state.isSubmitting]} - children={([canSubmit, isSubmitting]) => ( - - )} - /> - -
- ) -} - -const rootElement = document.getElementById('root')! - -createRoot(rootElement).render( - - - , -) diff --git a/examples/react/valibot/tsconfig.json b/examples/react/valibot/tsconfig.json deleted file mode 100644 index 22b43163b..000000000 --- a/examples/react/valibot/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"] -} diff --git a/examples/react/yup/.eslintrc.cjs b/examples/react/yup/.eslintrc.cjs deleted file mode 100644 index 35853b617..000000000 --- a/examples/react/yup/.eslintrc.cjs +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-check - -/** @type {import('eslint').Linter.Config} */ -const config = { - extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], - rules: { - 'react/no-children-prop': 'off', - }, -} - -module.exports = config diff --git a/examples/react/yup/.gitignore b/examples/react/yup/.gitignore deleted file mode 100644 index 4673b022e..000000000 --- a/examples/react/yup/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -pnpm-lock.yaml -yarn.lock -package-lock.json - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/examples/react/yup/README.md b/examples/react/yup/README.md deleted file mode 100644 index 1cf889265..000000000 --- a/examples/react/yup/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Example - -To run this example: - -- `npm install` -- `npm run dev` diff --git a/examples/react/yup/index.html b/examples/react/yup/index.html deleted file mode 100644 index 69a550ae2..000000000 --- a/examples/react/yup/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - TanStack Form React Yup Example App - - - -
- - - diff --git a/examples/react/yup/package.json b/examples/react/yup/package.json deleted file mode 100644 index b0b77d6d5..000000000 --- a/examples/react/yup/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@tanstack/form-example-react-yup", - "private": true, - "type": "module", - "scripts": { - "dev": "vite --port=3001", - "build": "vite build", - "preview": "vite preview", - "test:types": "tsc" - }, - "dependencies": { - "@tanstack/react-form": "^0.42.1", - "@tanstack/yup-form-adapter": "^0.42.1", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "yup": "^1.5.0" - }, - "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "vite": "^5.4.11" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/examples/react/yup/public/emblem-light.svg b/examples/react/yup/public/emblem-light.svg deleted file mode 100644 index a58e69ad5..000000000 --- a/examples/react/yup/public/emblem-light.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - emblem-light - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/examples/react/yup/src/index.tsx b/examples/react/yup/src/index.tsx deleted file mode 100644 index f3fa3f44e..000000000 --- a/examples/react/yup/src/index.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import * as React from 'react' -import { createRoot } from 'react-dom/client' -import { useForm } from '@tanstack/react-form' -import { yupValidator } from '@tanstack/yup-form-adapter' -import * as yup from 'yup' -import type { FieldApi } from '@tanstack/react-form' - -function FieldInfo({ field }: { field: FieldApi }) { - return ( - <> - {field.state.meta.isTouched && field.state.meta.errors.length ? ( - {field.state.meta.errors.join(',')} - ) : null} - {field.state.meta.isValidating ? 'Validating...' : null} - - ) -} - -export default function App() { - const form = useForm({ - defaultValues: { - firstName: '', - lastName: '', - }, - onSubmit: async ({ value }) => { - // Do something with form data - console.log(value) - }, - // Add a validator to support Yup usage in Form and Field - validatorAdapter: yupValidator(), - }) - - return ( -
-

Yup Form Example

-
{ - e.preventDefault() - e.stopPropagation() - form.handleSubmit() - }} - > -
- {/* A type-safe field component*/} - { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value?.includes('error') - }, - ), - }} - children={(field) => { - // Avoid hasty abstractions. Render props are great! - return ( - <> - - field.handleChange(e.target.value)} - /> - - - ) - }} - /> -
-
- ( - <> - - field.handleChange(e.target.value)} - /> - - - )} - /> -
- [state.canSubmit, state.isSubmitting]} - children={([canSubmit, isSubmitting]) => ( - - )} - /> - -
- ) -} - -const rootElement = document.getElementById('root')! - -createRoot(rootElement).render( - - - , -) diff --git a/examples/react/yup/tsconfig.json b/examples/react/yup/tsconfig.json deleted file mode 100644 index 22b43163b..000000000 --- a/examples/react/yup/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"] -} diff --git a/examples/react/zod/.eslintrc.cjs b/examples/react/zod/.eslintrc.cjs deleted file mode 100644 index 35853b617..000000000 --- a/examples/react/zod/.eslintrc.cjs +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-check - -/** @type {import('eslint').Linter.Config} */ -const config = { - extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], - rules: { - 'react/no-children-prop': 'off', - }, -} - -module.exports = config diff --git a/examples/react/zod/.gitignore b/examples/react/zod/.gitignore deleted file mode 100644 index 4673b022e..000000000 --- a/examples/react/zod/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -pnpm-lock.yaml -yarn.lock -package-lock.json - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/examples/react/zod/README.md b/examples/react/zod/README.md deleted file mode 100644 index 1cf889265..000000000 --- a/examples/react/zod/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Example - -To run this example: - -- `npm install` -- `npm run dev` diff --git a/examples/react/zod/index.html b/examples/react/zod/index.html deleted file mode 100644 index 7e4a7587e..000000000 --- a/examples/react/zod/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - TanStack Form React Zod Example App - - - -
- - - diff --git a/examples/react/zod/package.json b/examples/react/zod/package.json deleted file mode 100644 index b9cb58d9b..000000000 --- a/examples/react/zod/package.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "@tanstack/form-example-react-zod", - "private": true, - "type": "module", - "scripts": { - "dev": "vite --port=3001", - "build": "vite build", - "preview": "vite preview", - "test:types": "tsc" - }, - "dependencies": { - "@tanstack/react-form": "^0.42.1", - "@tanstack/zod-form-adapter": "^0.42.1", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "zod": "^3.24.0" - }, - "devDependencies": { - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "@vitejs/plugin-react": "^4.3.3", - "vite": "^5.4.11" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/examples/react/zod/public/emblem-light.svg b/examples/react/zod/public/emblem-light.svg deleted file mode 100644 index a58e69ad5..000000000 --- a/examples/react/zod/public/emblem-light.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - emblem-light - Created with Sketch. - - - - - - - - \ No newline at end of file diff --git a/examples/react/zod/src/index.tsx b/examples/react/zod/src/index.tsx deleted file mode 100644 index 1f92a6bee..000000000 --- a/examples/react/zod/src/index.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import * as React from 'react' -import { createRoot } from 'react-dom/client' -import { useForm } from '@tanstack/react-form' -import { zodValidator } from '@tanstack/zod-form-adapter' -import { z } from 'zod' -import type { FieldApi } from '@tanstack/react-form' - -function FieldInfo({ field }: { field: FieldApi }) { - return ( - <> - {field.state.meta.isTouched && field.state.meta.errors.length ? ( - {field.state.meta.errors.join(',')} - ) : null} - {field.state.meta.isValidating ? 'Validating...' : null} - - ) -} - -const userSchema = z.object({ - firstName: z.string().refine((val) => val !== 'John', { - message: '[Form] First name cannot be John', - }), - lastName: z.string().min(3, '[Form] Last name must be at least 3 characters'), -}) - -type User = z.infer - -export default function App() { - const form = useForm({ - defaultValues: { - firstName: '', - lastName: '', - } as User, - onSubmit: async ({ value }) => { - // Do something with form data - console.log(value) - }, - // Add a validator to support Zod usage in Form and Field (no longer needed with zod@3.24.0 or higher) - validatorAdapter: zodValidator(), - validators: { - onChange: userSchema, - }, - }) - - return ( -
-

Zod Form Example

-
{ - e.preventDefault() - e.stopPropagation() - form.handleSubmit() - }} - > -
- {/* A type-safe field component*/} - { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value.includes('error') - }, - { - message: "[Field] No 'error' allowed in first name", - }, - ), - }} - children={(field) => { - // Avoid hasty abstractions. Render props are great! - return ( - <> - - field.handleChange(e.target.value)} - /> - - - ) - }} - /> -
-
- ( - <> - - field.handleChange(e.target.value)} - /> - - - )} - /> -
- [state.canSubmit, state.isSubmitting]} - children={([canSubmit, isSubmitting]) => ( - - )} - /> - -
- ) -} - -const rootElement = document.getElementById('root')! - -createRoot(rootElement).render( - - - , -) diff --git a/examples/react/zod/tsconfig.json b/examples/react/zod/tsconfig.json deleted file mode 100644 index 22b43163b..000000000 --- a/examples/react/zod/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "lib": ["DOM", "DOM.Iterable", "ESNext"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"] -} diff --git a/examples/solid/array/package.json b/examples/solid/array/package.json index 7aa7d199c..37f5ecec9 100644 --- a/examples/solid/array/package.json +++ b/examples/solid/array/package.json @@ -10,11 +10,11 @@ }, "dependencies": { "@tanstack/solid-form": "^0.42.1", - "solid-js": "^1.9.3" + "solid-js": "^1.9.4" }, "devDependencies": { "typescript": "5.6.3", - "vite": "^5.4.11", - "vite-plugin-solid": "^2.11.0" + "vite": "^6.1.1", + "vite-plugin-solid": "^2.11.2" } } diff --git a/examples/solid/simple/package.json b/examples/solid/simple/package.json index f38ed66db..e29bf3765 100644 --- a/examples/solid/simple/package.json +++ b/examples/solid/simple/package.json @@ -10,11 +10,11 @@ }, "dependencies": { "@tanstack/solid-form": "^0.42.1", - "solid-js": "^1.9.3" + "solid-js": "^1.9.4" }, "devDependencies": { "typescript": "5.6.3", - "vite": "^5.4.11", - "vite-plugin-solid": "^2.11.0" + "vite": "^6.1.1", + "vite-plugin-solid": "^2.11.2" } } diff --git a/examples/solid/simple/src/index.tsx b/examples/solid/simple/src/index.tsx index 740dc0e78..480787f02 100644 --- a/examples/solid/simple/src/index.tsx +++ b/examples/solid/simple/src/index.tsx @@ -2,10 +2,10 @@ import { render } from 'solid-js/web' import { createForm } from '@tanstack/solid-form' -import type { FieldApi } from '@tanstack/solid-form' +import type { AnyFieldApi } from '@tanstack/solid-form' interface FieldInfoProps { - field: FieldApi + field: AnyFieldApi } function FieldInfo(props: FieldInfoProps) { diff --git a/examples/solid/valibot/.gitignore b/examples/solid/valibot/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/examples/solid/valibot/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/examples/solid/valibot/README.md b/examples/solid/valibot/README.md deleted file mode 100644 index 99613fc0a..000000000 --- a/examples/solid/valibot/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Usage - -```bash -$ npm install # or pnpm install or yarn install -``` - -### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs) - -## Available Scripts - -In the project directory, you can run: - -### `npm run dev` - -Runs the app in the development mode.
-Open [http://localhost:5173](http://localhost:5173) to view it in the browser. - -### `npm run build` - -Builds the app for production to the `dist` folder.
-It correctly bundles Solid in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-Your app is ready to be deployed! - -## Deployment - -Learn more about deploying your application with the [documentations](https://vitejs.dev/guide/static-deploy.html) diff --git a/examples/solid/valibot/index.html b/examples/solid/valibot/index.html deleted file mode 100644 index b03bbaa4f..000000000 --- a/examples/solid/valibot/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - TanStack Form Solid Valibot Example App - - -
- - - diff --git a/examples/solid/valibot/package.json b/examples/solid/valibot/package.json deleted file mode 100644 index 5ba29285f..000000000 --- a/examples/solid/valibot/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@tanstack/form-example-solid-valibot", - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "test:types": "tsc", - "preview": "vite preview" - }, - "dependencies": { - "@tanstack/solid-form": "^0.42.1", - "@tanstack/valibot-form-adapter": "^0.42.1", - "solid-js": "^1.9.3", - "valibot": "^1.0.0-beta.9" - }, - "devDependencies": { - "typescript": "5.6.3", - "vite": "^5.4.11", - "vite-plugin-solid": "^2.11.0" - } -} diff --git a/examples/solid/valibot/src/index.tsx b/examples/solid/valibot/src/index.tsx deleted file mode 100644 index a1b0ee3f0..000000000 --- a/examples/solid/valibot/src/index.tsx +++ /dev/null @@ -1,123 +0,0 @@ -/* @refresh reload */ -import { render } from 'solid-js/web' - -import { createForm } from '@tanstack/solid-form' -import { valibotValidator } from '@tanstack/valibot-form-adapter' -import * as v from 'valibot' -import type { FieldApi } from '@tanstack/solid-form' - -interface FieldInfoProps { - field: FieldApi -} - -function FieldInfo(props: FieldInfoProps) { - return ( - <> - {props.field.state.meta.isTouched && - props.field.state.meta.errors.length ? ( - {props.field.state.meta.errors.join(',')} - ) : null} - {props.field.state.meta.isValidating ? 'Validating...' : null} - - ) -} - -function App() { - const form = createForm(() => ({ - defaultValues: { - firstName: '', - lastName: '', - }, - onSubmit: async ({ value }) => { - // Do something with form data - console.log(value) - }, - // Add a validator to support Valibot usage in Form and Field (no longer needed with valibot@1.0.0 or higher) - validatorAdapter: valibotValidator(), - })) - - return ( -
-

Valibot Form Example

-
{ - e.preventDefault() - e.stopPropagation() - form.handleSubmit() - }} - > -
- {/* A type-safe field component*/} - { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value.includes('error') - }, "No 'error' allowed in first name"), - ), - }} - children={(field) => { - // Avoid hasty abstractions. Render props are great! - return ( - <> - - field().handleChange(e.target.value)} - /> - - - ) - }} - /> -
-
- ( - <> - - field().handleChange(e.target.value)} - /> - - - )} - /> -
- ({ - canSubmit: state.canSubmit, - isSubmitting: state.isSubmitting, - })} - children={(state) => { - return ( - - ) - }} - /> - -
- ) -} - -const root = document.getElementById('root') - -render(() => , root!) diff --git a/examples/solid/valibot/src/vite-env.d.ts b/examples/solid/valibot/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/examples/solid/valibot/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/examples/solid/valibot/tsconfig.json b/examples/solid/valibot/tsconfig.json deleted file mode 100644 index 576a7f010..000000000 --- a/examples/solid/valibot/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "jsxImportSource": "solid-js", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "vite.config.ts"] -} diff --git a/examples/solid/valibot/vite.config.ts b/examples/solid/valibot/vite.config.ts deleted file mode 100644 index 4095d9be5..000000000 --- a/examples/solid/valibot/vite.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'vite' -import solid from 'vite-plugin-solid' - -export default defineConfig({ - plugins: [solid()], -}) diff --git a/examples/solid/yup/.gitignore b/examples/solid/yup/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/examples/solid/yup/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/examples/solid/yup/README.md b/examples/solid/yup/README.md deleted file mode 100644 index 99613fc0a..000000000 --- a/examples/solid/yup/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Usage - -```bash -$ npm install # or pnpm install or yarn install -``` - -### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs) - -## Available Scripts - -In the project directory, you can run: - -### `npm run dev` - -Runs the app in the development mode.
-Open [http://localhost:5173](http://localhost:5173) to view it in the browser. - -### `npm run build` - -Builds the app for production to the `dist` folder.
-It correctly bundles Solid in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-Your app is ready to be deployed! - -## Deployment - -Learn more about deploying your application with the [documentations](https://vitejs.dev/guide/static-deploy.html) diff --git a/examples/solid/yup/index.html b/examples/solid/yup/index.html deleted file mode 100644 index 5541800f8..000000000 --- a/examples/solid/yup/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - TanStack Form Solid Yup Example App - - -
- - - diff --git a/examples/solid/yup/package.json b/examples/solid/yup/package.json deleted file mode 100644 index e15015c41..000000000 --- a/examples/solid/yup/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@tanstack/form-example-solid-yup", - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "test:types": "tsc", - "preview": "vite preview" - }, - "dependencies": { - "@tanstack/solid-form": "^0.42.1", - "@tanstack/yup-form-adapter": "^0.42.1", - "solid-js": "^1.9.3", - "yup": "^1.5.0" - }, - "devDependencies": { - "typescript": "5.6.3", - "vite": "^5.4.11", - "vite-plugin-solid": "^2.11.0" - } -} diff --git a/examples/solid/yup/src/index.tsx b/examples/solid/yup/src/index.tsx deleted file mode 100644 index 86f303e3b..000000000 --- a/examples/solid/yup/src/index.tsx +++ /dev/null @@ -1,125 +0,0 @@ -/* @refresh reload */ -import { render } from 'solid-js/web' - -import { createForm } from '@tanstack/solid-form' -import { yupValidator } from '@tanstack/yup-form-adapter' -import * as yup from 'yup' -import type { FieldApi } from '@tanstack/solid-form' - -interface FieldInfoProps { - field: FieldApi -} - -function FieldInfo(props: FieldInfoProps) { - return ( - <> - {props.field.state.meta.isTouched && - props.field.state.meta.errors.length ? ( - {props.field.state.meta.errors.join(',')} - ) : null} - {props.field.state.meta.isValidating ? 'Validating...' : null} - - ) -} - -function App() { - const form = createForm(() => ({ - defaultValues: { - firstName: '', - lastName: '', - }, - onSubmit: async ({ value }) => { - // Do something with form data - console.log(value) - }, - // Add a validator to support Yup usage in Form and Field - validatorAdapter: yupValidator(), - })) - - return ( -
-

Yup Form Example

-
{ - e.preventDefault() - e.stopPropagation() - form.handleSubmit() - }} - > -
- {/* A type-safe field component*/} - { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value?.includes('error') - }, - ), - }} - children={(field) => { - // Avoid hasty abstractions. Render props are great! - return ( - <> - - field().handleChange(e.target.value)} - /> - - - ) - }} - /> -
-
- ( - <> - - field().handleChange(e.target.value)} - /> - - - )} - /> -
- ({ - canSubmit: state.canSubmit, - isSubmitting: state.isSubmitting, - })} - children={(state) => { - return ( - - ) - }} - /> - -
- ) -} - -const root = document.getElementById('root') - -render(() => , root!) diff --git a/examples/solid/yup/src/vite-env.d.ts b/examples/solid/yup/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/examples/solid/yup/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/examples/solid/yup/tsconfig.json b/examples/solid/yup/tsconfig.json deleted file mode 100644 index 576a7f010..000000000 --- a/examples/solid/yup/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "jsxImportSource": "solid-js", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "vite.config.ts"] -} diff --git a/examples/solid/yup/vite.config.ts b/examples/solid/yup/vite.config.ts deleted file mode 100644 index 4095d9be5..000000000 --- a/examples/solid/yup/vite.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'vite' -import solid from 'vite-plugin-solid' - -export default defineConfig({ - plugins: [solid()], -}) diff --git a/examples/solid/zod/.gitignore b/examples/solid/zod/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/examples/solid/zod/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/examples/solid/zod/README.md b/examples/solid/zod/README.md deleted file mode 100644 index 99613fc0a..000000000 --- a/examples/solid/zod/README.md +++ /dev/null @@ -1,28 +0,0 @@ -## Usage - -```bash -$ npm install # or pnpm install or yarn install -``` - -### Learn more on the [Solid Website](https://solidjs.com) and come chat with us on our [Discord](https://discord.com/invite/solidjs) - -## Available Scripts - -In the project directory, you can run: - -### `npm run dev` - -Runs the app in the development mode.
-Open [http://localhost:5173](http://localhost:5173) to view it in the browser. - -### `npm run build` - -Builds the app for production to the `dist` folder.
-It correctly bundles Solid in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-Your app is ready to be deployed! - -## Deployment - -Learn more about deploying your application with the [documentations](https://vitejs.dev/guide/static-deploy.html) diff --git a/examples/solid/zod/index.html b/examples/solid/zod/index.html deleted file mode 100644 index c190da3c3..000000000 --- a/examples/solid/zod/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - TanStack Form Solid Zod Example App - - -
- - - diff --git a/examples/solid/zod/package.json b/examples/solid/zod/package.json deleted file mode 100644 index 9d897d9b1..000000000 --- a/examples/solid/zod/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "@tanstack/form-example-solid-zod", - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "test:types": "tsc", - "preview": "vite preview" - }, - "dependencies": { - "@tanstack/solid-form": "^0.42.1", - "@tanstack/zod-form-adapter": "^0.42.1", - "solid-js": "^1.9.3", - "zod": "^3.24.0" - }, - "devDependencies": { - "typescript": "5.6.3", - "vite": "^5.4.11", - "vite-plugin-solid": "^2.11.0" - } -} diff --git a/examples/solid/zod/src/index.tsx b/examples/solid/zod/src/index.tsx deleted file mode 100644 index 34121192e..000000000 --- a/examples/solid/zod/src/index.tsx +++ /dev/null @@ -1,124 +0,0 @@ -/* @refresh reload */ -import { render } from 'solid-js/web' - -import { createForm } from '@tanstack/solid-form' -import { zodValidator } from '@tanstack/zod-form-adapter' -import { z } from 'zod' -import type { FieldApi } from '@tanstack/solid-form' - -interface FieldInfoProps { - field: FieldApi -} - -function FieldInfo(props: FieldInfoProps) { - return ( - <> - {props.field.state.meta.isTouched && - props.field.state.meta.errors.length ? ( - {props.field.state.meta.errors.join(',')} - ) : null} - {props.field.state.meta.isValidating ? 'Validating...' : null} - - ) -} - -function App() { - const form = createForm(() => ({ - defaultValues: { - firstName: '', - lastName: '', - }, - onSubmit: async ({ value }) => { - // Do something with form data - console.log(value) - }, - // Add a validator to support Zod usage in Form and Field (no longer needed with zod@3.24.0 or higher) - validatorAdapter: zodValidator(), - })) - - return ( -
-

Zod Form Example

-
{ - e.preventDefault() - e.stopPropagation() - form.handleSubmit() - }} - > -
- {/* A type-safe field component*/} - { - await new Promise((resolve) => setTimeout(resolve, 1000)) - return !value.includes('error') - }, - { - message: "No 'error' allowed in first name", - }, - ), - }} - children={(field) => { - // Avoid hasty abstractions. Render props are great! - return ( - <> - - field().handleChange(e.target.value)} - /> - - - ) - }} - /> -
-
- ( - <> - - field().handleChange(e.target.value)} - /> - - - )} - /> -
- ({ - canSubmit: state.canSubmit, - isSubmitting: state.isSubmitting, - })} - children={(state) => { - return ( - - ) - }} - /> - -
- ) -} - -const root = document.getElementById('root') - -render(() => , root!) diff --git a/examples/solid/zod/src/vite-env.d.ts b/examples/solid/zod/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/examples/solid/zod/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/examples/solid/zod/tsconfig.json b/examples/solid/zod/tsconfig.json deleted file mode 100644 index 576a7f010..000000000 --- a/examples/solid/zod/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "jsxImportSource": "solid-js", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "vite.config.ts"] -} diff --git a/examples/solid/zod/vite.config.ts b/examples/solid/zod/vite.config.ts deleted file mode 100644 index 4095d9be5..000000000 --- a/examples/solid/zod/vite.config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { defineConfig } from 'vite' -import solid from 'vite-plugin-solid' - -export default defineConfig({ - plugins: [solid()], -}) diff --git a/examples/vue/array/package.json b/examples/vue/array/package.json index b4cbfc2f1..416d37ec0 100644 --- a/examples/vue/array/package.json +++ b/examples/vue/array/package.json @@ -11,12 +11,12 @@ }, "dependencies": { "@tanstack/vue-form": "^0.42.1", - "vue": "^3.5.12" + "vue": "^3.5.13" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", "typescript": "5.6.3", - "vite": "^5.4.11", - "vue-tsc": "^2.0.26" + "vite": "^6.1.1", + "vue-tsc": "^2.2.2" } } diff --git a/examples/vue/simple/package.json b/examples/vue/simple/package.json index 0a7349993..560fe8e02 100644 --- a/examples/vue/simple/package.json +++ b/examples/vue/simple/package.json @@ -11,12 +11,12 @@ }, "dependencies": { "@tanstack/vue-form": "^0.42.1", - "vue": "^3.5.12" + "vue": "^3.5.13" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", "typescript": "5.6.3", - "vite": "^5.4.11", - "vue-tsc": "^2.0.26" + "vite": "^6.1.1", + "vue-tsc": "^2.2.2" } } diff --git a/examples/vue/simple/src/App.vue b/examples/vue/simple/src/App.vue index 2338de016..1e85c8e97 100644 --- a/examples/vue/simple/src/App.vue +++ b/examples/vue/simple/src/App.vue @@ -30,9 +30,6 @@ async function onChangeFirstName({ value }: { value: string }) { " >
- - - -import { FieldApi } from '@tanstack/vue-form' +import { AnyFieldApi } from '@tanstack/vue-form' const props = defineProps<{ - state: FieldApi['state'] + state: AnyFieldApi['state'] }>() diff --git a/examples/vue/valibot/.gitignore b/examples/vue/valibot/.gitignore deleted file mode 100644 index 449e8098b..000000000 --- a/examples/vue/valibot/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -node_modules -.DS_Store -dist -dist-ssr -*.local - -package-lock.json -yarn.lock -pnpm-lock.yaml diff --git a/examples/vue/valibot/README.md b/examples/vue/valibot/README.md deleted file mode 100644 index 28462a4ad..000000000 --- a/examples/vue/valibot/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Basic example - -To run this example: - -- `npm install` or `yarn` or `pnpm i` -- `npm run dev` or `yarn dev` or `pnpm dev` diff --git a/examples/vue/valibot/index.html b/examples/vue/valibot/index.html deleted file mode 100644 index 892a37a95..000000000 --- a/examples/vue/valibot/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - TanStack Form Vue Valibot Example App - - -
- - - diff --git a/examples/vue/valibot/package.json b/examples/vue/valibot/package.json deleted file mode 100644 index c154ae1e1..000000000 --- a/examples/vue/valibot/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@tanstack/form-example-vue-valibot", - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "build:dev": "vite build -m development", - "test:types": "vue-tsc", - "serve": "vite preview" - }, - "dependencies": { - "@tanstack/valibot-form-adapter": "^0.42.1", - "@tanstack/vue-form": "^0.42.1", - "valibot": "^1.0.0-beta.9", - "vue": "^3.5.12" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^5.2.1", - "typescript": "5.6.3", - "vite": "^5.4.11", - "vue-tsc": "^2.0.26" - } -} diff --git a/examples/vue/valibot/src/App.vue b/examples/vue/valibot/src/App.vue deleted file mode 100644 index ed7b79611..000000000 --- a/examples/vue/valibot/src/App.vue +++ /dev/null @@ -1,94 +0,0 @@ - - - diff --git a/examples/vue/valibot/src/FieldInfo.vue b/examples/vue/valibot/src/FieldInfo.vue deleted file mode 100644 index 96e068714..000000000 --- a/examples/vue/valibot/src/FieldInfo.vue +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/examples/vue/valibot/src/main.ts b/examples/vue/valibot/src/main.ts deleted file mode 100644 index 912d54f8d..000000000 --- a/examples/vue/valibot/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createApp } from 'vue' - -import App from './App.vue' - -createApp(App).mount('#app') diff --git a/examples/vue/valibot/src/shims-vue.d.ts b/examples/vue/valibot/src/shims-vue.d.ts deleted file mode 100644 index ac1ded792..000000000 --- a/examples/vue/valibot/src/shims-vue.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module '*.vue' { - import { DefineComponent } from 'vue' - const component: DefineComponent<{}, {}, any> - export default component -} diff --git a/examples/vue/valibot/src/types.d.ts b/examples/vue/valibot/src/types.d.ts deleted file mode 100644 index 4851e8102..000000000 --- a/examples/vue/valibot/src/types.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface Post { - userId: number - id: number - title: string - body: string -} diff --git a/examples/vue/valibot/tsconfig.json b/examples/vue/valibot/tsconfig.json deleted file mode 100644 index 62eb2b161..000000000 --- a/examples/vue/valibot/tsconfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"] -} diff --git a/examples/vue/valibot/vite.config.ts b/examples/vue/valibot/vite.config.ts deleted file mode 100644 index 804a28720..000000000 --- a/examples/vue/valibot/vite.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vue()], - optimizeDeps: { - exclude: ['@tanstack/vue-form'], - }, -}) diff --git a/examples/vue/yup/.gitignore b/examples/vue/yup/.gitignore deleted file mode 100644 index 449e8098b..000000000 --- a/examples/vue/yup/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -node_modules -.DS_Store -dist -dist-ssr -*.local - -package-lock.json -yarn.lock -pnpm-lock.yaml diff --git a/examples/vue/yup/README.md b/examples/vue/yup/README.md deleted file mode 100644 index 28462a4ad..000000000 --- a/examples/vue/yup/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Basic example - -To run this example: - -- `npm install` or `yarn` or `pnpm i` -- `npm run dev` or `yarn dev` or `pnpm dev` diff --git a/examples/vue/yup/index.html b/examples/vue/yup/index.html deleted file mode 100644 index 85423040d..000000000 --- a/examples/vue/yup/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - TanStack Form Vue Yup Example App - - -
- - - diff --git a/examples/vue/yup/package.json b/examples/vue/yup/package.json deleted file mode 100644 index b143e67ec..000000000 --- a/examples/vue/yup/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@tanstack/form-example-vue-yup", - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "build:dev": "vite build -m development", - "test:types": "vue-tsc", - "serve": "vite preview" - }, - "dependencies": { - "@tanstack/vue-form": "^0.42.1", - "@tanstack/yup-form-adapter": "^0.42.1", - "vue": "^3.5.12", - "yup": "^1.5.0" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^5.2.1", - "typescript": "5.6.3", - "vite": "^5.4.11", - "vue-tsc": "^2.0.26" - } -} diff --git a/examples/vue/yup/src/App.vue b/examples/vue/yup/src/App.vue deleted file mode 100644 index 32d3c59e0..000000000 --- a/examples/vue/yup/src/App.vue +++ /dev/null @@ -1,92 +0,0 @@ - - - diff --git a/examples/vue/yup/src/FieldInfo.vue b/examples/vue/yup/src/FieldInfo.vue deleted file mode 100644 index 96e068714..000000000 --- a/examples/vue/yup/src/FieldInfo.vue +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/examples/vue/yup/src/main.ts b/examples/vue/yup/src/main.ts deleted file mode 100644 index 912d54f8d..000000000 --- a/examples/vue/yup/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createApp } from 'vue' - -import App from './App.vue' - -createApp(App).mount('#app') diff --git a/examples/vue/yup/src/shims-vue.d.ts b/examples/vue/yup/src/shims-vue.d.ts deleted file mode 100644 index ac1ded792..000000000 --- a/examples/vue/yup/src/shims-vue.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module '*.vue' { - import { DefineComponent } from 'vue' - const component: DefineComponent<{}, {}, any> - export default component -} diff --git a/examples/vue/yup/src/types.d.ts b/examples/vue/yup/src/types.d.ts deleted file mode 100644 index 4851e8102..000000000 --- a/examples/vue/yup/src/types.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface Post { - userId: number - id: number - title: string - body: string -} diff --git a/examples/vue/yup/tsconfig.json b/examples/vue/yup/tsconfig.json deleted file mode 100644 index 62eb2b161..000000000 --- a/examples/vue/yup/tsconfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"] -} diff --git a/examples/vue/yup/vite.config.ts b/examples/vue/yup/vite.config.ts deleted file mode 100644 index 804a28720..000000000 --- a/examples/vue/yup/vite.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vue()], - optimizeDeps: { - exclude: ['@tanstack/vue-form'], - }, -}) diff --git a/examples/vue/zod/.gitignore b/examples/vue/zod/.gitignore deleted file mode 100644 index 449e8098b..000000000 --- a/examples/vue/zod/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -node_modules -.DS_Store -dist -dist-ssr -*.local - -package-lock.json -yarn.lock -pnpm-lock.yaml diff --git a/examples/vue/zod/README.md b/examples/vue/zod/README.md deleted file mode 100644 index 28462a4ad..000000000 --- a/examples/vue/zod/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Basic example - -To run this example: - -- `npm install` or `yarn` or `pnpm i` -- `npm run dev` or `yarn dev` or `pnpm dev` diff --git a/examples/vue/zod/index.html b/examples/vue/zod/index.html deleted file mode 100644 index 86c212697..000000000 --- a/examples/vue/zod/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - TanStack Form Vue Zod Example App - - -
- - - diff --git a/examples/vue/zod/package.json b/examples/vue/zod/package.json deleted file mode 100644 index d4cedc7fb..000000000 --- a/examples/vue/zod/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "@tanstack/form-example-vue-zod", - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "build:dev": "vite build -m development", - "test:types": "vue-tsc", - "serve": "vite preview" - }, - "dependencies": { - "@tanstack/vue-form": "^0.42.1", - "@tanstack/zod-form-adapter": "^0.42.1", - "vue": "^3.5.12", - "zod": "^3.24.0" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^5.2.1", - "typescript": "5.6.3", - "vite": "^5.4.11", - "vue-tsc": "^2.0.26" - } -} diff --git a/examples/vue/zod/src/App.vue b/examples/vue/zod/src/App.vue deleted file mode 100644 index 0700e0afd..000000000 --- a/examples/vue/zod/src/App.vue +++ /dev/null @@ -1,95 +0,0 @@ - - - diff --git a/examples/vue/zod/src/FieldInfo.vue b/examples/vue/zod/src/FieldInfo.vue deleted file mode 100644 index 96e068714..000000000 --- a/examples/vue/zod/src/FieldInfo.vue +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/examples/vue/zod/src/main.ts b/examples/vue/zod/src/main.ts deleted file mode 100644 index 912d54f8d..000000000 --- a/examples/vue/zod/src/main.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createApp } from 'vue' - -import App from './App.vue' - -createApp(App).mount('#app') diff --git a/examples/vue/zod/src/shims-vue.d.ts b/examples/vue/zod/src/shims-vue.d.ts deleted file mode 100644 index ac1ded792..000000000 --- a/examples/vue/zod/src/shims-vue.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module '*.vue' { - import { DefineComponent } from 'vue' - const component: DefineComponent<{}, {}, any> - export default component -} diff --git a/examples/vue/zod/src/types.d.ts b/examples/vue/zod/src/types.d.ts deleted file mode 100644 index 4851e8102..000000000 --- a/examples/vue/zod/src/types.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface Post { - userId: number - id: number - title: string - body: string -} diff --git a/examples/vue/zod/tsconfig.json b/examples/vue/zod/tsconfig.json deleted file mode 100644 index 62eb2b161..000000000 --- a/examples/vue/zod/tsconfig.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "Bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"] -} diff --git a/examples/vue/zod/vite.config.ts b/examples/vue/zod/vite.config.ts deleted file mode 100644 index 804a28720..000000000 --- a/examples/vue/zod/vite.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vue()], - optimizeDeps: { - exclude: ['@tanstack/vue-form'], - }, -}) diff --git a/knip.json b/knip.json index e7d196211..5e796abe1 100644 --- a/knip.json +++ b/knip.json @@ -1,5 +1,5 @@ { "$schema": "https://unpkg.com/knip@5/schema.json", - "ignoreDependencies": ["@tanstack/start"], + "ignoreDependencies": ["@tanstack/start", "vinxi"], "ignoreWorkspaces": ["examples/**"] } diff --git a/package.json b/package.json index 23a4c2b53..c73db5063 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "test:ci": "nx run-many --targets=test:sherif,test:knip,test:eslint,test:lib,test:types,test:build,build", "test:eslint": "nx affected --target=test:eslint", "test:format": "pnpm run prettier --check", - "test:sherif": "sherif -i react -i react-dom", + "test:sherif": "sherif", "test:lib": "nx affected --target=test:lib --exclude=examples/**", "test:lib:dev": "pnpm run test:lib && nx watch --all -- pnpm run test:lib", "test:build": "nx affected --target=test:build --exclude=examples/**", @@ -38,23 +38,23 @@ ] }, "devDependencies": { - "@eslint-react/eslint-plugin": "^1.23.2", + "@eslint-react/eslint-plugin": "^1.17.3", "@solidjs/testing-library": "^0.8.10", - "@tanstack/config": "^0.15.1", + "@tanstack/config": "0.15.1", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.1.0", "@testing-library/user-event": "^14.5.2", "@testing-library/vue": "^8.1.0", - "@types/node": "^22.10.1", - "@vitest/coverage-istanbul": "^2.1.8", - "eslint": "^9.16.0", + "@types/node": "^22.10.6", + "@vitest/coverage-istanbul": "^3.0.6", + "eslint": "9.18.0", "eslint-plugin-react-hooks": "^5.1.0", - "jsdom": "^25.0.1", + "jsdom": "^26.0.0", "knip": "^5.39.2", "nx": "20.4.0", "premove": "^4.0.0", "prettier": "^3.4.2", - "publint": "^0.2.12", + "publint": "^0.3.2", "sherif": "^1.0.2", "typescript": "5.6.3", "typescript51": "npm:typescript@5.1", @@ -62,7 +62,13 @@ "typescript53": "npm:typescript@5.3", "typescript54": "npm:typescript@5.4", "typescript55": "npm:typescript@5.5", - "vite": "^5.4.11", - "vitest": "^2.1.8" + "vite": "^6.1.1", + "vitest": "^3.0.6" + }, + "pnpm": { + "//": "https://github.com/jsdom/cssstyle/issues/182", + "overrides": { + "cssstyle": "4.1.0" + } } } diff --git a/packages/angular-form/package.json b/packages/angular-form/package.json index d7f1a954e..9023b8fff 100644 --- a/packages/angular-form/package.json +++ b/packages/angular-form/package.json @@ -43,11 +43,11 @@ ], "dependencies": { "@tanstack/angular-store": "^0.7.0", - "@tanstack/form-core": "workspace:*", + "@tanstack/form-core": "^0.42.1", "tslib": "^2.8.1" }, "devDependencies": { - "@analogjs/vite-plugin-angular": "^1.12.0", + "@analogjs/vite-plugin-angular": "^1.13.1", "@angular/common": "^19.0.0", "@angular/compiler": "^19.0.0", "@angular/compiler-cli": "^19.0.0", diff --git a/packages/angular-form/src/inject-form.ts b/packages/angular-form/src/inject-form.ts index 4c5ac3a64..1eb6820d9 100644 --- a/packages/angular-form/src/inject-form.ts +++ b/packages/angular-form/src/inject-form.ts @@ -1,12 +1,45 @@ import { FormApi } from '@tanstack/form-core' import { injectStore } from '@tanstack/angular-store' -import type { FormOptions, Validator } from '@tanstack/form-core' +import type { + FormAsyncValidateOrFn, + FormOptions, + FormValidateOrFn, +} from '@tanstack/form-core' export function injectForm< TFormData, - TFormValidator extends Validator | undefined = undefined, ->(opts?: FormOptions) { - const api = new FormApi(opts) + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, +>( + opts?: FormOptions< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >, +) { + const api = new FormApi< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >(opts) injectStore(api.store, (state) => state.isSubmitting) diff --git a/packages/angular-form/src/inject-store.ts b/packages/angular-form/src/inject-store.ts index 5d499d836..6b7177d85 100644 --- a/packages/angular-form/src/inject-store.ts +++ b/packages/angular-form/src/inject-store.ts @@ -1,13 +1,61 @@ import { injectStore as injectAngularStore } from '@tanstack/angular-store' -import type { FormApi, FormState, Validator } from '@tanstack/form-core' +import type { + FormApi, + FormAsyncValidateOrFn, + FormState, + FormValidateOrFn, +} from '@tanstack/form-core' export function injectStore< TFormData, - TFormValidator extends Validator | undefined = undefined, - TSelected = NoInfer>, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, + TSelected = NoInfer< + FormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > + >, >( - form: FormApi, - selector?: (state: NoInfer>) => TSelected, + form: FormApi< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >, + selector?: ( + state: NoInfer< + FormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > + >, + ) => TSelected, ) { return injectAngularStore(form.store, selector) } diff --git a/packages/angular-form/src/tanstack-field.directive.ts b/packages/angular-form/src/tanstack-field.directive.ts index c23fa9189..05c28daa8 100644 --- a/packages/angular-form/src/tanstack-field.directive.ts +++ b/packages/angular-form/src/tanstack-field.directive.ts @@ -4,8 +4,13 @@ import { booleanAttribute, numberAttribute, } from '@angular/core' -import { FieldApi, FormApi } from '@tanstack/form-core' -import type { OnChanges, OnDestroy, OnInit } from '@angular/core' +import { + FieldApi, + FieldApiOptions, + FieldAsyncValidateOrFn, + FieldValidateOrFn, + FormApi, +} from '@tanstack/form-core' import type { DeepKeys, DeepValue, @@ -13,9 +18,11 @@ import type { FieldMeta, FieldOptions, FieldValidators, + FormAsyncValidateOrFn, + FormValidateOrFn, NoInfer as NoInferHack, - Validator, } from '@tanstack/form-core' +import type { OnChanges, OnDestroy, OnInit } from '@angular/core' @Directive({ selector: '[tanstackField]', @@ -25,19 +32,45 @@ import type { export class TanStackField< TParentData, const TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFormOnServer extends undefined | FormAsyncValidateOrFn, > implements OnInit, OnChanges, OnDestroy, - FieldOptions + FieldOptions< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > { @Input({ required: true }) name!: TName // Setting as NoInferHack as it's the same internal type cast as TanStack Form Core @@ -46,27 +79,101 @@ export class TanStackField< @Input() defaultValue?: NoInferHack @Input({ transform: numberAttribute }) asyncDebounceMs?: number @Input({ transform: booleanAttribute }) asyncAlways?: boolean - @Input() validatorAdapter?: TFieldValidator @Input({ required: true }) tanstackField!: FormApi< TParentData, - TFormValidator + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer > @Input() validators?: NoInfer< - FieldValidators + FieldValidators< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > > - @Input() listeners?: NoInfer< - FieldListeners + @Input() listeners?: NoInfer> + @Input() defaultMeta?: Partial< + FieldMeta< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync + > > - @Input() defaultMeta?: Partial + @Input() disableErrorFlat?: boolean - api!: FieldApi + api!: FieldApi< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + > - private getOptions() { + private getOptions(): FieldApiOptions< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + > { return { defaultValue: this.defaultValue, asyncDebounceMs: this.asyncDebounceMs, asyncAlways: this.asyncAlways, - validatorAdapter: this.validatorAdapter, + disableErrorFlat: this.disableErrorFlat, validators: this.validators, listeners: this.listeners, defaultMeta: this.defaultMeta, diff --git a/packages/angular-form/tests/test.component.spec.ts b/packages/angular-form/tests/test.component.spec.ts index 04d1e4c1e..db994a786 100644 --- a/packages/angular-form/tests/test.component.spec.ts +++ b/packages/angular-form/tests/test.component.spec.ts @@ -67,11 +67,11 @@ describe('TanStackFieldDirective', () => { imports: [TanStackField], }) class TestComponent { - form = injectForm({ + form = injectForm({ defaultValues: { firstName: 'FirstName', lastName: 'LastName', - }, + } as Person, }) } @@ -119,11 +119,11 @@ describe('TanStackFieldDirective', () => { otherValidator: FieldValidateFn = ({ value }) => value === 'other' ? error : undefined - form = injectForm({ + form = injectForm({ defaultValues: { firstName: 'FirstName', lastName: 'LastName', - }, + } as Person, }) } @@ -166,11 +166,11 @@ describe('TanStackFieldDirective', () => { otherValidator: FieldValidateFn = ({ value }) => value === 'other' ? error : undefined - form = injectForm({ + form = injectForm({ defaultValues: { firstName: '', lastName: '', - }, + } as Person, }) } @@ -224,11 +224,11 @@ describe('TanStackFieldDirective', () => { onBlur: FieldValidateFn = ({ value }) => value === 'other' ? onBlurError : undefined - form = injectForm({ + form = injectForm({ defaultValues: { firstName: '', lastName: '', - }, + } as Person, }) } @@ -278,11 +278,11 @@ describe('TanStackFieldDirective', () => { return error } - form = injectForm({ + form = injectForm({ defaultValues: { firstName: '', lastName: '', - }, + } as Person, }) } @@ -341,11 +341,11 @@ describe('TanStackFieldDirective', () => { return onBlurError } - form = injectForm({ + form = injectForm({ defaultValues: { firstName: '', lastName: '', - }, + } as Person, }) } diff --git a/packages/form-core/package.json b/packages/form-core/package.json index 5d7774fc3..8c38586b1 100644 --- a/packages/form-core/package.json +++ b/packages/form-core/package.json @@ -55,7 +55,7 @@ "@tanstack/store": "^0.7.0" }, "devDependencies": { - "arktype": "2.0.0-rc.23", + "arktype": "^2.0.0", "valibot": "^1.0.0-beta.9", "zod": "^3.24.0" } diff --git a/packages/form-core/src/FieldApi.ts b/packages/form-core/src/FieldApi.ts index 87dbaa650..ca08c40d2 100644 --- a/packages/form-core/src/FieldApi.ts +++ b/packages/form-core/src/FieldApi.ts @@ -1,39 +1,104 @@ import { Derived, batch } from '@tanstack/store' import { isStandardSchemaValidator, - standardSchemaValidator, + standardSchemaValidators, } from './standardSchemaValidator' import { getAsyncValidatorArray, getBy, getSyncValidatorArray } from './utils' -import type { FieldInfo, FieldsErrorMapFromValidator, FormApi } from './FormApi' -import type { StandardSchemaV1 } from './standardSchemaValidator' +import type { + DeepKeys, + DeepValue, + NoInfer, + UnwrapOneLevelOfArray, +} from './util-types' +import type { + StandardSchemaV1, + StandardSchemaV1Issue, + TStandardSchemaValidatorValue, +} from './standardSchemaValidator' +import type { + FieldInfo, + FormApi, + FormAsyncValidateOrFn, + FormValidateOrFn, + UnwrapFormAsyncValidateOrFn, + UnwrapFormValidateOrFn, +} from './FormApi' import type { UpdateMetaOptions, ValidationCause, ValidationError, ValidationErrorMap, - ValidationSource, - Validator, } from './types' -import type { DeepKeys, DeepValue, NoInfer } from './util-types' import type { AsyncValidator, SyncValidator, Updater } from './utils' +/** + * @private + */ +// TODO: Add the `Unwrap` type to the errors +type FieldErrorMapFromValidator< + TFormData, + TName extends DeepKeys, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, +> = Partial< + Record< + DeepKeys, + ValidationErrorMap< + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > + > +> + /** * @private */ export type FieldValidateFn< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, TData extends DeepValue = DeepValue, > = (props: { value: TData - fieldApi: FieldApi -}) => ValidationError + fieldApi: FieldApi< + TParentData, + TName, + TData, + // This is technically an edge-type; which we try to keep non-`any`, but in this case + // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any + > +}) => unknown /** * @private @@ -41,37 +106,69 @@ export type FieldValidateFn< export type FieldValidateOrFn< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, TData extends DeepValue = DeepValue, > = - | (TFieldValidator extends Validator ? TFN : never) - | (TFormValidator extends Validator ? FFN : never) - | FieldValidateFn + | FieldValidateFn | StandardSchemaV1 +export type UnwrapFieldValidateOrFn< + TParentData, + TName extends DeepKeys, + TValidateOrFn extends undefined | FieldValidateOrFn, + TFormValidateOrFn extends undefined | FormValidateOrFn, +> = + | ([TFormValidateOrFn] extends [StandardSchemaV1] + ? TName extends keyof TStandardOut + ? StandardSchemaV1Issue[] + : undefined + : undefined) + | (UnwrapFormValidateOrFn extends infer TFormValidateVal + ? TFormValidateVal extends { fields: any } + ? TName extends keyof TFormValidateVal['fields'] + ? TFormValidateVal['fields'][TName] + : undefined + : undefined + : never) + | ([TValidateOrFn] extends [FieldValidateFn] + ? ReturnType + : [TValidateOrFn] extends [StandardSchemaV1] + ? // TODO: Check if `disableErrorFlat` is enabled, if so, return StandardSchemaV1Issue[][] + StandardSchemaV1Issue[] + : undefined) + /** * @private */ export type FieldValidateAsyncFn< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, TData extends DeepValue = DeepValue, > = (options: { value: TData - fieldApi: FieldApi + fieldApi: FieldApi< + TParentData, + TName, + TData, + // This is technically an edge-type; which we try to keep non-`any`, but in this case + // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any + > signal: AbortSignal -}) => ValidationError | Promise +}) => unknown | Promise /** * @private @@ -79,90 +176,103 @@ export type FieldValidateAsyncFn< export type FieldAsyncValidateOrFn< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, TData extends DeepValue = DeepValue, > = - | (TFieldValidator extends Validator ? TFN : never) - | (TFormValidator extends Validator ? FFN : never) - | FieldValidateAsyncFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + | FieldValidateAsyncFn | StandardSchemaV1 +export type UnwrapFieldAsyncValidateOrFn< + TParentData, + TName extends DeepKeys, + TValidateOrFn extends undefined | FieldAsyncValidateOrFn, + TFormValidateOrFn extends undefined | FormAsyncValidateOrFn, +> = + | ([TFormValidateOrFn] extends [StandardSchemaV1] + ? TName extends keyof TStandardOut + ? StandardSchemaV1Issue[] + : undefined + : undefined) + | (UnwrapFormAsyncValidateOrFn extends infer TFormValidateVal + ? TFormValidateVal extends { fields: any } + ? TName extends keyof TFormValidateVal['fields'] + ? TFormValidateVal['fields'][TName] + : undefined + : undefined + : never) + | ([TValidateOrFn] extends [FieldValidateAsyncFn] + ? Awaited> + : [TValidateOrFn] extends [StandardSchemaV1] + ? // TODO: Check if `disableErrorFlat` is enabled, if so, return StandardSchemaV1Issue[][] + StandardSchemaV1Issue[] + : undefined) + /** * @private */ export type FieldListenerFn< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, TData extends DeepValue = DeepValue, > = (props: { value: TData - fieldApi: FieldApi + fieldApi: FieldApi< + TParentData, + TName, + TData, + // This is technically an edge-type; which we try to keep non-`any`, but in this case + // It's referring to an inaccessible type from the field listener function inner types, so it's not a big deal + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any + > }) => void export interface FieldValidators< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, > { /** - * An optional function that takes a param of `formApi` which is a generic type of `TData` and `TParentData` + * An optional function, that runs on the mount event of input. */ - onMount?: FieldValidateOrFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + onMount?: TOnMount /** - * An optional property that takes a `ValidateFn` which is a generic of `TData` and `TParentData`. - * If `validatorAdapter` is passed, this may also accept a property from the respective adapter + * An optional function, that runs on the change event of input. * - * @example z.string().min(1) // if `zodAdapter` is passed + * @example z.string().min(1) */ - onChange?: FieldValidateOrFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + onChange?: TOnChange /** - * An optional property similar to `onChange` but async validation. If `validatorAdapter` - * is passed, this may also accept a property from the respective adapter + * An optional property similar to `onChange` but async validation * - * @example z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // if `zodAdapter` is passed + * @example z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) */ - onChangeAsync?: FieldAsyncValidateOrFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + onChangeAsync?: TOnChangeAsync /** * An optional number to represent how long the `onChangeAsync` should wait before running * @@ -175,30 +285,16 @@ export interface FieldValidators< onChangeListenTo?: DeepKeys[] /** * An optional function, that runs on the blur event of input. - * If `validatorAdapter` is passed, this may also accept a property from the respective adapter * - * @example z.string().min(1) // if `zodAdapter` is passed + * @example z.string().min(1) */ - onBlur?: FieldValidateOrFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + onBlur?: TOnBlur /** - * An optional property similar to `onBlur` but async validation. If `validatorAdapter` - * is passed, this may also accept a property from the respective adapter + * An optional property similar to `onBlur` but async validation. * - * @example z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // if `zodAdapter` is passed + * @example z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) */ - onBlurAsync?: FieldAsyncValidateOrFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + onBlurAsync?: TOnBlurAsync /** * An optional number to represent how long the `onBlurAsync` should wait before running @@ -212,71 +308,27 @@ export interface FieldValidators< onBlurListenTo?: DeepKeys[] /** * An optional function, that runs on the submit event of form. - * If `validatorAdapter` is passed, this may also accept a property from the respective adapter * - * @example z.string().min(1) // if `zodAdapter` is passed + * @example z.string().min(1) */ - onSubmit?: FieldValidateOrFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + onSubmit?: TOnSubmit /** - * An optional property similar to `onSubmit` but async validation. If `validatorAdapter` - * is passed, this may also accept a property from the respective adapter + * An optional property similar to `onSubmit` but async validation. * - * @example z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) // if `zodAdapter` is passed + * @example z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) */ - onSubmitAsync?: FieldAsyncValidateOrFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + onSubmitAsync?: TOnSubmitAsync } export interface FieldListeners< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, TData extends DeepValue = DeepValue, > { - onChange?: FieldListenerFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > - onBlur?: FieldListenerFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > - onMount?: FieldListenerFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > - onSubmit?: FieldListenerFn< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + onChange?: FieldListenerFn + onBlur?: FieldListenerFn + onMount?: FieldListenerFn + onSubmit?: FieldListenerFn } /** @@ -285,13 +337,20 @@ export interface FieldListeners< export interface FieldOptions< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, > { /** * The field name. The type will be `DeepKeys` to ensure your name is a deep key of the parent dataset. @@ -309,34 +368,53 @@ export interface FieldOptions< * If `true`, always run async validation, even if there are errors emitted during synchronous validation. */ asyncAlways?: boolean - /** - * A validator provided by an extension, like `yupValidator` from `@tanstack/yup-form-adapter` - */ - validatorAdapter?: TFieldValidator /** * A list of validators to pass to the field */ validators?: FieldValidators< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync > /** * An optional object with default metadata for the field. */ - defaultMeta?: Partial + defaultMeta?: Partial< + FieldMeta< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + any, + any, + any, + any, + any, + any, + any + > + > /** * A list of listeners which attach to the corresponding events */ - listeners?: FieldListeners< - TParentData, - TName, - TFieldValidator, - TFormValidator, - TData - > + listeners?: FieldListeners + /** + * Disable the `flat(1)` operation on `field.errors`. This is useful if you want to keep the error structure as is. Not suggested for most use-cases. + */ + disableErrorFlat?: boolean } /** @@ -345,24 +423,78 @@ export interface FieldOptions< export interface FieldApiOptions< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFormOnServer extends undefined | FormAsyncValidateOrFn, > extends FieldOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync > { - form: FormApi + form: FormApi< + TParentData, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + > } -export type FieldMetaBase = { +export type FieldMetaBase< + TParentData, + TName extends DeepKeys, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, +> = { /** * A flag indicating whether the field has been touched. */ @@ -378,33 +510,262 @@ export type FieldMetaBase = { /** * A map of errors related to the field value. */ - errorMap: ValidationErrorMap + errorMap: ValidationErrorMap< + UnwrapFieldValidateOrFn, + UnwrapFieldValidateOrFn, + UnwrapFieldAsyncValidateOrFn< + TParentData, + TName, + TOnChangeAsync, + TFormOnChangeAsync + >, + UnwrapFieldValidateOrFn, + UnwrapFieldAsyncValidateOrFn< + TParentData, + TName, + TOnBlurAsync, + TFormOnBlurAsync + >, + UnwrapFieldValidateOrFn, + UnwrapFieldAsyncValidateOrFn< + TParentData, + TName, + TOnSubmitAsync, + TFormOnSubmitAsync + > + > /** * A flag indicating whether the field is currently being validated. */ isValidating: boolean } -export type FieldMetaDerived = { +export type AnyFieldMetaBase = FieldMetaBase< + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any +> + +export type FieldMetaDerived< + TParentData, + TName extends DeepKeys, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, +> = { /** * An array of errors related to the field value. */ - errors: ValidationError[] + errors: Array< + | UnwrapOneLevelOfArray< + UnwrapFieldValidateOrFn + > + | UnwrapOneLevelOfArray< + UnwrapFieldValidateOrFn + > + | UnwrapOneLevelOfArray< + UnwrapFieldAsyncValidateOrFn< + TParentData, + TName, + TOnChangeAsync, + TFormOnChangeAsync + > + > + | UnwrapOneLevelOfArray< + UnwrapFieldValidateOrFn + > + | UnwrapOneLevelOfArray< + UnwrapFieldAsyncValidateOrFn< + TParentData, + TName, + TOnBlurAsync, + TFormOnBlurAsync + > + > + | UnwrapOneLevelOfArray< + UnwrapFieldValidateOrFn + > + | UnwrapOneLevelOfArray< + UnwrapFieldAsyncValidateOrFn< + TParentData, + TName, + TOnSubmitAsync, + TFormOnSubmitAsync + > + > + > /** * A flag that is `true` if the field's value has not been modified by the user. Opposite of `isDirty`. */ isPristine: boolean } +export type AnyFieldMetaDerived = FieldMetaDerived< + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any +> + /** * An object type representing the metadata of a field in a form. */ -export type FieldMeta = FieldMetaBase & FieldMetaDerived +export type FieldMeta< + TParentData, + TName extends DeepKeys, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, +> = FieldMetaBase< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync +> & + FieldMetaDerived< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync + > + +export type AnyFieldMeta = FieldMeta< + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any +> /** * An object type representing the state of a field. */ -export type FieldState = { +export type FieldState< + TParentData, + TName extends DeepKeys, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, +> = { /** * The current value of the field. */ @@ -412,9 +773,53 @@ export type FieldState = { /** * The current metadata of the field. */ - meta: FieldMeta + meta: FieldMeta< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync + > } +/** + * @public + * + * A type representing the Field API with all generics set to `any` for convenience. + */ +export type AnyFieldApi = FieldApi< + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any +> + /** * A class representing the API for managing a form field. * @@ -427,13 +832,28 @@ export type FieldState = { export class FieldApi< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFormOnServer extends undefined | FormAsyncValidateOrFn, > { /** * A reference to the form API instance. @@ -441,9 +861,22 @@ export class FieldApi< form: FieldApiOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer >['form'] /** * The field name. @@ -455,14 +888,47 @@ export class FieldApi< options: FieldApiOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer > = {} as any /** * The field state store. */ - store!: Derived> + store!: Derived< + FieldState< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync + > + > /** * The current field state. */ @@ -478,9 +944,22 @@ export class FieldApi< opts: FieldApiOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer >, ) { this.form = opts.form as never @@ -510,7 +989,25 @@ export class FieldApi< return { value, meta, - } as FieldState + } as FieldState< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync + > }, }) @@ -521,38 +1018,20 @@ export class FieldApi< * @private */ runValidator< - TValue extends { - value: TData - fieldApi: FieldApi - validationSource: ValidationSource + TValue extends TStandardSchemaValidatorValue & { + fieldApi: AnyFieldApi }, TType extends 'validate' | 'validateAsync', >(props: { validate: TType extends 'validate' - ? FieldValidateOrFn - : FieldAsyncValidateOrFn + ? FieldValidateOrFn + : FieldAsyncValidateOrFn value: TValue type: TType // When `api` is 'field', the return type cannot be `FormValidationError` - }): TType extends 'validate' ? ValidationError : Promise { - const adapters = [ - this.form.options.validatorAdapter, - this.options.validatorAdapter, - ] as const - for (const adapter of adapters) { - if ( - adapter && - (typeof props.validate !== 'function' || '~standard' in props.validate) - ) { - return adapter()[props.type]( - props.value as never, - props.validate, - ) as never - } - } - + }): unknown { if (isStandardSchemaValidator(props.validate)) { - return standardSchemaValidator()()[props.type]( + return standardSchemaValidators[props.type]( props.value, props.validate, ) as never @@ -584,11 +1063,14 @@ export class FieldApi< type: 'validate', }) if (error) { - this.setMeta((prev) => ({ - ...prev, - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - errorMap: { ...prev?.errorMap, onMount: error }, - })) + this.setMeta( + (prev) => + ({ + ...prev, + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + errorMap: { ...prev?.errorMap, onMount: error }, + }) as never, + ) } } @@ -607,9 +1089,22 @@ export class FieldApi< opts: FieldApiOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer >, ) => { // Default Value @@ -664,8 +1159,29 @@ export class FieldApi< /** * Sets the field metadata. */ - setMeta = (updater: Updater) => - this.form.setFieldMeta(this.name, updater) + setMeta = ( + updater: Updater< + FieldMeta< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync + > + >, + ) => this.form.setFieldMeta(this.name, updater) /** * Gets the field information object. @@ -720,12 +1236,9 @@ export class FieldApi< * @private */ getLinkedFields = (cause: ValidationCause) => { - const fields = Object.values(this.form.fieldInfo) as FieldInfo< - any, - TFormValidator - >[] + const fields = Object.values(this.form.fieldInfo) as FieldInfo[] - const linkedFields: FieldApi[] = [] + const linkedFields: AnyFieldApi[] = [] for (const field of fields) { if (!field.instance) continue const { onChangeListenTo, onBlurListenTo } = @@ -762,7 +1275,11 @@ export class FieldApi< }) return acc.concat(fieldValidates as never) }, - [] as Array & { field: FieldApi }>, + [] as Array< + SyncValidator & { + field: AnyFieldApi + } + >, ) // Needs type cast as eslint errantly believes this is always falsy @@ -770,7 +1287,7 @@ export class FieldApi< batch(() => { const validateFieldFn = ( - field: FieldApi, + field: AnyFieldApi, validateObj: SyncValidator, ) => { const errorMapKey = getErrorMapKey(validateObj.cause) @@ -850,7 +1367,18 @@ export class FieldApi< validateAsync = async ( cause: ValidationCause, formValidationResultPromise: Promise< - FieldsErrorMapFromValidator + FieldErrorMapFromValidator< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > >, ) => { const validates = getAsyncValidatorArray(cause, this.options) @@ -868,7 +1396,9 @@ export class FieldApi< return acc.concat(fieldValidates as never) }, [] as Array< - AsyncValidator & { field: FieldApi } + AsyncValidator & { + field: AnyFieldApi + } >, ) @@ -888,7 +1418,7 @@ export class FieldApi< const linkedPromises: Promise[] = [] const validateFieldAsyncFn = ( - field: FieldApi, + field: AnyFieldApi, validateObj: AsyncValidator, promises: Promise[], ) => { @@ -957,6 +1487,7 @@ export class FieldApi< // TODO: Dedupe this logic to reduce bundle size for (const validateObj of validates) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!validateObj.validate) continue validateFieldAsyncFn(this, validateObj, validatesPromises) } @@ -1048,22 +1579,21 @@ export class FieldApi< * Updates the field's errorMap */ setErrorMap(errorMap: ValidationErrorMap) { - this.setMeta((prev) => ({ - ...prev, - errorMap: { - ...prev.errorMap, - ...errorMap, - }, - })) + this.setMeta( + (prev) => + ({ + ...prev, + errorMap: { + ...prev.errorMap, + ...errorMap, + }, + }) as never, + ) } } function normalizeError(rawError?: ValidationError) { if (rawError) { - if (typeof rawError !== 'string') { - return 'Invalid Form Values' - } - return rawError } diff --git a/packages/form-core/src/FormApi.ts b/packages/form-core/src/FormApi.ts index 7f4ad8bc0..e4810fd7f 100644 --- a/packages/form-core/src/FormApi.ts +++ b/packages/form-core/src/FormApi.ts @@ -5,17 +5,22 @@ import { getAsyncValidatorArray, getBy, getSyncValidatorArray, + isGlobalFormValidationError, isNonEmptyArray, setBy, shallow, } from './utils' import { isStandardSchemaValidator, - standardSchemaValidator, + standardSchemaValidators, } from './standardSchemaValidator' import { metaHelper } from './metaHelper' -import type { StandardSchemaV1 } from './standardSchemaValidator' -import type { FieldApi, FieldMeta, FieldMetaBase } from './FieldApi' +import type { + StandardSchemaV1, + StandardSchemaV1Issue, + TStandardSchemaValidatorValue, +} from './standardSchemaValidator' +import type { AnyFieldMeta, AnyFieldMetaBase, FieldApi } from './FieldApi' import type { FormValidationError, FormValidationErrorMap, @@ -24,48 +29,90 @@ import type { ValidationError, ValidationErrorMap, ValidationErrorMapKeys, - ValidationSource, - Validator, } from './types' import type { DeepKeys, DeepValue } from './util-types' import type { Updater } from './utils' -export type FieldsErrorMapFromValidator = Partial< - Record, ValidationErrorMap> +/** + * @private + */ +// TODO: Add the `Unwrap` type to the errors +type FormErrorMapFromValidator< + TFormData, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, +> = Partial< + Record< + DeepKeys, + ValidationErrorMap< + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > + > > -export type FormValidateFn< - TFormData, - TFormValidator extends Validator | undefined = undefined, -> = (props: { +export type FormValidateFn = (props: { value: TFormData - formApi: FormApi -}) => FormValidationError + formApi: FormApi< + TFormData, + // This is technically an edge-type; which we try to keep non-`any`, but in this case + // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal + any, + any, + any, + any, + any, + any, + any, + any + > +}) => unknown /** * @private */ -export type FormValidateOrFn< - TFormData, - TFormValidator extends Validator | undefined = undefined, -> = - TFormValidator extends Validator - ? TFN | FormValidateFn - : - | FormValidateFn - | StandardSchemaV1 +export type FormValidateOrFn = + | FormValidateFn + | StandardSchemaV1 + +export type UnwrapFormValidateOrFn< + TValidateOrFn extends undefined | FormValidateOrFn, +> = [TValidateOrFn] extends [FormValidateFn] + ? ReturnType + : [TValidateOrFn] extends [StandardSchemaV1] + ? Record + : undefined /** * @private */ -export type FormValidateAsyncFn< - TFormData, - TFormValidator extends Validator | undefined = undefined, -> = (props: { +export type FormValidateAsyncFn = (props: { value: TFormData - formApi: FormApi + formApi: FormApi< + TFormData, + // This is technically an edge-type; which we try to keep non-`any`, but in this case + // It's referring to an inaccessible type from the field validate function inner types, so it's not a big deal + any, + any, + any, + any, + any, + any, + any, + any + > signal: AbortSignal -}) => FormValidationError | Promise> +}) => unknown | Promise export type FormValidator = { validate(options: { value: TType }, fn: TFn): ValidationError @@ -85,32 +132,40 @@ type ValidationPromiseResult = /** * @private */ -export type FormAsyncValidateOrFn< - TFormData, - TFormValidator extends Validator | undefined = undefined, -> = - TFormValidator extends Validator - ? FFN | FormValidateAsyncFn - : - | FormValidateAsyncFn - | StandardSchemaV1 +export type FormAsyncValidateOrFn = + | FormValidateAsyncFn + | StandardSchemaV1 + +export type UnwrapFormAsyncValidateOrFn< + TValidateOrFn extends undefined | FormAsyncValidateOrFn, +> = [TValidateOrFn] extends [FormValidateAsyncFn] + ? Awaited> + : [TValidateOrFn] extends [StandardSchemaV1] + ? Record + : undefined export interface FormValidators< TFormData, - TFormValidator extends Validator | undefined = undefined, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, > { /** * Optional function that fires as soon as the component mounts. */ - onMount?: FormValidateOrFn + onMount?: TOnMount /** * Optional function that checks the validity of your data whenever a value changes */ - onChange?: FormValidateOrFn + onChange?: TOnChange /** * Optional onChange asynchronous counterpart to onChange. Useful for more complex validation logic that might involve server requests. */ - onChangeAsync?: FormAsyncValidateOrFn + onChangeAsync?: TOnChangeAsync /** * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds. */ @@ -118,17 +173,17 @@ export interface FormValidators< /** * Optional function that validates the form data when a field loses focus, returns a `FormValidationError` */ - onBlur?: FormValidateOrFn + onBlur?: TOnBlur /** * Optional onBlur asynchronous validation method for when a field loses focus returns a ` FormValidationError` or a promise of `Promise` */ - onBlurAsync?: FormAsyncValidateOrFn + onBlurAsync?: TOnBlurAsync /** * The default time in milliseconds that if set to a number larger than 0, will debounce the async validation event by this length of time in milliseconds. */ onBlurAsyncDebounceMs?: number - onSubmit?: FormValidateOrFn - onSubmitAsync?: FormAsyncValidateOrFn + onSubmit?: TOnSubmit + onSubmitAsync?: TOnSubmitAsync } /** @@ -136,11 +191,38 @@ export interface FormValidators< */ export interface FormTransform< TFormData, - TFormValidator extends Validator | undefined = undefined, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, > { fn: ( - formBase: FormApi, - ) => FormApi + formBase: FormApi< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >, + ) => FormApi< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > deps: unknown[] } @@ -149,7 +231,14 @@ export interface FormTransform< */ export interface FormOptions< TFormData, - TFormValidator extends Validator | undefined = undefined, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, > { /** * Set initial values for your form. @@ -158,7 +247,19 @@ export interface FormOptions< /** * The default state for the form. */ - defaultState?: Partial> + defaultState?: Partial< + FormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > + > /** * If true, always run async validation, even when sync validation has produced an error. Defaults to undefined. */ @@ -167,29 +268,64 @@ export interface FormOptions< * Optional time in milliseconds if you want to introduce a delay before firing off an async action. */ asyncDebounceMs?: number - /** - * A validator adapter to support usage of extra validation types (IE: Zod, Yup, or Valibot usage) - */ - validatorAdapter?: TFormValidator /** * A list of validators to pass to the form */ - validators?: FormValidators + validators?: FormValidators< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > /** * A function to be called when the form is submitted, what should happen once the user submits a valid form returns `any` or a promise `Promise` */ onSubmit?: (props: { value: TFormData - formApi: FormApi + formApi: FormApi< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > }) => any | Promise /** * Specify an action for scenarios where the user tries to submit an invalid form. */ onSubmitInvalid?: (props: { value: TFormData - formApi: FormApi + formApi: FormApi< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > }) => void - transform?: FormTransform + transform?: FormTransform< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > } /** @@ -205,18 +341,29 @@ export type ValidationMeta = { /** * An object representing the field information for a specific field within the form. */ -export type FieldInfo< - TFormData, - TFormValidator extends Validator | undefined = undefined, -> = { +export type FieldInfo = { /** * An instance of the FieldAPI. */ instance: FieldApi< TFormData, any, - Validator | undefined, - TFormValidator + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any, + any > | null /** * A record of field validation internal handling. @@ -227,7 +374,17 @@ export type FieldInfo< /** * An object representing the current state of the form. */ -export type BaseFormState = { +export type BaseFormState< + TFormData, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, +> = { /** * The current values of the form fields. */ @@ -235,7 +392,16 @@ export type BaseFormState = { /** * The error map for the form itself. */ - errorMap: FormValidationErrorMap + errorMap: FormValidationErrorMap< + UnwrapFormValidateOrFn, + UnwrapFormValidateOrFn, + UnwrapFormAsyncValidateOrFn, + UnwrapFormValidateOrFn, + UnwrapFormAsyncValidateOrFn, + UnwrapFormValidateOrFn, + UnwrapFormAsyncValidateOrFn, + UnwrapFormAsyncValidateOrFn + > /** * An internal mechanism used for keeping track of validation logic in a form. */ @@ -243,7 +409,7 @@ export type BaseFormState = { /** * A record of field metadata for each field in the form, not including the derived properties, like `errors` and such */ - fieldMetaBase: Record, FieldMetaBase> + fieldMetaBase: Record, AnyFieldMetaBase> /** * A boolean indicating if the form is currently in the process of being submitted after `handleSubmit` is called. * @@ -271,7 +437,17 @@ export type BaseFormState = { submissionAttempts: number } -export type DerivedFormState = { +export type DerivedFormState< + TFormData, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, +> = { /** * A boolean indicating if the form is currently validating. */ @@ -283,7 +459,16 @@ export type DerivedFormState = { /** * The error array for the form itself. */ - errors: ValidationError[] + errors: Array< + | UnwrapFormValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormAsyncValidateOrFn + > /** * A boolean indicating if any of the form fields are currently validating. */ @@ -319,15 +504,89 @@ export type DerivedFormState = { /** * A record of field metadata for each field in the form. */ - fieldMeta: Record, FieldMeta> + fieldMeta: Record, AnyFieldMeta> } -export type FormState = BaseFormState & - DerivedFormState +export type FormState< + TFormData, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, +> = BaseFormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer +> & + DerivedFormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > + +export type AnyFormState = FormState< + any, + any, + any, + any, + any, + any, + any, + any, + any +> -function getDefaultFormState( - defaultState: Partial>, -): BaseFormState { +function getDefaultFormState< + TFormData, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, +>( + defaultState: Partial< + FormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > + >, +): BaseFormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer +> { return { values: defaultState.values ?? ({} as never), errorMap: defaultState.errorMap ?? {}, @@ -346,11 +605,12 @@ function getDefaultFormState( } } -const isFormValidationError = ( - error: unknown, -): error is FormValidationError => { - return typeof error === 'object' -} +/** + * @public + * + * A type representing the Form API with all generics set to `any` for convenience. + */ +export type AnyFormApi = FormApi /** * A class representing the Form API. It handles the logic and interactions with the form state. @@ -361,20 +621,60 @@ const isFormValidationError = ( */ export class FormApi< TFormData, - TFormValidator extends Validator | undefined = undefined, + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, > { /** * The options for the form. */ - options: FormOptions = {} - baseStore!: Store> - fieldMetaDerived!: Derived, FieldMeta>> - store!: Derived> + options: FormOptions< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > = {} + baseStore!: Store< + BaseFormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > + > + fieldMetaDerived!: Derived, AnyFieldMeta>> + store!: Derived< + FormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > + > /** * A record of field information for each field in the form. */ - fieldInfo: Record, FieldInfo> = - {} as any + fieldInfo: Record, FieldInfo> = {} as any get state() { return this.store.state @@ -388,7 +688,19 @@ export class FormApi< /** * Constructs a new `FormApi` instance with the given form options. */ - constructor(opts?: FormOptions) { + constructor( + opts?: FormOptions< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >, + ) { this.baseStore = new Store( getDefaultFormState({ ...(opts?.defaultState as any), @@ -401,24 +713,35 @@ export class FormApi< deps: [this.baseStore], fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => { const prevVal = _prevVal as - | Record, FieldMeta> + | Record, AnyFieldMeta> | undefined const prevBaseStore = prevDepVals?.[0] const currBaseStore = currDepVals[0] let originalMetaCount = 0 - const fieldMeta = {} as FormState['fieldMeta'] + const fieldMeta = {} as FormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >['fieldMeta'] + for (const fieldName of Object.keys( currBaseStore.fieldMetaBase, ) as Array) { const currBaseVal = currBaseStore.fieldMetaBase[ fieldName as never - ] as FieldMetaBase + ] as AnyFieldMetaBase const prevBaseVal = prevBaseStore?.fieldMetaBase[ fieldName as never - ] as FieldMetaBase | undefined + ] as AnyFieldMetaBase | undefined const prevFieldInfo = prevVal?.[fieldName as never as keyof typeof prevVal] @@ -427,11 +750,20 @@ export class FormApi< if (!prevBaseVal || currBaseVal.errorMap !== prevBaseVal.errorMap) { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition fieldErrors = Object.values(currBaseVal.errorMap ?? {}).filter( - (val: unknown) => val !== undefined, - ) + (val) => val !== undefined, + ) as never + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + const fieldInstance = this.getFieldInfo(fieldName)?.instance + + if (fieldInstance && !fieldInstance.options.disableErrorFlat) { + fieldErrors = (fieldErrors as undefined | string[])?.flat( + 1, + ) as never + } } - // As a primitive, we don't need to aggressively persist the same referencial value for performance reasons + // As a primitive, we don't need to aggressively persist the same referential value for performance reasons const isFieldPristine = !currBaseVal.isDirty if ( @@ -449,7 +781,7 @@ export class FormApi< ...currBaseVal, errors: fieldErrors, isPristine: isFieldPristine, - } as FieldMeta + } as AnyFieldMeta } if ( @@ -466,13 +798,25 @@ export class FormApi< this.store = new Derived({ deps: [this.baseStore, this.fieldMetaDerived], fn: ({ prevDepVals, currDepVals, prevVal: _prevVal }) => { - const prevVal = _prevVal as FormState | undefined + const prevVal = _prevVal as + | FormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > + | undefined const prevBaseStore = prevDepVals?.[0] const currBaseStore = currDepVals[0] // Computed state const fieldMetaValues = Object.values(currBaseStore.fieldMetaBase) as ( - | FieldMeta + | AnyFieldMeta | undefined )[] @@ -511,21 +855,27 @@ export class FormApi< !prevBaseStore || currBaseStore.errorMap !== prevBaseStore.errorMap ) { - errors = Object.values(currBaseStore.errorMap).reduce( - (prev, curr) => { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (curr === undefined) return prev - if (typeof curr === 'string') { - prev.push(curr) - return prev - } else if (curr && isFormValidationError(curr)) { - prev.push(curr.form) - return prev - } + errors = Object.values(currBaseStore.errorMap).reduce< + Array< + | UnwrapFormValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormAsyncValidateOrFn + > + >((prev, curr) => { + if (curr === undefined) return prev + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (curr && isGlobalFormValidationError(curr)) { + prev.push(curr.form as never) return prev - }, - [] as ValidationError[], - ) + } + prev.push(curr as never) + return prev + }, []) } const isFormValid = errors.length === 0 @@ -578,7 +928,17 @@ export class FormApi< isBlurred, isPristine, isDirty, - } as FormState + } as FormState< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + > // Only run transform if state has shallowly changed - IE how React.useEffect works const transformArray = this.options.transform?.deps ?? [] @@ -605,35 +965,25 @@ export class FormApi< * @private */ runValidator< - TValue extends { - value: TFormData - formApi: FormApi - validationSource: ValidationSource + TValue extends TStandardSchemaValidatorValue & { + formApi: AnyFormApi }, TType extends 'validate' | 'validateAsync', >(props: { validate: TType extends 'validate' - ? FormValidateOrFn - : FormAsyncValidateOrFn + ? FormValidateOrFn + : FormAsyncValidateOrFn value: TValue type: TType - }): ReturnType>[TType]> { - const adapter = this.options.validatorAdapter - if ( - adapter && - (typeof props.validate !== 'function' || '~standard' in props.validate) - ) { - return adapter()[props.type](props.value, props.validate) as never - } - + }): unknown { if (isStandardSchemaValidator(props.validate)) { - return standardSchemaValidator()()[props.type]( + return standardSchemaValidators[props.type]( props.value, props.validate, ) as never } - return (props.validate as FormValidateFn)(props.value) as never + return (props.validate as FormValidateFn)(props.value) as never } mount = () => { @@ -653,7 +1003,19 @@ export class FormApi< /** * Updates the form options and form state. */ - update = (options?: FormOptions) => { + update = ( + options?: FormOptions< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >, + ) => { if (!options) return const oldOptions = this.options @@ -728,24 +1090,24 @@ export class FormApi< validateAllFields = async (cause: ValidationCause) => { const fieldValidationPromises: Promise[] = [] as any batch(() => { - void ( - Object.values(this.fieldInfo) as FieldInfo[] - ).forEach((field) => { - if (!field.instance) return - const fieldInstance = field.instance - // Validate the field - fieldValidationPromises.push( - // Remember, `validate` is either a sync operation or a promise - Promise.resolve().then(() => - fieldInstance.validate(cause, { skipFormValidation: true }), - ), - ) - // If any fields are not touched - if (!field.instance.state.meta.isTouched) { - // Mark them as touched - field.instance.setMeta((prev) => ({ ...prev, isTouched: true })) - } - }) + void (Object.values(this.fieldInfo) as FieldInfo[]).forEach( + (field) => { + if (!field.instance) return + const fieldInstance = field.instance + // Validate the field + fieldValidationPromises.push( + // Remember, `validate` is either a sync operation or a promise + Promise.resolve().then(() => + fieldInstance.validate(cause, { skipFormValidation: true }), + ), + ) + // If any fields are not touched + if (!field.instance.state.meta.isTouched) { + // Mark them as touched + field.instance.setMeta((prev) => ({ ...prev, isTouched: true })) + } + }, + ) }) const fieldErrorMapMap = await Promise.all(fieldValidationPromises) @@ -819,12 +1181,30 @@ export class FormApi< cause: ValidationCause, ): { hasErrored: boolean - fieldsErrorMap: FieldsErrorMapFromValidator + fieldsErrorMap: FormErrorMapFromValidator< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > } => { const validates = getSyncValidatorArray(cause, this.options) let hasErrored = false as boolean - const fieldsErrorMap: FieldsErrorMapFromValidator = {} + const fieldsErrorMap: FormErrorMapFromValidator< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > = {} batch(() => { for (const validateObj of validates) { @@ -910,7 +1290,18 @@ export class FormApi< */ validateAsync = async ( cause: ValidationCause, - ): Promise> => { + ): Promise< + FormErrorMapFromValidator< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > + > => { const validates = getAsyncValidatorArray(cause, this.options) if (!this.state.isFormValidating) { @@ -928,6 +1319,7 @@ export class FormApi< | undefined for (const validateObj of validates) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!validateObj.validate) continue const key = getErrorMapKey(validateObj.cause) const fieldValidatorMeta = this.state.validationMetaMap[key] @@ -1009,7 +1401,16 @@ export class FormApi< let results: ValidationPromiseResult[] = [] - const fieldsErrorMap: FieldsErrorMapFromValidator = {} + const fieldsErrorMap: FormErrorMapFromValidator< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > = {} if (promises.length) { results = await Promise.all(promises) for (const fieldValidationResult of results) { @@ -1045,8 +1446,28 @@ export class FormApi< validate = ( cause: ValidationCause, ): - | FieldsErrorMapFromValidator - | Promise> => { + | FormErrorMapFromValidator< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > + | Promise< + FormErrorMapFromValidator< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + > + > => { // Attempt to sync validate first const { hasErrored, fieldsErrorMap } = this.validateSync(cause) @@ -1103,14 +1524,14 @@ export class FormApi< } batch(() => { - void ( - Object.values(this.fieldInfo) as FieldInfo[] - ).forEach((field) => { - field.instance?.options.listeners?.onSubmit?.({ - value: field.instance.state.value, - fieldApi: field.instance, - }) - }) + void (Object.values(this.fieldInfo) as FieldInfo[]).forEach( + (field) => { + field.instance?.options.listeners?.onSubmit?.({ + value: field.instance.state.value, + fieldApi: field.instance, + }) + }, + ) }) try { @@ -1139,7 +1560,7 @@ export class FormApi< */ getFieldMeta = >( field: TField, - ): FieldMeta | undefined => { + ): AnyFieldMeta | undefined => { return this.state.fieldMeta[field] } @@ -1148,7 +1569,7 @@ export class FormApi< */ getFieldInfo = >( field: TField, - ): FieldInfo => { + ): FieldInfo => { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return (this.fieldInfo[field] ||= { instance: null, @@ -1167,7 +1588,7 @@ export class FormApi< */ setFieldMeta = >( field: TField, - updater: Updater, + updater: Updater, ) => { this.baseStore.setState((prev) => { return { @@ -1184,10 +1605,10 @@ export class FormApi< } resetFieldMeta = >( - fieldMeta: Record, - ): Record => { + fieldMeta: Record, + ): Record => { return Object.keys(fieldMeta).reduce( - (acc: Record, key) => { + (acc: Record, key) => { const fieldKey = key as TField acc[fieldKey] = { isValidating: false, @@ -1200,7 +1621,7 @@ export class FormApi< } return acc }, - {} as Record, + {} as Record, ) } @@ -1422,14 +1843,27 @@ export class FormApi< /** * Updates the form's errorMap */ - setErrorMap(errorMap: ValidationErrorMap) { - this.baseStore.setState((prev) => ({ - ...prev, - errorMap: { - ...prev.errorMap, - ...errorMap, - }, - })) + setErrorMap( + errorMap: ValidationErrorMap< + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync + >, + ) { + this.baseStore.setState( + (prev) => + ({ + ...prev, + errorMap: { + ...prev.errorMap, + ...errorMap, + }, + }) as never, + ) } } @@ -1438,16 +1872,12 @@ function normalizeError(rawError?: FormValidationError): { fieldErrors?: Partial, ValidationError>> } { if (rawError) { - if (typeof rawError === 'object') { + if (isGlobalFormValidationError(rawError)) { const formError = normalizeError(rawError.form).formError const fieldErrors = rawError.fields return { formError, fieldErrors } as never } - if (typeof rawError !== 'string') { - return { formError: 'Invalid Form Values' } - } - return { formError: rawError } } diff --git a/packages/form-core/src/formOptions.ts b/packages/form-core/src/formOptions.ts index 6089cec87..a457e5ad3 100644 --- a/packages/form-core/src/formOptions.ts +++ b/packages/form-core/src/formOptions.ts @@ -1,9 +1,31 @@ -import type { Validator } from './types' -import type { FormOptions } from './FormApi' +import type { + FormAsyncValidateOrFn, + FormOptions, + FormValidateOrFn, +} from './FormApi' export function formOptions< TFormData, - TFormValidator extends Validator | undefined = undefined, ->(defaultOpts?: FormOptions) { + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, +>( + defaultOpts?: FormOptions< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >, +) { return defaultOpts } diff --git a/packages/form-core/src/mergeForm.ts b/packages/form-core/src/mergeForm.ts index b212c69b9..ef1605aa0 100644 --- a/packages/form-core/src/mergeForm.ts +++ b/packages/form-core/src/mergeForm.ts @@ -1,5 +1,4 @@ import type { FormApi } from './FormApi' -import type { Validator } from './types' import type { NoInfer } from './util-types' function isValidKey(key: string | number | symbol): boolean { @@ -72,12 +71,11 @@ export function mutateMergeDeep( return target } -export function mergeForm< - TFormData, - TFormValidator extends Validator | undefined = undefined, ->( - baseForm: FormApi, NoInfer>, - state: Partial['state']>, +export function mergeForm( + baseForm: FormApi, any, any, any, any, any, any, any, any>, + state: Partial< + FormApi['state'] + >, ) { mutateMergeDeep(baseForm.state, state) return baseForm diff --git a/packages/form-core/src/metaHelper.ts b/packages/form-core/src/metaHelper.ts index 5fc14f1c1..4e9c9a825 100644 --- a/packages/form-core/src/metaHelper.ts +++ b/packages/form-core/src/metaHelper.ts @@ -1,14 +1,36 @@ -import type { FieldMeta } from './FieldApi' -import type { FormApi } from './FormApi' -import type { Validator } from './types' +import type { + FormApi, + FormAsyncValidateOrFn, + FormValidateOrFn, +} from './FormApi' +import type { AnyFieldMeta } from './FieldApi' import type { DeepKeys } from './util-types' type ArrayFieldMode = 'insert' | 'remove' | 'swap' | 'move' export function metaHelper< TFormData, - TFormValidator extends Validator | undefined = undefined, ->(formApi: FormApi) { + TOnMount extends undefined | FormValidateOrFn, + TOnChange extends undefined | FormValidateOrFn, + TOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TOnBlur extends undefined | FormValidateOrFn, + TOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TOnSubmit extends undefined | FormValidateOrFn, + TOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TOnServer extends undefined | FormAsyncValidateOrFn, +>( + formApi: FormApi< + TFormData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TOnServer + >, +) { function handleArrayFieldMetaShift( field: DeepKeys, index: number, @@ -90,7 +112,7 @@ export function metaHelper< }) } - const getEmptyFieldMeta = (): FieldMeta => ({ + const getEmptyFieldMeta = (): AnyFieldMeta => ({ isValidating: false, isTouched: false, isBlurred: false, diff --git a/packages/form-core/src/standardSchemaValidator.ts b/packages/form-core/src/standardSchemaValidator.ts index 356e7a579..08b6a139e 100644 --- a/packages/form-core/src/standardSchemaValidator.ts +++ b/packages/form-core/src/standardSchemaValidator.ts @@ -1,16 +1,11 @@ -import type { - ValidationError, - Validator, - ValidatorAdapterParams, -} from './types' +import type { ValidationSource } from './types' -type Params = ValidatorAdapterParams -type TransformFn = NonNullable +export type TStandardSchemaValidatorValue = { + value: TData + validationSource: ValidationSource +} -function prefixSchemaToErrors( - issues: readonly StandardSchemaV1Issue[], - transformErrors: TransformFn, -) { +function prefixSchemaToErrors(issues: readonly StandardSchemaV1Issue[]) { const schema = new Map() for (const issue of issues) { @@ -28,60 +23,54 @@ function prefixSchemaToErrors( schema.set(path, (schema.get(path) ?? []).concat(issue)) } - const transformedSchema = {} as Record - - schema.forEach((value, key) => { - transformedSchema[key] = transformErrors(value) - }) - - return transformedSchema + return Object.fromEntries(schema) } -function defaultFormTransformer(transformErrors: TransformFn) { - return (issues: readonly StandardSchemaV1Issue[]) => ({ - form: transformErrors(issues as StandardSchemaV1Issue[]), - fields: prefixSchemaToErrors(issues, transformErrors), - }) -} - -export const standardSchemaValidator = - (params: Params = {}): Validator> => - () => { - const transformFieldErrors = - params.transformErrors ?? - ((issues: StandardSchemaV1Issue[]) => - issues.map((issue) => issue.message).join(', ')) - - const getTransformStrategy = (validationSource: 'form' | 'field') => - validationSource === 'form' - ? defaultFormTransformer(transformFieldErrors) - : transformFieldErrors - - return { - validate({ value, validationSource }, fn) { - const result = fn['~standard'].validate(value) +const defaultFieldTransformer = (issues: readonly StandardSchemaV1Issue[]) => + issues - if (result instanceof Promise) { - throw new Error('async function passed to sync validator') - } - - if (!result.issues) return +const defaultFormTransformer = (issues: readonly StandardSchemaV1Issue[]) => { + const schemaErrors = prefixSchemaToErrors(issues) + return { + form: schemaErrors, + fields: schemaErrors, + } +} - const transformer = getTransformStrategy(validationSource) +const transformIssues = ( + validationSource: 'form' | 'field', + issues: readonly StandardSchemaV1Issue[], +) => + validationSource === 'form' + ? defaultFormTransformer(issues) + : defaultFieldTransformer(issues) + +export const standardSchemaValidators = { + validate( + { value, validationSource }: TStandardSchemaValidatorValue, + schema: StandardSchemaV1, + ) { + const result = schema['~standard'].validate(value) + + if (result instanceof Promise) { + throw new Error('async function passed to sync validator') + } - return transformer(result.issues as StandardSchemaV1Issue[]) - }, - async validateAsync({ value, validationSource }, fn) { - const result = await fn['~standard'].validate(value) + if (!result.issues) return - if (!result.issues) return + return transformIssues(validationSource, result.issues) + }, + async validateAsync( + { value, validationSource }: TStandardSchemaValidatorValue, + schema: StandardSchemaV1, + ) { + const result = await schema['~standard'].validate(value) - const transformer = getTransformStrategy(validationSource) + if (!result.issues) return - return transformer(result.issues as StandardSchemaV1Issue[]) - }, - } - } + return transformIssues(validationSource, result.issues) + }, +} export const isStandardSchemaValidator = ( validator: unknown, @@ -152,7 +141,7 @@ interface StandardSchemaV1FailureResult { /** * The issue interface of the failure output. */ -interface StandardSchemaV1Issue { +export interface StandardSchemaV1Issue { /** * The error message of the issue. */ diff --git a/packages/form-core/src/types.ts b/packages/form-core/src/types.ts index cff62ae7c..7dacf8b42 100644 --- a/packages/form-core/src/types.ts +++ b/packages/form-core/src/types.ts @@ -1,32 +1,9 @@ import type { DeepKeys } from './util-types' -export type ValidationError = undefined | false | null | string +export type ValidationError = unknown export type ValidationSource = 'form' | 'field' -/** - * If/when TypeScript supports higher-kinded types, this should not be `unknown` anymore - * @private - */ -export type Validator = () => { - validate( - options: { value: Type; validationSource: ValidationSource }, - fn: Fn, - ): ValidationError | FormValidationError - validateAsync( - options: { value: Type; validationSource: ValidationSource }, - fn: Fn, - ): Promise> -} - -/** - * Parameters in common for all validator adapters, making it easier to swap adapter - * @private - */ -export type ValidatorAdapterParams = { - transformErrors?: (errors: TError[]) => ValidationError -} - /** * "server" is only intended for SSR/SSG validation and should not execute anything * @private @@ -41,17 +18,47 @@ export type ValidationErrorMapKeys = `on${Capitalize}` /** * @private */ -export type ValidationErrorMap = { - [K in ValidationErrorMapKeys]?: ValidationError +export type ValidationErrorMap< + TOnMountReturn = unknown, + TOnChangeReturn = unknown, + TOnChangeAsyncReturn = unknown, + TOnBlurReturn = unknown, + TOnBlurAsyncReturn = unknown, + TOnSubmitReturn = unknown, + TOnSubmitAsyncReturn = unknown, + TOnServerReturn = unknown, +> = { + onMount?: TOnMountReturn + onChange?: TOnChangeReturn | TOnChangeAsyncReturn + onBlur?: TOnBlurReturn | TOnBlurAsyncReturn + onSubmit?: TOnSubmitReturn | TOnSubmitAsyncReturn + onServer?: TOnServerReturn } /** * @private */ -export type FormValidationErrorMap = { - [K in ValidationErrorMapKeys]?: ValidationError | FormValidationError +export type FormValidationErrorMap< + TOnMountReturn = unknown, + TOnChangeReturn = unknown, + TOnChangeAsyncReturn = unknown, + TOnBlurReturn = unknown, + TOnBlurAsyncReturn = unknown, + TOnSubmitReturn = unknown, + TOnSubmitAsyncReturn = unknown, + TOnServerReturn = unknown, +> = { + onMount?: TOnMountReturn + onChange?: TOnChangeReturn | TOnChangeAsyncReturn + onBlur?: TOnBlurReturn | TOnBlurAsyncReturn + onSubmit?: TOnSubmitReturn | TOnSubmitAsyncReturn + onServer?: TOnServerReturn } +export type FormValidationError = + | ValidationError + | GlobalFormValidationError + /** * @private * @@ -65,12 +72,10 @@ export type FormValidationErrorMap = { * } * ```` */ -export type FormValidationError = - | ValidationError - | { - form?: ValidationError - fields: Partial, ValidationError>> - } +export type GlobalFormValidationError = { + form?: ValidationError + fields: Partial, ValidationError>> +} /** * @private diff --git a/packages/form-core/src/util-types.ts b/packages/form-core/src/util-types.ts index 8a9a107cd..bc99c7600 100644 --- a/packages/form-core/src/util-types.ts +++ b/packages/form-core/src/util-types.ts @@ -1,6 +1,8 @@ type Nullable = T | null type IsNullable = [null] extends [T] ? true : false +export type UnwrapOneLevelOfArray = T extends (infer U)[] ? U : T + /** * @private */ diff --git a/packages/form-core/src/utils.ts b/packages/form-core/src/utils.ts index b2a52d496..4568ffed1 100644 --- a/packages/form-core/src/utils.ts +++ b/packages/form-core/src/utils.ts @@ -1,4 +1,4 @@ -import type { ValidationCause } from './types' +import type { GlobalFormValidationError, ValidationCause } from './types' import type { FormValidators } from './FormApi' import type { FieldValidators } from './FieldApi' @@ -195,11 +195,11 @@ export interface AsyncValidator { export function getAsyncValidatorArray( cause: ValidationCause, options: AsyncValidatorArrayPartialOptions, -): T extends FieldValidators +): T extends FieldValidators ? Array< AsyncValidator > - : T extends FormValidators + : T extends FormValidators ? Array< AsyncValidator< T['onChangeAsync'] | T['onBlurAsync'] | T['onSubmitAsync'] @@ -214,8 +214,8 @@ export function getAsyncValidatorArray( onBlurAsyncDebounceMs, onChangeAsyncDebounceMs, } = (options.validators || {}) as - | FieldValidators - | FormValidators + | FieldValidators + | FormValidators const defaultDebounceMs = asyncDebounceMs ?? 0 @@ -279,11 +279,11 @@ export interface SyncValidator { export function getSyncValidatorArray( cause: ValidationCause, options: SyncValidatorArrayPartialOptions, -): T extends FieldValidators +): T extends FieldValidators ? Array< SyncValidator > - : T extends FormValidators + : T extends FormValidators ? Array< SyncValidator< T['onChange'] | T['onBlur'] | T['onSubmit'] | T['onMount'] @@ -291,8 +291,8 @@ export function getSyncValidatorArray( > : never { const { onChange, onBlur, onSubmit, onMount } = (options.validators || {}) as - | FieldValidators - | FormValidators + | FieldValidators + | FormValidators const changeValidator = { cause: 'change', validate: onChange } as const const blurValidator = { cause: 'blur', validate: onBlur } as const @@ -325,6 +325,12 @@ export function getSyncValidatorArray( } } +export const isGlobalFormValidationError = ( + error: unknown, +): error is GlobalFormValidationError => { + return !!error && typeof error === 'object' && 'fields' in error +} + export function shallow(objA: T, objB: T) { if (Object.is(objA, objB)) { return true diff --git a/packages/form-core/tests/FieldApi.spec.ts b/packages/form-core/tests/FieldApi.spec.ts index 157bda920..5bbaadb87 100644 --- a/packages/form-core/tests/FieldApi.spec.ts +++ b/packages/form-core/tests/FieldApi.spec.ts @@ -1309,7 +1309,7 @@ describe('field api', () => { interface Form { name: string } - const form = new FormApi
() + const form = new FormApi({ defaultValues: {} as Form }) form.mount() @@ -1681,7 +1681,7 @@ describe('field api', () => { interface Form { name: string } - const form = new FormApi() + const form = new FormApi({ defaultValues: {} as Form }) form.mount() const nameField = new FieldApi({ form, @@ -1697,7 +1697,7 @@ describe('field api', () => { interface Form { name: string } - const form = new FormApi() + const form = new FormApi({ defaultValues: {} as Form }) form.mount() const nameField = new FieldApi({ form, @@ -1720,7 +1720,7 @@ describe('field api', () => { interface Form { name: string } - const form = new FormApi() + const form = new FormApi({ defaultValues: {} as Form }) form.mount() const nameField = new FieldApi({ form, @@ -1753,7 +1753,7 @@ describe('field api', () => { defaultMeta: { errorMap: { onChange: 'THERE IS AN ERROR', - }, + } as never, }, }) diff --git a/packages/form-core/tests/FieldApi.test-d.ts b/packages/form-core/tests/FieldApi.test-d.ts index 92ad5cb20..96b57acdc 100644 --- a/packages/form-core/tests/FieldApi.test-d.ts +++ b/packages/form-core/tests/FieldApi.test-d.ts @@ -1,4 +1,4 @@ -import { assertType, it } from 'vitest' +import { assertType, describe, it } from 'vitest' import { FieldApi, FormApi } from '../src/index' it('should type value properly', () => { @@ -24,7 +24,7 @@ it('should type value when nothing is passed into constructor', () => { age?: number } - const form = new FormApi() + const form = new FormApi({ defaultValues: {} as FormValues }) const field = new FieldApi({ form, @@ -42,10 +42,10 @@ it('should type required fields in constructor', () => { age?: number } - const form = new FormApi({ + const form = new FormApi({ defaultValues: { name: 'test', - }, + } as FormValues, }) const field = new FieldApi({ @@ -64,8 +64,8 @@ it('should type value properly for completely partial forms', () => { age?: number } - const form = new FormApi({ - defaultValues: {}, + const form = new FormApi({ + defaultValues: {} as CompletelyPartialFormValues, }) const field = new FieldApi({ @@ -146,3 +146,187 @@ it('should type an array sub-field properly', () => { assertType(field.state.value) }) + +it('should have the correct types returned from form validators', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + validators: { + onChange: () => { + return '123' as const + }, + }, + } as const) + + assertType<'123' | undefined>(form.state.errorMap.onChange) +}) + +it('should have the correct types returned from form validators even when both onChange and onChangeAsync are present', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + validators: { + onChange: () => { + return '123' as const + }, + onChangeAsync: async () => { + return '123' as const + }, + }, + } as const) + + assertType<'123' | undefined>(form.state.errorMap.onChange) +}) + +it('should have the correct types returned from field validators', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validators: { + onChange: () => { + return '123' as const + }, + }, + }) + + assertType<'123' | undefined>(field.state.meta.errorMap.onChange) +}) + +it('should have the correct types returned from field validators in array', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + } as const) + + const field = new FieldApi({ + form, + name: 'name', + validators: { + onChange: () => { + return '123' as const + }, + }, + }) + + assertType>(field.state.meta.errors) +}) + +it('should have the correct types returned from form validators in array', () => { + const form = new FormApi({ + defaultValues: { + name: 'test', + }, + validators: { + onChange: () => { + return '123' as const + }, + }, + } as const) + + assertType>(form.state.errors) +}) + +it('should handle "fields" return types added to the field\'s errorMap itself', () => { + const form = new FormApi({ + defaultValues: { + firstName: '', + }, + validators: { + onChange: () => { + return { + fields: { + firstName: 'Testing' as const, + }, + } + }, + }, + }) + + const field = new FieldApi({ + form, + name: 'firstName', + }) + + assertType<'Testing' | undefined>(field.getMeta().errorMap.onChange) +}) + +it('should handle "fields" return types added to the field\'s error array itself', () => { + const form = new FormApi({ + defaultValues: { + firstName: '', + }, + validators: { + onChange: () => { + return { + fields: { + firstName: 'Testing' as const, + }, + } + }, + }, + }) + + const field = new FieldApi({ + form, + name: 'firstName', + }) + + assertType>(field.getMeta().errors) +}) + +it('should handle "fields" async return types added to the field\'s errorMap itself', () => { + const form = new FormApi({ + defaultValues: { + firstName: '', + }, + validators: { + onChangeAsync: async () => { + return { + fields: { + firstName: 'Testing' as const, + }, + } + }, + }, + }) + + const field = new FieldApi({ + form, + name: 'firstName', + }) + + assertType<'Testing' | undefined>(field.getMeta().errorMap.onChange) +}) + +it('should handle "fields" async return types added to the field\'s error array itself', () => { + const form = new FormApi({ + defaultValues: { + firstName: '', + }, + validators: { + onChangeAsync: async () => { + return { + fields: { + firstName: 'Testing' as const, + }, + } + }, + }, + }) + + const field = new FieldApi({ + form, + name: 'firstName', + }) + + assertType>(field.getMeta().errors) +}) diff --git a/packages/form-core/tests/FormApi.spec.ts b/packages/form-core/tests/FormApi.spec.ts index 165eef691..a7dd0ea54 100644 --- a/packages/form-core/tests/FormApi.spec.ts +++ b/packages/form-core/tests/FormApi.spec.ts @@ -993,7 +993,9 @@ describe('form api', () => { employees: Partial[] } - const form = new FormApi() + const form = new FormApi({ + defaultValues: {} as Form, + }) form.mount() @@ -1023,7 +1025,9 @@ describe('form api', () => { employees: Partial[] } - const form = new FormApi() + const form = new FormApi({ + defaultValues: {} as Form, + }) form.mount() const field = new FieldApi({ form, @@ -1985,11 +1989,11 @@ describe('form api', () => { interface Form { name: string } - const form = new FormApi() + const form = new FormApi({ defaultValues: {} as Form }) form.mount() form.setErrorMap({ onChange: "name can't be Josh", - }) + } as never) expect(form.state.errorMap.onChange).toEqual("name can't be Josh") }) @@ -1997,15 +2001,15 @@ describe('form api', () => { interface Form { name: string } - const form = new FormApi() + const form = new FormApi({ defaultValues: {} as Form }) form.mount() form.setErrorMap({ onChange: "name can't be Josh", - }) + } as never) expect(form.state.errorMap.onChange).toEqual("name can't be Josh") form.setErrorMap({ onBlur: 'name must begin with uppercase', - }) + } as never) expect(form.state.errorMap.onChange).toEqual("name can't be Josh") expect(form.state.errorMap.onBlur).toEqual('name must begin with uppercase') }) @@ -2014,15 +2018,15 @@ describe('form api', () => { interface Form { name: string } - const form = new FormApi() + const form = new FormApi({ defaultValues: {} as Form }) form.mount() form.setErrorMap({ onChange: "name can't be Josh", - }) + } as never) expect(form.state.errorMap.onChange).toEqual("name can't be Josh") form.setErrorMap({ onChange: 'other validation error', - }) + } as never) expect(form.state.errorMap.onChange).toEqual('other validation error') }) @@ -2392,7 +2396,7 @@ describe('form api', () => { employees: Partial[] } - const form = new FormApi({ + const form = new FormApi({ validators: { onSubmit: ({ value }) => { const fieldWithErrorIndex = value.employees.findIndex( @@ -2410,6 +2414,7 @@ describe('form api', () => { return null }, }, + defaultValues: {} as Form, }) form.mount() const field = new FieldApi({ diff --git a/packages/form-core/tests/formOptions.test.ts b/packages/form-core/tests/formOptions.test.ts index 08ec895c2..b716983dc 100644 --- a/packages/form-core/tests/formOptions.test.ts +++ b/packages/form-core/tests/formOptions.test.ts @@ -8,11 +8,11 @@ describe('formOptions', () => { lastName: string } - const formOpts = formOptions({ + const formOpts = formOptions({ defaultValues: { firstName: 'FirstName', lastName: 'LastName', - }, + } as Person, }) const form = new FormApi({ diff --git a/packages/form-core/tests/standardSchemaValidator.spec.ts b/packages/form-core/tests/standardSchemaValidator.spec.ts index b390d35f9..2a03c1968 100644 --- a/packages/form-core/tests/standardSchemaValidator.spec.ts +++ b/packages/form-core/tests/standardSchemaValidator.spec.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest' import * as v from 'valibot' import { z } from 'zod' import { type } from 'arktype' -import { FieldApi, FormApi, standardSchemaValidator } from '../src/index' +import { FieldApi, FormApi } from '../src/index' import { sleep } from './utils' describe('standard schema validator', () => { @@ -33,41 +33,14 @@ describe('standard schema validator', () => { field.mount() field.setValue('') - expect(form.state.errors).toStrictEqual([ - 'First name is too short, You must end with an "a"', - ]) - }) - - it('should support standard schema sync validation with valibot and reads adapter params', async () => { - const form = new FormApi({ - defaultValues: { - firstName: '', - lastName: '', + expect(form.state.errors).toMatchObject([ + { + firstName: [ + { message: 'First name is too short' }, + { message: 'You must end with an "a"' }, + ], }, - validators: { - onChange: v.object({ - firstName: v.pipe( - v.string(), - v.minLength(3, 'First name is too short'), - v.endsWith('a', 'You must end with an "a"'), - ), - lastName: v.string(), - }), - }, - validatorAdapter: standardSchemaValidator({ - transformErrors: (issues) => issues.map((issue) => issue.message)[0], - }), - }) - - const field = new FieldApi({ - form, - name: 'firstName', - }) - - field.mount() - - field.setValue('') - expect(form.state.errors).toStrictEqual(['First name is too short']) + ]) }) it('should detect an async standard schema validator even without a validator adapter', async () => { @@ -101,7 +74,11 @@ describe('standard schema validator', () => { field.setValue('') await vi.runAllTimersAsync() - expect(form.state.errors).toStrictEqual(['First name is too short']) + expect(form.state.errors).toMatchObject([ + { + firstName: [{ message: 'First name is too short' }], + }, + ]) }) it('should support standard schema sync validation with zod', async () => { @@ -124,8 +101,10 @@ describe('standard schema validator', () => { field.mount() field.setValue('test') - expect(form.state.errors).toStrictEqual([ - 'email must be an email address', + expect(form.state.errors).toMatchObject([ + { + email: [{ message: 'email must be an email address' }], + }, ]) }) @@ -152,8 +131,8 @@ describe('standard schema validator', () => { field.setValue('test') await vi.runAllTimersAsync() - expect(form.state.errors).toStrictEqual([ - 'email must be an email address', + expect(form.state.errors).toMatchObject([ + { email: [{ message: 'email must be an email address' }] }, ]) }) @@ -188,7 +167,9 @@ describe('standard schema validator', () => { field.setValue('') await vi.runAllTimersAsync() - expect(form.state.errors).toStrictEqual(['First name is too short']) + expect(form.state.errors).toMatchObject([ + { firstName: [{ message: 'First name is too short' }] }, + ]) }) it('should support standard schema sync validation with arktype', async () => { @@ -209,8 +190,14 @@ describe('standard schema validator', () => { field.mount() field.setValue('test') - expect(form.state.errors).toStrictEqual([ - 'email must be an email address (was "test")', + expect(form.state.errors).toMatchObject([ + { + email: [ + { + message: 'email must be an email address (was "test")', + }, + ], + }, ]) }) @@ -248,18 +235,23 @@ describe('standard schema validator', () => { nameField.mount() surnameField.mount() - expect(nameField.getMeta().errors).toEqual([]) + expect(nameField.getMeta().errors).toMatchObject([]) nameField.setValue('q') - expect(nameField.getMeta().errors).toEqual([ - 'You must have a length of at least 3, You must end with an "a"', + expect(nameField.getMeta().errors).toMatchObject([ + { + message: 'You must have a length of at least 3', + }, + { message: 'You must end with an "a"' }, ]) - expect(surnameField.getMeta().errors).toEqual([ - 'You must have a length of at least 3', + expect(surnameField.getMeta().errors).toMatchObject([ + { message: 'You must have a length of at least 3' }, ]) nameField.setValue('qwer') - expect(nameField.getMeta().errors).toEqual(['You must end with an "a"']) + expect(nameField.getMeta().errors).toMatchObject([ + { message: 'You must end with an "a"' }, + ]) nameField.setValue('qwera') - expect(nameField.getMeta().errors).toEqual([]) + expect(nameField.getMeta().errors).toMatchObject([]) }) }) @@ -282,8 +274,10 @@ describe('standard schema validator', () => { field.mount() field.setValue('test') - expect(field.getMeta().errors).toStrictEqual([ - 'must be an email address (was "test")', + expect(field.getMeta().errors).toMatchObject([ + { + message: 'must be an email address (was "test")', + }, ]) }) @@ -309,7 +303,9 @@ describe('standard schema validator', () => { field.mount() field.setValue('') - expect(field.getMeta().errors).toStrictEqual(['First name is too short']) + expect(field.getMeta().errors).toMatchObject([ + { message: 'First name is too short' }, + ]) }) it('should support standard schema async validation with valibot', async () => { @@ -340,7 +336,9 @@ describe('standard schema validator', () => { field.setValue('') await vi.runAllTimersAsync() - expect(field.getMeta().errors).toStrictEqual(['First name is too short']) + expect(field.getMeta().errors).toMatchObject([ + { message: 'First name is too short' }, + ]) }) it('should support standard schema sync validation with arktype', async () => { @@ -361,8 +359,10 @@ describe('standard schema validator', () => { field.mount() field.setValue('test') - expect(field.getMeta().errors).toStrictEqual([ - 'must be an email address (was "test")', + expect(field.getMeta().errors).toMatchObject([ + { + message: 'must be an email address (was "test")', + }, ]) }) }) @@ -390,8 +390,12 @@ describe('standard schema validator', () => { field.mount() field.setValue('test') - expect(field.getMeta().errors).toStrictEqual([ - 'email must be an email address', + expect(field.getMeta().errors).toMatchObject([ + { message: 'email must be an email address' }, ]) }) + + it.todo( + 'Should allow for `disableErrorFlat` to disable flattening `errors` array', + ) }) diff --git a/packages/form-core/tests/standardSchemaValidator.test-d.ts b/packages/form-core/tests/standardSchemaValidator.test-d.ts new file mode 100644 index 000000000..79c92a207 --- /dev/null +++ b/packages/form-core/tests/standardSchemaValidator.test-d.ts @@ -0,0 +1,30 @@ +import { assertType, describe, it } from 'vitest' +import { z } from 'zod' +import { FieldApi, FormApi } from '../src/index' +import type { StandardSchemaV1Issue } from '../src/index' + +describe('standard schema validator', () => { + it("Should add field's onChange erorrMap from the form", () => { + const form = new FormApi({ + defaultValues: { + firstName: '', + }, + validators: { + onChange: z.object({ + firstName: z.string().min(1, 'Testing'), + }), + }, + }) + + form.state.errorMap.onChange + + const field = new FieldApi({ + form, + name: 'firstName', + }) + + assertType( + field.getMeta().errorMap.onChange, + ) + }) +}) diff --git a/packages/lit-form/package.json b/packages/lit-form/package.json index e619c61fd..497e178b0 100644 --- a/packages/lit-form/package.json +++ b/packages/lit-form/package.json @@ -48,7 +48,7 @@ "src" ], "dependencies": { - "@tanstack/form-core": "workspace:*" + "@tanstack/form-core": "^0.42.1" }, "devDependencies": { "lit": "^3.2.1" diff --git a/packages/lit-form/src/tanstack-form-controller.ts b/packages/lit-form/src/tanstack-form-controller.ts index f248007b2..31f64f874 100644 --- a/packages/lit-form/src/tanstack-form-controller.ts +++ b/packages/lit-form/src/tanstack-form-controller.ts @@ -5,9 +5,12 @@ import { AsyncDirective } from 'lit/async-directive.js' import type { DeepKeys, DeepValue, + FieldAsyncValidateOrFn, FieldOptions, + FieldValidateOrFn, + FormAsyncValidateOrFn, FormOptions, - Validator, + FormValidateOrFn, } from '@tanstack/form-core' import type { ElementPart, PartInfo } from 'lit/directive.js' import type { ReactiveController, ReactiveControllerHost } from 'lit' @@ -15,88 +18,222 @@ import type { ReactiveController, ReactiveControllerHost } from 'lit' type renderCallback< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFormOnServer extends undefined | FormAsyncValidateOrFn, > = ( fieldOptions: FieldApi< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer >, ) => unknown type fieldDirectiveType< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFormOnServer extends undefined | FormAsyncValidateOrFn, > = ( - form: FormApi, + form: FormApi< + TParentData, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + >, options: FieldOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync >, render: renderCallback< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer >, ) => { values: { - form: FormApi + form: FormApi< + TParentData, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + > options: FieldOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync > render: renderCallback< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer > } } export class TanStackFormController< TParentData, - TFormValidator extends - | Validator - | undefined = undefined, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFormOnServer extends undefined | FormAsyncValidateOrFn, > implements ReactiveController { #host: ReactiveControllerHost #subscription?: () => void - api: FormApi + api: FormApi< + TParentData, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + > constructor( host: ReactiveControllerHost, - config?: FormOptions, + config?: FormOptions< + TParentData, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + >, ) { ;(this.#host = host).addController(this) - this.api = new FormApi(config) + this.api = new FormApi< + TParentData, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + >(config) } hostConnected() { @@ -111,33 +248,74 @@ export class TanStackFormController< field< TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, >( fieldConfig: FieldOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync >, render: renderCallback< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer >, ) { return ( fieldDirective as unknown as fieldDirectiveType< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer > )(this.api, fieldConfig, render) } @@ -146,16 +324,50 @@ export class TanStackFormController< class FieldDirective< TParentData, TName extends DeepKeys, - TFieldValidator extends - | Validator, unknown> - | undefined = undefined, - TFormValidator extends - | Validator - | undefined = undefined, - TData extends DeepValue = DeepValue, + TData extends DeepValue, + TOnMount extends undefined | FieldValidateOrFn, + TOnChange extends undefined | FieldValidateOrFn, + TOnChangeAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnBlur extends undefined | FieldValidateOrFn, + TOnBlurAsync extends + | undefined + | FieldAsyncValidateOrFn, + TOnSubmit extends undefined | FieldValidateOrFn, + TOnSubmitAsync extends + | undefined + | FieldAsyncValidateOrFn, + TFormOnMount extends undefined | FormValidateOrFn, + TFormOnChange extends undefined | FormValidateOrFn, + TFormOnChangeAsync extends undefined | FormAsyncValidateOrFn, + TFormOnBlur extends undefined | FormValidateOrFn, + TFormOnBlurAsync extends undefined | FormAsyncValidateOrFn, + TFormOnSubmit extends undefined | FormValidateOrFn, + TFormOnSubmitAsync extends undefined | FormAsyncValidateOrFn, + TFormOnServer extends undefined | FormAsyncValidateOrFn, > extends AsyncDirective { #registered = false - #field?: FieldApi + #field?: FieldApi< + TParentData, + TName, + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + > #unmount?: () => void constructor(partInfo: PartInfo) { @@ -198,20 +410,48 @@ class FieldDirective< } render( - _form: FormApi, + _form: FormApi< + TParentData, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer + >, _fieldConfig: FieldOptions< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync >, _renderCallback: renderCallback< TParentData, TName, - TFieldValidator, - TFormValidator, - TData + TData, + TOnMount, + TOnChange, + TOnChangeAsync, + TOnBlur, + TOnBlurAsync, + TOnSubmit, + TOnSubmitAsync, + TFormOnMount, + TFormOnChange, + TFormOnChangeAsync, + TFormOnBlur, + TFormOnBlurAsync, + TFormOnSubmit, + TFormOnSubmitAsync, + TFormOnServer >, ) { if (this.#field) { diff --git a/packages/lit-form/tests/simple.ts b/packages/lit-form/tests/simple.ts index 25a36404f..db783209a 100644 --- a/packages/lit-form/tests/simple.ts +++ b/packages/lit-form/tests/simple.ts @@ -1,6 +1,5 @@ import { LitElement, html } from 'lit' import { TanStackFormController } from '../src/index.js' -import type { FieldApi, FormOptions } from '../src/index.js' interface Employee { firstName: string @@ -17,7 +16,7 @@ export const sampleData: Employee = { jobTitle: '', } -const formConfig: FormOptions = { +const formConfig = { defaultValues: sampleData, } @@ -42,7 +41,7 @@ export class TestForm extends LitElement { value.length < 3 ? 'Not long enough' : undefined, }, }, - (field: FieldApi) => { + (field) => { return html`
) => { + (field) => { return html`
` }, )} - ${this.form.field( - { name: `color` }, - (field: FieldApi) => { - return html`
- - + + + + +
` + })} + ${this.form.field({ name: `employed` }, (field) => { + return html` +
+ + - - - - -
` - }, - )} - ${this.form.field( - { name: `employed` }, - (field: FieldApi) => { - return html` -
- - -
- ${field.state.value - ? this.form.field( - { - name: `jobTitle`, - validators: { - onChange: ({ value }) => - value.length === 0 - ? 'Needs to have a job here' - : null, - }, - }, - (subField: FieldApi) => { - return html`
- - -
` + id="employed" + .type=${'checkbox'} + /> +
+ ${field.state.value + ? this.form.field( + { + name: `jobTitle`, + validators: { + onChange: ({ value }) => + value.length === 0 ? 'Needs to have a job here' : null, }, - ) - : ''} - ` - }, - )} + }, + (subField) => { + return html`
+ + +
` + }, + ) + : ''} + ` + })}