@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/index.js ADDED
@@ -0,0 +1,278 @@
1
+ import { watchEffect as T, ref as y, computed as V, onUnmounted as C } from "vue";
2
+ import { g as h, s as x, u as F, e as O, p as D, m as U, d as I, c as W, f as X, h as k, V as _ } from "./MaskEngine-D22m29OM.js";
3
+ import { a as se, b as re, r as ie } from "./MaskEngine-D22m29OM.js";
4
+ const z = /^[\w\s\d.'"[\]()!<>=&|?:+\-*/%]+$/;
5
+ function G(l, n) {
6
+ if (!z.test(l))
7
+ return console.warn(`[vue-form-schema] Blocked unsafe expression: "${l}"`), !0;
8
+ try {
9
+ return !!new Function("values", `"use strict"; return (${l})`)(n);
10
+ } catch {
11
+ return !0;
12
+ }
13
+ }
14
+ class H {
15
+ constructor() {
16
+ this.stopHandle = null;
17
+ }
18
+ /**
19
+ * Start reactively watching values and writing evaluated fields into
20
+ * `resolvedFields`. Also handles clearOnHide side effect.
21
+ */
22
+ start(n, e, t, a) {
23
+ this.stopHandle = T(() => {
24
+ const f = e.value, u = t.value, i = this.evaluateFields(n, f);
25
+ a && this.clearHiddenValues(n, i, f, e, u), t.value = i;
26
+ });
27
+ }
28
+ stop() {
29
+ var n;
30
+ (n = this.stopHandle) == null || n.call(this), this.stopHandle = null;
31
+ }
32
+ /** Recursively evaluate visible/disabled/required for each field */
33
+ evaluateFields(n, e) {
34
+ return n.map((t) => {
35
+ const a = this.resolveBoolean(t.visible, e, !0), f = this.resolveBoolean(t.disabled, e, !1);
36
+ return {
37
+ ...t,
38
+ visible: a,
39
+ disabled: f,
40
+ fields: t.fields ? this.evaluateFields(t.fields, e) : void 0
41
+ };
42
+ });
43
+ }
44
+ resolveBoolean(n, e, t) {
45
+ return n === void 0 ? t : typeof n == "boolean" ? n : typeof n == "function" ? n(e) : typeof n == "string" ? G(n, e) : t;
46
+ }
47
+ clearHiddenValues(n, e, t, a, f) {
48
+ for (let u = 0; u < n.length; u++) {
49
+ const i = n[u], p = e[u], r = this.wasVisible(f, i.name), o = p.visible;
50
+ if (r && !o) {
51
+ const m = h(t, i.name), b = i.defaultValue ?? null;
52
+ m !== b && (a.value = x(a.value, i.name, b));
53
+ }
54
+ i.fields && p.fields && this.clearHiddenValues(i.fields, p.fields, t, a, f);
55
+ }
56
+ }
57
+ wasVisible(n, e) {
58
+ const t = n.find((a) => a.name === e);
59
+ return t ? t.visible !== !1 : !0;
60
+ }
61
+ }
62
+ function te(l, n) {
63
+ return new H().evaluateFields(l, n);
64
+ }
65
+ function K(l, n, e) {
66
+ switch (l) {
67
+ case "required":
68
+ return e ? (t, a) => k(t) ? e : null : k;
69
+ case "minLength":
70
+ return X(Number(n), e);
71
+ case "maxLength":
72
+ return W(Number(n), e);
73
+ case "min":
74
+ return I(Number(n), e);
75
+ case "max":
76
+ return U(Number(n), e);
77
+ case "pattern":
78
+ return D(new RegExp(String(n)), e);
79
+ case "email":
80
+ return e ? (t, a) => O(t) ? e : null : O;
81
+ case "url":
82
+ return e ? (t, a) => F(t) ? e : null : F;
83
+ default:
84
+ return console.warn(`[vue-form-schema] Unknown validator rule: "${l}"`), null;
85
+ }
86
+ }
87
+ function N(l) {
88
+ const n = [];
89
+ for (const e of l.validators ?? []) {
90
+ const t = K(e.rule, e.value, e.message);
91
+ t && n.push(t);
92
+ }
93
+ return {
94
+ type: l.type,
95
+ name: l.name,
96
+ label: l.label,
97
+ placeholder: l.placeholder,
98
+ defaultValue: l.default,
99
+ required: l.required,
100
+ disabled: l.disabled,
101
+ visible: l.visible,
102
+ mask: l.mask,
103
+ options: l.options,
104
+ validators: n.length ? n : void 0,
105
+ fields: l.fields ? l.fields.map(N) : void 0
106
+ };
107
+ }
108
+ function Q(l) {
109
+ return l.map(N);
110
+ }
111
+ function R(l) {
112
+ if (!Array.isArray(l) || l.length === 0) return !1;
113
+ for (const n of l) {
114
+ const e = n.validators;
115
+ if (Array.isArray(e) && e.some((t) => typeof t == "function"))
116
+ return !1;
117
+ }
118
+ return l.some((n) => {
119
+ const e = n;
120
+ if ("default" in e) return !0;
121
+ const t = e.validators;
122
+ return Array.isArray(t) && t.length > 0 && typeof t[0] == "object" && t[0] !== null && "rule" in t[0];
123
+ });
124
+ }
125
+ function Y(l) {
126
+ return R(l) ? Q(l) : l;
127
+ }
128
+ function g(l, n = {}) {
129
+ const e = {};
130
+ for (const t of l)
131
+ if (t.type === "group" && t.fields) {
132
+ const a = g(t.fields, n);
133
+ Object.assign(e, a);
134
+ } else if (t.type === "array") {
135
+ const a = h(n, t.name);
136
+ e[t.name] = a ?? t.defaultValue ?? [];
137
+ } else {
138
+ const a = h(n, t.name);
139
+ e[t.name] = a !== void 0 ? a : t.defaultValue ?? null;
140
+ }
141
+ for (const [t, a] of Object.entries(n))
142
+ t in e || (e[t] = a);
143
+ return e;
144
+ }
145
+ function ne(l) {
146
+ const {
147
+ schema: n,
148
+ initialValues: e = {},
149
+ validateOn: t = "blur",
150
+ clearOnHide: a = !1,
151
+ onSubmit: f
152
+ } = l, u = Y(n), i = new _(), p = new H(), r = y(
153
+ g(u, e)
154
+ ), o = y({}), m = y({}), b = y(!1), v = y(u);
155
+ p.start(u, r, v, a ?? !1);
156
+ const S = V(() => v.value), L = V(() => {
157
+ const s = g(u, e);
158
+ return JSON.stringify(r.value) !== JSON.stringify(s);
159
+ }), j = V(() => {
160
+ const s = i.validateAll(v.value, r.value);
161
+ return Object.values(s).every((c) => c.length === 0);
162
+ });
163
+ function E(s) {
164
+ if (s) {
165
+ const c = i.validateField(
166
+ s,
167
+ h(r.value, s.name),
168
+ r.value
169
+ );
170
+ o.value = { ...o.value, [s.name]: c }, i.validateAsync(
171
+ s,
172
+ h(r.value, s.name),
173
+ r.value,
174
+ (d, P) => {
175
+ o.value = {
176
+ ...o.value,
177
+ [d]: [...o.value[d] ?? [], ...P]
178
+ };
179
+ }
180
+ );
181
+ } else
182
+ o.value = i.validateAll(
183
+ v.value,
184
+ r.value
185
+ );
186
+ }
187
+ function q(s, c) {
188
+ if (r.value = x(
189
+ r.value,
190
+ s,
191
+ c
192
+ ), t === "input") {
193
+ const d = A(v.value, s);
194
+ d && E(d);
195
+ }
196
+ }
197
+ function J(s) {
198
+ return h(r.value, s);
199
+ }
200
+ function $(s) {
201
+ if (m.value = { ...m.value, [s]: !0 }, t === "blur") {
202
+ const c = A(v.value, s);
203
+ c && E(c);
204
+ }
205
+ }
206
+ async function w() {
207
+ const s = {};
208
+ for (const d of v.value) B(d, s);
209
+ if (m.value = s, o.value = i.validateAll(
210
+ v.value,
211
+ r.value
212
+ ), !Object.values(o.value).some((d) => d.length > 0)) {
213
+ b.value = !0;
214
+ try {
215
+ await (f == null ? void 0 : f(r.value));
216
+ } finally {
217
+ b.value = !1;
218
+ }
219
+ }
220
+ }
221
+ function M(s) {
222
+ const c = s ?? e;
223
+ r.value = g(
224
+ u,
225
+ c ?? {}
226
+ ), o.value = {}, m.value = {}, b.value = !1;
227
+ }
228
+ return C(() => {
229
+ p.stop(), i.destroy();
230
+ }), {
231
+ fields: S,
232
+ values: r,
233
+ errors: o,
234
+ touched: m,
235
+ isDirty: L,
236
+ isValid: j,
237
+ isSubmitting: b,
238
+ submit: w,
239
+ reset: M,
240
+ setField: q,
241
+ getField: J,
242
+ // expose touch for FormRenderer
243
+ // @ts-expect-error - internal
244
+ touchField: $
245
+ };
246
+ }
247
+ function A(l, n) {
248
+ for (const e of l) {
249
+ if (e.name === n) return e;
250
+ if (e.fields) {
251
+ const t = A(e.fields, n);
252
+ if (t) return t;
253
+ }
254
+ }
255
+ }
256
+ function B(l, n = {}) {
257
+ return n[l.name] = !0, l.fields && l.fields.forEach((e) => B(e, n)), n;
258
+ }
259
+ export {
260
+ H as ConditionEvaluator,
261
+ _ as ValidationEngine,
262
+ se as applyMask,
263
+ re as bindMask,
264
+ O as email,
265
+ te as evaluateFieldConditions,
266
+ h as getByPath,
267
+ U as max,
268
+ W as maxLength,
269
+ I as min,
270
+ X as minLength,
271
+ Q as parseJSON,
272
+ D as pattern,
273
+ ie as removeMask,
274
+ k as required,
275
+ x as setByPath,
276
+ F as url,
277
+ ne as useForm
278
+ };
@@ -0,0 +1,3 @@
1
+ import type { FieldDefinition, JSONSchema } from '../core/types';
2
+ export declare function parseJSON(schema: JSONSchema): FieldDefinition[];
3
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/parsers/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAgC,MAAM,eAAe,CAAA;AA4E9F,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,EAAE,CAE/D"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Yup adapter — subentry-point 'vue-form-schema/yup'
3
+ * Yup is a peer dependency; this file does a lazy import so the core bundle
4
+ * is not bloated when Yup is not used.
5
+ */
6
+ import type { FieldDefinition } from '../core/types';
7
+ type YupSchema = any;
8
+ export declare function parseYup(schema: YupSchema): FieldDefinition[];
9
+ export {};
10
+ //# sourceMappingURL=yup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yup.d.ts","sourceRoot":"","sources":["../../src/parsers/yup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,eAAe,CAAA;AAGjE,KAAK,SAAS,GAAG,GAAG,CAAA;AAsEpB,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,eAAe,EAAE,CAO7D"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Zod adapter — subentry-point 'vue-form-schema/zod'
3
+ * Zod is a peer dependency; this file does a lazy import so the core bundle
4
+ * is not bloated when Zod is not used.
5
+ */
6
+ import type { FieldDefinition } from '../core/types';
7
+ type ZodTypeAny = any;
8
+ export declare function parseZod(schema: ZodTypeAny): FieldDefinition[];
9
+ export {};
10
+ //# sourceMappingURL=zod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../../src/parsers/zod.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,eAAe,CAAA;AAMjE,KAAK,UAAU,GAAG,GAAG,CAAA;AA8HrB,wBAAgB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,eAAe,EAAE,CAM9D"}
@@ -0,0 +1,9 @@
1
+ export { default as FormRenderer } from './FormRenderer.vue';
2
+ export { default as TextField } from './fields/TextField.vue';
3
+ export { default as NumberField } from './fields/NumberField.vue';
4
+ export { default as TextareaField } from './fields/TextareaField.vue';
5
+ export { default as SelectField } from './fields/SelectField.vue';
6
+ export { default as CheckboxField } from './fields/CheckboxField.vue';
7
+ export { default as RadioField } from './fields/RadioField.vue';
8
+ export { default as DateField } from './fields/DateField.vue';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,wBAAwB,CAAA"}
package/dist/ui.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),V=require("./MaskEngine-hd5xHed7.cjs"),N=["for"],q={key:0,class:"vfs-field__required","aria-hidden":"true"},D={key:1,class:"vfs-field__errors",role:"alert"},f=e.defineComponent({__name:"BaseField",props:{field:{},error:{},touched:{type:Boolean}},setup(t){const d=t;return(n,c)=>{var o,l;return e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["vfs-field",[`vfs-field--${d.field.type}`,{"vfs-field--error":t.touched&&((o=t.error)==null?void 0:o.length)}]])},[d.field.label?(e.openBlock(),e.createElementBlock("label",{key:0,for:d.field.name,class:"vfs-field__label"},[e.createTextVNode(e.toDisplayString(d.field.label)+" ",1),d.field.required?(e.openBlock(),e.createElementBlock("span",q,"*")):e.createCommentVNode("",!0)],8,N)):e.createCommentVNode("",!0),e.renderSlot(n.$slots,"default"),t.touched&&((l=t.error)!=null&&l.length)?(e.openBlock(),e.createElementBlock("ul",D,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.error,(u,i)=>(e.openBlock(),e.createElementBlock("li",{key:i,class:"vfs-field__error"},e.toDisplayString(u),1))),128))])):e.createCommentVNode("",!0)],2)}}}),w=["id","type","name","value","placeholder","disabled","required"],k=e.defineComponent({__name:"TextField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=t,c=d,o=e.ref(null);let l=null;e.onMounted(()=>{o.value&&n.field.mask&&(l=V.bindMask(o.value,n.field.mask))}),e.onUnmounted(()=>l==null?void 0:l());function u(i){c("update:modelValue",i.target.value)}return(i,s)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,ref_key:"inputRef",ref:o,type:t.field.type==="email"?"email":"text",name:t.field.name,value:t.modelValue,placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:u,onBlur:s[0]||(s[0]=b=>c("blur"))},null,40,w)]),_:1},8,["field","error","touched"]))}}),p=["id","name","value","placeholder","disabled","required"],y=e.defineComponent({__name:"NumberField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;function c(o){const l=o.target.value;n("update:modelValue",l===""?null:Number(l))}return(o,l)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,type:"number",name:t.field.name,value:t.modelValue??"",placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:c,onBlur:l[0]||(l[0]=u=>n("blur"))},null,40,p)]),_:1},8,["field","error","touched"]))}}),R=["id","name","value","placeholder","disabled","required"],$=e.defineComponent({__name:"TextareaField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;return(c,o)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("textarea",{id:t.field.name,name:t.field.name,value:t.modelValue,placeholder:t.field.placeholder,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-textarea",onInput:o[0]||(o[0]=l=>n("update:modelValue",l.target.value)),onBlur:o[1]||(o[1]=l=>n("blur"))},null,40,R)]),_:1},8,["field","error","touched"]))}}),T=["id","name","disabled","required"],L=["selected"],I=["value","selected"],g=e.defineComponent({__name:"SelectField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=t,c=d;function o(l){var s;const u=l.target,i=(s=n.field.options)==null?void 0:s.find(b=>String(b.value)===u.value);c("update:modelValue",(i==null?void 0:i.value)??u.value)}return(l,u)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("select",{id:t.field.name,name:t.field.name,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-select",onChange:o,onBlur:u[0]||(u[0]=i=>c("blur"))},[e.createElementVNode("option",{value:"",disabled:"",selected:t.modelValue===null||t.modelValue===void 0||t.modelValue===""},e.toDisplayString(t.field.placeholder??"Select an option"),9,L),(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.field.options,i=>(e.openBlock(),e.createElementBlock("option",{key:String(i.value),value:String(i.value),selected:t.modelValue===i.value},e.toDisplayString(i.label),9,I))),128))],40,T)]),_:1},8,["field","error","touched"]))}}),M={class:"vfs-checkbox-label"},U=["id","name","checked","disabled","required"],P={key:0,class:"vfs-checkbox-text"},C=e.defineComponent({__name:"CheckboxField",props:{field:{},modelValue:{type:Boolean},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;return(c,o)=>(e.openBlock(),e.createBlock(f,{field:{...t.field,label:void 0},error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("label",M,[e.createElementVNode("input",{id:t.field.name,type:"checkbox",name:t.field.name,checked:t.modelValue,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-checkbox",onChange:o[0]||(o[0]=l=>n("update:modelValue",l.target.checked)),onBlur:o[1]||(o[1]=l=>n("blur"))},null,40,U),t.field.label?(e.openBlock(),e.createElementBlock("span",P,e.toDisplayString(t.field.label),1)):e.createCommentVNode("",!0)])]),_:1},8,["field","error","touched"]))}}),j=["aria-labelledby"],z=["name","value","checked","disabled","onChange"],x=e.defineComponent({__name:"RadioField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;return(c,o)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("div",{class:"vfs-radio-group",role:"radiogroup","aria-labelledby":t.field.name+"-label"},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.field.options,l=>(e.openBlock(),e.createElementBlock("label",{key:String(l.value),class:"vfs-radio-label"},[e.createElementVNode("input",{type:"radio",name:t.field.name,value:String(l.value),checked:t.modelValue===l.value,disabled:t.field.disabled===!0,class:"vfs-radio",onChange:u=>n("update:modelValue",l.value),onBlur:o[0]||(o[0]=u=>n("blur"))},null,40,z),e.createTextVNode(" "+e.toDisplayString(l.label),1)]))),128))],8,j)]),_:1},8,["field","error","touched"]))}}),O=["id","name","value","disabled","required"],E=e.defineComponent({__name:"DateField",props:{field:{},modelValue:{},error:{},touched:{type:Boolean}},emits:["update:modelValue","blur"],setup(t,{emit:d}){const n=d;return(c,o)=>(e.openBlock(),e.createBlock(f,{field:t.field,error:t.error,touched:t.touched},{default:e.withCtx(()=>[e.createElementVNode("input",{id:t.field.name,type:"date",name:t.field.name,value:t.modelValue,disabled:t.field.disabled===!0,required:t.field.required,class:"vfs-input",onInput:o[0]||(o[0]=l=>n("update:modelValue",l.target.value)),onBlur:o[1]||(o[1]=l=>n("blur"))},null,40,O)]),_:1},8,["field","error","touched"]))}}),A={key:1,class:"vfs-group"},G={key:0},H=["disabled"],J=e.defineComponent({__name:"FormRenderer",props:{form:{},components:{},submitLabel:{}},emits:["submit"],setup(t,{emit:d}){const n=t,c=d,o={text:k,email:k,number:y,textarea:$,select:g,checkbox:C,radio:x,date:E};function l(a){var m;return((m=n.components)==null?void 0:m[a])??o[a]??null}function u(a){return V.getByPath(n.form.values.value,a.name)}function i(a,m){n.form.setField(a.name,m)}function s(a){var v;const m=n.form;(v=m.touchField)==null||v.call(m,a.name)}function b(a){return n.form.errors.value[a.name]??[]}function B(a){return n.form.touched.value[a.name]??!1}const S=e.computed(()=>n.form.fields.value.filter(a=>a.visible!==!1));async function F(a){a.preventDefault(),await n.form.submit(),c("submit")}return(a,m)=>{const v=e.resolveComponent("FormRenderer",!0);return e.openBlock(),e.createElementBlock("form",{class:"vfs-form",novalidate:"",onSubmit:F},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(S.value,r=>(e.openBlock(),e.createElementBlock(e.Fragment,{key:r.name},[a.$slots[`field-${r.name}`]?e.renderSlot(a.$slots,`field-${r.name}`,{key:0,field:r,value:u(r),error:b(r),touched:B(r),setValue:h=>i(r,h),touch:()=>s(r)}):r.type==="group"?(e.openBlock(),e.createElementBlock("fieldset",A,[r.label?(e.openBlock(),e.createElementBlock("legend",G,e.toDisplayString(r.label),1)):e.createCommentVNode("",!0),r.fields?(e.openBlock(),e.createBlock(v,{key:1,form:t.form,components:t.components},null,8,["form","components"])):e.createCommentVNode("",!0)])):l(r.type)?(e.openBlock(),e.createBlock(e.resolveDynamicComponent(l(r.type)),{key:2,field:r,"model-value":u(r),error:b(r),touched:B(r),"onUpdate:modelValue":h=>i(r,h),onBlur:h=>s(r)},e.createSlots({_:2},[a.$slots[`label-${r.name}`]?{name:"label",fn:e.withCtx(()=>[e.renderSlot(a.$slots,`label-${r.name}`,{field:r})]),key:"0"}:void 0,a.$slots[`error-${r.name}`]?{name:"error",fn:e.withCtx(()=>[e.renderSlot(a.$slots,`error-${r.name}`,{field:r,error:b(r)})]),key:"1"}:void 0]),1064,["field","model-value","error","touched","onUpdate:modelValue","onBlur"])):e.createCommentVNode("",!0)],64))),128)),e.renderSlot(a.$slots,"submit",{isSubmitting:t.form.isSubmitting.value,isValid:t.form.isValid.value},()=>[e.createElementVNode("button",{type:"submit",disabled:t.form.isSubmitting.value,class:"vfs-submit"},e.toDisplayString(t.submitLabel??"Submit"),9,H)])],32)}}});exports.CheckboxField=C;exports.DateField=E;exports.FormRenderer=J;exports.NumberField=y;exports.RadioField=x;exports.SelectField=g;exports.TextField=k;exports.TextareaField=$;
package/dist/ui.d.ts ADDED
@@ -0,0 +1,324 @@
1
+ import { Component } from 'vue';
2
+ import { ComponentOptionsMixin } from 'vue';
3
+ import { ComponentProvideOptions } from 'vue';
4
+ import { ComputedRef } from 'vue';
5
+ import { DefineComponent } from 'vue';
6
+ import { ExtractPropTypes } from 'vue';
7
+ import { PropType } from 'vue';
8
+ import { PublicProps } from 'vue';
9
+ import { Ref } from 'vue';
10
+
11
+ declare const __VLS_component: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
12
+ form: UseFormReturn;
13
+ /** Override individual field renderers: { text: MyTextInput, ... } */
14
+ components?: Partial<Record<FieldDefinition["type"], Component>>;
15
+ /** Label for the submit button */
16
+ submitLabel?: string;
17
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
18
+ submit: () => void;
19
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
20
+ form: UseFormReturn;
21
+ /** Override individual field renderers: { text: MyTextInput, ... } */
22
+ components?: Partial<Record<FieldDefinition["type"], Component>>;
23
+ /** Label for the submit button */
24
+ submitLabel?: string;
25
+ }>>> & Readonly<{
26
+ onSubmit?: (() => any) | undefined;
27
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
28
+
29
+ declare type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
30
+
31
+ declare type __VLS_NonUndefinedable_2<T> = T extends undefined ? never : T;
32
+
33
+ declare type __VLS_NonUndefinedable_3<T> = T extends undefined ? never : T;
34
+
35
+ declare type __VLS_NonUndefinedable_4<T> = T extends undefined ? never : T;
36
+
37
+ declare type __VLS_NonUndefinedable_5<T> = T extends undefined ? never : T;
38
+
39
+ declare type __VLS_NonUndefinedable_6<T> = T extends undefined ? never : T;
40
+
41
+ declare type __VLS_NonUndefinedable_7<T> = T extends undefined ? never : T;
42
+
43
+ declare type __VLS_NonUndefinedable_8<T> = T extends undefined ? never : T;
44
+
45
+ declare function __VLS_template(): Partial<Record<`field-${string}`, (_: {
46
+ field: FieldDefinition;
47
+ value: unknown;
48
+ error: string[];
49
+ touched: boolean;
50
+ setValue: (v: unknown) => void;
51
+ touch: () => void;
52
+ }) => any>> & Partial<Record<`label-${string}`, (_: {
53
+ field: FieldDefinition;
54
+ }) => any>> & Partial<Record<`error-${string}`, (_: {
55
+ field: FieldDefinition;
56
+ error: string[];
57
+ }) => any>> & {
58
+ submit?(_: {
59
+ isSubmitting: boolean;
60
+ isValid: boolean;
61
+ }): any;
62
+ };
63
+
64
+ declare type __VLS_TypePropsToRuntimeProps<T> = {
65
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
66
+ type: PropType<__VLS_NonUndefinedable<T[K]>>;
67
+ } : {
68
+ type: PropType<T[K]>;
69
+ required: true;
70
+ };
71
+ };
72
+
73
+ declare type __VLS_TypePropsToRuntimeProps_2<T> = {
74
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
75
+ type: PropType<__VLS_NonUndefinedable_2<T[K]>>;
76
+ } : {
77
+ type: PropType<T[K]>;
78
+ required: true;
79
+ };
80
+ };
81
+
82
+ declare type __VLS_TypePropsToRuntimeProps_3<T> = {
83
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
84
+ type: PropType<__VLS_NonUndefinedable_3<T[K]>>;
85
+ } : {
86
+ type: PropType<T[K]>;
87
+ required: true;
88
+ };
89
+ };
90
+
91
+ declare type __VLS_TypePropsToRuntimeProps_4<T> = {
92
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
93
+ type: PropType<__VLS_NonUndefinedable_4<T[K]>>;
94
+ } : {
95
+ type: PropType<T[K]>;
96
+ required: true;
97
+ };
98
+ };
99
+
100
+ declare type __VLS_TypePropsToRuntimeProps_5<T> = {
101
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
102
+ type: PropType<__VLS_NonUndefinedable_5<T[K]>>;
103
+ } : {
104
+ type: PropType<T[K]>;
105
+ required: true;
106
+ };
107
+ };
108
+
109
+ declare type __VLS_TypePropsToRuntimeProps_6<T> = {
110
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
111
+ type: PropType<__VLS_NonUndefinedable_6<T[K]>>;
112
+ } : {
113
+ type: PropType<T[K]>;
114
+ required: true;
115
+ };
116
+ };
117
+
118
+ declare type __VLS_TypePropsToRuntimeProps_7<T> = {
119
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
120
+ type: PropType<__VLS_NonUndefinedable_7<T[K]>>;
121
+ } : {
122
+ type: PropType<T[K]>;
123
+ required: true;
124
+ };
125
+ };
126
+
127
+ declare type __VLS_TypePropsToRuntimeProps_8<T> = {
128
+ [K in keyof T]-?: {} extends Pick<T, K> ? {
129
+ type: PropType<__VLS_NonUndefinedable_8<T[K]>>;
130
+ } : {
131
+ type: PropType<T[K]>;
132
+ required: true;
133
+ };
134
+ };
135
+
136
+ declare type __VLS_WithTemplateSlots<T, S> = T & {
137
+ new (): {
138
+ $slots: S;
139
+ };
140
+ };
141
+
142
+ declare type AsyncValidatorFn = (value: unknown, values: Record<string, unknown>) => Promise<string | null>;
143
+
144
+ export declare const CheckboxField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_6<{
145
+ field: FieldDefinition;
146
+ modelValue: boolean;
147
+ error?: string[];
148
+ touched?: boolean;
149
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
150
+ blur: () => void;
151
+ "update:modelValue": (value: boolean) => void;
152
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_6<{
153
+ field: FieldDefinition;
154
+ modelValue: boolean;
155
+ error?: string[];
156
+ touched?: boolean;
157
+ }>>> & Readonly<{
158
+ onBlur?: (() => any) | undefined;
159
+ "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
160
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
161
+
162
+ export declare const DateField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_8<{
163
+ field: FieldDefinition;
164
+ modelValue: string;
165
+ error?: string[];
166
+ touched?: boolean;
167
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
168
+ blur: () => void;
169
+ "update:modelValue": (value: string) => void;
170
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_8<{
171
+ field: FieldDefinition;
172
+ modelValue: string;
173
+ error?: string[];
174
+ touched?: boolean;
175
+ }>>> & Readonly<{
176
+ onBlur?: (() => any) | undefined;
177
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
178
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
179
+
180
+ declare interface FieldDefinition {
181
+ type: FieldType;
182
+ /** Dot-path for nested fields, e.g. "address.city" */
183
+ name: string;
184
+ label?: string;
185
+ placeholder?: string;
186
+ defaultValue?: unknown;
187
+ required?: boolean;
188
+ /** Static or dynamic disabled state */
189
+ disabled?: boolean | ((values: Record<string, unknown>) => boolean);
190
+ /** Static or dynamic visibility; string is evaluated as expression */
191
+ visible?: boolean | string | ((values: Record<string, unknown>) => boolean);
192
+ validators?: ValidatorFn[];
193
+ asyncValidators?: AsyncValidatorFn[];
194
+ mask?: string | MaskConfig;
195
+ /** For select / radio */
196
+ options?: FieldOption[];
197
+ /** For group and array */
198
+ fields?: FieldDefinition[];
199
+ }
200
+
201
+ declare interface FieldOption {
202
+ label: string;
203
+ value: unknown;
204
+ }
205
+
206
+ declare type FieldType = 'text' | 'number' | 'email' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'date' | 'array' | 'group';
207
+
208
+ export declare const FormRenderer: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
209
+
210
+ declare interface MaskConfig {
211
+ preset?: MaskPreset;
212
+ /** Custom mask pattern: '#' = digit, 'A' = letter, other chars are literals */
213
+ pattern?: string;
214
+ }
215
+
216
+ declare type MaskPreset = 'phone-ru' | 'phone-eu' | 'date' | 'inn' | 'iban';
217
+
218
+ export declare const NumberField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_3<{
219
+ field: FieldDefinition;
220
+ modelValue: number | null;
221
+ error?: string[];
222
+ touched?: boolean;
223
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
224
+ blur: () => void;
225
+ "update:modelValue": (value: number | null) => void;
226
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_3<{
227
+ field: FieldDefinition;
228
+ modelValue: number | null;
229
+ error?: string[];
230
+ touched?: boolean;
231
+ }>>> & Readonly<{
232
+ onBlur?: (() => any) | undefined;
233
+ "onUpdate:modelValue"?: ((value: number | null) => any) | undefined;
234
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
235
+
236
+ export declare const RadioField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_7<{
237
+ field: FieldDefinition;
238
+ modelValue: unknown;
239
+ error?: string[];
240
+ touched?: boolean;
241
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
242
+ blur: () => void;
243
+ "update:modelValue": (value: unknown) => void;
244
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_7<{
245
+ field: FieldDefinition;
246
+ modelValue: unknown;
247
+ error?: string[];
248
+ touched?: boolean;
249
+ }>>> & Readonly<{
250
+ onBlur?: (() => any) | undefined;
251
+ "onUpdate:modelValue"?: ((value: unknown) => any) | undefined;
252
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
253
+
254
+ export declare const SelectField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_5<{
255
+ field: FieldDefinition;
256
+ modelValue: unknown;
257
+ error?: string[];
258
+ touched?: boolean;
259
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
260
+ blur: () => void;
261
+ "update:modelValue": (value: unknown) => void;
262
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_5<{
263
+ field: FieldDefinition;
264
+ modelValue: unknown;
265
+ error?: string[];
266
+ touched?: boolean;
267
+ }>>> & Readonly<{
268
+ onBlur?: (() => any) | undefined;
269
+ "onUpdate:modelValue"?: ((value: unknown) => any) | undefined;
270
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
271
+
272
+ export declare const TextareaField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_4<{
273
+ field: FieldDefinition;
274
+ modelValue: string;
275
+ error?: string[];
276
+ touched?: boolean;
277
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
278
+ blur: () => void;
279
+ "update:modelValue": (value: string) => void;
280
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_4<{
281
+ field: FieldDefinition;
282
+ modelValue: string;
283
+ error?: string[];
284
+ touched?: boolean;
285
+ }>>> & Readonly<{
286
+ onBlur?: (() => any) | undefined;
287
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
288
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
289
+
290
+ export declare const TextField: DefineComponent<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
291
+ field: FieldDefinition;
292
+ modelValue: string;
293
+ error?: string[];
294
+ touched?: boolean;
295
+ }>>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
296
+ blur: () => void;
297
+ "update:modelValue": (value: string) => void;
298
+ }, string, PublicProps, Readonly<ExtractPropTypes<__VLS_TypePropsToRuntimeProps_2<{
299
+ field: FieldDefinition;
300
+ modelValue: string;
301
+ error?: string[];
302
+ touched?: boolean;
303
+ }>>> & Readonly<{
304
+ onBlur?: (() => any) | undefined;
305
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
306
+ }>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
307
+
308
+ declare interface UseFormReturn<T extends Record<string, unknown> = Record<string, unknown>> {
309
+ fields: ComputedRef<FieldDefinition[]>;
310
+ values: Ref<T>;
311
+ errors: Ref<Record<string, string[]>>;
312
+ touched: Ref<Record<string, boolean>>;
313
+ isDirty: ComputedRef<boolean>;
314
+ isValid: ComputedRef<boolean>;
315
+ isSubmitting: Ref<boolean>;
316
+ submit(): Promise<void>;
317
+ reset(values?: Partial<T>): void;
318
+ setField(path: string, value: unknown): void;
319
+ getField(path: string): unknown;
320
+ }
321
+
322
+ declare type ValidatorFn = (value: unknown, values: Record<string, unknown>) => string | null;
323
+
324
+ export { }