@volverjs/form-vue 1.0.0-beta.2 → 1.0.0-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,171 +1,166 @@
1
1
  import {
2
- type InjectionKey,
3
- type Ref,
4
- computed,
5
- defineComponent,
6
- inject,
7
- provide,
8
- readonly,
9
- ref,
10
- toRefs,
11
- watch,
12
- h,
13
- type DeepReadonly,
2
+ type DeepReadonly,
3
+ type InjectionKey,
4
+ type Ref,
5
+ type SlotsType,
6
+ computed,
7
+ defineComponent,
8
+ h,
9
+ inject,
10
+ provide,
11
+ readonly,
12
+ ref,
13
+ toRefs,
14
+ watch,
14
15
  } from 'vue'
15
- import type { TypeOf, z } from 'zod'
16
+ import type { inferFormattedError, TypeOf, z } from 'zod'
16
17
  import type {
17
- FormSchema,
18
- InjectedFormData,
19
- InjectedFormWrapperData,
18
+ FormSchema,
19
+ InjectedFormData,
20
+ InjectedFormWrapperData,
20
21
  } from './types'
21
22
 
22
- export const defineFormWrapper = <Schema extends FormSchema>(
23
- formProvideKey: InjectionKey<InjectedFormData<Schema>>,
24
- wrapperProvideKey: InjectionKey<InjectedFormWrapperData<Schema>>,
25
- ) => {
26
- const VvFormWrapper = defineComponent({
27
- name: 'VvFormWrapper',
28
- props: {
29
- name: {
30
- type: String,
31
- required: true,
32
- },
33
- tag: {
34
- type: String,
35
- default: undefined,
36
- },
37
- },
38
- emits: ['invalid', 'valid'],
39
- expose: ['fields', 'invalid'],
40
- setup(props, { emit }) {
41
- const injectedFormData = inject(formProvideKey)
42
- const wrapperProvided = inject(wrapperProvideKey, undefined)
43
- const fields = ref(new Set<string>())
44
- const fieldsErrors: Ref<
45
- Map<string, z.inferFormattedError<Schema>>
46
- > = ref(new Map())
47
- const { name } = toRefs(props)
23
+ export function defineFormWrapper<Schema extends FormSchema>(formProvideKey: InjectionKey<InjectedFormData<Schema>>, wrapperProvideKey: InjectionKey<InjectedFormWrapperData<Schema>>) {
24
+ return defineComponent({
25
+ name: 'VvFormWrapper',
26
+ props: {
27
+ name: {
28
+ type: String,
29
+ required: true,
30
+ },
31
+ tag: {
32
+ type: String,
33
+ default: undefined,
34
+ },
35
+ },
36
+ emits: ['invalid', 'valid'],
37
+ expose: [
38
+ 'clear',
39
+ 'errors',
40
+ 'fields',
41
+ 'fieldsErrors',
42
+ 'formData',
43
+ 'invalid',
44
+ 'reset',
45
+ 'submit',
46
+ 'tag',
47
+ 'validate',
48
+ 'validateWrapper',
49
+ ],
50
+ slots: Object as SlotsType<{
51
+ default: {
52
+ errors?: DeepReadonly<z.inferFormattedError<Schema>>
53
+ formData?: Partial<TypeOf<Schema>>
54
+ formErrors?: DeepReadonly<inferFormattedError<Schema, string>>
55
+ invalid: boolean
56
+ submit?: InjectedFormData<Schema>['submit']
57
+ validate?: InjectedFormData<Schema>['validate']
58
+ validateWrapper?: () => Promise<boolean>
59
+ fieldsErrors: Map<string, inferFormattedError<Schema, string>>
60
+ clear?: InjectedFormData<Schema>['clear']
61
+ reset?: InjectedFormData<Schema>['reset']
62
+ }
63
+ }>,
64
+ setup(props, { emit }) {
65
+ const injectedFormData = inject(formProvideKey)
66
+ const wrapperProvided = inject(wrapperProvideKey, undefined)
67
+ const fields = ref(new Set<string>())
68
+ const fieldsErrors: Ref<
69
+ Map<string, z.inferFormattedError<Schema>>
70
+ > = ref(new Map())
71
+ const { name } = toRefs(props)
48
72
 
49
- // provide data to child fields
50
- provide(wrapperProvideKey, {
51
- name: readonly(name),
52
- errors: fieldsErrors,
53
- fields,
54
- })
73
+ // provide data to child fields
74
+ provide(wrapperProvideKey, {
75
+ name: readonly(name),
76
+ errors: fieldsErrors,
77
+ fields,
78
+ })
55
79
 
56
- // add fields to parent wrapper
57
- watch(
58
- fields,
59
- (newValue) => {
60
- if (wrapperProvided?.fields) {
61
- newValue.forEach((field) => {
62
- wrapperProvided?.fields.value.add(field)
63
- })
64
- }
65
- },
66
- { deep: true },
67
- )
80
+ // add fields to parent wrapper
81
+ watch(
82
+ fields,
83
+ (newValue) => {
84
+ if (wrapperProvided?.fields) {
85
+ newValue.forEach((field) => {
86
+ wrapperProvided?.fields.value.add(field)
87
+ })
88
+ }
89
+ },
90
+ { deep: true },
91
+ )
68
92
 
69
- // add fields to parent wrapper
70
- watch(
71
- () => new Map(fieldsErrors.value),
72
- (newValue, oldValue) => {
73
- if (wrapperProvided?.errors) {
74
- Array.from(oldValue.keys()).forEach((key) => {
75
- wrapperProvided.errors.value.delete(key)
76
- })
77
- Array.from(newValue.keys()).forEach((key) => {
78
- const value = newValue.get(key)
79
- if (value) {
80
- wrapperProvided.errors.value.set(key, value)
81
- }
82
- })
83
- }
84
- },
85
- { deep: true },
86
- )
93
+ // add fields to parent wrapper
94
+ watch(
95
+ () => new Map(fieldsErrors.value),
96
+ (newValue, oldValue) => {
97
+ if (wrapperProvided?.errors) {
98
+ Array.from(oldValue.keys()).forEach((key) => {
99
+ wrapperProvided.errors.value.delete(key)
100
+ })
101
+ Array.from(newValue.keys()).forEach((key) => {
102
+ const value = newValue.get(key)
103
+ if (value) {
104
+ wrapperProvided.errors.value.set(key, value)
105
+ }
106
+ })
107
+ }
108
+ },
109
+ { deep: true },
110
+ )
87
111
 
88
- const invalid = computed(() => {
89
- if (!injectedFormData?.invalid.value) {
90
- return false
91
- }
92
- return fieldsErrors.value.size > 0
93
- })
112
+ const invalid = computed(() => {
113
+ if (!injectedFormData?.invalid.value) {
114
+ return false
115
+ }
116
+ return fieldsErrors.value.size > 0
117
+ })
94
118
 
95
- watch(invalid, () => {
96
- if (invalid.value) {
97
- emit('invalid')
98
- } else {
99
- emit('valid')
100
- }
101
- })
119
+ watch(invalid, () => {
120
+ if (invalid.value) {
121
+ emit('invalid')
122
+ }
123
+ else {
124
+ emit('valid')
125
+ }
126
+ })
102
127
 
103
- return {
104
- formData: injectedFormData?.formData,
105
- errors: injectedFormData?.errors,
106
- submit: injectedFormData?.submit,
107
- validate: injectedFormData?.validate,
108
- invalid,
109
- fields,
110
- fieldsErrors,
111
- }
112
- },
113
- render() {
114
- if (this.tag) {
115
- return h(this.tag, null, {
116
- default: () =>
117
- this.$slots.default?.({
118
- invalid: this.invalid,
119
- formData: this.formData,
120
- submit: this.submit,
121
- validate: this.validate,
122
- errors: this.errors,
123
- fieldsErrors: this.fieldsErrors,
124
- }) ?? this.$slots.defalut,
125
- })
126
- }
127
- return (
128
- this.$slots.default?.({
129
- invalid: this.invalid,
130
- formData: this.formData,
131
- submit: this.submit,
132
- validate: this.validate,
133
- errors: this.errors,
134
- fieldsErrors: this.fieldsErrors,
135
- }) ?? this.$slots.defalut
136
- )
137
- },
138
- })
139
- /**
140
- * An hack to add types to the default slot
141
- */
142
- return VvFormWrapper as typeof VvFormWrapper & {
143
- new (): {
144
- $slots: {
145
- default: (_: {
146
- invalid: boolean
147
- formData: unknown extends
148
- | Partial<TypeOf<Schema>>
149
- | undefined
150
- ? undefined
151
- : Partial<TypeOf<Schema>> | undefined
152
- submit: () => Promise<boolean>
153
- validate: () => Promise<boolean>
154
- errors: Readonly<
155
- Ref<DeepReadonly<z.inferFormattedError<Schema>>>
156
- >
157
- fieldsErrors: Map<
158
- string,
159
- Record<
160
- string,
161
- {
162
- _errors: string[]
163
- }
164
- >
165
- >
166
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
167
- }) => any
168
- }
169
- }
170
- }
128
+ const validateWrapper = () => {
129
+ return injectedFormData?.validate(undefined, fields.value) ?? Promise.resolve(true)
130
+ }
131
+
132
+ return {
133
+ clear: injectedFormData?.clear,
134
+ errors: injectedFormData?.errors,
135
+ fields,
136
+ fieldsErrors,
137
+ formData: injectedFormData?.formData,
138
+ invalid,
139
+ reset: injectedFormData?.reset,
140
+ submit: injectedFormData?.submit,
141
+ validate: injectedFormData?.validate,
142
+ validateWrapper,
143
+ }
144
+ },
145
+ render() {
146
+ const defaultSlot = () =>
147
+ this.$slots.default?.({
148
+ clear: this.clear,
149
+ errors: this.errors,
150
+ fieldsErrors: this.fieldsErrors,
151
+ formData: this.formData,
152
+ invalid: this.invalid,
153
+ reset: this.reset,
154
+ submit: this.submit,
155
+ validate: this.validate,
156
+ validateWrapper: this.validateWrapper,
157
+ })
158
+ if (this.tag) {
159
+ return h(this.tag, null, {
160
+ default: defaultSlot,
161
+ })
162
+ }
163
+ return defaultSlot()
164
+ },
165
+ })
171
166
  }
package/src/enums.ts CHANGED
@@ -1,31 +1,32 @@
1
1
  export enum FormFieldType {
2
- text = 'text',
3
- number = 'number',
4
- email = 'email',
5
- password = 'password',
6
- tel = 'tel',
7
- url = 'url',
8
- search = 'search',
9
- date = 'date',
10
- time = 'time',
11
- datetimeLocal = 'datetime-local',
12
- month = 'month',
13
- week = 'week',
14
- color = 'color',
15
- select = 'select',
16
- checkbox = 'checkbox',
17
- radio = 'radio',
18
- textarea = 'textarea',
19
- radioGroup = 'radioGroup',
20
- checkboxGroup = 'checkboxGroup',
21
- combobox = 'combobox',
22
- custom = 'custom',
2
+ text = 'text',
3
+ number = 'number',
4
+ email = 'email',
5
+ password = 'password',
6
+ tel = 'tel',
7
+ url = 'url',
8
+ search = 'search',
9
+ date = 'date',
10
+ time = 'time',
11
+ datetimeLocal = 'datetime-local',
12
+ month = 'month',
13
+ week = 'week',
14
+ color = 'color',
15
+ select = 'select',
16
+ checkbox = 'checkbox',
17
+ radio = 'radio',
18
+ textarea = 'textarea',
19
+ radioGroup = 'radioGroup',
20
+ checkboxGroup = 'checkboxGroup',
21
+ combobox = 'combobox',
22
+ custom = 'custom',
23
23
  }
24
24
 
25
25
  export enum FormStatus {
26
- invalid = 'invalid',
27
- valid = 'valid',
28
- submitting = 'submitting',
29
- updated = 'updated',
30
- unknown = 'unknown',
26
+ invalid = 'invalid',
27
+ valid = 'valid',
28
+ submitting = 'submitting',
29
+ reset = 'reset',
30
+ updated = 'updated',
31
+ unknown = 'unknown',
31
32
  }
package/src/index.ts CHANGED
@@ -1,130 +1,130 @@
1
1
  import {
2
- getCurrentInstance,
3
- type App,
4
- inject,
5
- type InjectionKey,
6
- type Plugin,
2
+ getCurrentInstance,
3
+ type App,
4
+ inject,
5
+ type InjectionKey,
6
+ type Plugin,
7
7
  } from 'vue'
8
+ import type { AnyZodObject } from 'zod'
8
9
  import { defineFormField } from './VvFormField'
9
10
  import { defineForm } from './VvForm'
10
11
  import { defineFormWrapper } from './VvFormWrapper'
11
12
  import { defineFormTemplate } from './VvFormTemplate'
12
13
  import type {
13
- InjectedFormData,
14
- InjectedFormWrapperData,
15
- InjectedFormFieldData,
16
- FormComposableOptions,
17
- FormPluginOptions,
18
- FormTemplateItem,
19
- Path,
20
- PathValue,
21
- FormSchema,
22
- FormTemplate,
14
+ InjectedFormData,
15
+ InjectedFormWrapperData,
16
+ InjectedFormFieldData,
17
+ FormComposableOptions,
18
+ FormPluginOptions,
19
+ FormTemplateItem,
20
+ Path,
21
+ PathValue,
22
+ FormSchema,
23
+ FormTemplate,
23
24
  } from './types'
24
- import type { AnyZodObject } from 'zod'
25
25
 
26
- const _formFactory = <Schema extends FormSchema>(
27
- schema: Schema,
28
- options: FormComposableOptions<Schema> = {},
29
- ) => {
30
- // create injection keys
31
- const formInjectionKey = Symbol() as InjectionKey<InjectedFormData<Schema>>
32
- const formWrapperInjectionKey = Symbol() as InjectionKey<
33
- InjectedFormWrapperData<Schema>
34
- >
35
- const formFieldInjectionKey = Symbol() as InjectionKey<
36
- InjectedFormFieldData<Schema>
37
- >
26
+ function _formFactory<Schema extends FormSchema>(schema: Schema, options: FormComposableOptions<Schema> = {}) {
27
+ // create injection keys
28
+ const formInjectionKey = Symbol('formInjectionKey') as InjectionKey<InjectedFormData<Schema>>
29
+ const formWrapperInjectionKey = Symbol('formWrapperInjectionKey') as InjectionKey<
30
+ InjectedFormWrapperData<Schema>
31
+ >
32
+ const formFieldInjectionKey = Symbol('formFieldInjectionKey') as InjectionKey<
33
+ InjectedFormFieldData<Schema>
34
+ >
38
35
 
39
- // create components
40
- const VvFormWrapper = defineFormWrapper(
41
- formInjectionKey,
42
- formWrapperInjectionKey,
43
- )
44
- const VvFormField = defineFormField(
45
- formInjectionKey,
46
- formWrapperInjectionKey,
47
- formFieldInjectionKey,
48
- options,
49
- )
50
- const VvFormTemplate = defineFormTemplate(formInjectionKey, VvFormField)
51
- const {
52
- VvForm,
53
- errors,
54
- status,
55
- formData,
56
- validate,
57
- submit,
58
- ignoreUpdates,
59
- stopUpdatesWatch,
60
- } = defineForm(schema, formInjectionKey, options, VvFormTemplate)
36
+ // create components
37
+ const VvFormWrapper = defineFormWrapper(
38
+ formInjectionKey,
39
+ formWrapperInjectionKey,
40
+ )
41
+ const VvFormField = defineFormField(
42
+ formInjectionKey,
43
+ formWrapperInjectionKey,
44
+ formFieldInjectionKey,
45
+ options,
46
+ )
47
+ const VvFormTemplate = defineFormTemplate(formInjectionKey, VvFormField)
48
+ const {
49
+ clear,
50
+ errors,
51
+ formData,
52
+ ignoreUpdates,
53
+ invalid,
54
+ readonly,
55
+ reset,
56
+ status,
57
+ stopUpdatesWatch,
58
+ submit,
59
+ validate,
60
+ VvForm,
61
+ } = defineForm(schema, formInjectionKey, options, VvFormTemplate)
61
62
 
62
- return {
63
- VvForm,
64
- VvFormWrapper,
65
- VvFormField,
66
- VvFormTemplate,
67
- formInjectionKey,
68
- formWrapperInjectionKey,
69
- formFieldInjectionKey,
70
- errors,
71
- status,
72
- formData,
73
- validate,
74
- submit,
75
- ignoreUpdates,
76
- stopUpdatesWatch,
77
- }
63
+ return {
64
+ clear,
65
+ errors,
66
+ formData,
67
+ formFieldInjectionKey,
68
+ formInjectionKey,
69
+ formWrapperInjectionKey,
70
+ ignoreUpdates,
71
+ invalid,
72
+ readonly,
73
+ reset,
74
+ status,
75
+ stopUpdatesWatch,
76
+ submit,
77
+ validate,
78
+ VvForm,
79
+ VvFormField,
80
+ VvFormTemplate,
81
+ VvFormWrapper,
82
+ }
78
83
  }
79
84
 
80
- export const pluginInjectionKey = Symbol() as InjectionKey<FormPluginOptions>
85
+ export const pluginInjectionKey = Symbol('pluginInjectionKey') as InjectionKey<FormPluginOptions>
81
86
 
82
- export const createForm = (
83
- options: FormPluginOptions,
84
- ): Plugin & Partial<ReturnType<typeof useForm>> => {
85
- let toReturn: Partial<ReturnType<typeof useForm>> = {}
86
- if (options.schema) {
87
- toReturn = _formFactory(options.schema as AnyZodObject, options)
88
- }
89
- return {
90
- ...toReturn,
91
- install(app: App, { global = false } = {}) {
92
- app.provide(pluginInjectionKey, options)
87
+ export function createForm(options: FormPluginOptions): Plugin & Partial<ReturnType<typeof useForm>> {
88
+ let toReturn: Partial<ReturnType<typeof useForm>> = {}
89
+ if (options.schema) {
90
+ toReturn = _formFactory(options.schema as AnyZodObject, options)
91
+ }
92
+ return {
93
+ ...toReturn,
94
+ install(app: App, { global = false } = {}) {
95
+ app.provide(pluginInjectionKey, options)
93
96
 
94
- if (global) {
95
- app.config.globalProperties.$vvForm = options
97
+ if (global) {
98
+ app.config.globalProperties.$vvForm = options
96
99
 
97
- if (toReturn?.VvForm) {
98
- app.component('VvForm', toReturn.VvForm)
99
- }
100
- if (toReturn?.VvFormWrapper) {
101
- app.component('VvFormWrapper', toReturn.VvFormWrapper)
102
- }
103
- if (toReturn?.VvFormField) {
104
- app.component('VvFormField', toReturn.VvFormField)
105
- }
106
- if (toReturn?.VvFormTemplate) {
107
- app.component('VvFormTemplate', toReturn.VvFormTemplate)
108
- }
109
- }
110
- },
111
- }
100
+ if (toReturn?.VvForm) {
101
+ app.component('VvForm', toReturn.VvForm)
102
+ }
103
+ if (toReturn?.VvFormWrapper) {
104
+ app.component('VvFormWrapper', toReturn.VvFormWrapper)
105
+ }
106
+ if (toReturn?.VvFormField) {
107
+ app.component('VvFormField', toReturn.VvFormField)
108
+ }
109
+ if (toReturn?.VvFormTemplate) {
110
+ app.component('VvFormTemplate', toReturn.VvFormTemplate)
111
+ }
112
+ }
113
+ },
114
+ }
112
115
  }
113
116
 
114
- export const useForm = <Schema extends FormSchema>(
115
- schema: Schema,
116
- options: FormComposableOptions<Schema> = {},
117
- ) => {
118
- if (!getCurrentInstance()) {
119
- return _formFactory(schema, options)
120
- }
121
- return _formFactory(
122
- schema as AnyZodObject,
123
- {
124
- ...inject(pluginInjectionKey, {}),
125
- ...options,
126
- } as FormComposableOptions<AnyZodObject>,
127
- )
117
+ export function useForm<Schema extends FormSchema>(schema: Schema, options: FormComposableOptions<Schema> = {}) {
118
+ if (!getCurrentInstance()) {
119
+ return _formFactory(schema, options)
120
+ }
121
+ return _formFactory(
122
+ schema as AnyZodObject,
123
+ {
124
+ ...inject(pluginInjectionKey, {}),
125
+ ...options,
126
+ } as FormComposableOptions<AnyZodObject>,
127
+ )
128
128
  }
129
129
 
130
130
  export { FormFieldType } from './enums'
@@ -136,28 +136,25 @@ type FormFieldComponent = ReturnType<typeof defineFormField>
136
136
  type FormTemplateComponent = ReturnType<typeof defineFormTemplate>
137
137
 
138
138
  export type {
139
- InjectedFormData,
140
- InjectedFormWrapperData,
141
- InjectedFormFieldData,
142
- FormComposableOptions,
143
- FormSchema,
144
- FormPluginOptions,
145
- FormComponent,
146
- FormWrapperComponent,
147
- FormFieldComponent,
148
- FormTemplate,
149
- FormTemplateComponent,
150
- FormTemplateItem,
151
- Path,
152
- PathValue,
139
+ FormComponent,
140
+ FormComposableOptions,
141
+ FormFieldComponent,
142
+ FormPluginOptions,
143
+ FormSchema,
144
+ FormTemplate,
145
+ FormTemplateComponent,
146
+ FormTemplateItem,
147
+ FormWrapperComponent,
148
+ InjectedFormData,
149
+ InjectedFormFieldData,
150
+ InjectedFormWrapperData,
151
+ Path,
152
+ PathValue,
153
153
  }
154
154
 
155
155
  /**
156
156
  * @deprecated Use `useForm()` instead
157
157
  */
158
- export const formFactory = <Schema extends FormSchema>(
159
- schema: Schema,
160
- options: FormComposableOptions<Schema> = {},
161
- ) => {
162
- return _formFactory(schema, options)
158
+ export function formFactory<Schema extends FormSchema>(schema: Schema, options: FormComposableOptions<Schema> = {}) {
159
+ return _formFactory(schema, options)
163
160
  }