@volverjs/form-vue
Version:
Vue 3 Forms with @volverjs/ui-vue
156 lines (143 loc) • 3.66 kB
text/typescript
import {
getCurrentInstance,
type App,
inject,
type InjectionKey,
type Plugin,
} from 'vue'
import { defineFormField } from './VvFormField'
import { defineForm } from './VvForm'
import { defineFormWrapper } from './VvFormWrapper'
import { defineFormTemplate } from './VvFormTemplate'
import type {
InjectedFormData,
InjectedFormWrapperData,
InjectedFormFieldData,
FormComposableOptions,
FormPluginOptions,
FormTemplateItem,
Path,
PathValue,
FormSchema,
FormTemplate,
} from './types'
import type { AnyZodObject } from 'zod'
const _formFactory = <Schema extends FormSchema>(
schema: Schema,
options: FormComposableOptions<Schema> = {},
) => {
// create injection keys
const formInjectionKey = Symbol() as InjectionKey<InjectedFormData<Schema>>
const formWrapperInjectionKey = Symbol() as InjectionKey<
InjectedFormWrapperData<Schema>
>
const formFieldInjectionKey = Symbol() as InjectionKey<
InjectedFormFieldData<Schema>
>
// create components
const VvFormWrapper = defineFormWrapper(
formInjectionKey,
formWrapperInjectionKey,
)
const VvFormField = defineFormField(
formInjectionKey,
formWrapperInjectionKey,
formFieldInjectionKey,
options,
)
const VvFormTemplate = defineFormTemplate(formInjectionKey, VvFormField)
const { VvForm, errors, status, formData } = defineForm(
schema,
formInjectionKey,
options,
VvFormTemplate,
)
return {
VvForm,
VvFormWrapper,
VvFormField,
VvFormTemplate,
formInjectionKey,
formWrapperInjectionKey,
formFieldInjectionKey,
errors,
status,
formData,
}
}
export const pluginInjectionKey = Symbol() as InjectionKey<FormPluginOptions>
export const createForm = (
options: FormPluginOptions,
): Plugin & Partial<ReturnType<typeof useForm>> => {
let toReturn: Partial<ReturnType<typeof useForm>> = {}
if (options.schema) {
toReturn = _formFactory(options.schema as AnyZodObject, options)
}
return {
...toReturn,
install(app: App, { global = false } = {}) {
app.provide(pluginInjectionKey, options)
if (global) {
app.config.globalProperties.$vvForm = options
if (toReturn?.VvForm) {
app.component('VvForm', toReturn.VvForm)
}
if (toReturn?.VvFormWrapper) {
app.component('VvFormWrapper', toReturn.VvFormWrapper)
}
if (toReturn?.VvFormField) {
app.component('VvFormField', toReturn.VvFormField)
}
if (toReturn?.VvFormTemplate) {
app.component('VvFormTemplate', toReturn.VvFormTemplate)
}
}
},
}
}
export const useForm = <Schema extends FormSchema>(
schema: Schema,
options: FormComposableOptions<Schema> = {},
) => {
if (!getCurrentInstance()) {
return _formFactory(schema, options)
}
return _formFactory(
schema as AnyZodObject,
{
...inject(pluginInjectionKey, {}),
...options,
} as FormComposableOptions<AnyZodObject>,
)
}
export { FormFieldType } from './enums'
export { defaultObjectBySchema } from './utils'
type FormComponent = ReturnType<typeof defineForm>
type FormWrapperComponent = ReturnType<typeof defineFormWrapper>
type FormFieldComponent = ReturnType<typeof defineFormField>
type FormTemplateComponent = ReturnType<typeof defineFormTemplate>
export type {
InjectedFormData,
InjectedFormWrapperData,
InjectedFormFieldData,
FormComposableOptions,
FormSchema,
FormPluginOptions,
FormComponent,
FormWrapperComponent,
FormFieldComponent,
FormTemplate,
FormTemplateComponent,
FormTemplateItem,
Path,
PathValue,
}
/**
* @deprecated Use `useForm()` instead
*/
export const formFactory = <Schema extends FormSchema>(
schema: Schema,
options: FormComposableOptions<Schema> = {},
) => {
return _formFactory(schema, options)
}