@macrulez/vue-form-schema 0.1.9 → 0.2.0

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.
Files changed (82) hide show
  1. package/README.md +461 -180
  2. package/dist/MaskEngine-BEXwX4BK.js +144 -0
  3. package/dist/MaskEngine-CPr-fSPy.cjs +1 -0
  4. package/dist/ValidationEngine-BC4U1ef1.js +135 -0
  5. package/dist/ValidationEngine-Diz-qTFs.cjs +1 -0
  6. package/dist/_plugin-vue_export-helper-BHFhmbuH.cjs +1 -0
  7. package/dist/_plugin-vue_export-helper-CHgC5LLL.js +9 -0
  8. package/dist/core/ConditionEvaluator.d.ts.map +1 -1
  9. package/dist/core/MaskEngine.d.ts.map +1 -1
  10. package/dist/core/ValidationEngine.d.ts +7 -0
  11. package/dist/core/ValidationEngine.d.ts.map +1 -1
  12. package/dist/core/formRegistry.d.ts +33 -0
  13. package/dist/core/formRegistry.d.ts.map +1 -0
  14. package/dist/core/inferTypes.d.ts.map +1 -1
  15. package/dist/core/schemaUtils.d.ts +38 -0
  16. package/dist/core/schemaUtils.d.ts.map +1 -1
  17. package/dist/core/serverErrors.d.ts +69 -0
  18. package/dist/core/serverErrors.d.ts.map +1 -0
  19. package/dist/core/types.d.ts +12 -0
  20. package/dist/core/types.d.ts.map +1 -1
  21. package/dist/core/useForm.d.ts +4 -1
  22. package/dist/core/useForm.d.ts.map +1 -1
  23. package/dist/core/useMultiStepForm.d.ts.map +1 -1
  24. package/dist/devtools/index.d.ts +26 -0
  25. package/dist/devtools/index.d.ts.map +1 -0
  26. package/dist/devtools.cjs +1 -0
  27. package/dist/devtools.d.ts +6 -0
  28. package/dist/devtools.js +93 -0
  29. package/dist/formRegistry-Bv1eaWQ-.js +31 -0
  30. package/dist/formRegistry-DaDmXyYY.cjs +1 -0
  31. package/dist/index.cjs +1 -1
  32. package/dist/index.d.ts +4 -2
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +393 -368
  35. package/dist/openapi.cjs +1 -0
  36. package/dist/openapi.d.ts +202 -0
  37. package/dist/openapi.js +118 -0
  38. package/dist/parsers/json.d.ts.map +1 -1
  39. package/dist/parsers/openapi.d.ts +139 -0
  40. package/dist/parsers/openapi.d.ts.map +1 -0
  41. package/dist/parsers/valibot.d.ts +13 -4
  42. package/dist/parsers/valibot.d.ts.map +1 -1
  43. package/dist/parsers/yup.d.ts +10 -4
  44. package/dist/parsers/yup.d.ts.map +1 -1
  45. package/dist/parsers/zod.d.ts +18 -4
  46. package/dist/parsers/zod.d.ts.map +1 -1
  47. package/dist/schemaUtils-Cc7CwGXB.cjs +1 -0
  48. package/dist/schemaUtils-Cvlsk24U.js +337 -0
  49. package/dist/style.css +1 -0
  50. package/dist/ui/naive/index.d.ts +11 -0
  51. package/dist/ui/naive/index.d.ts.map +1 -0
  52. package/dist/ui/primevue/index.d.ts +11 -0
  53. package/dist/ui/primevue/index.d.ts.map +1 -0
  54. package/dist/ui/shadcn/index.d.ts +11 -0
  55. package/dist/ui/shadcn/index.d.ts.map +1 -0
  56. package/dist/ui-naive.cjs +1 -0
  57. package/dist/ui-naive.d.ts +411 -0
  58. package/dist/ui-naive.js +667 -0
  59. package/dist/ui-primevue.cjs +1 -0
  60. package/dist/ui-primevue.d.ts +411 -0
  61. package/dist/ui-primevue.js +651 -0
  62. package/dist/ui-shadcn.cjs +1 -0
  63. package/dist/ui-shadcn.d.ts +411 -0
  64. package/dist/ui-shadcn.js +650 -0
  65. package/dist/ui-tailwind.cjs +1 -1
  66. package/dist/ui-tailwind.d.ts +14 -0
  67. package/dist/ui-tailwind.js +180 -161
  68. package/dist/ui.cjs +1 -1
  69. package/dist/ui.d.ts +14 -0
  70. package/dist/ui.js +130 -131
  71. package/dist/valibot.cjs +1 -1
  72. package/dist/valibot.d.ts +25 -2
  73. package/dist/valibot.js +47 -20
  74. package/dist/yup.cjs +1 -1
  75. package/dist/yup.d.ts +23 -3
  76. package/dist/yup.js +16 -15
  77. package/dist/zod.cjs +1 -1
  78. package/dist/zod.d.ts +31 -3
  79. package/dist/zod.js +58 -28
  80. package/package.json +66 -6
  81. package/dist/MaskEngine-DAKSNIHQ.cjs +0 -1
  82. package/dist/MaskEngine-mLoXKd4d.js +0 -251
package/dist/valibot.js CHANGED
@@ -1,26 +1,53 @@
1
- function u(t) {
2
- if (!t || t.type !== "object" || !t.entries)
3
- throw new Error("[vue-form-schema] parseValibot expects a v.object() schema");
4
- return Object.entries(t.entries).map(
5
- ([r, n]) => o(r, n)
1
+ import { d as u } from "./schemaUtils-Cvlsk24U.js";
2
+ function y(r) {
3
+ const e = r;
4
+ if ((e == null ? void 0 : e.type) === "variant")
5
+ return f(e);
6
+ if (!e || e.type !== "object" || !e.entries)
7
+ throw new Error("[vue-form-schema] parseValibot expects a v.object() or v.variant() schema");
8
+ return Object.entries(e.entries).map(
9
+ ([i, t]) => l(i, t)
6
10
  );
7
11
  }
8
- function o(t, r) {
9
- let n = !0, e = r;
10
- (e.type === "optional" || e.type === "nullable" || e.type === "nullish") && (n = !1, e = e.wrapped ?? e);
11
- const a = l(e), s = { type: a, name: t, required: n };
12
- return a === "select" && (s.options = e.options.map((i) => ({
13
- label: String(i),
14
- value: i
15
- }))), a === "group" && e.entries && (s.fields = Object.entries(e.entries).map(
16
- ([i, p]) => o(i, p)
17
- )), s;
12
+ function f(r) {
13
+ const e = r.key, i = r.options;
14
+ function t(n) {
15
+ var o;
16
+ const s = n.entries ?? {};
17
+ return String((o = s[e]) == null ? void 0 : o.literal);
18
+ }
19
+ const c = {
20
+ type: "select",
21
+ name: e,
22
+ label: e,
23
+ required: !0,
24
+ options: i.map((n) => {
25
+ const s = t(n);
26
+ return { label: s, value: s };
27
+ })
28
+ }, a = {};
29
+ for (const n of i) {
30
+ const s = n.entries ?? {};
31
+ a[t(n)] = Object.entries(s).filter(([o]) => o !== e).map(([o, p]) => l(o, p));
32
+ }
33
+ return [c, ...u(e, a)];
34
+ }
35
+ function l(r, e) {
36
+ let i = !0, t = e;
37
+ (t.type === "optional" || t.type === "nullable" || t.type === "nullish") && (i = !1, t = t.wrapped ?? t);
38
+ const c = m(t), a = { type: c, name: r, required: i };
39
+ return c === "select" && (a.options = t.options.map((n) => ({
40
+ label: String(n),
41
+ value: n
42
+ }))), c === "group" && t.entries && (a.fields = Object.entries(t.entries).map(
43
+ ([n, s]) => l(`${r}.${n}`, s)
44
+ )), a;
18
45
  }
19
- function l(t) {
20
- const r = t.type;
21
- if (r === "string" && Array.isArray(t.pipe) && t.pipe.some((e) => e.type === "email"))
46
+ function m(r) {
47
+ const e = r.type;
48
+ if (e === "string" && Array.isArray(r.pipe) && r.pipe.some((t) => t.type === "email"))
22
49
  return "email";
23
- switch (r) {
50
+ switch (e) {
24
51
  case "string":
25
52
  return "text";
26
53
  case "number":
@@ -39,5 +66,5 @@ function l(t) {
39
66
  }
40
67
  }
41
68
  export {
42
- u as parseValibot
69
+ y as parseValibot
43
70
  };
package/dist/yup.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function s(r){switch(r){case"string":return"text";case"number":return"number";case"boolean":return"checkbox";case"array":return"array";case"object":return"group";default:return"text"}}function p(r,e){const t=[];return e&&t.push(u=>u==null||u===""?"This field is required":null),t.push(u=>{try{return r.validateSync(u,{abortEarly:!0}),null}catch(n){return n&&typeof n=="object"&&"message"in n?n.message:"Invalid value"}}),t}function i(r,e){const t=!e.spec.optional&&!e.spec.nullable,u=e.spec.label??r,n=s(e.type);return e.type==="object"&&e.fields?{type:"group",name:r,label:u,required:t,fields:Object.entries(e.fields).map(([o,l])=>i(`${r}.${o}`,l))}:{type:n,name:r,label:u,defaultValue:e.spec.default,required:t,validators:p(e,t)}}function a(r){if(r.type!=="object")throw new Error("[vue-form-schema] parseYup expects an object schema");return Object.entries(r.fields??{}).map(([e,t])=>i(e,t))}exports.parseYup=a;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function s(r){switch(r){case"string":return"text";case"number":return"number";case"boolean":return"checkbox";case"array":return"array";case"object":return"group";default:return"text"}}function p(r,e){const u=[];return e&&u.push(t=>t==null||t===""?"This field is required":null),u.push(t=>{try{return r.validateSync(t,{abortEarly:!0}),null}catch(n){return n&&typeof n=="object"&&"message"in n?n.message:"Invalid value"}}),u}function i(r,e){const u=!e.spec.optional&&!e.spec.nullable,t=e.spec.label??r,n=s(e.type);return e.type==="object"&&e.fields?{type:"group",name:r,label:t,required:u,fields:Object.entries(e.fields).map(([o,l])=>i(`${r}.${o}`,l))}:{type:n,name:r,label:t,defaultValue:e.spec.default,required:u,validators:p(e,u)}}function a(r){const e=r;if(e.type!=="object")throw new Error("[vue-form-schema] parseYup expects an object schema");return Object.entries(e.fields??{}).map(([u,t])=>i(u,t))}exports.parseYup=a;
package/dist/yup.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import { AnySchema } from 'yup';
1
2
  import { Component } from 'vue';
3
+ import { InferType } from 'yup';
2
4
 
3
5
  declare type AsyncValidatorFn = (value: unknown, values: Record<string, unknown>) => Promise<string | null>;
4
6
 
@@ -68,10 +70,28 @@ declare interface MaskConfig {
68
70
 
69
71
  declare type MaskPreset = 'phone-ru' | 'phone-eu' | 'date' | 'inn' | 'iban';
70
72
 
71
- export declare function parseYup(schema: YupSchema): FieldDefinition[];
73
+ /**
74
+ * Parses a `yup.object({...})` schema into a `FieldDefinition[]`.
75
+ *
76
+ * The return type carries the schema's inferred value type (`InferType<S>`),
77
+ * so `useForm({ schema: parseYup(mySchema) })` picks up fully typed
78
+ * `values`/`errors`/`onSubmit` without an explicit `useForm<Values>(...)`.
79
+ */
80
+ export declare function parseYup<S extends AnySchema>(schema: S): TypedFieldDefinitions<InferType<S>>;
72
81
 
73
- declare type ValidatorFn = (value: unknown, values: Record<string, unknown>) => string | null;
82
+ /**
83
+ * A `FieldDefinition[]` returned by a schema adapter (`parseZod` / `parseYup`
84
+ * / `parseValibot`) that also carries the source schema's inferred value
85
+ * type at the type level. `useForm({ schema: parseZod(mySchema) })` then
86
+ * infers `T` automatically — no `useForm<Values>(...)` needed.
87
+ *
88
+ * `__inferredValues` does not exist at runtime; it is a type-only marker
89
+ * erased by the compiler.
90
+ */
91
+ declare type TypedFieldDefinitions<T> = FieldDefinition[] & {
92
+ readonly __inferredValues?: T;
93
+ };
74
94
 
75
- declare type YupSchema = any;
95
+ declare type ValidatorFn = (value: unknown, values: Record<string, unknown>) => string | null;
76
96
 
77
97
  export { }
package/dist/yup.js CHANGED
@@ -1,4 +1,4 @@
1
- function p(r) {
1
+ function s(r) {
2
2
  switch (r) {
3
3
  case "string":
4
4
  return "text";
@@ -14,40 +14,41 @@ function p(r) {
14
14
  return "text";
15
15
  }
16
16
  }
17
- function s(r, e) {
18
- const t = [];
19
- return e && t.push((u) => u == null || u === "" ? "This field is required" : null), t.push((u) => {
17
+ function p(r, e) {
18
+ const u = [];
19
+ return e && u.push((t) => t == null || t === "" ? "This field is required" : null), u.push((t) => {
20
20
  try {
21
- return r.validateSync(u, { abortEarly: !0 }), null;
21
+ return r.validateSync(t, { abortEarly: !0 }), null;
22
22
  } catch (n) {
23
23
  return n && typeof n == "object" && "message" in n ? n.message : "Invalid value";
24
24
  }
25
- }), t;
25
+ }), u;
26
26
  }
27
27
  function i(r, e) {
28
- const t = !e.spec.optional && !e.spec.nullable, u = e.spec.label ?? r, n = p(e.type);
28
+ const u = !e.spec.optional && !e.spec.nullable, t = e.spec.label ?? r, n = s(e.type);
29
29
  return e.type === "object" && e.fields ? {
30
30
  type: "group",
31
31
  name: r,
32
- label: u,
33
- required: t,
32
+ label: t,
33
+ required: u,
34
34
  fields: Object.entries(e.fields).map(
35
35
  ([o, l]) => i(`${r}.${o}`, l)
36
36
  )
37
37
  } : {
38
38
  type: n,
39
39
  name: r,
40
- label: u,
40
+ label: t,
41
41
  defaultValue: e.spec.default,
42
- required: t,
43
- validators: s(e, t)
42
+ required: u,
43
+ validators: p(e, u)
44
44
  };
45
45
  }
46
46
  function a(r) {
47
- if (r.type !== "object")
47
+ const e = r;
48
+ if (e.type !== "object")
48
49
  throw new Error("[vue-form-schema] parseYup expects an object schema");
49
- return Object.entries(r.fields ?? {}).map(
50
- ([e, t]) => i(e, t)
50
+ return Object.entries(e.fields ?? {}).map(
51
+ ([u, t]) => i(u, t)
51
52
  );
52
53
  }
53
54
  export {
package/dist/zod.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function i(s){var n;let e=s._def;for(;e.typeName==="ZodOptional"||e.typeName==="ZodNullable"||e.typeName==="ZodDefault";){e=((n=e.innerType)==null?void 0:n._def)??e;break}return e.typeName}function p(s){switch(i(s)){case"ZodString":return"text";case"ZodNumber":return"number";case"ZodBoolean":return"checkbox";case"ZodArray":return"array";case"ZodObject":return"group";case"ZodEnum":return"select";default:return"text"}}function o(s,e){const n=[],u=s._def;e&&n.push(t=>t==null||t===""?"This field is required":null);for(const t of u.checks??[])switch(t.kind){case"min":n.push(r=>typeof r!="string"||r.length>=Number(t.value)?null:t.message??`Minimum length is ${t.value}`);break;case"max":n.push(r=>typeof r!="string"||r.length<=Number(t.value)?null:t.message??`Maximum length is ${t.value}`);break;case"email":n.push(r=>r?/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(r))?null:t.message??"Invalid email address":null);break;case"url":n.push(r=>{if(!r)return null;try{return new URL(String(r)),null}catch{return t.message??"Invalid URL"}});break;case"regex":n.push(r=>typeof r!="string"||t.regex.test(r)?null:t.message??"Invalid format");break}return n.push(t=>{var l,a;const r=s.safeParse(t);return r.success?null:((a=(l=r.error)==null?void 0:l.errors[0])==null?void 0:a.message)??"Invalid value"}),n}function d(s,e){const n=i(e),u=e.isOptional(),t=p(e),r=e._def.description??s;if(n==="ZodObject"&&e._def.shape){const l=e._def.shape();return{type:"group",name:s,label:r,required:!u,fields:Object.entries(l).map(([a,c])=>d(`${s}.${a}`,c))}}if(n==="ZodEnum"&&e._def.values){const l=e._def.values;return{type:"select",name:s,label:r,required:!u,options:Object.entries(l).map(([,a])=>({label:a,value:a})),validators:o(e,!u)}}return{type:t,name:s,label:r,required:!u,validators:o(e,!u)}}function f(s){var n,u;if(s._def.typeName!=="ZodObject")throw new Error("[vue-form-schema] parseZod expects a ZodObject schema");const e=((u=(n=s._def).shape)==null?void 0:u.call(n))??{};return Object.entries(e).map(([t,r])=>d(t,r))}exports.parseZod=f;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./schemaUtils-Cc7CwGXB.cjs");function h(s){var n;let e=s._def;for(;e.typeName==="ZodOptional"||e.typeName==="ZodNullable"||e.typeName==="ZodDefault";){e=((n=e.innerType)==null?void 0:n._def)??e;break}return e.typeName}function g(s){switch(h(s)){case"ZodString":return"text";case"ZodNumber":return"number";case"ZodBoolean":return"checkbox";case"ZodArray":return"array";case"ZodObject":return"group";case"ZodEnum":return"select";default:return"text"}}function b(s,e){const n=[],i=s._def;e&&n.push(t=>t==null||t===""?"This field is required":null);for(const t of i.checks??[])switch(t.kind){case"min":n.push(r=>typeof r!="string"||r.length>=Number(t.value)?null:t.message??`Minimum length is ${t.value}`);break;case"max":n.push(r=>typeof r!="string"||r.length<=Number(t.value)?null:t.message??`Maximum length is ${t.value}`);break;case"email":n.push(r=>r?/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(r))?null:t.message??"Invalid email address":null);break;case"url":n.push(r=>{if(!r)return null;try{return new URL(String(r)),null}catch{return t.message??"Invalid URL"}});break;case"regex":n.push(r=>typeof r!="string"||t.regex.test(r)?null:t.message??"Invalid format");break}return n.push(t=>{var o,a;const r=s.safeParse(t);return r.success?null:((a=(o=r.error)==null?void 0:o.errors[0])==null?void 0:a.message)??"Invalid value"}),n}function p(s,e){const n=h(e),i=e.isOptional(),t=g(e),r=e._def.description??s;if(n==="ZodObject"&&e._def.shape){const o=e._def.shape();return{type:"group",name:s,label:r,required:!i,fields:Object.entries(o).map(([a,u])=>p(`${s}.${a}`,u))}}if(n==="ZodEnum"&&e._def.values){const o=e._def.values;return{type:"select",name:s,label:r,required:!i,options:Object.entries(o).map(([,a])=>({label:a,value:a})),validators:b(e,!i)}}return{type:t,name:s,label:r,required:!i,validators:b(e,!i)}}function Z(s){var o,a;const e=s._def,n=e.discriminator;function i(u){var c,f,m;const l=(((f=(c=u._def).shape)==null?void 0:f.call(c))??{})[n];return String((m=l==null?void 0:l._def)==null?void 0:m.value)}const t={type:"select",name:n,label:n,required:!0,options:e.options.map(u=>{const d=i(u);return{label:d,value:d}})},r={};for(const u of e.options){const d=((a=(o=u._def).shape)==null?void 0:a.call(o))??{};r[i(u)]=Object.entries(d).filter(([l])=>l!==n).map(([l,c])=>p(l,c))}return[t,...y.discriminatedFields(n,r)]}function v(s){var i,t;const e=s;if(e._def.typeName==="ZodDiscriminatedUnion")return Z(e);if(e._def.typeName!=="ZodObject")throw new Error("[vue-form-schema] parseZod expects a ZodObject or ZodDiscriminatedUnion schema");const n=((t=(i=e._def).shape)==null?void 0:t.call(i))??{};return Object.entries(n).map(([r,o])=>p(r,o))}exports.parseZod=v;
package/dist/zod.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Component } from 'vue';
2
+ import { z } from 'zod';
2
3
 
3
4
  declare type AsyncValidatorFn = (value: unknown, values: Record<string, unknown>) => Promise<string | null>;
4
5
 
@@ -68,10 +69,37 @@ declare interface MaskConfig {
68
69
 
69
70
  declare type MaskPreset = 'phone-ru' | 'phone-eu' | 'date' | 'inn' | 'iban';
70
71
 
71
- export declare function parseZod(schema: ZodTypeAny): FieldDefinition[];
72
+ /**
73
+ * Parses a `z.object({...})` schema into a `FieldDefinition[]`.
74
+ *
75
+ * The return type carries the schema's inferred value type (`z.infer<S>`),
76
+ * so `useForm({ schema: parseZod(mySchema) })` picks up fully typed
77
+ * `values`/`errors`/`onSubmit` without an explicit `useForm<Values>(...)`.
78
+ */
79
+ export declare function parseZod<S extends z.ZodObject<z.ZodRawShape>>(schema: S): TypedFieldDefinitions<z.infer<S>>;
72
80
 
73
- declare type ValidatorFn = (value: unknown, values: Record<string, unknown>) => string | null;
81
+ /**
82
+ * Parses a `z.discriminatedUnion(key, [...])` schema into a `FieldDefinition[]`
83
+ * — a `select` for the discriminator plus every variant's fields, each only
84
+ * visible while the discriminator matches its variant (see
85
+ * `discriminatedFields`). Combine with `clearOnHide: true` on `useForm` so
86
+ * switching variants resets the now-hidden variant's values.
87
+ */
88
+ export declare function parseZod<Discriminator extends string, Options extends readonly z.ZodDiscriminatedUnionOption<Discriminator>[]>(schema: z.ZodDiscriminatedUnion<Discriminator, Options>): TypedFieldDefinitions<z.infer<z.ZodDiscriminatedUnion<Discriminator, Options>>>;
89
+
90
+ /**
91
+ * A `FieldDefinition[]` returned by a schema adapter (`parseZod` / `parseYup`
92
+ * / `parseValibot`) that also carries the source schema's inferred value
93
+ * type at the type level. `useForm({ schema: parseZod(mySchema) })` then
94
+ * infers `T` automatically — no `useForm<Values>(...)` needed.
95
+ *
96
+ * `__inferredValues` does not exist at runtime; it is a type-only marker
97
+ * erased by the compiler.
98
+ */
99
+ declare type TypedFieldDefinitions<T> = FieldDefinition[] & {
100
+ readonly __inferredValues?: T;
101
+ };
74
102
 
75
- declare type ZodTypeAny = any;
103
+ declare type ValidatorFn = (value: unknown, values: Record<string, unknown>) => string | null;
76
104
 
77
105
  export { }
package/dist/zod.js CHANGED
@@ -1,4 +1,5 @@
1
- function i(s) {
1
+ import { d as y } from "./schemaUtils-Cvlsk24U.js";
2
+ function h(s) {
2
3
  var n;
3
4
  let e = s._def;
4
5
  for (; e.typeName === "ZodOptional" || e.typeName === "ZodNullable" || e.typeName === "ZodDefault"; ) {
@@ -7,8 +8,8 @@ function i(s) {
7
8
  }
8
9
  return e.typeName;
9
10
  }
10
- function p(s) {
11
- switch (i(s)) {
11
+ function g(s) {
12
+ switch (h(s)) {
12
13
  case "ZodString":
13
14
  return "text";
14
15
  case "ZodNumber":
@@ -25,10 +26,10 @@ function p(s) {
25
26
  return "text";
26
27
  }
27
28
  }
28
- function o(s, e) {
29
- const n = [], u = s._def;
29
+ function b(s, e) {
30
+ const n = [], i = s._def;
30
31
  e && n.push((t) => t == null || t === "" ? "This field is required" : null);
31
- for (const t of u.checks ?? [])
32
+ for (const t of i.checks ?? [])
32
33
  switch (t.kind) {
33
34
  case "min":
34
35
  n.push((r) => typeof r != "string" || r.length >= Number(t.value) ? null : t.message ?? `Minimum length is ${t.value}`);
@@ -54,51 +55,80 @@ function o(s, e) {
54
55
  break;
55
56
  }
56
57
  return n.push((t) => {
57
- var l, a;
58
+ var o, a;
58
59
  const r = s.safeParse(t);
59
- return r.success ? null : ((a = (l = r.error) == null ? void 0 : l.errors[0]) == null ? void 0 : a.message) ?? "Invalid value";
60
+ return r.success ? null : ((a = (o = r.error) == null ? void 0 : o.errors[0]) == null ? void 0 : a.message) ?? "Invalid value";
60
61
  }), n;
61
62
  }
62
- function d(s, e) {
63
- const n = i(e), u = e.isOptional(), t = p(e), r = e._def.description ?? s;
63
+ function p(s, e) {
64
+ const n = h(e), i = e.isOptional(), t = g(e), r = e._def.description ?? s;
64
65
  if (n === "ZodObject" && e._def.shape) {
65
- const l = e._def.shape();
66
+ const o = e._def.shape();
66
67
  return {
67
68
  type: "group",
68
69
  name: s,
69
70
  label: r,
70
- required: !u,
71
- fields: Object.entries(l).map(
72
- ([a, c]) => d(`${s}.${a}`, c)
73
- )
71
+ required: !i,
72
+ fields: Object.entries(o).map(([a, u]) => p(`${s}.${a}`, u))
74
73
  };
75
74
  }
76
75
  if (n === "ZodEnum" && e._def.values) {
77
- const l = e._def.values;
76
+ const o = e._def.values;
78
77
  return {
79
78
  type: "select",
80
79
  name: s,
81
80
  label: r,
82
- required: !u,
83
- options: Object.entries(l).map(([, a]) => ({ label: a, value: a })),
84
- validators: o(e, !u)
81
+ required: !i,
82
+ options: Object.entries(o).map(([, a]) => ({ label: a, value: a })),
83
+ validators: b(e, !i)
85
84
  };
86
85
  }
87
86
  return {
88
87
  type: t,
89
88
  name: s,
90
89
  label: r,
91
- required: !u,
92
- validators: o(e, !u)
90
+ required: !i,
91
+ validators: b(e, !i)
93
92
  };
94
93
  }
95
- function f(s) {
96
- var n, u;
97
- if (s._def.typeName !== "ZodObject")
98
- throw new Error("[vue-form-schema] parseZod expects a ZodObject schema");
99
- const e = ((u = (n = s._def).shape) == null ? void 0 : u.call(n)) ?? {};
100
- return Object.entries(e).map(([t, r]) => d(t, r));
94
+ function Z(s) {
95
+ var o, a;
96
+ const e = s._def, n = e.discriminator;
97
+ function i(u) {
98
+ var c, f, m;
99
+ const l = (((f = (c = u._def).shape) == null ? void 0 : f.call(c)) ?? {})[n];
100
+ return String((m = l == null ? void 0 : l._def) == null ? void 0 : m.value);
101
+ }
102
+ const t = {
103
+ type: "select",
104
+ name: n,
105
+ label: n,
106
+ required: !0,
107
+ options: e.options.map((u) => {
108
+ const d = i(u);
109
+ return { label: d, value: d };
110
+ })
111
+ }, r = {};
112
+ for (const u of e.options) {
113
+ const d = ((a = (o = u._def).shape) == null ? void 0 : a.call(o)) ?? {};
114
+ r[i(u)] = Object.entries(d).filter(([l]) => l !== n).map(([l, c]) => p(l, c));
115
+ }
116
+ return [t, ...y(n, r)];
117
+ }
118
+ function _(s) {
119
+ var i, t;
120
+ const e = s;
121
+ if (e._def.typeName === "ZodDiscriminatedUnion")
122
+ return Z(e);
123
+ if (e._def.typeName !== "ZodObject")
124
+ throw new Error(
125
+ "[vue-form-schema] parseZod expects a ZodObject or ZodDiscriminatedUnion schema"
126
+ );
127
+ const n = ((t = (i = e._def).shape) == null ? void 0 : t.call(i)) ?? {};
128
+ return Object.entries(n).map(
129
+ ([r, o]) => p(r, o)
130
+ );
101
131
  }
102
132
  export {
103
- f as parseZod
133
+ _ as parseZod
104
134
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@macrulez/vue-form-schema",
3
- "version": "0.1.9",
3
+ "version": "0.2.0",
4
4
  "description": "Reactive Vue 3 forms generated from JSON, Zod, Yup or Valibot schemas, with validation, input masking, conditional UI and SSR support.",
5
5
  "author": "macrulez <macrulezru@gmail.com> (https://macrulez.ru/en)",
6
6
  "license": "MIT",
@@ -13,6 +13,9 @@
13
13
  "url": "https://github.com/macrulezru/vue-form-schema/issues"
14
14
  },
15
15
  "type": "module",
16
+ "workspaces": [
17
+ "packages/*"
18
+ ],
16
19
  "main": "./dist/index.cjs",
17
20
  "module": "./dist/index.js",
18
21
  "types": "./dist/index.d.ts",
@@ -37,6 +40,11 @@
37
40
  "import": "./dist/valibot.js",
38
41
  "require": "./dist/valibot.cjs"
39
42
  },
43
+ "./openapi": {
44
+ "types": "./dist/openapi.d.ts",
45
+ "import": "./dist/openapi.js",
46
+ "require": "./dist/openapi.cjs"
47
+ },
40
48
  "./ui": {
41
49
  "types": "./dist/ui.d.ts",
42
50
  "import": "./dist/ui.js",
@@ -46,6 +54,26 @@
46
54
  "types": "./dist/ui-tailwind.d.ts",
47
55
  "import": "./dist/ui-tailwind.js",
48
56
  "require": "./dist/ui-tailwind.cjs"
57
+ },
58
+ "./ui/shadcn": {
59
+ "types": "./dist/ui-shadcn.d.ts",
60
+ "import": "./dist/ui-shadcn.js",
61
+ "require": "./dist/ui-shadcn.cjs"
62
+ },
63
+ "./ui/primevue": {
64
+ "types": "./dist/ui-primevue.d.ts",
65
+ "import": "./dist/ui-primevue.js",
66
+ "require": "./dist/ui-primevue.cjs"
67
+ },
68
+ "./ui/naive": {
69
+ "types": "./dist/ui-naive.d.ts",
70
+ "import": "./dist/ui-naive.js",
71
+ "require": "./dist/ui-naive.cjs"
72
+ },
73
+ "./devtools": {
74
+ "types": "./dist/devtools.d.ts",
75
+ "import": "./dist/devtools.js",
76
+ "require": "./dist/devtools.cjs"
49
77
  }
50
78
  },
51
79
  "files": [
@@ -54,19 +82,25 @@
54
82
  "LICENSE"
55
83
  ],
56
84
  "engines": {
57
- "node": ">=18"
85
+ "node": ">=20.12"
58
86
  },
59
87
  "publishConfig": {
60
88
  "access": "public"
61
89
  },
62
90
  "scripts": {
63
- "prepublishOnly": "npm run build",
91
+ "prepublishOnly": "npm run typecheck && npm run lint && npm run format:check && npm run test:run && npm run build",
64
92
  "dev": "vite",
65
93
  "build": "vite build && tsc -p tsconfig.build.json",
66
94
  "demo": "vite --config vite.demo.config.ts",
67
95
  "test": "vitest --config vitest.config.ts",
96
+ "test:run": "vitest --config vitest.config.ts --run",
68
97
  "test:coverage": "vitest --config vitest.config.ts --coverage",
69
- "typecheck": "tsc --noEmit"
98
+ "typecheck": "vue-tsc --noEmit",
99
+ "lint": "eslint .",
100
+ "format": "prettier --write .",
101
+ "format:check": "prettier --check .",
102
+ "build:nuxt": "npm run build --workspace=packages/nuxt",
103
+ "typecheck:nuxt": "npm run typecheck --workspace=packages/nuxt"
70
104
  },
71
105
  "keywords": [
72
106
  "vue",
@@ -77,15 +111,20 @@
77
111
  "zod",
78
112
  "yup",
79
113
  "valibot",
114
+ "json-schema",
115
+ "openapi",
80
116
  "mask",
81
117
  "ssr",
82
118
  "typescript"
83
119
  ],
84
120
  "peerDependencies": {
121
+ "@vue/devtools-api": "^6 || ^7 || ^8",
122
+ "naive-ui": ">=2.38.0",
123
+ "primevue": ">=4.0.0",
124
+ "valibot": ">=1.0.0",
85
125
  "vue": "^3.3.0",
86
- "zod": ">=3.22.0",
87
126
  "yup": ">=1.3.0",
88
- "valibot": ">=1.0.0"
127
+ "zod": ">=3.22.0"
89
128
  },
90
129
  "peerDependenciesMeta": {
91
130
  "zod": {
@@ -96,22 +135,43 @@
96
135
  },
97
136
  "valibot": {
98
137
  "optional": true
138
+ },
139
+ "primevue": {
140
+ "optional": true
141
+ },
142
+ "naive-ui": {
143
+ "optional": true
144
+ },
145
+ "@vue/devtools-api": {
146
+ "optional": true
99
147
  }
100
148
  },
101
149
  "devDependencies": {
150
+ "@eslint/js": "^9.39.5",
151
+ "@primeuix/themes": "^3.0.0",
102
152
  "@vitejs/plugin-vue": "^5.0.0",
103
153
  "@vitest/coverage-v8": "^1.0.0",
154
+ "@vue/devtools-api": "^8.2.1",
104
155
  "@vue/test-utils": "^2.4.0",
105
156
  "autoprefixer": "^10.5.0",
157
+ "eslint": "^9.39.5",
158
+ "eslint-config-prettier": "^9.1.2",
159
+ "eslint-plugin-vue": "^9.33.0",
106
160
  "happy-dom": "^20.9.0",
161
+ "naive-ui": "^2.45.1",
107
162
  "postcss": "^8.5.15",
163
+ "prettier": "^3.9.6",
164
+ "primevue": "^5.0.1",
108
165
  "tailwindcss": "^3.4.19",
109
166
  "typescript": "^5.3.0",
167
+ "typescript-eslint": "^8.67.0",
110
168
  "valibot": "^1.4.0",
111
169
  "vite": "^5.0.0",
112
170
  "vite-plugin-dts": "^3.7.0",
113
171
  "vitest": "^1.0.0",
114
172
  "vue": "^3.4.0",
173
+ "vue-eslint-parser": "^9.4.3",
174
+ "vue-tsc": "^2.2.12",
115
175
  "yup": "^1.3.0",
116
176
  "zod": "^3.22.0"
117
177
  }
@@ -1 +0,0 @@
1
- "use strict";const g=require("vue"),A=Symbol("vfs:registry");function I(t){return{install(e){e.provide(A,t)}}}function S(){return g.inject(A,{})}function L(t){g.provide(A,t)}function P(t,e){const n=g.computed(()=>T(t.fields.value,e)),r=g.computed(()=>(t.getField(e)??[]).map((c,a)=>{var p;return{key:`${e}__${a}`,index:a,fields:$(((p=n.value)==null?void 0:p.fields)??[],e,a)}})),s=g.computed(()=>r.value.length);function i(){return[...t.getField(e)??[]]}function o(f={}){const c=i();c.push(f),t.setField(e,c)}function l(f={}){const c=i();c.unshift(f),t.setField(e,c)}function u(f){const c=i();c.splice(f,1),t.setField(e,c)}function d(f,c){const a=i(),[p]=a.splice(f,1);a.splice(c,0,p),t.setField(e,a)}function h(f,c){const a=i();[a[f],a[c]]=[a[c],a[f]],t.setField(e,a)}function x(f,c){const a=i();a[f]=c,t.setField(e,a)}return{rows:r,count:s,append:o,prepend:l,remove:u,move:d,swap:h,replace:x}}function $(t,e,n){return t.map(r=>({...r,name:`${e}.${n}.${r.name}`,fields:r.fields?$(r.fields,e,n):void 0}))}function T(t,e){for(const n of t){if(n.name===e)return n;if(n.fields){const r=T(n.fields,e);if(r)return r}}}const w=t=>t==null||t===""||Array.isArray(t)&&t.length===0?"This field is required":null,k=(t,e)=>n=>typeof n!="string"&&!Array.isArray(n)||n.length>=t?null:e??`Minimum length is ${t}`,z=(t,e)=>n=>typeof n!="string"&&!Array.isArray(n)||n.length<=t?null:e??`Maximum length is ${t}`,B=(t,e)=>n=>{const r=Number(n);return isNaN(r)||r>=t?null:e??`Minimum value is ${t}`},q=(t,e)=>n=>{const r=Number(n);return isNaN(r)||r<=t?null:e??`Maximum value is ${t}`},b=(t,e)=>n=>typeof n!="string"||t.test(n)?null:e??"Invalid format",j=t=>t?/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(t))?null:"Invalid email address":null,C=t=>{if(!t)return null;try{return new URL(String(t)),null}catch{return"Invalid URL"}},_=(t,e)=>(n,r)=>n===r[t]?null:e??`Must match ${t}`;function F(t){return t?t instanceof File?[t]:Array.isArray(t)?t.filter(e=>e instanceof File):[]:[]}function U(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}const K=(t,e)=>n=>{const r=F(n);return r.length&&r.filter(i=>!t.some(o=>i.type.startsWith(o)||i.name.toLowerCase().endsWith(o))).length?e??`Accepted formats: ${t.join(", ")}`:null},V=(t,e)=>n=>{const r=F(n);return r.length&&r.filter(i=>i.size>t).length?e??`File size must not exceed ${U(t)}`:null},W=(t,e)=>n=>F(n).length>t?e??`Maximum ${t} file${t===1?"":"s"} allowed`:null;class Y{constructor(e=300,n="first"){this.asyncTimers=new Map,this.debounceMs=e,this.validateMode=n}validateField(e,n,r){const s=[];if(e.required){const i=w(n);if(i&&(s.push(i),this.validateMode==="first"))return s}for(const i of e.validators??[]){const o=i(n,r);if(o&&(s.push(o),this.validateMode==="first"))return s}return s}validateAll(e,n){const r={};return this.collectErrors(e,n,r),r}collectErrors(e,n,r){for(const s of e){const i=E(n,s.name),o=this.validateField(s,i,n);o.length&&(r[s.name]=o),(s.type==="group"||s.type==="array")&&s.fields&&this.collectErrors(s.fields,n,r)}}validateAsync(e,n,r,s){var l;if(!((l=e.asyncValidators)!=null&&l.length))return;const i=this.asyncTimers.get(e.name);i&&clearTimeout(i);const o=setTimeout(async()=>{const d=(await Promise.all(e.asyncValidators.map(h=>h(n,r)))).filter(h=>h!==null);s(e.name,d),this.asyncTimers.delete(e.name)},this.debounceMs);this.asyncTimers.set(e.name,o)}destroy(){for(const e of this.asyncTimers.values())clearTimeout(e);this.asyncTimers.clear()}}function E(t,e){return e.split(".").reduce((n,r)=>{if(n&&typeof n=="object")return n[r]},t)}function G(t,e,n){const r=e.split("."),s={...t};let i=s;for(let o=0;o<r.length-1;o++){const l=r[o],u=i[l];Array.isArray(u)?i[l]=[...u]:u&&typeof u=="object"?i[l]={...u}:i[l]={},i=i[l]}return i[r[r.length-1]]=n,s}const Z={"phone-ru":"+7 (###) ###-##-##","phone-eu":"+## (##) ###-##-##",date:"##.##.####",inn:"############",iban:"AA## #### #### #### #### #### ####"};function R(t){return t.preset?Z[t.preset]:t.pattern??""}function y(t){return t==="#"||t==="A"}function M(t,e){return e==="#"?/\d/.test(t):e==="A"?/[a-zA-Z]/.test(t):!1}function m(t,e){const r=R(typeof e=="string"?{pattern:e}:e);if(!r)return t;const s=Array.from(t);let i=0,o=-1;for(let u=0;u<r.length&&i<s.length;u++){const d=r[u];if(y(d)){for(;i<s.length&&!M(s[i],d);)i++;i<s.length&&(o=u,i++)}}if(o===-1)return"";let l="";i=0;for(let u=0;u<=o;u++){const d=r[u];if(y(d)){for(;i<s.length&&!M(s[i],d);)i++;i<s.length&&(l+=d==="A"?s[i++].toUpperCase():s[i++])}else l+=d}return l}function v(t,e){const r=R(typeof e=="string"?{pattern:e}:e);if(!r)return t;const s=[];let i=0;for(let o=0;o<r.length&&i<t.length;o++){const l=r[o],u=t[i];y(l)?(s.push(u),i++):u===l&&i++}return s.join("")}function D(t,e){function n(){const s=v(t.value,e),i=m(s,e);if(t.value!==i){const o=t.selectionStart??i.length;t.value=i;const l=Math.min(o,i.length);t.setSelectionRange(l,l)}}t.addEventListener("input",n);const r=m(v(t.value,e),e);return t.value!==r&&r&&(t.value=r),()=>t.removeEventListener("input",n)}exports.ValidationEngine=Y;exports.applyMask=m;exports.bindMask=D;exports.createFormRegistry=I;exports.email=j;exports.fileCount=W;exports.fileSize=V;exports.fileType=K;exports.getByPath=E;exports.max=q;exports.maxLength=z;exports.min=B;exports.minLength=k;exports.pattern=b;exports.provideRegistry=L;exports.removeMask=v;exports.required=w;exports.sameAs=_;exports.setByPath=G;exports.url=C;exports.useFieldArray=P;exports.useRegistry=S;