@macrulez/vue-form-schema 0.1.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 (45) hide show
  1. package/README.md +829 -0
  2. package/dist/MaskEngine-D22m29OM.js +157 -0
  3. package/dist/MaskEngine-hd5xHed7.cjs +1 -0
  4. package/dist/__tests__/ConditionEvaluator.test.d.ts +2 -0
  5. package/dist/__tests__/ConditionEvaluator.test.d.ts.map +1 -0
  6. package/dist/__tests__/MaskEngine.test.d.ts +2 -0
  7. package/dist/__tests__/MaskEngine.test.d.ts.map +1 -0
  8. package/dist/__tests__/ValidationEngine.test.d.ts +2 -0
  9. package/dist/__tests__/ValidationEngine.test.d.ts.map +1 -0
  10. package/dist/__tests__/parsers.test.d.ts +2 -0
  11. package/dist/__tests__/parsers.test.d.ts.map +1 -0
  12. package/dist/__tests__/useForm.test.d.ts +2 -0
  13. package/dist/__tests__/useForm.test.d.ts.map +1 -0
  14. package/dist/core/ConditionEvaluator.d.ts +18 -0
  15. package/dist/core/ConditionEvaluator.d.ts.map +1 -0
  16. package/dist/core/MaskEngine.d.ts +21 -0
  17. package/dist/core/MaskEngine.d.ts.map +1 -0
  18. package/dist/core/ValidationEngine.d.ts +25 -0
  19. package/dist/core/ValidationEngine.d.ts.map +1 -0
  20. package/dist/core/types.d.ts +76 -0
  21. package/dist/core/types.d.ts.map +1 -0
  22. package/dist/core/useForm.d.ts +3 -0
  23. package/dist/core/useForm.d.ts.map +1 -0
  24. package/dist/index.cjs +1 -0
  25. package/dist/index.d.ts +7 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +278 -0
  28. package/dist/parsers/json.d.ts +3 -0
  29. package/dist/parsers/json.d.ts.map +1 -0
  30. package/dist/parsers/yup.d.ts +10 -0
  31. package/dist/parsers/yup.d.ts.map +1 -0
  32. package/dist/parsers/zod.d.ts +10 -0
  33. package/dist/parsers/zod.d.ts.map +1 -0
  34. package/dist/ui/index.d.ts +9 -0
  35. package/dist/ui/index.d.ts.map +1 -0
  36. package/dist/ui.cjs +1 -0
  37. package/dist/ui.d.ts +324 -0
  38. package/dist/ui.js +438 -0
  39. package/dist/yup.cjs +1 -0
  40. package/dist/yup.d.ts +45 -0
  41. package/dist/yup.js +55 -0
  42. package/dist/zod.cjs +1 -0
  43. package/dist/zod.d.ts +45 -0
  44. package/dist/zod.js +104 -0
  45. package/package.json +69 -0
package/dist/ui.js ADDED
@@ -0,0 +1,438 @@
1
+ import { defineComponent as h, openBlock as r, createElementBlock as i, normalizeClass as I, createTextVNode as N, toDisplayString as y, createCommentVNode as V, renderSlot as F, Fragment as B, renderList as S, ref as w, onMounted as E, onUnmounted as L, createBlock as b, withCtx as v, createElementVNode as c, computed as U, resolveComponent as z, resolveDynamicComponent as M, createSlots as P } from "vue";
2
+ import { b as j, g as A } from "./MaskEngine-D22m29OM.js";
3
+ const G = ["for"], H = {
4
+ key: 0,
5
+ class: "vfs-field__required",
6
+ "aria-hidden": "true"
7
+ }, J = {
8
+ key: 1,
9
+ class: "vfs-field__errors",
10
+ role: "alert"
11
+ }, k = /* @__PURE__ */ h({
12
+ __name: "BaseField",
13
+ props: {
14
+ field: {},
15
+ error: {},
16
+ touched: { type: Boolean }
17
+ },
18
+ setup(e) {
19
+ const n = e;
20
+ return (d, m) => {
21
+ var t, l;
22
+ return r(), i("div", {
23
+ class: I(["vfs-field", [`vfs-field--${n.field.type}`, { "vfs-field--error": e.touched && ((t = e.error) == null ? void 0 : t.length) }]])
24
+ }, [
25
+ n.field.label ? (r(), i("label", {
26
+ key: 0,
27
+ for: n.field.name,
28
+ class: "vfs-field__label"
29
+ }, [
30
+ N(y(n.field.label) + " ", 1),
31
+ n.field.required ? (r(), i("span", H, "*")) : V("", !0)
32
+ ], 8, G)) : V("", !0),
33
+ F(d.$slots, "default"),
34
+ e.touched && ((l = e.error) != null && l.length) ? (r(), i("ul", J, [
35
+ (r(!0), i(B, null, S(e.error, (s, o) => (r(), i("li", {
36
+ key: o,
37
+ class: "vfs-field__error"
38
+ }, y(s), 1))), 128))
39
+ ])) : V("", !0)
40
+ ], 2);
41
+ };
42
+ }
43
+ }), K = ["id", "type", "name", "value", "placeholder", "disabled", "required"], R = /* @__PURE__ */ h({
44
+ __name: "TextField",
45
+ props: {
46
+ field: {},
47
+ modelValue: {},
48
+ error: {},
49
+ touched: { type: Boolean }
50
+ },
51
+ emits: ["update:modelValue", "blur"],
52
+ setup(e, { emit: n }) {
53
+ const d = e, m = n, t = w(null);
54
+ let l = null;
55
+ E(() => {
56
+ t.value && d.field.mask && (l = j(t.value, d.field.mask));
57
+ }), L(() => l == null ? void 0 : l());
58
+ function s(o) {
59
+ m("update:modelValue", o.target.value);
60
+ }
61
+ return (o, $) => (r(), b(k, {
62
+ field: e.field,
63
+ error: e.error,
64
+ touched: e.touched
65
+ }, {
66
+ default: v(() => [
67
+ c("input", {
68
+ id: e.field.name,
69
+ ref_key: "inputRef",
70
+ ref: t,
71
+ type: e.field.type === "email" ? "email" : "text",
72
+ name: e.field.name,
73
+ value: e.modelValue,
74
+ placeholder: e.field.placeholder,
75
+ disabled: e.field.disabled === !0,
76
+ required: e.field.required,
77
+ class: "vfs-input",
78
+ onInput: s,
79
+ onBlur: $[0] || ($[0] = (g) => m("blur"))
80
+ }, null, 40, K)
81
+ ]),
82
+ _: 1
83
+ }, 8, ["field", "error", "touched"]));
84
+ }
85
+ }), O = ["id", "name", "value", "placeholder", "disabled", "required"], Q = /* @__PURE__ */ h({
86
+ __name: "NumberField",
87
+ props: {
88
+ field: {},
89
+ modelValue: {},
90
+ error: {},
91
+ touched: { type: Boolean }
92
+ },
93
+ emits: ["update:modelValue", "blur"],
94
+ setup(e, { emit: n }) {
95
+ const d = n;
96
+ function m(t) {
97
+ const l = t.target.value;
98
+ d("update:modelValue", l === "" ? null : Number(l));
99
+ }
100
+ return (t, l) => (r(), b(k, {
101
+ field: e.field,
102
+ error: e.error,
103
+ touched: e.touched
104
+ }, {
105
+ default: v(() => [
106
+ c("input", {
107
+ id: e.field.name,
108
+ type: "number",
109
+ name: e.field.name,
110
+ value: e.modelValue ?? "",
111
+ placeholder: e.field.placeholder,
112
+ disabled: e.field.disabled === !0,
113
+ required: e.field.required,
114
+ class: "vfs-input",
115
+ onInput: m,
116
+ onBlur: l[0] || (l[0] = (s) => d("blur"))
117
+ }, null, 40, O)
118
+ ]),
119
+ _: 1
120
+ }, 8, ["field", "error", "touched"]));
121
+ }
122
+ }), W = ["id", "name", "value", "placeholder", "disabled", "required"], X = /* @__PURE__ */ h({
123
+ __name: "TextareaField",
124
+ props: {
125
+ field: {},
126
+ modelValue: {},
127
+ error: {},
128
+ touched: { type: Boolean }
129
+ },
130
+ emits: ["update:modelValue", "blur"],
131
+ setup(e, { emit: n }) {
132
+ const d = n;
133
+ return (m, t) => (r(), b(k, {
134
+ field: e.field,
135
+ error: e.error,
136
+ touched: e.touched
137
+ }, {
138
+ default: v(() => [
139
+ c("textarea", {
140
+ id: e.field.name,
141
+ name: e.field.name,
142
+ value: e.modelValue,
143
+ placeholder: e.field.placeholder,
144
+ disabled: e.field.disabled === !0,
145
+ required: e.field.required,
146
+ class: "vfs-textarea",
147
+ onInput: t[0] || (t[0] = (l) => d("update:modelValue", l.target.value)),
148
+ onBlur: t[1] || (t[1] = (l) => d("blur"))
149
+ }, null, 40, W)
150
+ ]),
151
+ _: 1
152
+ }, 8, ["field", "error", "touched"]));
153
+ }
154
+ }), Y = ["id", "name", "disabled", "required"], Z = ["selected"], p = ["value", "selected"], _ = /* @__PURE__ */ h({
155
+ __name: "SelectField",
156
+ props: {
157
+ field: {},
158
+ modelValue: {},
159
+ error: {},
160
+ touched: { type: Boolean }
161
+ },
162
+ emits: ["update:modelValue", "blur"],
163
+ setup(e, { emit: n }) {
164
+ const d = e, m = n;
165
+ function t(l) {
166
+ var $;
167
+ const s = l.target, o = ($ = d.field.options) == null ? void 0 : $.find((g) => String(g.value) === s.value);
168
+ m("update:modelValue", (o == null ? void 0 : o.value) ?? s.value);
169
+ }
170
+ return (l, s) => (r(), b(k, {
171
+ field: e.field,
172
+ error: e.error,
173
+ touched: e.touched
174
+ }, {
175
+ default: v(() => [
176
+ c("select", {
177
+ id: e.field.name,
178
+ name: e.field.name,
179
+ disabled: e.field.disabled === !0,
180
+ required: e.field.required,
181
+ class: "vfs-select",
182
+ onChange: t,
183
+ onBlur: s[0] || (s[0] = (o) => m("blur"))
184
+ }, [
185
+ c("option", {
186
+ value: "",
187
+ disabled: "",
188
+ selected: e.modelValue === null || e.modelValue === void 0 || e.modelValue === ""
189
+ }, y(e.field.placeholder ?? "Select an option"), 9, Z),
190
+ (r(!0), i(B, null, S(e.field.options, (o) => (r(), i("option", {
191
+ key: String(o.value),
192
+ value: String(o.value),
193
+ selected: e.modelValue === o.value
194
+ }, y(o.label), 9, p))), 128))
195
+ ], 40, Y)
196
+ ]),
197
+ _: 1
198
+ }, 8, ["field", "error", "touched"]));
199
+ }
200
+ }), ee = { class: "vfs-checkbox-label" }, le = ["id", "name", "checked", "disabled", "required"], te = {
201
+ key: 0,
202
+ class: "vfs-checkbox-text"
203
+ }, de = /* @__PURE__ */ h({
204
+ __name: "CheckboxField",
205
+ props: {
206
+ field: {},
207
+ modelValue: { type: Boolean },
208
+ error: {},
209
+ touched: { type: Boolean }
210
+ },
211
+ emits: ["update:modelValue", "blur"],
212
+ setup(e, { emit: n }) {
213
+ const d = n;
214
+ return (m, t) => (r(), b(k, {
215
+ field: { ...e.field, label: void 0 },
216
+ error: e.error,
217
+ touched: e.touched
218
+ }, {
219
+ default: v(() => [
220
+ c("label", ee, [
221
+ c("input", {
222
+ id: e.field.name,
223
+ type: "checkbox",
224
+ name: e.field.name,
225
+ checked: e.modelValue,
226
+ disabled: e.field.disabled === !0,
227
+ required: e.field.required,
228
+ class: "vfs-checkbox",
229
+ onChange: t[0] || (t[0] = (l) => d("update:modelValue", l.target.checked)),
230
+ onBlur: t[1] || (t[1] = (l) => d("blur"))
231
+ }, null, 40, le),
232
+ e.field.label ? (r(), i("span", te, y(e.field.label), 1)) : V("", !0)
233
+ ])
234
+ ]),
235
+ _: 1
236
+ }, 8, ["field", "error", "touched"]));
237
+ }
238
+ }), ae = ["aria-labelledby"], re = ["name", "value", "checked", "disabled", "onChange"], ue = /* @__PURE__ */ h({
239
+ __name: "RadioField",
240
+ props: {
241
+ field: {},
242
+ modelValue: {},
243
+ error: {},
244
+ touched: { type: Boolean }
245
+ },
246
+ emits: ["update:modelValue", "blur"],
247
+ setup(e, { emit: n }) {
248
+ const d = n;
249
+ return (m, t) => (r(), b(k, {
250
+ field: e.field,
251
+ error: e.error,
252
+ touched: e.touched
253
+ }, {
254
+ default: v(() => [
255
+ c("div", {
256
+ class: "vfs-radio-group",
257
+ role: "radiogroup",
258
+ "aria-labelledby": e.field.name + "-label"
259
+ }, [
260
+ (r(!0), i(B, null, S(e.field.options, (l) => (r(), i("label", {
261
+ key: String(l.value),
262
+ class: "vfs-radio-label"
263
+ }, [
264
+ c("input", {
265
+ type: "radio",
266
+ name: e.field.name,
267
+ value: String(l.value),
268
+ checked: e.modelValue === l.value,
269
+ disabled: e.field.disabled === !0,
270
+ class: "vfs-radio",
271
+ onChange: (s) => d("update:modelValue", l.value),
272
+ onBlur: t[0] || (t[0] = (s) => d("blur"))
273
+ }, null, 40, re),
274
+ N(" " + y(l.label), 1)
275
+ ]))), 128))
276
+ ], 8, ae)
277
+ ]),
278
+ _: 1
279
+ }, 8, ["field", "error", "touched"]));
280
+ }
281
+ }), ne = ["id", "name", "value", "disabled", "required"], oe = /* @__PURE__ */ h({
282
+ __name: "DateField",
283
+ props: {
284
+ field: {},
285
+ modelValue: {},
286
+ error: {},
287
+ touched: { type: Boolean }
288
+ },
289
+ emits: ["update:modelValue", "blur"],
290
+ setup(e, { emit: n }) {
291
+ const d = n;
292
+ return (m, t) => (r(), b(k, {
293
+ field: e.field,
294
+ error: e.error,
295
+ touched: e.touched
296
+ }, {
297
+ default: v(() => [
298
+ c("input", {
299
+ id: e.field.name,
300
+ type: "date",
301
+ name: e.field.name,
302
+ value: e.modelValue,
303
+ disabled: e.field.disabled === !0,
304
+ required: e.field.required,
305
+ class: "vfs-input",
306
+ onInput: t[0] || (t[0] = (l) => d("update:modelValue", l.target.value)),
307
+ onBlur: t[1] || (t[1] = (l) => d("blur"))
308
+ }, null, 40, ne)
309
+ ]),
310
+ _: 1
311
+ }, 8, ["field", "error", "touched"]));
312
+ }
313
+ }), ie = {
314
+ key: 1,
315
+ class: "vfs-group"
316
+ }, se = { key: 0 }, me = ["disabled"], be = /* @__PURE__ */ h({
317
+ __name: "FormRenderer",
318
+ props: {
319
+ form: {},
320
+ components: {},
321
+ submitLabel: {}
322
+ },
323
+ emits: ["submit"],
324
+ setup(e, { emit: n }) {
325
+ const d = e, m = n, t = {
326
+ text: R,
327
+ email: R,
328
+ number: Q,
329
+ textarea: X,
330
+ select: _,
331
+ checkbox: de,
332
+ radio: ue,
333
+ date: oe
334
+ };
335
+ function l(u) {
336
+ var f;
337
+ return ((f = d.components) == null ? void 0 : f[u]) ?? t[u] ?? null;
338
+ }
339
+ function s(u) {
340
+ return A(d.form.values.value, u.name);
341
+ }
342
+ function o(u, f) {
343
+ d.form.setField(u.name, f);
344
+ }
345
+ function $(u) {
346
+ var x;
347
+ const f = d.form;
348
+ (x = f.touchField) == null || x.call(f, u.name);
349
+ }
350
+ function g(u) {
351
+ return d.form.errors.value[u.name] ?? [];
352
+ }
353
+ function C(u) {
354
+ return d.form.touched.value[u.name] ?? !1;
355
+ }
356
+ const T = U(
357
+ () => d.form.fields.value.filter((u) => u.visible !== !1)
358
+ );
359
+ async function D(u) {
360
+ u.preventDefault(), await d.form.submit(), m("submit");
361
+ }
362
+ return (u, f) => {
363
+ const x = z("FormRenderer", !0);
364
+ return r(), i("form", {
365
+ class: "vfs-form",
366
+ novalidate: "",
367
+ onSubmit: D
368
+ }, [
369
+ (r(!0), i(B, null, S(T.value, (a) => (r(), i(B, {
370
+ key: a.name
371
+ }, [
372
+ u.$slots[`field-${a.name}`] ? F(u.$slots, `field-${a.name}`, {
373
+ key: 0,
374
+ field: a,
375
+ value: s(a),
376
+ error: g(a),
377
+ touched: C(a),
378
+ setValue: (q) => o(a, q),
379
+ touch: () => $(a)
380
+ }) : a.type === "group" ? (r(), i("fieldset", ie, [
381
+ a.label ? (r(), i("legend", se, y(a.label), 1)) : V("", !0),
382
+ a.fields ? (r(), b(x, {
383
+ key: 1,
384
+ form: e.form,
385
+ components: e.components
386
+ }, null, 8, ["form", "components"])) : V("", !0)
387
+ ])) : l(a.type) ? (r(), b(M(l(a.type)), {
388
+ key: 2,
389
+ field: a,
390
+ "model-value": s(a),
391
+ error: g(a),
392
+ touched: C(a),
393
+ "onUpdate:modelValue": (q) => o(a, q),
394
+ onBlur: (q) => $(a)
395
+ }, P({ _: 2 }, [
396
+ u.$slots[`label-${a.name}`] ? {
397
+ name: "label",
398
+ fn: v(() => [
399
+ F(u.$slots, `label-${a.name}`, { field: a })
400
+ ]),
401
+ key: "0"
402
+ } : void 0,
403
+ u.$slots[`error-${a.name}`] ? {
404
+ name: "error",
405
+ fn: v(() => [
406
+ F(u.$slots, `error-${a.name}`, {
407
+ field: a,
408
+ error: g(a)
409
+ })
410
+ ]),
411
+ key: "1"
412
+ } : void 0
413
+ ]), 1064, ["field", "model-value", "error", "touched", "onUpdate:modelValue", "onBlur"])) : V("", !0)
414
+ ], 64))), 128)),
415
+ F(u.$slots, "submit", {
416
+ isSubmitting: e.form.isSubmitting.value,
417
+ isValid: e.form.isValid.value
418
+ }, () => [
419
+ c("button", {
420
+ type: "submit",
421
+ disabled: e.form.isSubmitting.value,
422
+ class: "vfs-submit"
423
+ }, y(e.submitLabel ?? "Submit"), 9, me)
424
+ ])
425
+ ], 32);
426
+ };
427
+ }
428
+ });
429
+ export {
430
+ de as CheckboxField,
431
+ oe as DateField,
432
+ be as FormRenderer,
433
+ Q as NumberField,
434
+ ue as RadioField,
435
+ _ as SelectField,
436
+ R as TextField,
437
+ X as TextareaField
438
+ };
package/dist/yup.cjs ADDED
@@ -0,0 +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;
package/dist/yup.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ declare type AsyncValidatorFn = (value: unknown, values: Record<string, unknown>) => Promise<string | null>;
2
+
3
+ declare interface FieldDefinition {
4
+ type: FieldType;
5
+ /** Dot-path for nested fields, e.g. "address.city" */
6
+ name: string;
7
+ label?: string;
8
+ placeholder?: string;
9
+ defaultValue?: unknown;
10
+ required?: boolean;
11
+ /** Static or dynamic disabled state */
12
+ disabled?: boolean | ((values: Record<string, unknown>) => boolean);
13
+ /** Static or dynamic visibility; string is evaluated as expression */
14
+ visible?: boolean | string | ((values: Record<string, unknown>) => boolean);
15
+ validators?: ValidatorFn[];
16
+ asyncValidators?: AsyncValidatorFn[];
17
+ mask?: string | MaskConfig;
18
+ /** For select / radio */
19
+ options?: FieldOption[];
20
+ /** For group and array */
21
+ fields?: FieldDefinition[];
22
+ }
23
+
24
+ declare interface FieldOption {
25
+ label: string;
26
+ value: unknown;
27
+ }
28
+
29
+ declare type FieldType = 'text' | 'number' | 'email' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'date' | 'array' | 'group';
30
+
31
+ declare interface MaskConfig {
32
+ preset?: MaskPreset;
33
+ /** Custom mask pattern: '#' = digit, 'A' = letter, other chars are literals */
34
+ pattern?: string;
35
+ }
36
+
37
+ declare type MaskPreset = 'phone-ru' | 'phone-eu' | 'date' | 'inn' | 'iban';
38
+
39
+ export declare function parseYup(schema: YupSchema): FieldDefinition[];
40
+
41
+ declare type ValidatorFn = (value: unknown, values: Record<string, unknown>) => string | null;
42
+
43
+ declare type YupSchema = any;
44
+
45
+ export { }
package/dist/yup.js ADDED
@@ -0,0 +1,55 @@
1
+ function p(r) {
2
+ switch (r) {
3
+ case "string":
4
+ return "text";
5
+ case "number":
6
+ return "number";
7
+ case "boolean":
8
+ return "checkbox";
9
+ case "array":
10
+ return "array";
11
+ case "object":
12
+ return "group";
13
+ default:
14
+ return "text";
15
+ }
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) => {
20
+ try {
21
+ return r.validateSync(u, { abortEarly: !0 }), null;
22
+ } catch (n) {
23
+ return n && typeof n == "object" && "message" in n ? n.message : "Invalid value";
24
+ }
25
+ }), t;
26
+ }
27
+ function i(r, e) {
28
+ const t = !e.spec.optional && !e.spec.nullable, u = e.spec.label ?? r, n = p(e.type);
29
+ return e.type === "object" && e.fields ? {
30
+ type: "group",
31
+ name: r,
32
+ label: u,
33
+ required: t,
34
+ fields: Object.entries(e.fields).map(
35
+ ([o, l]) => i(`${r}.${o}`, l)
36
+ )
37
+ } : {
38
+ type: n,
39
+ name: r,
40
+ label: u,
41
+ defaultValue: e.spec.default,
42
+ required: t,
43
+ validators: s(e, t)
44
+ };
45
+ }
46
+ function a(r) {
47
+ if (r.type !== "object")
48
+ throw new Error("[vue-form-schema] parseYup expects an object schema");
49
+ return Object.entries(r.fields ?? {}).map(
50
+ ([e, t]) => i(e, t)
51
+ );
52
+ }
53
+ export {
54
+ a as parseYup
55
+ };
package/dist/zod.cjs ADDED
@@ -0,0 +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;
package/dist/zod.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ declare type AsyncValidatorFn = (value: unknown, values: Record<string, unknown>) => Promise<string | null>;
2
+
3
+ declare interface FieldDefinition {
4
+ type: FieldType;
5
+ /** Dot-path for nested fields, e.g. "address.city" */
6
+ name: string;
7
+ label?: string;
8
+ placeholder?: string;
9
+ defaultValue?: unknown;
10
+ required?: boolean;
11
+ /** Static or dynamic disabled state */
12
+ disabled?: boolean | ((values: Record<string, unknown>) => boolean);
13
+ /** Static or dynamic visibility; string is evaluated as expression */
14
+ visible?: boolean | string | ((values: Record<string, unknown>) => boolean);
15
+ validators?: ValidatorFn[];
16
+ asyncValidators?: AsyncValidatorFn[];
17
+ mask?: string | MaskConfig;
18
+ /** For select / radio */
19
+ options?: FieldOption[];
20
+ /** For group and array */
21
+ fields?: FieldDefinition[];
22
+ }
23
+
24
+ declare interface FieldOption {
25
+ label: string;
26
+ value: unknown;
27
+ }
28
+
29
+ declare type FieldType = 'text' | 'number' | 'email' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'date' | 'array' | 'group';
30
+
31
+ declare interface MaskConfig {
32
+ preset?: MaskPreset;
33
+ /** Custom mask pattern: '#' = digit, 'A' = letter, other chars are literals */
34
+ pattern?: string;
35
+ }
36
+
37
+ declare type MaskPreset = 'phone-ru' | 'phone-eu' | 'date' | 'inn' | 'iban';
38
+
39
+ export declare function parseZod(schema: ZodTypeAny): FieldDefinition[];
40
+
41
+ declare type ValidatorFn = (value: unknown, values: Record<string, unknown>) => string | null;
42
+
43
+ declare type ZodTypeAny = any;
44
+
45
+ export { }
package/dist/zod.js ADDED
@@ -0,0 +1,104 @@
1
+ function i(s) {
2
+ var n;
3
+ let e = s._def;
4
+ for (; e.typeName === "ZodOptional" || e.typeName === "ZodNullable" || e.typeName === "ZodDefault"; ) {
5
+ e = ((n = e.innerType) == null ? void 0 : n._def) ?? e;
6
+ break;
7
+ }
8
+ return e.typeName;
9
+ }
10
+ function p(s) {
11
+ switch (i(s)) {
12
+ case "ZodString":
13
+ return "text";
14
+ case "ZodNumber":
15
+ return "number";
16
+ case "ZodBoolean":
17
+ return "checkbox";
18
+ case "ZodArray":
19
+ return "array";
20
+ case "ZodObject":
21
+ return "group";
22
+ case "ZodEnum":
23
+ return "select";
24
+ default:
25
+ return "text";
26
+ }
27
+ }
28
+ function o(s, e) {
29
+ const n = [], u = s._def;
30
+ e && n.push((t) => t == null || t === "" ? "This field is required" : null);
31
+ for (const t of u.checks ?? [])
32
+ switch (t.kind) {
33
+ case "min":
34
+ n.push((r) => typeof r != "string" || r.length >= Number(t.value) ? null : t.message ?? `Minimum length is ${t.value}`);
35
+ break;
36
+ case "max":
37
+ n.push((r) => typeof r != "string" || r.length <= Number(t.value) ? null : t.message ?? `Maximum length is ${t.value}`);
38
+ break;
39
+ case "email":
40
+ n.push((r) => r ? /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(r)) ? null : t.message ?? "Invalid email address" : null);
41
+ break;
42
+ case "url":
43
+ n.push((r) => {
44
+ if (!r) return null;
45
+ try {
46
+ return new URL(String(r)), null;
47
+ } catch {
48
+ return t.message ?? "Invalid URL";
49
+ }
50
+ });
51
+ break;
52
+ case "regex":
53
+ n.push((r) => typeof r != "string" || t.regex.test(r) ? null : t.message ?? "Invalid format");
54
+ break;
55
+ }
56
+ return n.push((t) => {
57
+ var l, a;
58
+ 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
+ }), n;
61
+ }
62
+ function d(s, e) {
63
+ const n = i(e), u = e.isOptional(), t = p(e), r = e._def.description ?? s;
64
+ if (n === "ZodObject" && e._def.shape) {
65
+ const l = e._def.shape();
66
+ return {
67
+ type: "group",
68
+ name: s,
69
+ label: r,
70
+ required: !u,
71
+ fields: Object.entries(l).map(
72
+ ([a, c]) => d(`${s}.${a}`, c)
73
+ )
74
+ };
75
+ }
76
+ if (n === "ZodEnum" && e._def.values) {
77
+ const l = e._def.values;
78
+ return {
79
+ type: "select",
80
+ name: s,
81
+ label: r,
82
+ required: !u,
83
+ options: Object.entries(l).map(([, a]) => ({ label: a, value: a })),
84
+ validators: o(e, !u)
85
+ };
86
+ }
87
+ return {
88
+ type: t,
89
+ name: s,
90
+ label: r,
91
+ required: !u,
92
+ validators: o(e, !u)
93
+ };
94
+ }
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));
101
+ }
102
+ export {
103
+ f as parseZod
104
+ };