@volverjs/form-vue
Version:
Vue 3 Forms with @volverjs/ui-vue
228 lines (198 loc) • 8.38 kB
text/typescript
import type { Component, DeepReadonly, Ref, RendererElement, RendererNode, VNode, WatchStopHandle } from 'vue'
import type * as z3 from 'zod/v3'
import type * as z4 from 'zod/v4/core'
import type { RefinementCtx as z4RefinementCtx } from 'zod/v4'
import type { IgnoredUpdater } from '@vueuse/core'
import type { FormFieldType, FormStatus } from './enums'
type Depth = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
type DecrementDepth<D extends Depth[number]> = Depth[D]
export type EffectType<T extends z3.ZodTypeAny, D extends Depth[number] = 10>
= D extends 0
? T
: T | z3.ZodOptional<T> | z3.ZodNullable<T> | z3.ZodDefault<T> | z3.ZodEffects<EffectType<T, DecrementDepth<D>>>
export type $EffectType<T extends z4.$ZodType, D extends Depth[number] = 10>
= D extends 0
? T
: T
| z4.$ZodOptional<$EffectType<T, DecrementDepth<D>>>
| z4.$ZodNullable<$EffectType<T, DecrementDepth<D>>>
| z4.$ZodDefault<$EffectType<T, DecrementDepth<D>>>
| z4.$ZodPipe<$EffectType<T, DecrementDepth<D>>, z4.$ZodType>
// FormSchema garantisce sempre la presenza di safeParse
export type FormSchema = z3.ZodTypeAny | z4.$ZodType
export type InferSchema<T extends FormSchema> = T extends EffectType<z3.AnyZodObject>
? z3.z.infer<T>
: z4.infer<T>
export type InferFormattedError<T extends FormSchema> = T extends EffectType<z3.AnyZodObject>
? z3.z.inferFormattedError<T>
: z4.$ZodFormattedError<T>
export type RefinementCtx<T extends FormSchema> = z3.RefinementCtx | z4RefinementCtx<T>
export type VvZodError<T extends FormSchema> = T extends EffectType<z3.AnyZodObject>
? z3.ZodError<T>
: z4.$ZodError<T>
export type ZodIssue = z3.ZodIssue | z4.$ZodIssue
export type FormFieldComponentOptions = {
lazyLoad?: boolean
sideEffects?: (type: `${FormFieldType}`) => Promise<void> | void
}
export type FormComponentOptions<Schema, Type> = {
updateThrottle?: number
continuousValidation?: boolean
readonly?: boolean
template?: Schema extends FormSchema ? FormTemplate<Schema, Type> : never
class?: Schema extends FormSchema ? new (data?: Partial<InferSchema<Schema>>) => Type : never
onUpdate?: Schema extends FormSchema
? (data?: undefined extends Type ? Partial<InferSchema<Schema>> : Type) => void
: never
onSubmit?: Schema extends FormSchema
? (data?: undefined extends Type ? Partial<InferSchema<Schema>> : Type) => void
: never
onReset?: Schema extends FormSchema ? (data?: undefined extends Type ? Partial<InferSchema<Schema>> : Type) => void : never
onInvalid?: Schema extends FormSchema
? (error?: InferFormattedError<Schema>) => void
: never
onValid?: Schema extends FormSchema
? (data?: undefined extends Type ? Partial<InferSchema<Schema>> : Type) => void
: never
}
export type FormComposableOptions<Schema, Type> = FormFieldComponentOptions
& FormComponentOptions<Schema, Type> & {
scope?: string
}
type FormPluginOptionsSchema<T = Partial<InferSchema<FormSchema>>> = {
schema?: FormSchema
factory?: (data?: Partial<InferSchema<FormSchema>>) => T
}
export type FormPluginOptions = FormPluginOptionsSchema
& FormComposableOptions<FormPluginOptionsSchema['schema'], FormPluginOptionsSchema['factory']>
export type InjectedFormData<Schema extends FormSchema, Type> = {
formData: Ref<(undefined extends Type ? Partial<InferSchema<Schema>> : Type) | undefined>
errors: Readonly<
Ref<DeepReadonly<InferFormattedError<Schema>> | undefined>
>
submit: () => Promise<boolean>
validate: (formData?: undefined extends Type
? Partial<InferSchema<Schema>>
: Type, options?: {
fields?: Set<Path<InferSchema<Schema>>>
superRefine?: (arg: InferSchema<Schema>, ctx: RefinementCtx<Schema>) => void | Promise<void>
}) => Promise<boolean>
clear: () => void
reset: () => void
ignoreUpdates: IgnoredUpdater
stopUpdatesWatch: WatchStopHandle
status: Readonly<Ref<FormStatus | undefined>>
invalid: Readonly<Ref<boolean>>
readonly: Ref<boolean>
wrappers: Map<string, InjectedFormWrapperData<Schema>>
}
export type InjectedFormWrapperData<Schema extends FormSchema> = {
name: Readonly<Ref<string>>
errors: Ref<Map<string, InferFormattedError<Schema> | undefined>>
invalid: Readonly<Ref<boolean>>
readonly: Readonly<Ref<boolean>>
fields: Ref<Map<string, string>>
}
export type InjectedFormFieldData<Schema extends FormSchema> = {
name: Readonly<Ref<Path<InferSchema<Schema>>>>
errors: Readonly<Ref<DeepReadonly<InferFormattedError<Schema> | undefined>>>
}
export type InjectedFormFieldsGroupData<Schema extends FormSchema> = {
names: DeepReadonly<Ref<Path<InferSchema<Schema>>[]>>
errors: Readonly<Ref<DeepReadonly<Record<string, InferFormattedError<Schema>> | undefined>>>
}
export type Primitive
= | null
| undefined
| string
| number
| boolean
| symbol
| bigint
type IsTuple<T extends readonly any[]> = number extends T['length']
? false
: true
type TupleKeys<T extends readonly any[]> = Exclude<keyof T, keyof any[]>
export type PathConcat<
TKey extends string | number,
TValue,
> = TValue extends Primitive ? `${TKey}` : `${TKey}` | `${TKey}.${Path<TValue>}`
export type Path<T> = T extends readonly (infer V)[]
? IsTuple<T> extends true
? {
[K in TupleKeys<T>]-?: PathConcat<K & string, T[K]>
}[TupleKeys<T>]
: PathConcat<number, V>
: {
[K in keyof T]-?: PathConcat<K & string, T[K]>
}[keyof T]
export type PathValue<T, TPath extends Path<T> | Path<T>[]> = T extends any
? TPath extends `${infer K}.${infer R}`
? K extends keyof T
? R extends Path<T[K]>
? undefined extends T[K]
? PathValue<T[K], R> | undefined
: PathValue<T[K], R>
: never
: K extends `${number}`
? T extends readonly (infer V)[]
? PathValue<V, R & Path<V>>
: never
: never
: TPath extends keyof T
? T[TPath]
: TPath extends `${number}`
? T extends readonly (infer V)[]
? V
: never
: never
: never
export type AnyBoolean<Schema extends FormSchema, Type>
= | boolean
| Ref<boolean>
| ((data?: InjectedFormData<Schema, Type>) => boolean | Ref<boolean>)
export type SimpleFormTemplateItem<Schema extends FormSchema, Type> = Record<
string,
any
> & {
vvIs?: string | Component
vvName?: Path<InferSchema<Schema>>
vvSlots?: Record<string, any>
vvChildren?:
| Array<
| SimpleFormTemplateItem<Schema, Type>
| ((
data?: InjectedFormData<Schema, Type>,
scope?: Record<string, unknown>,
) => SimpleFormTemplateItem<Schema, Type>)
>
| ((
data?: InjectedFormData<Schema, Type>,
scope?: Record<string, unknown>,
) => Array<
| SimpleFormTemplateItem<Schema, Type>
| ((
data?: InjectedFormData<Schema, Type>,
scope?: Record<string, unknown>,
) => SimpleFormTemplateItem<Schema, Type>)
>)
vvIf?: AnyBoolean<Schema, Type> | Path<InferSchema<Schema>>
vvElseIf?: AnyBoolean<Schema, Type> | Path<InferSchema<Schema>>
vvType?: `${FormFieldType}`
vvShowValid?: boolean
vvContent?: string
vvDefaultValue?: any
}
export type FormTemplateItem<Schema extends FormSchema, Type = undefined>
= | SimpleFormTemplateItem<Schema, Type>
| ((
data?: InjectedFormData<Schema, Type>,
scope?: Record<string, unknown>,
) => SimpleFormTemplateItem<Schema, Type>)
export type FormTemplate<Schema extends FormSchema, Type = undefined>
= | FormTemplateItem<Schema, Type>[]
| ((
data?: InjectedFormData<Schema, Type>,
scope?: Record<string, unknown>,
) => FormTemplateItem<Schema, Type>[])
export type RenderFunctionOutput = VNode<RendererNode, RendererElement, { [key: string]: any }>