@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
@@ -0,0 +1,157 @@
1
+ const y = (t) => t == null || t === "" || Array.isArray(t) && t.length === 0 ? "This field is required" : null, M = (t, e) => (r) => typeof r != "string" && !Array.isArray(r) || r.length >= t ? null : e ?? `Minimum length is ${t}`, T = (t, e) => (r) => typeof r != "string" && !Array.isArray(r) || r.length <= t ? null : e ?? `Maximum length is ${t}`, v = (t, e) => (r) => {
2
+ const s = Number(r);
3
+ return isNaN(s) || s >= t ? null : e ?? `Minimum value is ${t}`;
4
+ }, x = (t, e) => (r) => {
5
+ const s = Number(r);
6
+ return isNaN(s) || s <= t ? null : e ?? `Maximum value is ${t}`;
7
+ }, I = (t, e) => (r) => typeof r != "string" || t.test(r) ? null : e ?? "Invalid format", b = (t) => t ? /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(t)) ? null : "Invalid email address" : null, E = (t) => {
8
+ if (!t) return null;
9
+ try {
10
+ return new URL(String(t)), null;
11
+ } catch {
12
+ return "Invalid URL";
13
+ }
14
+ };
15
+ class w {
16
+ constructor(e = 300) {
17
+ this.asyncTimers = /* @__PURE__ */ new Map(), this.debounceMs = e;
18
+ }
19
+ /** Run sync validators for a single field; returns list of error messages */
20
+ validateField(e, r, s) {
21
+ const i = [];
22
+ if (e.required) {
23
+ const n = y(r);
24
+ n && i.push(n);
25
+ }
26
+ for (const n of e.validators ?? []) {
27
+ const o = n(r, s);
28
+ o && i.push(o);
29
+ }
30
+ return i;
31
+ }
32
+ /** Run all sync validators across all visible fields */
33
+ validateAll(e, r) {
34
+ const s = {};
35
+ return this.collectErrors(e, r, s), s;
36
+ }
37
+ collectErrors(e, r, s) {
38
+ for (const i of e) {
39
+ const n = p(r, i.name), o = this.validateField(i, n, r);
40
+ o.length && (s[i.name] = o), (i.type === "group" || i.type === "array") && i.fields && this.collectErrors(i.fields, r, s);
41
+ }
42
+ }
43
+ /** Run async validators with debounce; calls onResult when done */
44
+ validateAsync(e, r, s, i) {
45
+ var l;
46
+ if (!((l = e.asyncValidators) != null && l.length)) return;
47
+ const n = this.asyncTimers.get(e.name);
48
+ n && clearTimeout(n);
49
+ const o = setTimeout(async () => {
50
+ const c = (await Promise.all(
51
+ e.asyncValidators.map((u) => u(r, s))
52
+ )).filter((u) => u !== null);
53
+ i(e.name, c), this.asyncTimers.delete(e.name);
54
+ }, this.debounceMs);
55
+ this.asyncTimers.set(e.name, o);
56
+ }
57
+ destroy() {
58
+ for (const e of this.asyncTimers.values()) clearTimeout(e);
59
+ this.asyncTimers.clear();
60
+ }
61
+ }
62
+ function p(t, e) {
63
+ return e.split(".").reduce((r, s) => {
64
+ if (r && typeof r == "object") return r[s];
65
+ }, t);
66
+ }
67
+ function P(t, e, r) {
68
+ const s = e.split("."), i = { ...t };
69
+ let n = i;
70
+ for (let o = 0; o < s.length - 1; o++) {
71
+ const l = s[o];
72
+ n[l] = n[l] && typeof n[l] == "object" ? { ...n[l] } : {}, n = n[l];
73
+ }
74
+ return n[s[s.length - 1]] = r, i;
75
+ }
76
+ const A = {
77
+ "phone-ru": "+7 (###) ###-##-##",
78
+ "phone-eu": "+## (##) ###-##-##",
79
+ date: "##.##.####",
80
+ inn: "############",
81
+ iban: "AA## #### #### #### #### #### ####"
82
+ };
83
+ function m(t) {
84
+ return t.preset ? A[t.preset] : t.pattern ?? "";
85
+ }
86
+ function f(t) {
87
+ return t === "#" || t === "A";
88
+ }
89
+ function h(t, e) {
90
+ return e === "#" ? /\d/.test(t) : e === "A" ? /[a-zA-Z]/.test(t) : !1;
91
+ }
92
+ function d(t, e) {
93
+ const s = m(typeof e == "string" ? { pattern: e } : e);
94
+ if (!s) return t;
95
+ const i = Array.from(t);
96
+ let n = 0, o = -1;
97
+ for (let a = 0; a < s.length && n < i.length; a++) {
98
+ const c = s[a];
99
+ if (f(c)) {
100
+ for (; n < i.length && !h(i[n], c); ) n++;
101
+ n < i.length && (o = a, n++);
102
+ }
103
+ }
104
+ if (o === -1) return "";
105
+ let l = "";
106
+ n = 0;
107
+ for (let a = 0; a <= o; a++) {
108
+ const c = s[a];
109
+ if (f(c)) {
110
+ for (; n < i.length && !h(i[n], c); ) n++;
111
+ n < i.length && (l += c === "A" ? i[n++].toUpperCase() : i[n++]);
112
+ } else
113
+ l += c;
114
+ }
115
+ return l;
116
+ }
117
+ function g(t, e) {
118
+ const s = m(typeof e == "string" ? { pattern: e } : e);
119
+ if (!s) return t;
120
+ const i = [];
121
+ let n = 0;
122
+ for (let o = 0; o < s.length && n < t.length; o++) {
123
+ const l = s[o], a = t[n];
124
+ f(l) ? (i.push(a), n++) : a === l && n++;
125
+ }
126
+ return i.join("");
127
+ }
128
+ function S(t, e) {
129
+ function r() {
130
+ const i = g(t.value, e), n = d(i, e);
131
+ if (t.value !== n) {
132
+ const o = t.selectionStart ?? n.length;
133
+ t.value = n;
134
+ const l = Math.min(o, n.length);
135
+ t.setSelectionRange(l, l);
136
+ }
137
+ }
138
+ t.addEventListener("input", r);
139
+ const s = d(g(t.value, e), e);
140
+ return t.value !== s && s && (t.value = s), () => t.removeEventListener("input", r);
141
+ }
142
+ export {
143
+ w as V,
144
+ d as a,
145
+ S as b,
146
+ T as c,
147
+ v as d,
148
+ b as e,
149
+ M as f,
150
+ p as g,
151
+ y as h,
152
+ x as m,
153
+ I as p,
154
+ g as r,
155
+ P as s,
156
+ E as u
157
+ };
@@ -0,0 +1 @@
1
+ "use strict";const m=t=>t==null||t===""||Array.isArray(t)&&t.length===0?"This field is required":null,A=(t,e)=>r=>typeof r!="string"&&!Array.isArray(r)||r.length>=t?null:e??`Minimum length is ${t}`,M=(t,e)=>r=>typeof r!="string"&&!Array.isArray(r)||r.length<=t?null:e??`Maximum length is ${t}`,v=(t,e)=>r=>{const s=Number(r);return isNaN(s)||s>=t?null:e??`Minimum value is ${t}`},T=(t,e)=>r=>{const s=Number(r);return isNaN(s)||s<=t?null:e??`Maximum value is ${t}`},x=(t,e)=>r=>typeof r!="string"||t.test(r)?null:e??"Invalid format",E=t=>t?/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(t))?null:"Invalid email address":null,I=t=>{if(!t)return null;try{return new URL(String(t)),null}catch{return"Invalid URL"}};class b{constructor(e=300){this.asyncTimers=new Map,this.debounceMs=e}validateField(e,r,s){const i=[];if(e.required){const n=m(r);n&&i.push(n)}for(const n of e.validators??[]){const o=n(r,s);o&&i.push(o)}return i}validateAll(e,r){const s={};return this.collectErrors(e,r,s),s}collectErrors(e,r,s){for(const i of e){const n=y(r,i.name),o=this.validateField(i,n,r);o.length&&(s[i.name]=o),(i.type==="group"||i.type==="array")&&i.fields&&this.collectErrors(i.fields,r,s)}}validateAsync(e,r,s,i){var l;if(!((l=e.asyncValidators)!=null&&l.length))return;const n=this.asyncTimers.get(e.name);n&&clearTimeout(n);const o=setTimeout(async()=>{const c=(await Promise.all(e.asyncValidators.map(u=>u(r,s)))).filter(u=>u!==null);i(e.name,c),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 y(t,e){return e.split(".").reduce((r,s)=>{if(r&&typeof r=="object")return r[s]},t)}function P(t,e,r){const s=e.split("."),i={...t};let n=i;for(let o=0;o<s.length-1;o++){const l=s[o];n[l]=n[l]&&typeof n[l]=="object"?{...n[l]}:{},n=n[l]}return n[s[s.length-1]]=r,i}const w={"phone-ru":"+7 (###) ###-##-##","phone-eu":"+## (##) ###-##-##",date:"##.##.####",inn:"############",iban:"AA## #### #### #### #### #### ####"};function p(t){return t.preset?w[t.preset]:t.pattern??""}function f(t){return t==="#"||t==="A"}function g(t,e){return e==="#"?/\d/.test(t):e==="A"?/[a-zA-Z]/.test(t):!1}function h(t,e){const s=p(typeof e=="string"?{pattern:e}:e);if(!s)return t;const i=Array.from(t);let n=0,o=-1;for(let a=0;a<s.length&&n<i.length;a++){const c=s[a];if(f(c)){for(;n<i.length&&!g(i[n],c);)n++;n<i.length&&(o=a,n++)}}if(o===-1)return"";let l="";n=0;for(let a=0;a<=o;a++){const c=s[a];if(f(c)){for(;n<i.length&&!g(i[n],c);)n++;n<i.length&&(l+=c==="A"?i[n++].toUpperCase():i[n++])}else l+=c}return l}function d(t,e){const s=p(typeof e=="string"?{pattern:e}:e);if(!s)return t;const i=[];let n=0;for(let o=0;o<s.length&&n<t.length;o++){const l=s[o],a=t[n];f(l)?(i.push(a),n++):a===l&&n++}return i.join("")}function L(t,e){function r(){const i=d(t.value,e),n=h(i,e);if(t.value!==n){const o=t.selectionStart??n.length;t.value=n;const l=Math.min(o,n.length);t.setSelectionRange(l,l)}}t.addEventListener("input",r);const s=h(d(t.value,e),e);return t.value!==s&&s&&(t.value=s),()=>t.removeEventListener("input",r)}exports.ValidationEngine=b;exports.applyMask=h;exports.bindMask=L;exports.email=E;exports.getByPath=y;exports.max=T;exports.maxLength=M;exports.min=v;exports.minLength=A;exports.pattern=x;exports.removeMask=d;exports.required=m;exports.setByPath=P;exports.url=I;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ConditionEvaluator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConditionEvaluator.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ConditionEvaluator.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=MaskEngine.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaskEngine.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/MaskEngine.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ValidationEngine.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValidationEngine.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ValidationEngine.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parsers.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/parsers.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=useForm.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useForm.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/useForm.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { type Ref } from 'vue';
2
+ import type { FieldDefinition } from './types';
3
+ export declare class ConditionEvaluator {
4
+ private stopHandle;
5
+ /**
6
+ * Start reactively watching values and writing evaluated fields into
7
+ * `resolvedFields`. Also handles clearOnHide side effect.
8
+ */
9
+ start(rawFields: FieldDefinition[], values: Ref<Record<string, unknown>>, resolvedFields: Ref<FieldDefinition[]>, clearOnHide: boolean): void;
10
+ stop(): void;
11
+ /** Recursively evaluate visible/disabled/required for each field */
12
+ evaluateFields(fields: FieldDefinition[], values: Record<string, unknown>): FieldDefinition[];
13
+ private resolveBoolean;
14
+ private clearHiddenValues;
15
+ private wasVisible;
16
+ }
17
+ export declare function evaluateFieldConditions(fields: FieldDefinition[], values: Record<string, unknown>): FieldDefinition[];
18
+ //# sourceMappingURL=ConditionEvaluator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConditionEvaluator.d.ts","sourceRoot":"","sources":["../../src/core/ConditionEvaluator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAsB9C,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,UAAU,CAA4B;IAE9C;;;OAGG;IACH,KAAK,CACH,SAAS,EAAE,eAAe,EAAE,EAC5B,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACpC,cAAc,EAAE,GAAG,CAAC,eAAe,EAAE,CAAC,EACtC,WAAW,EAAE,OAAO;IAgBtB,IAAI;IAKJ,oEAAoE;IACpE,cAAc,CACZ,MAAM,EAAE,eAAe,EAAE,EACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,eAAe,EAAE;IAiBpB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,iBAAiB;IA2BzB,OAAO,CAAC,UAAU;CAKnB;AAID,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,eAAe,EAAE,EACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,eAAe,EAAE,CAGnB"}
@@ -0,0 +1,21 @@
1
+ import type { MaskConfig } from './types';
2
+ /**
3
+ * Apply mask to a *raw* input (no existing literals).
4
+ * '#' = digit, 'A' = letter (uppercased), other mask chars are literals.
5
+ *
6
+ * Output extends only up to the last successfully filled placeholder —
7
+ * no trailing literals are appended.
8
+ */
9
+ export declare function applyMask(value: string, mask: string | MaskConfig): string;
10
+ /**
11
+ * Remove mask formatting from a *masked* string, returning only the raw chars
12
+ * that were placed in placeholder (#/A) slots.
13
+ * Works positionally: aligns each value character against the pattern.
14
+ */
15
+ export declare function removeMask(value: string, mask: string | MaskConfig): string;
16
+ /**
17
+ * Attach mask handling to a native <input> element.
18
+ * Returns a cleanup function.
19
+ */
20
+ export declare function bindMask(input: HTMLInputElement, mask: string | MaskConfig): () => void;
21
+ //# sourceMappingURL=MaskEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MaskEngine.d.ts","sourceRoot":"","sources":["../../src/core/MaskEngine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,SAAS,CAAA;AA+BrD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAyC1E;AAID;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAwB3E;AAID;;;GAGG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,MAAM,GAAG,UAAU,GACxB,MAAM,IAAI,CAiBZ"}
@@ -0,0 +1,25 @@
1
+ import type { FieldDefinition, ValidatorFn } from './types';
2
+ export declare const required: ValidatorFn;
3
+ export declare const minLength: (min: number, message?: string) => ValidatorFn;
4
+ export declare const maxLength: (max: number, message?: string) => ValidatorFn;
5
+ export declare const min: (minVal: number, message?: string) => ValidatorFn;
6
+ export declare const max: (maxVal: number, message?: string) => ValidatorFn;
7
+ export declare const pattern: (regex: RegExp, message?: string) => ValidatorFn;
8
+ export declare const email: ValidatorFn;
9
+ export declare const url: ValidatorFn;
10
+ export declare class ValidationEngine {
11
+ private asyncTimers;
12
+ private readonly debounceMs;
13
+ constructor(debounceMs?: number);
14
+ /** Run sync validators for a single field; returns list of error messages */
15
+ validateField(field: FieldDefinition, value: unknown, allValues: Record<string, unknown>): string[];
16
+ /** Run all sync validators across all visible fields */
17
+ validateAll(fields: FieldDefinition[], values: Record<string, unknown>): Record<string, string[]>;
18
+ private collectErrors;
19
+ /** Run async validators with debounce; calls onResult when done */
20
+ validateAsync(field: FieldDefinition, value: unknown, allValues: Record<string, unknown>, onResult: (path: string, errors: string[]) => void): void;
21
+ destroy(): void;
22
+ }
23
+ export declare function getByPath(obj: Record<string, unknown>, path: string): unknown;
24
+ export declare function setByPath(obj: Record<string, unknown>, path: string, value: unknown): Record<string, unknown>;
25
+ //# sourceMappingURL=ValidationEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValidationEngine.d.ts","sourceRoot":"","sources":["../../src/core/ValidationEngine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAoB,MAAM,SAAS,CAAA;AAI7E,eAAO,MAAM,QAAQ,EAAE,WAItB,CAAA;AAED,eAAO,MAAM,SAAS,GACnB,KAAK,MAAM,EAAE,UAAU,MAAM,KAAG,WAMhC,CAAA;AAEH,eAAO,MAAM,SAAS,GACnB,KAAK,MAAM,EAAE,UAAU,MAAM,KAAG,WAMhC,CAAA;AAEH,eAAO,MAAM,GAAG,GACb,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,WAKnC,CAAA;AAEH,eAAO,MAAM,GAAG,GACb,QAAQ,MAAM,EAAE,UAAU,MAAM,KAAG,WAKnC,CAAA;AAEH,eAAO,MAAM,OAAO,GACjB,OAAO,MAAM,EAAE,UAAU,MAAM,KAAG,WAIlC,CAAA;AAEH,eAAO,MAAM,KAAK,EAAE,WAInB,CAAA;AAED,eAAO,MAAM,GAAG,EAAE,WAQjB,CAAA;AAID,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,WAAW,CAAmD;IACtE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;gBAEvB,UAAU,SAAM;IAI5B,6EAA6E;IAC7E,aAAa,CACX,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,MAAM,EAAE;IAgBX,wDAAwD;IACxD,WAAW,CACT,MAAM,EAAE,eAAe,EAAE,EACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;IAM3B,OAAO,CAAC,aAAa;IAgBrB,mEAAmE;IACnE,aAAa,CACX,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,GACjD,IAAI;IAkBP,OAAO;CAIR;AAID,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAK7E;AAED,wBAAgB,SAAS,CACvB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,GACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAezB"}
@@ -0,0 +1,76 @@
1
+ export type ValidatorFn = (value: unknown, values: Record<string, unknown>) => string | null;
2
+ export type AsyncValidatorFn = (value: unknown, values: Record<string, unknown>) => Promise<string | null>;
3
+ export type MaskPreset = 'phone-ru' | 'phone-eu' | 'date' | 'inn' | 'iban';
4
+ export interface MaskConfig {
5
+ preset?: MaskPreset;
6
+ /** Custom mask pattern: '#' = digit, 'A' = letter, other chars are literals */
7
+ pattern?: string;
8
+ }
9
+ export interface FieldOption {
10
+ label: string;
11
+ value: unknown;
12
+ }
13
+ export type FieldType = 'text' | 'number' | 'email' | 'select' | 'checkbox' | 'radio' | 'textarea' | 'date' | 'array' | 'group';
14
+ export interface FieldDefinition {
15
+ type: FieldType;
16
+ /** Dot-path for nested fields, e.g. "address.city" */
17
+ name: string;
18
+ label?: string;
19
+ placeholder?: string;
20
+ defaultValue?: unknown;
21
+ required?: boolean;
22
+ /** Static or dynamic disabled state */
23
+ disabled?: boolean | ((values: Record<string, unknown>) => boolean);
24
+ /** Static or dynamic visibility; string is evaluated as expression */
25
+ visible?: boolean | string | ((values: Record<string, unknown>) => boolean);
26
+ validators?: ValidatorFn[];
27
+ asyncValidators?: AsyncValidatorFn[];
28
+ mask?: string | MaskConfig;
29
+ /** For select / radio */
30
+ options?: FieldOption[];
31
+ /** For group and array */
32
+ fields?: FieldDefinition[];
33
+ }
34
+ export interface JSONSchemaField {
35
+ type: FieldType;
36
+ name: string;
37
+ label?: string;
38
+ placeholder?: string;
39
+ default?: unknown;
40
+ required?: boolean;
41
+ disabled?: boolean;
42
+ visible?: boolean | string;
43
+ options?: FieldOption[];
44
+ fields?: JSONSchemaField[];
45
+ mask?: string | MaskConfig;
46
+ validators?: Array<{
47
+ rule: string;
48
+ value?: unknown;
49
+ message?: string;
50
+ }>;
51
+ }
52
+ export type JSONSchema = JSONSchemaField[];
53
+ export type ValidateOn = 'input' | 'blur' | 'submit';
54
+ export interface UseFormConfig<T extends Record<string, unknown> = Record<string, unknown>> {
55
+ schema: FieldDefinition[] | JSONSchema;
56
+ initialValues?: Partial<T>;
57
+ validateOn?: ValidateOn;
58
+ clearOnHide?: boolean;
59
+ onSubmit?: (values: T) => void | Promise<void>;
60
+ }
61
+ import type { ComputedRef, Ref } from 'vue';
62
+ export interface UseFormReturn<T extends Record<string, unknown> = Record<string, unknown>> {
63
+ fields: ComputedRef<FieldDefinition[]>;
64
+ values: Ref<T>;
65
+ errors: Ref<Record<string, string[]>>;
66
+ touched: Ref<Record<string, boolean>>;
67
+ isDirty: ComputedRef<boolean>;
68
+ isValid: ComputedRef<boolean>;
69
+ isSubmitting: Ref<boolean>;
70
+ submit(): Promise<void>;
71
+ reset(values?: Partial<T>): void;
72
+ setField(path: string, value: unknown): void;
73
+ getField(path: string): unknown;
74
+ }
75
+ export type BuiltinRule = 'required' | 'minLength' | 'maxLength' | 'min' | 'max' | 'pattern' | 'email' | 'url';
76
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { UseFormConfig, UseFormReturn } from './types';
2
+ export declare function useForm<T extends Record<string, unknown> = Record<string, unknown>>(config: UseFormConfig<T>): UseFormReturn<T>;
3
+ //# sourceMappingURL=useForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useForm.d.ts","sourceRoot":"","sources":["../../src/core/useForm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAmB,aAAa,EAAE,aAAa,EAAc,MAAM,SAAS,CAAA;AAwExF,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjF,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GACvB,aAAa,CAAC,CAAC,CAAC,CA6JlB"}
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("vue"),a=require("./MaskEngine-hd5xHed7.cjs"),j=/^[\w\s\d.'"[\]()!<>=&|?:+\-*/%]+$/;function J(l,n){if(!j.test(l))return console.warn(`[vue-form-schema] Blocked unsafe expression: "${l}"`),!0;try{return!!new Function("values",`"use strict"; return (${l})`)(n)}catch{return!0}}class V{constructor(){this.stopHandle=null}start(n,e,t,i){this.stopHandle=v.watchEffect(()=>{const c=e.value,o=t.value,u=this.evaluateFields(n,c);i&&this.clearHiddenValues(n,u,c,e,o),t.value=u})}stop(){var n;(n=this.stopHandle)==null||n.call(this),this.stopHandle=null}evaluateFields(n,e){return n.map(t=>{const i=this.resolveBoolean(t.visible,e,!0),c=this.resolveBoolean(t.disabled,e,!1);return{...t,visible:i,disabled:c,fields:t.fields?this.evaluateFields(t.fields,e):void 0}})}resolveBoolean(n,e,t){return n===void 0?t:typeof n=="boolean"?n:typeof n=="function"?n(e):typeof n=="string"?J(n,e):t}clearHiddenValues(n,e,t,i,c){for(let o=0;o<n.length;o++){const u=n[o],b=e[o],s=this.wasVisible(c,u.name),f=b.visible;if(s&&!f){const y=a.getByPath(t,u.name),p=u.defaultValue??null;y!==p&&(i.value=a.setByPath(i.value,u.name,p))}u.fields&&b.fields&&this.clearHiddenValues(u.fields,b.fields,t,i,c)}}wasVisible(n,e){const t=n.find(i=>i.name===e);return t?t.visible!==!1:!0}}function C(l,n){return new V().evaluateFields(l,n)}function T(l,n,e){switch(l){case"required":return e?(t,i)=>a.required(t)?e:null:a.required;case"minLength":return a.minLength(Number(n),e);case"maxLength":return a.maxLength(Number(n),e);case"min":return a.min(Number(n),e);case"max":return a.max(Number(n),e);case"pattern":return a.pattern(new RegExp(String(n)),e);case"email":return e?(t,i)=>a.email(t)?e:null:a.email;case"url":return e?(t,i)=>a.url(t)?e:null:a.url;default:return console.warn(`[vue-form-schema] Unknown validator rule: "${l}"`),null}}function P(l){const n=[];for(const e of l.validators??[]){const t=T(e.rule,e.value,e.message);t&&n.push(t)}return{type:l.type,name:l.name,label:l.label,placeholder:l.placeholder,defaultValue:l.default,required:l.required,disabled:l.disabled,visible:l.visible,mask:l.mask,options:l.options,validators:n.length?n:void 0,fields:l.fields?l.fields.map(P):void 0}}function k(l){return l.map(P)}function $(l){if(!Array.isArray(l)||l.length===0)return!1;for(const n of l){const e=n.validators;if(Array.isArray(e)&&e.some(t=>typeof t=="function"))return!1}return l.some(n=>{const e=n;if("default"in e)return!0;const t=e.validators;return Array.isArray(t)&&t.length>0&&typeof t[0]=="object"&&t[0]!==null&&"rule"in t[0]})}function w(l){return $(l)?k(l):l}function g(l,n={}){const e={};for(const t of l)if(t.type==="group"&&t.fields){const i=g(t.fields,n);Object.assign(e,i)}else if(t.type==="array"){const i=a.getByPath(n,t.name);e[t.name]=i??t.defaultValue??[]}else{const i=a.getByPath(n,t.name);e[t.name]=i!==void 0?i:t.defaultValue??null}for(const[t,i]of Object.entries(n))t in e||(e[t]=i);return e}function D(l){const{schema:n,initialValues:e={},validateOn:t="blur",clearOnHide:i=!1,onSubmit:c}=l,o=w(n),u=new a.ValidationEngine,b=new V,s=v.ref(g(o,e)),f=v.ref({}),y=v.ref({}),p=v.ref(!1),h=v.ref(o);b.start(o,s,h,i??!1);const O=v.computed(()=>h.value),x=v.computed(()=>{const r=g(o,e);return JSON.stringify(s.value)!==JSON.stringify(r)}),A=v.computed(()=>{const r=u.validateAll(h.value,s.value);return Object.values(r).every(d=>d.length===0)});function E(r){if(r){const d=u.validateField(r,a.getByPath(s.value,r.name),s.value);f.value={...f.value,[r.name]:d},u.validateAsync(r,a.getByPath(s.value,r.name),s.value,(m,M)=>{f.value={...f.value,[m]:[...f.value[m]??[],...M]}})}else f.value=u.validateAll(h.value,s.value)}function L(r,d){if(s.value=a.setByPath(s.value,r,d),t==="input"){const m=B(h.value,r);m&&E(m)}}function S(r){return a.getByPath(s.value,r)}function q(r){if(y.value={...y.value,[r]:!0},t==="blur"){const d=B(h.value,r);d&&E(d)}}async function N(){const r={};for(const m of h.value)F(m,r);if(y.value=r,f.value=u.validateAll(h.value,s.value),!Object.values(f.value).some(m=>m.length>0)){p.value=!0;try{await(c==null?void 0:c(s.value))}finally{p.value=!1}}}function H(r){const d=r??e;s.value=g(o,d??{}),f.value={},y.value={},p.value=!1}return v.onUnmounted(()=>{b.stop(),u.destroy()}),{fields:O,values:s,errors:f,touched:y,isDirty:x,isValid:A,isSubmitting:p,submit:N,reset:H,setField:L,getField:S,touchField:q}}function B(l,n){for(const e of l){if(e.name===n)return e;if(e.fields){const t=B(e.fields,n);if(t)return t}}}function F(l,n={}){return n[l.name]=!0,l.fields&&l.fields.forEach(e=>F(e,n)),n}exports.ValidationEngine=a.ValidationEngine;exports.applyMask=a.applyMask;exports.bindMask=a.bindMask;exports.email=a.email;exports.getByPath=a.getByPath;exports.max=a.max;exports.maxLength=a.maxLength;exports.min=a.min;exports.minLength=a.minLength;exports.pattern=a.pattern;exports.removeMask=a.removeMask;exports.required=a.required;exports.setByPath=a.setByPath;exports.url=a.url;exports.ConditionEvaluator=V;exports.evaluateFieldConditions=C;exports.parseJSON=k;exports.useForm=D;
@@ -0,0 +1,7 @@
1
+ export type { FieldDefinition, FieldType, FieldOption, MaskConfig, MaskPreset, ValidatorFn, AsyncValidatorFn, UseFormConfig, UseFormReturn, ValidateOn, JSONSchema, JSONSchemaField, BuiltinRule, } from './core/types';
2
+ export { useForm } from './core/useForm';
3
+ export { required, minLength, maxLength, min, max, pattern, email, url, ValidationEngine, getByPath, setByPath, } from './core/ValidationEngine';
4
+ export { ConditionEvaluator, evaluateFieldConditions } from './core/ConditionEvaluator';
5
+ export { applyMask, removeMask, bindMask } from './core/MaskEngine';
6
+ export { parseJSON } from './parsers/json';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,eAAe,EACf,SAAS,EACT,WAAW,EACX,UAAU,EACV,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,UAAU,EACV,UAAU,EACV,eAAe,EACf,WAAW,GACZ,MAAM,cAAc,CAAA;AAGrB,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAGxC,OAAO,EACL,QAAQ,EACR,SAAS,EACT,SAAS,EACT,GAAG,EACH,GAAG,EACH,OAAO,EACP,KAAK,EACL,GAAG,EACH,gBAAgB,EAChB,SAAS,EACT,SAAS,GACV,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAGvF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAGnE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}