@volverjs/form-vue 0.0.2 → 0.0.4

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.
package/README.md CHANGED
@@ -54,6 +54,7 @@ const form = createForm({
54
54
  schema
55
55
  // lazyLoad: boolean - default false
56
56
  // updateThrottle: number - default 500
57
+ // continuosValidation: boolean - default false
57
58
  // sideEffects?: (data: any) => void
58
59
  })
59
60
 
@@ -131,6 +132,31 @@ The throttle can be changed with the `updateThrottle` option.
131
132
  </template>
132
133
  ```
133
134
 
135
+ The `continuosValidation` can be passed through options or with VvForm prop.
136
+ With this field the validation doesn't stop and continue also after a validaton success.
137
+
138
+ ```vue
139
+ <script lang="ts" setup>
140
+ import { ref } from 'vue'
141
+
142
+ const { VvForm, VvFormField } = useForm(MyZodSchema, {
143
+ lazyLoad: true
144
+ // continuosValidation: true
145
+ })
146
+
147
+ const formData = ref({
148
+ name: '',
149
+ surname: ''
150
+ })
151
+ </script>
152
+
153
+ <template>
154
+ <VvForm v-model="formData" :continuosValidation="true">
155
+ <!-- form fields -->
156
+ </VvForm>
157
+ </template>
158
+ ```
159
+
134
160
  ### VvFormWrapper
135
161
 
136
162
  `VvFormWrapper` gives you the validation status of a part of your form.
@@ -214,7 +240,7 @@ You can also use the `VvFormField` component to render a default slot without a
214
240
  invalidLabel,
215
241
  formData,
216
242
  formErrors,
217
- erros,
243
+ errors,
218
244
  onUpdate
219
245
  }"
220
246
  name="surname"
@@ -250,6 +276,86 @@ Or a custom component.
250
276
  </template>
251
277
  ```
252
278
 
279
+ ## Nested VvFormField
280
+
281
+ In some use cases can be usefull nest `VvFormField`.
282
+ For example let's assume:
283
+
284
+ - a shopping list that is a field of our model (ex: ToDo list)
285
+ - the sum of all products of the shopping list cannot be 0
286
+ - we don't know all the products a priori
287
+
288
+ So our ToDo model and shopping list are structured like:
289
+
290
+ ```javascript
291
+ const toDo = {
292
+ shoppingList: {
293
+ bread: 0,
294
+ milk: 0,
295
+ tomato: 0,
296
+ potato: 0,
297
+ ...
298
+ }
299
+ }
300
+ ```
301
+
302
+ Our Zod schema can be:
303
+
304
+ ```typescript
305
+ const toDoSchema = z.object({
306
+ shoppingList: z
307
+ .object({})
308
+ .default({})
309
+ .superRefine((value, ctx) => {
310
+ const shoppingList = value as Record<string, number>
311
+ if (
312
+ Object.keys(value).length &&
313
+ !Object.keys(value).find((key) => shoppingList[key] > 0)
314
+ ) {
315
+ ctx.addIssue({
316
+ code: z.ZodIssueCode.custom,
317
+ message: i18n.global.t('atLeastOneProduct')
318
+ })
319
+ }
320
+ })
321
+ })
322
+ ```
323
+
324
+ And the Vue component:
325
+
326
+ ```vue
327
+ <script setup lang="ts">
328
+ const { VvForm, VvFormField } = useForm(toDoSchema, {
329
+ lazyLoad: true,
330
+ continuosValidation: true
331
+ })
332
+
333
+ // shopping list data, const or async
334
+ const shoppingList = {
335
+ bread: 0,
336
+ milk: 0,
337
+ tomato: 0,
338
+ potato: 0
339
+ }
340
+ </script>
341
+
342
+ <template>
343
+ <VvForm>
344
+ <VvFormField v-slot="{ invalid, invalidLabel }" name="shoppingList">
345
+ <VvFormField
346
+ v-for="key in Object.keys(shoppingList)"
347
+ :key="key"
348
+ :name="`shoppingList.${key}`"
349
+ :label="$t(key)"
350
+ />
351
+ <small v-if="invalid" class="input-counter__hint">{{
352
+ invalidLabel[0]
353
+ }}</small>
354
+ </VvFormField>
355
+ </VvForm>
356
+ </template>
357
+ ```
358
+
253
359
  ## Composable
254
360
 
255
361
  `useForm` can be used to create a form programmatically inside a Vue 3 Component.
@@ -268,6 +374,7 @@ The default settings are inherited from the plugin (if it was defined).
268
374
  const { VvForm, VvFormWrapper, VvFormField } = useForm(schema, {
269
375
  // lazyLoad: boolean - default false
270
376
  // updateThrottle: number - default 500
377
+ // continuosValidation: true - default false
271
378
  // sideEffects?: (formData: any) => void
272
379
  })
273
380
  </script>
@@ -297,6 +404,7 @@ const schema = z.object({
297
404
  const { VvForm, VvFormWrapper, VvFormField } = formFactory(schema, {
298
405
  // lazyLoad: boolean - default false
299
406
  // updateThrottle: number - default 500
407
+ // continuosValidation: true - default false
300
408
  // sideEffects?: (data: any) => void
301
409
  })
302
410
 
package/dist/VvForm.d.ts CHANGED
@@ -1,17 +1,22 @@
1
1
  import { type InjectionKey } from 'vue';
2
- import type { AnyZodObject } from 'zod';
2
+ import type { AnyZodObject, ZodEffects } from 'zod';
3
3
  import type { InjectedFormData } from './types';
4
4
  export declare enum FormStatus {
5
5
  invalid = "invalid",
6
6
  valid = "valid"
7
7
  }
8
- export declare const defineForm: (schema: AnyZodObject, provideKey: InjectionKey<InjectedFormData>, options?: {
8
+ export declare const defineForm: (schema: AnyZodObject | ZodEffects<AnyZodObject>, provideKey: InjectionKey<InjectedFormData>, options?: {
9
9
  updateThrottle?: number;
10
+ continuosValidation?: boolean;
10
11
  }) => import("vue").DefineComponent<{
11
12
  modelValue: {
12
13
  type: ObjectConstructor;
13
14
  default: () => {};
14
15
  };
16
+ continuosValidation: {
17
+ type: BooleanConstructor;
18
+ default: boolean;
19
+ };
15
20
  }, {
16
21
  submit: () => boolean;
17
22
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("valid" | "invalid" | "submit" | "update:modelValue")[], "valid" | "invalid" | "submit" | "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
@@ -19,6 +24,10 @@ export declare const defineForm: (schema: AnyZodObject, provideKey: InjectionKey
19
24
  type: ObjectConstructor;
20
25
  default: () => {};
21
26
  };
27
+ continuosValidation: {
28
+ type: BooleanConstructor;
29
+ default: boolean;
30
+ };
22
31
  }>> & {
23
32
  onValid?: ((...args: any[]) => any) | undefined;
24
33
  onInvalid?: ((...args: any[]) => any) | undefined;
@@ -26,4 +35,5 @@ export declare const defineForm: (schema: AnyZodObject, provideKey: InjectionKey
26
35
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
27
36
  }, {
28
37
  modelValue: Record<string, any>;
38
+ continuosValidation: boolean;
29
39
  }>;
package/dist/index.d.ts CHANGED
@@ -1,15 +1,19 @@
1
1
  import { type InjectionKey, type Plugin } from 'vue';
2
- import type { AnyZodObject } from 'zod';
2
+ import type { AnyZodObject, ZodEffects } from 'zod';
3
3
  import { defineFormField } from './VvFormField';
4
4
  import { defineForm } from './VvForm';
5
5
  import { defineFormWrapper } from './VvFormWrapper';
6
6
  import type { InjectedFormData, InjectedFormWrapperData, InjectedFormFieldData, FormComposableOptions, FormPluginOptions } from './types';
7
- export declare const formFactory: (schema: AnyZodObject, options?: FormComposableOptions) => {
7
+ export declare const formFactory: (schema: AnyZodObject | ZodEffects<AnyZodObject>, options?: FormComposableOptions) => {
8
8
  VvForm: import("vue").DefineComponent<{
9
9
  modelValue: {
10
10
  type: ObjectConstructor;
11
11
  default: () => {};
12
12
  };
13
+ continuosValidation: {
14
+ type: BooleanConstructor;
15
+ default: boolean;
16
+ };
13
17
  }, {
14
18
  submit: () => boolean;
15
19
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("valid" | "invalid" | "submit" | "update:modelValue")[], "valid" | "invalid" | "submit" | "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
@@ -17,6 +21,10 @@ export declare const formFactory: (schema: AnyZodObject, options?: FormComposabl
17
21
  type: ObjectConstructor;
18
22
  default: () => {};
19
23
  };
24
+ continuosValidation: {
25
+ type: BooleanConstructor;
26
+ default: boolean;
27
+ };
20
28
  }>> & {
21
29
  onValid?: ((...args: any[]) => any) | undefined;
22
30
  onInvalid?: ((...args: any[]) => any) | undefined;
@@ -24,6 +32,7 @@ export declare const formFactory: (schema: AnyZodObject, options?: FormComposabl
24
32
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
25
33
  }, {
26
34
  modelValue: Record<string, any>;
35
+ continuosValidation: boolean;
27
36
  }>;
28
37
  VvFormWrapper: import("vue").DefineComponent<{
29
38
  name: {
@@ -63,12 +72,16 @@ export declare const formFactory: (schema: AnyZodObject, options?: FormComposabl
63
72
  };
64
73
  export declare const pluginInjectionKey: InjectionKey<FormPluginOptions>;
65
74
  export declare const createForm: (options: FormPluginOptions) => Plugin & Partial<ReturnType<typeof useForm>>;
66
- export declare const useForm: (schema: AnyZodObject, options?: FormComposableOptions) => {
75
+ export declare const useForm: (schema: AnyZodObject | ZodEffects<AnyZodObject>, options?: FormComposableOptions) => {
67
76
  VvForm: import("vue").DefineComponent<{
68
77
  modelValue: {
69
78
  type: ObjectConstructor;
70
79
  default: () => {};
71
80
  };
81
+ continuosValidation: {
82
+ type: BooleanConstructor;
83
+ default: boolean;
84
+ };
72
85
  }, {
73
86
  submit: () => boolean;
74
87
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("valid" | "invalid" | "submit" | "update:modelValue")[], "valid" | "invalid" | "submit" | "update:modelValue", import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
@@ -76,6 +89,10 @@ export declare const useForm: (schema: AnyZodObject, options?: FormComposableOpt
76
89
  type: ObjectConstructor;
77
90
  default: () => {};
78
91
  };
92
+ continuosValidation: {
93
+ type: BooleanConstructor;
94
+ default: boolean;
95
+ };
79
96
  }>> & {
80
97
  onValid?: ((...args: any[]) => any) | undefined;
81
98
  onInvalid?: ((...args: any[]) => any) | undefined;
@@ -83,6 +100,7 @@ export declare const useForm: (schema: AnyZodObject, options?: FormComposableOpt
83
100
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
84
101
  }, {
85
102
  modelValue: Record<string, any>;
103
+ continuosValidation: boolean;
86
104
  }>;
87
105
  VvFormWrapper: import("vue").DefineComponent<{
88
106
  name: {
package/dist/index.es.js CHANGED
@@ -1,10 +1,10 @@
1
- import { defineComponent as w, computed as h, onMounted as q, inject as S, toRefs as G, watch as V, provide as $, readonly as A, resolveComponent as b, defineAsyncComponent as Z, h as O, ref as x, isProxy as Y, toRaw as H, withModifiers as Q } from "vue";
1
+ import { defineComponent as w, computed as h, onMounted as Z, inject as S, toRefs as G, watch as V, provide as k, readonly as M, resolveComponent as b, defineAsyncComponent as q, h as O, ref as x, isProxy as Y, toRaw as H, withModifiers as Q } from "vue";
2
2
  import { watchThrottled as X } from "@vueuse/core";
3
- import { ZodDefault as P, ZodObject as T } from "zod";
4
- function E(e) {
3
+ import { ZodEffects as P, ZodDefault as T, ZodObject as F } from "zod";
4
+ function A(e) {
5
5
  return Array.isArray(e);
6
6
  }
7
- function F(e) {
7
+ function ee(e) {
8
8
  return typeof e < "u";
9
9
  }
10
10
  function N(e) {
@@ -16,12 +16,12 @@ function L(e) {
16
16
  function D(e) {
17
17
  return typeof e == "string";
18
18
  }
19
- function M(e) {
19
+ function E(e) {
20
20
  return typeof e > "u";
21
21
  }
22
- const ee = /^[0-9]+$/, re = ["__proto__", "prototype", "constructor"];
22
+ const re = /^[0-9]+$/, te = ["__proto__", "prototype", "constructor"];
23
23
  function _(e, r, t) {
24
- const a = F(t) ? t : void 0;
24
+ const a = ee(t) ? t : void 0;
25
25
  if (!L(e) || !D(r))
26
26
  return a;
27
27
  const n = W(r);
@@ -29,13 +29,13 @@ function _(e, r, t) {
29
29
  for (const o of n) {
30
30
  if (o === "*")
31
31
  continue;
32
- const i = function(s) {
33
- return s.map((f) => M(f) || N(f) ? f : E(f) ? i(f) : f[o]);
32
+ const s = function(i) {
33
+ return i.map((f) => E(f) || N(f) ? f : A(f) ? s(f) : f[o]);
34
34
  };
35
- if (E(e) && !ee.test(o) ? e = i(e) : e = e[o], M(e) || N(e))
35
+ if (A(e) && !re.test(o) ? e = s(e) : e = e[o], E(e) || N(e))
36
36
  break;
37
37
  }
38
- return M(e) ? a : e;
38
+ return E(e) ? a : e;
39
39
  }
40
40
  }
41
41
  function U(e, r, t) {
@@ -46,26 +46,26 @@ function U(e, r, t) {
46
46
  return;
47
47
  const n = a.length;
48
48
  for (let o = 0; o < n; o++) {
49
- const i = a[o];
49
+ const s = a[o];
50
50
  if (o === n - 1) {
51
- e[i] = t;
51
+ e[s] = t;
52
52
  return;
53
53
  }
54
- if (i === "*" && E(e)) {
55
- const s = a.slice(o + 1).join(".");
54
+ if (s === "*" && A(e)) {
55
+ const i = a.slice(o + 1).join(".");
56
56
  for (const f of e)
57
- U(f, s, t);
57
+ U(f, i, t);
58
58
  return;
59
59
  }
60
- M(e[i]) && (e[i] = {}), e = e[i];
60
+ E(e[s]) && (e[s] = {}), e = e[s];
61
61
  }
62
62
  }
63
63
  function W(e) {
64
64
  const r = e.split(/[.]|(?:\[(\d|\*)\])/).filter((t) => !!t);
65
- return r.some((t) => re.indexOf(t) !== -1) ? [] : r;
65
+ return r.some((t) => te.indexOf(t) !== -1) ? [] : r;
66
66
  }
67
67
  var l = /* @__PURE__ */ ((e) => (e.text = "text", e.number = "number", e.email = "email", e.password = "password", e.tel = "tel", e.url = "url", e.search = "search", e.date = "date", e.time = "time", e.datetimeLocal = "datetimeLocal", e.month = "month", e.week = "week", e.color = "color", e.select = "select", e.checkbox = "checkbox", e.radio = "radio", e.textarea = "textarea", e.radioGroup = "radioGroup", e.checkboxGroup = "checkboxGroup", e.combobox = "combobox", e.custom = "custom", e))(l || {});
68
- const te = (e, r, t, a = {}) => w({
68
+ const ne = (e, r, t, a = {}) => w({
69
69
  name: "FieldComponent",
70
70
  props: {
71
71
  type: {
@@ -96,8 +96,8 @@ const te = (e, r, t, a = {}) => w({
96
96
  },
97
97
  emits: ["invalid", "valid", "update:formData", "update:modelValue"],
98
98
  expose: ["invalid", "invalidLabel", "errors"],
99
- setup(n, { slots: o, emit: i }) {
100
- const s = h({
99
+ setup(n, { slots: o, emit: s }) {
100
+ const i = h({
101
101
  get() {
102
102
  if (u != null && u.modelValue)
103
103
  return _(
@@ -110,44 +110,44 @@ const te = (e, r, t, a = {}) => w({
110
110
  Object(u.modelValue.value),
111
111
  String(n.name),
112
112
  c
113
- ), i("update:modelValue", {
114
- newValue: s.value,
113
+ ), s("update:modelValue", {
114
+ newValue: i.value,
115
115
  formData: u == null ? void 0 : u.modelValue
116
116
  }));
117
117
  }
118
118
  });
119
- q(() => {
120
- s.value === void 0 && n.defaultValue !== void 0 && (s.value = n.defaultValue);
119
+ Z(() => {
120
+ i.value === void 0 && n.defaultValue !== void 0 && (i.value = n.defaultValue);
121
121
  });
122
122
  const f = S(r, void 0);
123
123
  f && f.fields.value.add(n.name);
124
- const u = S(e), { props: d, name: m } = G(n), v = h(() => {
124
+ const u = S(e), { props: v, name: m } = G(n), d = h(() => {
125
125
  if (u != null && u.errors.value)
126
126
  return _(u.errors.value, String(n.name));
127
127
  }), y = h(() => {
128
128
  var c;
129
- return (c = v.value) == null ? void 0 : c._errors;
130
- }), p = h(() => v.value !== void 0);
129
+ return (c = d.value) == null ? void 0 : c._errors;
130
+ }), p = h(() => d.value !== void 0);
131
131
  V(p, () => {
132
- p.value ? (i("invalid", y.value), f && f.errors.value.set(n.name, {
132
+ p.value ? (s("invalid", y.value), f && f.errors.value.set(n.name, {
133
133
  _errors: y.value
134
- })) : (i("valid", s.value), f && f.errors.value.delete(
134
+ })) : (s("valid", i.value), f && f.errors.value.delete(
135
135
  n.name
136
136
  ));
137
137
  }), V(
138
138
  () => u == null ? void 0 : u.modelValue,
139
139
  () => {
140
- i("update:formData", u == null ? void 0 : u.modelValue);
140
+ s("update:formData", u == null ? void 0 : u.modelValue);
141
141
  },
142
142
  { deep: !0 }
143
143
  );
144
- const k = (c) => {
145
- s.value = c;
146
- }, I = h(() => typeof d.value == "function" ? d.value(u == null ? void 0 : u.modelValue) : d.value), R = h(() => ({
144
+ const $ = (c) => {
145
+ i.value = c;
146
+ }, I = h(() => typeof v.value == "function" ? v.value(u == null ? void 0 : u.modelValue) : v.value), R = h(() => ({
147
147
  ...I.value,
148
148
  name: I.value.name ?? n.name,
149
149
  invalid: p.value,
150
- valid: n.showValid ? Boolean(!p.value && s.value) : void 0,
150
+ valid: n.showValid ? Boolean(!p.value && i.value) : void 0,
151
151
  type: ((c) => {
152
152
  if ([
153
153
  l.text,
@@ -167,26 +167,26 @@ const te = (e, r, t, a = {}) => w({
167
167
  return c;
168
168
  })(n.type),
169
169
  invalidLabel: y.value,
170
- modelValue: s.value,
171
- errors: n.is ? v.value : void 0,
172
- "onUpdate:modelValue": k
170
+ modelValue: i.value,
171
+ errors: n.is ? d.value : void 0,
172
+ "onUpdate:modelValue": $
173
173
  }));
174
- return $(t, {
175
- name: A(m),
176
- errors: A(v)
174
+ return k(t, {
175
+ name: M(m),
176
+ errors: M(d)
177
177
  }), { component: h(() => {
178
178
  if (n.type === l.custom)
179
179
  return {
180
180
  render() {
181
181
  var c;
182
182
  return ((c = o.default) == null ? void 0 : c.call(o, {
183
- modelValue: s.value,
184
- onUpdate: k,
183
+ modelValue: i.value,
184
+ onUpdate: $,
185
185
  invalid: p.value,
186
186
  invalidLabel: y.value,
187
187
  formData: u == null ? void 0 : u.modelValue.value,
188
188
  formErrors: u == null ? void 0 : u.errors.value,
189
- errors: v.value
189
+ errors: d.value
190
190
  })) ?? o.defalut;
191
191
  }
192
192
  };
@@ -223,7 +223,7 @@ const te = (e, r, t, a = {}) => w({
223
223
  `[form-vue warn]: ${c} not found, the component will be loaded asynchronously. To avoid this warning, please set "lazyLoad" option.`
224
224
  );
225
225
  }
226
- return Z(async () => {
226
+ return q(async () => {
227
227
  switch (a.sideEffects && await Promise.resolve(a.sideEffects(n.type)), n.type) {
228
228
  case l.textarea:
229
229
  return import("@volverjs/ui-vue/vv-textarea");
@@ -246,44 +246,44 @@ const te = (e, r, t, a = {}) => w({
246
246
  return this.is ? O(this.is, this.hasProps, this.$slots) : this.type === l.custom ? O(this.component, null, this.$slots) : O(this.component, this.hasProps, this.$slots);
247
247
  }
248
248
  });
249
- var ne = function(r) {
250
- return ae(r) && !oe(r);
249
+ var ae = function(r) {
250
+ return oe(r) && !ue(r);
251
251
  };
252
- function ae(e) {
252
+ function oe(e) {
253
253
  return !!e && typeof e == "object";
254
254
  }
255
- function oe(e) {
255
+ function ue(e) {
256
256
  var r = Object.prototype.toString.call(e);
257
- return r === "[object RegExp]" || r === "[object Date]" || ie(e);
258
- }
259
- var ue = typeof Symbol == "function" && Symbol.for, le = ue ? Symbol.for("react.element") : 60103;
260
- function ie(e) {
261
- return e.$$typeof === le;
257
+ return r === "[object RegExp]" || r === "[object Date]" || se(e);
262
258
  }
259
+ var le = typeof Symbol == "function" && Symbol.for, ie = le ? Symbol.for("react.element") : 60103;
263
260
  function se(e) {
261
+ return e.$$typeof === ie;
262
+ }
263
+ function ce(e) {
264
264
  return Array.isArray(e) ? [] : {};
265
265
  }
266
266
  function j(e, r) {
267
- return r.clone !== !1 && r.isMergeableObject(e) ? g(se(e), e, r) : e;
267
+ return r.clone !== !1 && r.isMergeableObject(e) ? g(ce(e), e, r) : e;
268
268
  }
269
- function ce(e, r, t) {
269
+ function fe(e, r, t) {
270
270
  return e.concat(r).map(function(a) {
271
271
  return j(a, t);
272
272
  });
273
273
  }
274
- function fe(e, r) {
274
+ function de(e, r) {
275
275
  if (!r.customMerge)
276
276
  return g;
277
277
  var t = r.customMerge(e);
278
278
  return typeof t == "function" ? t : g;
279
279
  }
280
- function de(e) {
280
+ function me(e) {
281
281
  return Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(e).filter(function(r) {
282
282
  return Object.propertyIsEnumerable.call(e, r);
283
283
  }) : [];
284
284
  }
285
285
  function C(e) {
286
- return Object.keys(e).concat(de(e));
286
+ return Object.keys(e).concat(me(e));
287
287
  }
288
288
  function B(e, r) {
289
289
  try {
@@ -292,21 +292,21 @@ function B(e, r) {
292
292
  return !1;
293
293
  }
294
294
  }
295
- function me(e, r) {
295
+ function ve(e, r) {
296
296
  return B(e, r) && !(Object.hasOwnProperty.call(e, r) && Object.propertyIsEnumerable.call(e, r));
297
297
  }
298
- function ve(e, r, t) {
298
+ function be(e, r, t) {
299
299
  var a = {};
300
300
  return t.isMergeableObject(e) && C(e).forEach(function(n) {
301
301
  a[n] = j(e[n], t);
302
302
  }), C(r).forEach(function(n) {
303
- me(e, n) || (B(e, n) && t.isMergeableObject(r[n]) ? a[n] = fe(n, t)(e[n], r[n], t) : a[n] = j(r[n], t));
303
+ ve(e, n) || (B(e, n) && t.isMergeableObject(r[n]) ? a[n] = de(n, t)(e[n], r[n], t) : a[n] = j(r[n], t));
304
304
  }), a;
305
305
  }
306
306
  function g(e, r, t) {
307
- t = t || {}, t.arrayMerge = t.arrayMerge || ce, t.isMergeableObject = t.isMergeableObject || ne, t.cloneUnlessOtherwiseSpecified = j;
307
+ t = t || {}, t.arrayMerge = t.arrayMerge || fe, t.isMergeableObject = t.isMergeableObject || ae, t.cloneUnlessOtherwiseSpecified = j;
308
308
  var a = Array.isArray(r), n = Array.isArray(e), o = a === n;
309
- return o ? a ? t.arrayMerge(e, r, t) : ve(e, r, t) : j(r, t);
309
+ return o ? a ? t.arrayMerge(e, r, t) : be(e, r, t) : j(r, t);
310
310
  }
311
311
  g.all = function(r, t) {
312
312
  if (!Array.isArray(r))
@@ -315,18 +315,25 @@ g.all = function(r, t) {
315
315
  return g(a, n, t);
316
316
  }, {});
317
317
  };
318
- var be = g, he = be;
319
- const J = (e, r = {}) => he(
320
- Object.fromEntries(
321
- Object.entries(e.shape).map(([t, a]) => a instanceof P ? [t, a._def.defaultValue()] : a instanceof T ? [t, J(a)] : [t, void 0])
322
- ),
323
- r
324
- ), ye = (e, r, t) => w({
318
+ var he = g, ye = he;
319
+ const J = (e, r = {}) => {
320
+ const t = e instanceof P ? e.innerType().shape : e.shape;
321
+ return ye(
322
+ Object.fromEntries(
323
+ Object.entries(t).map(([a, n]) => n instanceof T ? [a, n._def.defaultValue()] : n instanceof F ? [a, J(n)] : [a, void 0])
324
+ ),
325
+ r
326
+ );
327
+ }, pe = (e, r, t) => w({
325
328
  name: "FormComponent",
326
329
  props: {
327
330
  modelValue: {
328
331
  type: Object,
329
332
  default: () => ({})
333
+ },
334
+ continuosValidation: {
335
+ type: Boolean,
336
+ default: !1
330
337
  }
331
338
  },
332
339
  emits: ["invalid", "valid", "submit", "update:modelValue"],
@@ -334,32 +341,32 @@ const J = (e, r = {}) => he(
334
341
  setup(a, { emit: n }) {
335
342
  const o = x(
336
343
  J(e, a.modelValue)
337
- );
344
+ ), s = (t == null ? void 0 : t.continuosValidation) || a.continuosValidation;
338
345
  V(
339
346
  () => a.modelValue,
340
- (d) => {
341
- if (d) {
342
- const m = Y(d) ? H(d) : d;
343
- o.value = typeof (m == null ? void 0 : m.clone) == "function" ? m.clone() : JSON.parse(JSON.stringify(m));
347
+ (m) => {
348
+ if (m) {
349
+ const d = Y(m) ? H(m) : m;
350
+ o.value = typeof (d == null ? void 0 : d.clone) == "function" ? d.clone() : JSON.parse(JSON.stringify(d));
344
351
  }
345
352
  },
346
353
  { deep: !0 }
347
354
  ), X(
348
355
  o,
349
- (d) => {
350
- i.value && f(), (!d || !a.modelValue || JSON.stringify(d) !== JSON.stringify(a.modelValue)) && n("update:modelValue", d);
356
+ (m) => {
357
+ (i.value || s) && u(), (!m || !a.modelValue || JSON.stringify(m) !== JSON.stringify(a.modelValue)) && n("update:modelValue", m);
351
358
  },
352
359
  { deep: !0, throttle: (t == null ? void 0 : t.updateThrottle) ?? 500 }
353
360
  );
354
- const i = x(), s = x(), f = (d = o.value) => {
355
- const m = e.safeParse(d);
356
- return m.success ? (i.value = void 0, s.value = "valid", o.value = m.data, n("valid", m.data), !0) : (i.value = m.error.format(), s.value = "invalid", n("invalid", i.value), !1);
357
- }, u = () => f() ? (n("submit", o.value), !0) : !1;
358
- return $(r, {
361
+ const i = x(), f = x(), u = (m = o.value) => {
362
+ const d = e.safeParse(m);
363
+ return d.success ? (i.value = void 0, f.value = "valid", o.value = d.data, n("valid", d.data), !0) : (i.value = d.error.format(), f.value = "invalid", n("invalid", i.value), !1);
364
+ }, v = () => u() ? (n("submit", o.value), !0) : !1;
365
+ return k(r, {
359
366
  modelValue: o,
360
- submit: u,
361
- errors: A(i)
362
- }), { submit: u };
367
+ submit: v,
368
+ errors: M(i)
369
+ }), { submit: v };
363
370
  },
364
371
  render() {
365
372
  return O(
@@ -370,7 +377,7 @@ const J = (e, r = {}) => he(
370
377
  this.$slots
371
378
  );
372
379
  }
373
- }), pe = (e, r) => w({
380
+ }), Ve = (e, r) => w({
374
381
  name: "WrapperComponent",
375
382
  props: {
376
383
  name: {
@@ -385,38 +392,38 @@ const J = (e, r = {}) => he(
385
392
  emits: ["invalid", "valid"],
386
393
  expose: ["fields", "invalid"],
387
394
  setup(t, { emit: a }) {
388
- const n = S(e), o = S(r, void 0), i = x(/* @__PURE__ */ new Set()), s = x(/* @__PURE__ */ new Map()), { name: f } = G(t);
389
- $(r, {
390
- name: A(f),
391
- errors: s,
392
- fields: i
395
+ const n = S(e), o = S(r, void 0), s = x(/* @__PURE__ */ new Set()), i = x(/* @__PURE__ */ new Map()), { name: f } = G(t);
396
+ k(r, {
397
+ name: M(f),
398
+ errors: i,
399
+ fields: s
393
400
  }), V(
394
- i,
395
- (d) => {
396
- o != null && o.fields && d.forEach((m) => {
401
+ s,
402
+ (v) => {
403
+ o != null && o.fields && v.forEach((m) => {
397
404
  o == null || o.fields.value.add(m);
398
405
  });
399
406
  },
400
407
  { deep: !0 }
401
408
  ), V(
402
- () => new Map(s.value),
403
- (d, m) => {
404
- o != null && o.errors && (Array.from(m.keys()).forEach((v) => {
405
- o.errors.value.delete(v);
406
- }), Array.from(d.keys()).forEach((v) => {
407
- const y = d.get(v);
408
- y && o.errors.value.set(v, y);
409
+ () => new Map(i.value),
410
+ (v, m) => {
411
+ o != null && o.errors && (Array.from(m.keys()).forEach((d) => {
412
+ o.errors.value.delete(d);
413
+ }), Array.from(v.keys()).forEach((d) => {
414
+ const y = v.get(d);
415
+ y && o.errors.value.set(d, y);
409
416
  }));
410
417
  },
411
418
  { deep: !0 }
412
419
  );
413
- const u = h(() => n != null && n.errors.value ? s.value.size > 0 : !1);
420
+ const u = h(() => n != null && n.errors.value ? i.value.size > 0 : !1);
414
421
  return V(u, () => {
415
422
  u.value ? a("invalid") : a("valid");
416
- }), { formProvided: n, invalid: u, fields: i, errors: s };
423
+ }), { formProvided: n, invalid: u, fields: s, errors: i };
417
424
  },
418
425
  render() {
419
- var t, a, n, o, i, s, f, u;
426
+ var t, a, n, o, s, i, f, u;
420
427
  return this.tag ? O(
421
428
  this.tag,
422
429
  null,
@@ -428,16 +435,16 @@ const J = (e, r = {}) => he(
428
435
  })) ?? this.$slots.defalut
429
436
  ) : ((u = (f = this.$slots).default) == null ? void 0 : u.call(f, {
430
437
  invalid: this.invalid,
431
- formData: (i = this.formProvided) == null ? void 0 : i.modelValue,
432
- errors: (s = this.formProvided) == null ? void 0 : s.errors,
438
+ formData: (s = this.formProvided) == null ? void 0 : s.modelValue,
439
+ errors: (i = this.formProvided) == null ? void 0 : i.errors,
433
440
  fieldsErrors: this.errors
434
441
  })) ?? this.$slots.defalut;
435
442
  }
436
443
  }), K = (e, r = {}) => {
437
- const t = Symbol(), a = Symbol(), n = Symbol(), o = ye(e, t, r), i = pe(
444
+ const t = Symbol(), a = Symbol(), n = Symbol(), o = pe(e, t, r), s = Ve(
438
445
  t,
439
446
  a
440
- ), s = te(
447
+ ), i = ne(
441
448
  t,
442
449
  a,
443
450
  n,
@@ -445,13 +452,13 @@ const J = (e, r = {}) => he(
445
452
  );
446
453
  return {
447
454
  VvForm: o,
448
- VvFormWrapper: i,
449
- VvFormField: s,
455
+ VvFormWrapper: s,
456
+ VvFormField: i,
450
457
  formInjectionKey: t,
451
458
  formWrapperInjectionKey: a,
452
459
  formFieldInjectionKey: n
453
460
  };
454
- }, z = Symbol(), Se = (e) => {
461
+ }, z = Symbol(), je = (e) => {
455
462
  let r = {};
456
463
  return e.schema && (r = K(e.schema, e)), {
457
464
  ...r,
@@ -459,15 +466,15 @@ const J = (e, r = {}) => he(
459
466
  t.provide(z, e), a && (t.config.globalProperties.$vvForm = e, r != null && r.VvForm && t.component("VvForm", r.VvForm), r != null && r.VvFormWrapper && t.component("VvFormWrapper", r.VvFormWrapper), r != null && r.VvFormField && t.component("VvFormField", r.VvFormField));
460
467
  }
461
468
  };
462
- }, je = (e, r = {}) => {
469
+ }, Ee = (e, r = {}) => {
463
470
  const t = { ...S(z, {}), ...r };
464
471
  return K(e, t);
465
472
  };
466
473
  export {
467
474
  l as FormFieldType,
468
- Se as createForm,
475
+ je as createForm,
469
476
  J as defaultObjectBySchema,
470
477
  K as formFactory,
471
478
  z as pluginInjectionKey,
472
- je as useForm
479
+ Ee as useForm
473
480
  };
package/dist/index.umd.js CHANGED
@@ -1 +1 @@
1
- (function(b,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("vue"),require("@vueuse/core"),require("zod")):typeof define=="function"&&define.amd?define(["exports","vue","@vueuse/core","zod"],n):(b=typeof globalThis<"u"?globalThis:b||self,n(b["@volverjs/form-vue"]={},b.Vue,b.VueUseCore,b.zod))})(this,function(b,n,D,M){"use strict";function S(e){return Array.isArray(e)}function U(e){return typeof e<"u"}function A(e){return e===null}function E(e){return typeof e=="object"}function C(e){return typeof e=="string"}function O(e){return typeof e>"u"}const W=/^[0-9]+$/,B=["__proto__","prototype","constructor"];function $(e,r,t){const o=U(t)?t:void 0;if(!E(e)||!C(r))return o;const a=I(r);if(a.length!==0){for(const l of a){if(l==="*")continue;const c=function(u){return u.map(d=>O(d)||A(d)?d:S(d)?c(d):d[l])};if(S(e)&&!W.test(l)?e=c(e):e=e[l],O(e)||A(e))break}return O(e)?o:e}}function k(e,r,t){if(!E(e)||!C(r))return;const o=I(r);if(o.length===0)return;const a=o.length;for(let l=0;l<a;l++){const c=o[l];if(l===a-1){e[c]=t;return}if(c==="*"&&S(e)){const u=o.slice(l+1).join(".");for(const d of e)k(d,u,t);return}O(e[c])&&(e[c]={}),e=e[c]}}function I(e){const r=e.split(/[.]|(?:\[(\d|\*)\])/).filter(t=>!!t);return r.some(t=>B.indexOf(t)!==-1)?[]:r}var s=(e=>(e.text="text",e.number="number",e.email="email",e.password="password",e.tel="tel",e.url="url",e.search="search",e.date="date",e.time="time",e.datetimeLocal="datetimeLocal",e.month="month",e.week="week",e.color="color",e.select="select",e.checkbox="checkbox",e.radio="radio",e.textarea="textarea",e.radioGroup="radioGroup",e.checkboxGroup="checkboxGroup",e.combobox="combobox",e.custom="custom",e))(s||{});const q=(e,r,t,o={})=>n.defineComponent({name:"FieldComponent",props:{type:{type:String,validator:a=>Object.values(s).includes(a),default:s.custom},is:{type:[Object,String],default:void 0},name:{type:[String,Number,Boolean,Symbol],required:!0},props:{type:[Object,Function],default:()=>({})},showValid:{type:Boolean,default:!1},defaultValue:{type:[String,Number,Boolean,Array,Object],default:void 0}},emits:["invalid","valid","update:formData","update:modelValue"],expose:["invalid","invalidLabel","errors"],setup(a,{slots:l,emit:c}){const u=n.computed({get(){if(i!=null&&i.modelValue)return $(Object(i.modelValue.value),String(a.name))},set(f){i!=null&&i.modelValue&&(k(Object(i.modelValue.value),String(a.name),f),c("update:modelValue",{newValue:u.value,formData:i==null?void 0:i.modelValue}))}});n.onMounted(()=>{u.value===void 0&&a.defaultValue!==void 0&&(u.value=a.defaultValue)});const d=n.inject(r,void 0);d&&d.fields.value.add(a.name);const i=n.inject(e),{props:m,name:h}=n.toRefs(a),p=n.computed(()=>{if(i!=null&&i.errors.value)return $(i.errors.value,String(a.name))}),v=n.computed(()=>{var f;return(f=p.value)==null?void 0:f._errors}),V=n.computed(()=>p.value!==void 0);n.watch(V,()=>{V.value?(c("invalid",v.value),d&&d.errors.value.set(a.name,{_errors:v.value})):(c("valid",u.value),d&&d.errors.value.delete(a.name))}),n.watch(()=>i==null?void 0:i.modelValue,()=>{c("update:formData",i==null?void 0:i.modelValue)},{deep:!0});const G=f=>{u.value=f},L=n.computed(()=>typeof m.value=="function"?m.value(i==null?void 0:i.modelValue):m.value),le=n.computed(()=>({...L.value,name:L.value.name??a.name,invalid:V.value,valid:a.showValid?Boolean(!V.value&&u.value):void 0,type:(f=>{if([s.text,s.number,s.email,s.password,s.tel,s.url,s.search,s.date,s.time,s.datetimeLocal,s.month,s.week,s.color].includes(f))return f})(a.type),invalidLabel:v.value,modelValue:u.value,errors:a.is?p.value:void 0,"onUpdate:modelValue":G}));return n.provide(t,{name:n.readonly(h),errors:n.readonly(p)}),{component:n.computed(()=>{if(a.type===s.custom)return{render(){var f;return((f=l.default)==null?void 0:f.call(l,{modelValue:u.value,onUpdate:G,invalid:V.value,invalidLabel:v.value,formData:i==null?void 0:i.modelValue.value,formErrors:i==null?void 0:i.errors.value,errors:p.value}))??l.defalut}};if(!o.lazyLoad){let f;switch(a.type){case s.select:f=n.resolveComponent("VvSelect");break;case s.checkbox:f=n.resolveComponent("VvCheckbox");break;case s.radio:f=n.resolveComponent("VvRadio");break;case s.textarea:f=n.resolveComponent("VvTextarea");break;case s.radioGroup:f=n.resolveComponent("VvRadioGroup");break;case s.checkboxGroup:f=n.resolveComponent("VvCheckboxGroup");break;case s.combobox:f=n.resolveComponent("VvCombobox");break;default:f=n.resolveComponent("VvInputText")}if(typeof f!="string")return f;console.warn(`[form-vue warn]: ${f} not found, the component will be loaded asynchronously. To avoid this warning, please set "lazyLoad" option.`)}return n.defineAsyncComponent(async()=>{switch(o.sideEffects&&await Promise.resolve(o.sideEffects(a.type)),a.type){case s.textarea:return import("@volverjs/ui-vue/vv-textarea");case s.radio:return import("@volverjs/ui-vue/vv-radio");case s.radioGroup:return import("@volverjs/ui-vue/vv-radio-group");case s.checkbox:return import("@volverjs/ui-vue/vv-checkbox");case s.checkboxGroup:return import("@volverjs/ui-vue/vv-checkbox-group");case s.combobox:return import("@volverjs/ui-vue/vv-combobox")}return import("@volverjs/ui-vue/vv-input-text")})}),hasProps:le,invalid:V}},render(){return this.is?n.h(this.is,this.hasProps,this.$slots):this.type===s.custom?n.h(this.component,null,this.$slots):n.h(this.component,this.hasProps,this.$slots)}});var z=function(r){return K(r)&&!J(r)};function K(e){return!!e&&typeof e=="object"}function J(e){var r=Object.prototype.toString.call(e);return r==="[object RegExp]"||r==="[object Date]"||Y(e)}var R=typeof Symbol=="function"&&Symbol.for,Z=R?Symbol.for("react.element"):60103;function Y(e){return e.$$typeof===Z}function H(e){return Array.isArray(e)?[]:{}}function g(e,r){return r.clone!==!1&&r.isMergeableObject(e)?y(H(e),e,r):e}function Q(e,r,t){return e.concat(r).map(function(o){return g(o,t)})}function X(e,r){if(!r.customMerge)return y;var t=r.customMerge(e);return typeof t=="function"?t:y}function P(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(r){return Object.propertyIsEnumerable.call(e,r)}):[]}function N(e){return Object.keys(e).concat(P(e))}function _(e,r){try{return r in e}catch{return!1}}function F(e,r){return _(e,r)&&!(Object.hasOwnProperty.call(e,r)&&Object.propertyIsEnumerable.call(e,r))}function T(e,r,t){var o={};return t.isMergeableObject(e)&&N(e).forEach(function(a){o[a]=g(e[a],t)}),N(r).forEach(function(a){F(e,a)||(_(e,a)&&t.isMergeableObject(r[a])?o[a]=X(a,t)(e[a],r[a],t):o[a]=g(r[a],t))}),o}function y(e,r,t){t=t||{},t.arrayMerge=t.arrayMerge||Q,t.isMergeableObject=t.isMergeableObject||z,t.cloneUnlessOtherwiseSpecified=g;var o=Array.isArray(r),a=Array.isArray(e),l=o===a;return l?o?t.arrayMerge(e,r,t):T(e,r,t):g(r,t)}y.all=function(r,t){if(!Array.isArray(r))throw new Error("first argument should be an array");return r.reduce(function(o,a){return y(o,a,t)},{})};var ee=y,re=ee;const j=(e,r={})=>re(Object.fromEntries(Object.entries(e.shape).map(([t,o])=>o instanceof M.ZodDefault?[t,o._def.defaultValue()]:o instanceof M.ZodObject?[t,j(o)]:[t,void 0])),r),te=(e,r,t)=>n.defineComponent({name:"FormComponent",props:{modelValue:{type:Object,default:()=>({})}},emits:["invalid","valid","submit","update:modelValue"],expose:["submit","errors","status"],setup(o,{emit:a}){const l=n.ref(j(e,o.modelValue));n.watch(()=>o.modelValue,m=>{if(m){const h=n.isProxy(m)?n.toRaw(m):m;l.value=typeof(h==null?void 0:h.clone)=="function"?h.clone():JSON.parse(JSON.stringify(h))}},{deep:!0}),D.watchThrottled(l,m=>{c.value&&d(),(!m||!o.modelValue||JSON.stringify(m)!==JSON.stringify(o.modelValue))&&a("update:modelValue",m)},{deep:!0,throttle:(t==null?void 0:t.updateThrottle)??500});const c=n.ref(),u=n.ref(),d=(m=l.value)=>{const h=e.safeParse(m);return h.success?(c.value=void 0,u.value="valid",l.value=h.data,a("valid",h.data),!0):(c.value=h.error.format(),u.value="invalid",a("invalid",c.value),!1)},i=()=>d()?(a("submit",l.value),!0):!1;return n.provide(r,{modelValue:l,submit:i,errors:n.readonly(c)}),{submit:i}},render(){return n.h("form",{onSubmit:n.withModifiers(this.submit,["prevent"])},this.$slots)}}),ne=(e,r)=>n.defineComponent({name:"WrapperComponent",props:{name:{type:String,required:!0},tag:{type:String,default:void 0}},emits:["invalid","valid"],expose:["fields","invalid"],setup(t,{emit:o}){const a=n.inject(e),l=n.inject(r,void 0),c=n.ref(new Set),u=n.ref(new Map),{name:d}=n.toRefs(t);n.provide(r,{name:n.readonly(d),errors:u,fields:c}),n.watch(c,m=>{l!=null&&l.fields&&m.forEach(h=>{l==null||l.fields.value.add(h)})},{deep:!0}),n.watch(()=>new Map(u.value),(m,h)=>{l!=null&&l.errors&&(Array.from(h.keys()).forEach(p=>{l.errors.value.delete(p)}),Array.from(m.keys()).forEach(p=>{const v=m.get(p);v&&l.errors.value.set(p,v)}))},{deep:!0});const i=n.computed(()=>a!=null&&a.errors.value?u.value.size>0:!1);return n.watch(i,()=>{i.value?o("invalid"):o("valid")}),{formProvided:a,invalid:i,fields:c,errors:u}},render(){var t,o,a,l,c,u,d,i;return this.tag?n.h(this.tag,null,((l=(a=this.$slots).default)==null?void 0:l.call(a,{invalid:this.invalid,formData:(t=this.formProvided)==null?void 0:t.modelValue,errors:(o=this.formProvided)==null?void 0:o.errors,fieldsErrors:this.errors}))??this.$slots.defalut):((i=(d=this.$slots).default)==null?void 0:i.call(d,{invalid:this.invalid,formData:(c=this.formProvided)==null?void 0:c.modelValue,errors:(u=this.formProvided)==null?void 0:u.errors,fieldsErrors:this.errors}))??this.$slots.defalut}}),x=(e,r={})=>{const t=Symbol(),o=Symbol(),a=Symbol(),l=te(e,t,r),c=ne(t,o),u=q(t,o,a,r);return{VvForm:l,VvFormWrapper:c,VvFormField:u,formInjectionKey:t,formWrapperInjectionKey:o,formFieldInjectionKey:a}},w=Symbol(),ae=e=>{let r={};return e.schema&&(r=x(e.schema,e)),{...r,install(t,{global:o=!1}={}){t.provide(w,e),o&&(t.config.globalProperties.$vvForm=e,r!=null&&r.VvForm&&t.component("VvForm",r.VvForm),r!=null&&r.VvFormWrapper&&t.component("VvFormWrapper",r.VvFormWrapper),r!=null&&r.VvFormField&&t.component("VvFormField",r.VvFormField))}}},oe=(e,r={})=>{const t={...n.inject(w,{}),...r};return x(e,t)};b.FormFieldType=s,b.createForm=ae,b.defaultObjectBySchema=j,b.formFactory=x,b.pluginInjectionKey=w,b.useForm=oe,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})});
1
+ (function(b,a){typeof exports=="object"&&typeof module<"u"?a(exports,require("vue"),require("@vueuse/core"),require("zod")):typeof define=="function"&&define.amd?define(["exports","vue","@vueuse/core","zod"],a):(b=typeof globalThis<"u"?globalThis:b||self,a(b["@volverjs/form-vue"]={},b.Vue,b.VueUseCore,b.zod))})(this,function(b,a,D,S){"use strict";function j(e){return Array.isArray(e)}function U(e){return typeof e<"u"}function E(e){return e===null}function A(e){return typeof e=="object"}function C(e){return typeof e=="string"}function O(e){return typeof e>"u"}const B=/^[0-9]+$/,W=["__proto__","prototype","constructor"];function k(e,r,t){const o=U(t)?t:void 0;if(!A(e)||!C(r))return o;const n=I(r);if(n.length!==0){for(const l of n){if(l==="*")continue;const u=function(c){return c.map(d=>O(d)||E(d)?d:j(d)?u(d):d[l])};if(j(e)&&!B.test(l)?e=u(e):e=e[l],O(e)||E(e))break}return O(e)?o:e}}function $(e,r,t){if(!A(e)||!C(r))return;const o=I(r);if(o.length===0)return;const n=o.length;for(let l=0;l<n;l++){const u=o[l];if(l===n-1){e[u]=t;return}if(u==="*"&&j(e)){const c=o.slice(l+1).join(".");for(const d of e)$(d,c,t);return}O(e[u])&&(e[u]={}),e=e[u]}}function I(e){const r=e.split(/[.]|(?:\[(\d|\*)\])/).filter(t=>!!t);return r.some(t=>W.indexOf(t)!==-1)?[]:r}var s=(e=>(e.text="text",e.number="number",e.email="email",e.password="password",e.tel="tel",e.url="url",e.search="search",e.date="date",e.time="time",e.datetimeLocal="datetimeLocal",e.month="month",e.week="week",e.color="color",e.select="select",e.checkbox="checkbox",e.radio="radio",e.textarea="textarea",e.radioGroup="radioGroup",e.checkboxGroup="checkboxGroup",e.combobox="combobox",e.custom="custom",e))(s||{});const q=(e,r,t,o={})=>a.defineComponent({name:"FieldComponent",props:{type:{type:String,validator:n=>Object.values(s).includes(n),default:s.custom},is:{type:[Object,String],default:void 0},name:{type:[String,Number,Boolean,Symbol],required:!0},props:{type:[Object,Function],default:()=>({})},showValid:{type:Boolean,default:!1},defaultValue:{type:[String,Number,Boolean,Array,Object],default:void 0}},emits:["invalid","valid","update:formData","update:modelValue"],expose:["invalid","invalidLabel","errors"],setup(n,{slots:l,emit:u}){const c=a.computed({get(){if(i!=null&&i.modelValue)return k(Object(i.modelValue.value),String(n.name))},set(f){i!=null&&i.modelValue&&($(Object(i.modelValue.value),String(n.name),f),u("update:modelValue",{newValue:c.value,formData:i==null?void 0:i.modelValue}))}});a.onMounted(()=>{c.value===void 0&&n.defaultValue!==void 0&&(c.value=n.defaultValue)});const d=a.inject(r,void 0);d&&d.fields.value.add(n.name);const i=a.inject(e),{props:y,name:h}=a.toRefs(n),m=a.computed(()=>{if(i!=null&&i.errors.value)return k(i.errors.value,String(n.name))}),p=a.computed(()=>{var f;return(f=m.value)==null?void 0:f._errors}),V=a.computed(()=>m.value!==void 0);a.watch(V,()=>{V.value?(u("invalid",p.value),d&&d.errors.value.set(n.name,{_errors:p.value})):(u("valid",c.value),d&&d.errors.value.delete(n.name))}),a.watch(()=>i==null?void 0:i.modelValue,()=>{u("update:formData",i==null?void 0:i.modelValue)},{deep:!0});const G=f=>{c.value=f},L=a.computed(()=>typeof y.value=="function"?y.value(i==null?void 0:i.modelValue):y.value),le=a.computed(()=>({...L.value,name:L.value.name??n.name,invalid:V.value,valid:n.showValid?Boolean(!V.value&&c.value):void 0,type:(f=>{if([s.text,s.number,s.email,s.password,s.tel,s.url,s.search,s.date,s.time,s.datetimeLocal,s.month,s.week,s.color].includes(f))return f})(n.type),invalidLabel:p.value,modelValue:c.value,errors:n.is?m.value:void 0,"onUpdate:modelValue":G}));return a.provide(t,{name:a.readonly(h),errors:a.readonly(m)}),{component:a.computed(()=>{if(n.type===s.custom)return{render(){var f;return((f=l.default)==null?void 0:f.call(l,{modelValue:c.value,onUpdate:G,invalid:V.value,invalidLabel:p.value,formData:i==null?void 0:i.modelValue.value,formErrors:i==null?void 0:i.errors.value,errors:m.value}))??l.defalut}};if(!o.lazyLoad){let f;switch(n.type){case s.select:f=a.resolveComponent("VvSelect");break;case s.checkbox:f=a.resolveComponent("VvCheckbox");break;case s.radio:f=a.resolveComponent("VvRadio");break;case s.textarea:f=a.resolveComponent("VvTextarea");break;case s.radioGroup:f=a.resolveComponent("VvRadioGroup");break;case s.checkboxGroup:f=a.resolveComponent("VvCheckboxGroup");break;case s.combobox:f=a.resolveComponent("VvCombobox");break;default:f=a.resolveComponent("VvInputText")}if(typeof f!="string")return f;console.warn(`[form-vue warn]: ${f} not found, the component will be loaded asynchronously. To avoid this warning, please set "lazyLoad" option.`)}return a.defineAsyncComponent(async()=>{switch(o.sideEffects&&await Promise.resolve(o.sideEffects(n.type)),n.type){case s.textarea:return import("@volverjs/ui-vue/vv-textarea");case s.radio:return import("@volverjs/ui-vue/vv-radio");case s.radioGroup:return import("@volverjs/ui-vue/vv-radio-group");case s.checkbox:return import("@volverjs/ui-vue/vv-checkbox");case s.checkboxGroup:return import("@volverjs/ui-vue/vv-checkbox-group");case s.combobox:return import("@volverjs/ui-vue/vv-combobox")}return import("@volverjs/ui-vue/vv-input-text")})}),hasProps:le,invalid:V}},render(){return this.is?a.h(this.is,this.hasProps,this.$slots):this.type===s.custom?a.h(this.component,null,this.$slots):a.h(this.component,this.hasProps,this.$slots)}});var K=function(r){return z(r)&&!J(r)};function z(e){return!!e&&typeof e=="object"}function J(e){var r=Object.prototype.toString.call(e);return r==="[object RegExp]"||r==="[object Date]"||Y(e)}var R=typeof Symbol=="function"&&Symbol.for,Z=R?Symbol.for("react.element"):60103;function Y(e){return e.$$typeof===Z}function H(e){return Array.isArray(e)?[]:{}}function g(e,r){return r.clone!==!1&&r.isMergeableObject(e)?v(H(e),e,r):e}function Q(e,r,t){return e.concat(r).map(function(o){return g(o,t)})}function X(e,r){if(!r.customMerge)return v;var t=r.customMerge(e);return typeof t=="function"?t:v}function P(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(r){return Object.propertyIsEnumerable.call(e,r)}):[]}function N(e){return Object.keys(e).concat(P(e))}function _(e,r){try{return r in e}catch{return!1}}function T(e,r){return _(e,r)&&!(Object.hasOwnProperty.call(e,r)&&Object.propertyIsEnumerable.call(e,r))}function F(e,r,t){var o={};return t.isMergeableObject(e)&&N(e).forEach(function(n){o[n]=g(e[n],t)}),N(r).forEach(function(n){T(e,n)||(_(e,n)&&t.isMergeableObject(r[n])?o[n]=X(n,t)(e[n],r[n],t):o[n]=g(r[n],t))}),o}function v(e,r,t){t=t||{},t.arrayMerge=t.arrayMerge||Q,t.isMergeableObject=t.isMergeableObject||K,t.cloneUnlessOtherwiseSpecified=g;var o=Array.isArray(r),n=Array.isArray(e),l=o===n;return l?o?t.arrayMerge(e,r,t):F(e,r,t):g(r,t)}v.all=function(r,t){if(!Array.isArray(r))throw new Error("first argument should be an array");return r.reduce(function(o,n){return v(o,n,t)},{})};var ee=v,re=ee;const x=(e,r={})=>{const t=e instanceof S.ZodEffects?e.innerType().shape:e.shape;return re(Object.fromEntries(Object.entries(t).map(([o,n])=>n instanceof S.ZodDefault?[o,n._def.defaultValue()]:n instanceof S.ZodObject?[o,x(n)]:[o,void 0])),r)},te=(e,r,t)=>a.defineComponent({name:"FormComponent",props:{modelValue:{type:Object,default:()=>({})},continuosValidation:{type:Boolean,default:!1}},emits:["invalid","valid","submit","update:modelValue"],expose:["submit","errors","status"],setup(o,{emit:n}){const l=a.ref(x(e,o.modelValue)),u=(t==null?void 0:t.continuosValidation)||o.continuosValidation;a.watch(()=>o.modelValue,h=>{if(h){const m=a.isProxy(h)?a.toRaw(h):h;l.value=typeof(m==null?void 0:m.clone)=="function"?m.clone():JSON.parse(JSON.stringify(m))}},{deep:!0}),D.watchThrottled(l,h=>{(c.value||u)&&i(),(!h||!o.modelValue||JSON.stringify(h)!==JSON.stringify(o.modelValue))&&n("update:modelValue",h)},{deep:!0,throttle:(t==null?void 0:t.updateThrottle)??500});const c=a.ref(),d=a.ref(),i=(h=l.value)=>{const m=e.safeParse(h);return m.success?(c.value=void 0,d.value="valid",l.value=m.data,n("valid",m.data),!0):(c.value=m.error.format(),d.value="invalid",n("invalid",c.value),!1)},y=()=>i()?(n("submit",l.value),!0):!1;return a.provide(r,{modelValue:l,submit:y,errors:a.readonly(c)}),{submit:y}},render(){return a.h("form",{onSubmit:a.withModifiers(this.submit,["prevent"])},this.$slots)}}),ne=(e,r)=>a.defineComponent({name:"WrapperComponent",props:{name:{type:String,required:!0},tag:{type:String,default:void 0}},emits:["invalid","valid"],expose:["fields","invalid"],setup(t,{emit:o}){const n=a.inject(e),l=a.inject(r,void 0),u=a.ref(new Set),c=a.ref(new Map),{name:d}=a.toRefs(t);a.provide(r,{name:a.readonly(d),errors:c,fields:u}),a.watch(u,y=>{l!=null&&l.fields&&y.forEach(h=>{l==null||l.fields.value.add(h)})},{deep:!0}),a.watch(()=>new Map(c.value),(y,h)=>{l!=null&&l.errors&&(Array.from(h.keys()).forEach(m=>{l.errors.value.delete(m)}),Array.from(y.keys()).forEach(m=>{const p=y.get(m);p&&l.errors.value.set(m,p)}))},{deep:!0});const i=a.computed(()=>n!=null&&n.errors.value?c.value.size>0:!1);return a.watch(i,()=>{i.value?o("invalid"):o("valid")}),{formProvided:n,invalid:i,fields:u,errors:c}},render(){var t,o,n,l,u,c,d,i;return this.tag?a.h(this.tag,null,((l=(n=this.$slots).default)==null?void 0:l.call(n,{invalid:this.invalid,formData:(t=this.formProvided)==null?void 0:t.modelValue,errors:(o=this.formProvided)==null?void 0:o.errors,fieldsErrors:this.errors}))??this.$slots.defalut):((i=(d=this.$slots).default)==null?void 0:i.call(d,{invalid:this.invalid,formData:(u=this.formProvided)==null?void 0:u.modelValue,errors:(c=this.formProvided)==null?void 0:c.errors,fieldsErrors:this.errors}))??this.$slots.defalut}}),w=(e,r={})=>{const t=Symbol(),o=Symbol(),n=Symbol(),l=te(e,t,r),u=ne(t,o),c=q(t,o,n,r);return{VvForm:l,VvFormWrapper:u,VvFormField:c,formInjectionKey:t,formWrapperInjectionKey:o,formFieldInjectionKey:n}},M=Symbol(),ae=e=>{let r={};return e.schema&&(r=w(e.schema,e)),{...r,install(t,{global:o=!1}={}){t.provide(M,e),o&&(t.config.globalProperties.$vvForm=e,r!=null&&r.VvForm&&t.component("VvForm",r.VvForm),r!=null&&r.VvFormWrapper&&t.component("VvFormWrapper",r.VvFormWrapper),r!=null&&r.VvFormField&&t.component("VvFormField",r.VvFormField))}}},oe=(e,r={})=>{const t={...a.inject(M,{}),...r};return w(e,t)};b.FormFieldType=s,b.createForm=ae,b.defaultObjectBySchema=x,b.formFactory=w,b.pluginInjectionKey=M,b.useForm=oe,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})});
package/dist/types.d.ts CHANGED
@@ -5,6 +5,7 @@ import type { FormFieldType } from './enums'
5
5
  export type FormComposableOptions = {
6
6
  lazyLoad?: boolean
7
7
  updateThrottle?: number
8
+ continuosValidation?: boolean
8
9
  sideEffects?: (type: `${FormFieldType}`) => Promise | void
9
10
  }
10
11
 
package/dist/utils.d.ts CHANGED
@@ -1,2 +1,6 @@
1
1
  import { type z } from 'zod';
2
- export declare const defaultObjectBySchema: <Schema extends z.AnyZodObject>(schema: Schema, original?: Partial<z.TypeOf<Schema>>) => Partial<z.TypeOf<Schema>>;
2
+ export declare const defaultObjectBySchema: <Schema extends z.AnyZodObject | z.ZodEffects<z.AnyZodObject, {
3
+ [x: string]: any;
4
+ }, {
5
+ [x: string]: any;
6
+ }>>(schema: Schema, original?: Partial<z.TypeOf<Schema>>) => Partial<z.TypeOf<Schema>>;
package/package.json CHANGED
@@ -19,7 +19,7 @@
19
19
  "bugs": {
20
20
  "url": "https://github.com/volverjs/form-vue/issues"
21
21
  },
22
- "version": "0.0.2",
22
+ "version": "0.0.4",
23
23
  "engines": {
24
24
  "node": ">= 16.x"
25
25
  },
package/src/VvForm.ts CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  } from 'vue'
13
13
  import { watchThrottled } from '@vueuse/core'
14
14
 
15
- import type { AnyZodObject } from 'zod'
15
+ import type { AnyZodObject, ZodEffects } from 'zod'
16
16
  import type { InjectedFormData } from './types'
17
17
  import { defaultObjectBySchema } from './utils'
18
18
 
@@ -22,10 +22,11 @@ export enum FormStatus {
22
22
  }
23
23
 
24
24
  export const defineForm = (
25
- schema: AnyZodObject,
25
+ schema: AnyZodObject | ZodEffects<AnyZodObject>,
26
26
  provideKey: InjectionKey<InjectedFormData>,
27
27
  options?: {
28
28
  updateThrottle?: number
29
+ continuosValidation?: boolean
29
30
  },
30
31
  ) => {
31
32
  return defineComponent({
@@ -35,6 +36,10 @@ export const defineForm = (
35
36
  type: Object,
36
37
  default: () => ({}),
37
38
  },
39
+ continuosValidation: {
40
+ type: Boolean,
41
+ default: false,
42
+ },
38
43
  },
39
44
  emits: ['invalid', 'valid', 'submit', 'update:modelValue'],
40
45
  expose: ['submit', 'errors', 'status'],
@@ -42,6 +47,10 @@ export const defineForm = (
42
47
  const localModelValue = ref(
43
48
  defaultObjectBySchema(schema, props.modelValue),
44
49
  )
50
+
51
+ const keepValidation =
52
+ options?.continuosValidation || props.continuosValidation
53
+
45
54
  watch(
46
55
  () => props.modelValue,
47
56
  (newValue) => {
@@ -61,7 +70,7 @@ export const defineForm = (
61
70
  watchThrottled(
62
71
  localModelValue,
63
72
  (newValue) => {
64
- if (errors.value) {
73
+ if (errors.value || keepValidation) {
65
74
  parseModelValue()
66
75
  }
67
76
  if (
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type App, inject, type InjectionKey, type Plugin } from 'vue'
2
- import type { AnyZodObject } from 'zod'
2
+ import type { AnyZodObject, ZodEffects } from 'zod'
3
3
  import { defineFormField } from './VvFormField'
4
4
  import { defineForm } from './VvForm'
5
5
  import { defineFormWrapper } from './VvFormWrapper'
@@ -12,7 +12,7 @@ import type {
12
12
  } from './types'
13
13
 
14
14
  export const formFactory = (
15
- schema: AnyZodObject,
15
+ schema: AnyZodObject | ZodEffects<AnyZodObject>,
16
16
  options: FormComposableOptions = {},
17
17
  ) => {
18
18
  // create injection keys form provide/inject
@@ -78,7 +78,7 @@ export const createForm = (
78
78
  }
79
79
 
80
80
  export const useForm = (
81
- schema: AnyZodObject,
81
+ schema: AnyZodObject | ZodEffects<AnyZodObject>,
82
82
  options: FormComposableOptions = {},
83
83
  ) => {
84
84
  const hasOptions = { ...inject(pluginInjectionKey, {}), ...options }
package/src/types.d.ts CHANGED
@@ -5,6 +5,7 @@ import type { FormFieldType } from './enums'
5
5
  export type FormComposableOptions = {
6
6
  lazyLoad?: boolean
7
7
  updateThrottle?: number
8
+ continuosValidation?: boolean
8
9
  sideEffects?: (type: `${FormFieldType}`) => Promise | void
9
10
  }
10
11
 
package/src/utils.ts CHANGED
@@ -1,13 +1,23 @@
1
1
  import merge from 'deepmerge'
2
- import { type z, type AnyZodObject, ZodDefault, ZodObject } from 'zod'
2
+ import {
3
+ type z,
4
+ type AnyZodObject,
5
+ ZodDefault,
6
+ ZodObject,
7
+ ZodEffects,
8
+ } from 'zod'
3
9
 
4
- export const defaultObjectBySchema = <Schema extends AnyZodObject>(
10
+ export const defaultObjectBySchema = <
11
+ Schema extends AnyZodObject | ZodEffects<AnyZodObject>,
12
+ >(
5
13
  schema: Schema,
6
14
  original: Partial<z.infer<Schema>> = {},
7
15
  ): Partial<z.infer<Schema>> => {
16
+ const shape =
17
+ schema instanceof ZodEffects ? schema.innerType().shape : schema.shape
8
18
  return merge(
9
19
  Object.fromEntries(
10
- Object.entries(schema.shape).map(([key, value]) => {
20
+ Object.entries(shape).map(([key, value]) => {
11
21
  if (value instanceof ZodDefault) {
12
22
  return [key, value._def.defaultValue()]
13
23
  }