@volverjs/form-vue
Version:
Vue 3 Forms with @volverjs/ui-vue
196 lines (171 loc) • 7.19 kB
text/typescript
import type { Component, DeepReadonly, Ref, RendererElement, RendererNode, VNode, WatchStopHandle } from 'vue'
import type { z, AnyZodObject, ZodEffects, ZodOptional, ZodTypeAny, RefinementCtx } from 'zod'
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] // Adjust the depth limit as needed
type DecrementDepth<D extends Depth[number]> = Depth[D]
export type EffectType<T extends ZodTypeAny, D extends Depth[number] = 10>
= D extends 0
? T
: T | ZodOptional<T> | ZodEffects<EffectType<T, DecrementDepth<D>>>
export type FormSchema = EffectType<AnyZodObject>
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<z.infer<Schema>>) => Type : never
onUpdate?: Schema extends FormSchema
? (data?: undefined extends Type ? Partial<z.infer<Schema>> : Type) => void
: never
onSubmit?: Schema extends FormSchema
? (data?: undefined extends Type ? Partial<z.infer<Schema>> : Type) => void
: never
onReset?: Schema extends FormSchema ? (data?: undefined extends Type ? Partial<z.infer<Schema>> : Type) => void : never
onInvalid?: Schema extends FormSchema
? (error?: z.inferFormattedError<Schema>) => void
: never
onValid?: Schema extends FormSchema
? (data?: undefined extends Type ? Partial<z.infer<Schema>> : Type) => void
: never
}
export type FormComposableOptions<Schema, Type> = FormFieldComponentOptions
& FormComponentOptions<Schema, Type> & {
scope?: string
}
type FormPluginOptionsSchema<T = Partial<z.infer<FormSchema>>> = {
schema?: FormSchema
factory?: (data?: Partial<z.infer<FormSchema>>) => T
}
export type FormPluginOptions = FormPluginOptionsSchema
& FormComposableOptions<FormPluginOptionsSchema['schema'], FormPluginOptionsSchema['factory']>
export type InjectedFormData<Schema extends FormSchema, Type> = {
formData: Ref<(undefined extends Type ? Partial<z.infer<Schema>> : Type) | undefined>
errors: Readonly<
Ref<DeepReadonly<z.inferFormattedError<Schema>> | undefined>
>
submit: () => Promise<boolean>
validate: (formData?: undefined extends Type ? Partial<z.infer<Schema>> : Type, options?: { fields?: Set<Path<z.infer<Schema>>>, superRefine?: (arg: z.infer<Schema>, ctx: RefinementCtx) => 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, z.inferFormattedError<Schema>>>
invalid: Readonly<Ref<boolean>>
readonly: Readonly<Ref<boolean>>
fields: Ref<Map<string, string>>
}
export type InjectedFormFieldData<Schema extends FormSchema> = {
name: Readonly<Ref<Path<z.infer<Schema>>>>
errors: Readonly<Ref<DeepReadonly<z.inferFormattedError<Schema>>>>
}
export type InjectedFormFieldsGroupData<Schema extends FormSchema> = {
names: DeepReadonly<Ref<Path<z.infer<Schema>>[]>>
errors: Readonly<Ref<DeepReadonly<Record<string, z.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<z.infer<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<z.infer<Schema>>
vvElseIf?: AnyBoolean<Schema, Type> | Path<z.infer<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 }>