vaniy 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.
package/README.md ADDED
@@ -0,0 +1,331 @@
1
+ # Vaniy
2
+
3
+ A lightweight, modular JavaScript utility library for common web development tasks.
4
+ Vaniy is how we say vanilla in my language.
5
+
6
+ ## Features
7
+
8
+ - **DOM Manipulation** - jQuery-like chainable API for element selection and manipulation
9
+ - **HTTP Client** - Full-featured HTTP client with caching, interceptors, and file upload/download
10
+ - **Event System** - Pub/Sub event emitter for decoupled communication
11
+ - **Form Handling** - Validation engine with error rendering
12
+ - **Zero Dependencies** - Pure vanilla JavaScript
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install vaniy
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```javascript
23
+ import { Q, HTTP, EVT, V } from "vaniy";
24
+
25
+ // DOM manipulation
26
+ Q("#button").text("Click me").addClass("primary");
27
+
28
+ // HTTP requests
29
+ const data = await HTTP.get("/api/users");
30
+
31
+ // Event system
32
+ EVT.sub("user:login", (user) => console.log(user));
33
+ EVT.pub("user:login", { name: "John" });
34
+
35
+ // Form validation
36
+ const { isValid, errors } = V.run(
37
+ { email: ["required", "email"] },
38
+ { email: "test@example.com" },
39
+ );
40
+ ```
41
+
42
+ ## Modules
43
+
44
+ ### DOM
45
+
46
+ Select and manipulate DOM elements with a chainable API.
47
+
48
+ ```javascript
49
+ import { Q, all, make, makeId, parseHtml, onPageLoad } from "vaniy";
50
+
51
+ // Select single element
52
+ Q("#header").text("Hello World").addClass("visible");
53
+
54
+ // Get/set values
55
+ Q("#input").val();
56
+ Q("#container").html("<p>New content</p>");
57
+
58
+ // Classes
59
+ Q(".box").addClass("active").removeClass("hidden");
60
+
61
+ // Styles
62
+ Q("#element").css({ color: "red", fontSize: "16px" });
63
+
64
+ // Events
65
+ Q("#button").on("click", () => console.log("Clicked!"));
66
+
67
+ // Select multiple elements
68
+ all(".items").forEach((el) => el.classList.add("loaded"));
69
+
70
+ // Create elements
71
+ const div = make("div");
72
+
73
+ // Generate random ID
74
+ const id = makeId(8); // "a1b2c3d4"
75
+
76
+ // Parse HTML string
77
+ const nodes = parseHtml("<div>Content</div>");
78
+
79
+ // DOM ready
80
+ onPageLoad(() => console.log("DOM loaded"));
81
+ ```
82
+
83
+ ### HTTP
84
+
85
+ HTTP client with caching, interceptors, and progress tracking.
86
+
87
+ ```javascript
88
+ import { HTTP, get, post, upload, download } from "vaniy";
89
+
90
+ // Configure base URL and timeout
91
+ HTTP.base("https://api.example.com").timeout(10000);
92
+
93
+ // Request interceptors
94
+ HTTP.interceptRequest((config) => {
95
+ config.headers["Authorization"] = "Bearer token";
96
+ return config;
97
+ });
98
+
99
+ // Response interceptors
100
+ HTTP.interceptResponse((response) => {
101
+ console.log("Response:", response);
102
+ return response;
103
+ });
104
+
105
+ // GET request
106
+ const users = await HTTP.get("/users");
107
+
108
+ // POST request
109
+ await HTTP.post("/users", { name: "John", email: "john@example.com" });
110
+
111
+ // PUT request
112
+ await HTTP.put("/users/1", { name: "John Updated" });
113
+
114
+ // DELETE request
115
+ await HTTP.delete("/users/1");
116
+
117
+ // With caching
118
+ const data = await HTTP.get("/data", {
119
+ cache: {
120
+ strategy: "cache-first", // or 'network-first'
121
+ storage: "localStorage", // or 'sessionStorage', 'memory'
122
+ ttl: 60000, // Time to live in ms
123
+ },
124
+ });
125
+
126
+ // File upload with progress
127
+ await HTTP.upload("/upload", fileInput.files[0], {
128
+ onProgress: (sent, total, percent) => {
129
+ console.log(`${percent}% uploaded`);
130
+ },
131
+ });
132
+
133
+ // File download with progress
134
+ await HTTP.download("/files/doc.pdf", {
135
+ onProgress: (received, total, percent) => {
136
+ console.log(`${percent}% downloaded`);
137
+ },
138
+ });
139
+ ```
140
+
141
+ ### Events
142
+
143
+ Pub/Sub event system for decoupled communication.
144
+
145
+ ```javascript
146
+ import { EVT } from "vaniy";
147
+
148
+ // Subscribe to event
149
+ EVT.sub("user:login", (user) => {
150
+ console.log("User logged in:", user);
151
+ });
152
+
153
+ // Subscribe once (auto-unsubscribe after first call)
154
+ EVT.once("init", () => {
155
+ console.log("Initialized");
156
+ });
157
+
158
+ // Publish event
159
+ EVT.pub("user:login", { id: 1, name: "John" });
160
+
161
+ // Unsubscribe
162
+ const handler = (data) => console.log(data);
163
+ EVT.sub("event", handler);
164
+ EVT.unsub("event", handler);
165
+
166
+ // Check if event has listeners
167
+ EVT.has("user:login"); // true
168
+
169
+ // Clear all listeners for an event
170
+ EVT.clear("user:login");
171
+
172
+ // Clear all listeners
173
+ EVT.clear();
174
+ ```
175
+
176
+ ### Validator
177
+
178
+ Form validation with built-in rules.
179
+
180
+ ```javascript
181
+ import { V } from "vaniy";
182
+
183
+ const schema = {
184
+ email: ["required", "email"],
185
+ password: ["required", "min:8", "max:100"],
186
+ birthdate: ["required", "date"],
187
+ amount: ["required", "currency"],
188
+ };
189
+
190
+ const formData = {
191
+ email: "test@example.com",
192
+ password: "secret123",
193
+ birthdate: "1990-01-15",
194
+ amount: "$1,234.56",
195
+ };
196
+
197
+ const { isValid, errors } = V.run(schema, formData);
198
+
199
+ if (!isValid) {
200
+ console.log(errors);
201
+ // { password: ['Must be at least 8 characters'] }
202
+ }
203
+ ```
204
+
205
+ **Built-in Rules:**
206
+
207
+ | Rule | Description |
208
+ | ---------- | ----------------------- |
209
+ | `required` | Field must not be empty |
210
+ | `email` | Valid email format |
211
+ | `min:n` | Minimum string length |
212
+ | `max:n` | Maximum string length |
213
+ | `date` | Valid YYYY-MM-DD format |
214
+ | `currency` | Valid currency format |
215
+
216
+ ### Form Handler
217
+
218
+ Complete form handling with validation and error rendering.
219
+
220
+ ```javascript
221
+ import { useFormHandler, FormHandler, FormErrorRenderer } from "vaniy";
222
+
223
+ // Quick setup with useFormHandler
224
+ const schema = {
225
+ email: ["required", "email"],
226
+ password: ["required", "min:8"],
227
+ };
228
+
229
+ const form = useFormHandler("myFormId", schema, (formData) => {
230
+ // Called on successful validation
231
+ console.log("Submit:", formData);
232
+ });
233
+
234
+ // Manual validation
235
+ form.validate();
236
+
237
+ // Reset form and errors
238
+ form.reset();
239
+
240
+ // Set custom error container
241
+ form.setContainer("email", document.querySelector("#email-errors"));
242
+
243
+ // Cleanup
244
+ form.destroy();
245
+ ```
246
+
247
+ **Form Events:**
248
+
249
+ | Event | Description |
250
+ | --------------------- | ------------------------- |
251
+ | `form:state:change` | Form data changed |
252
+ | `form:errors:change` | Validation errors changed |
253
+ | `form:submit:success` | Successful submission |
254
+ | `form:submit:error` | Validation failed |
255
+ | `form:reset` | Form was reset |
256
+ | `form:validated` | Validation completed |
257
+
258
+ ### Utilities
259
+
260
+ Additional helper functions.
261
+
262
+ ```javascript
263
+ import {
264
+ isValidRoutingNumber,
265
+ toCurrency,
266
+ formatByCountry,
267
+ redirect,
268
+ isFocus,
269
+ isArray,
270
+ isArrayEmpty,
271
+ } from "vaniy";
272
+
273
+ // Validate US bank routing number
274
+ isValidRoutingNumber("021000021"); // true
275
+
276
+ // Format as currency
277
+ toCurrency(1234.56); // "$1,234.56"
278
+ toCurrency(1234.56, { locale: "de-DE", currency: "EUR" }); // "1.234,56 €"
279
+
280
+ // Format by country code
281
+ formatByCountry(1234.56, "GB"); // "£1,234.56"
282
+
283
+ // Redirect to URL
284
+ redirect("/dashboard");
285
+
286
+ // Check if element has focus
287
+ isFocus(document.querySelector("#input"));
288
+
289
+ // Array utilities
290
+ isArray([1, 2, 3]); // true
291
+ isArrayEmpty([]); // true
292
+ ```
293
+
294
+ ## Development
295
+
296
+ ```bash
297
+ # Install dependencies
298
+ npm install
299
+
300
+ # Start dev server
301
+ npm run dev
302
+
303
+ # Run tests
304
+ npm test
305
+
306
+ # Run tests once
307
+ npm run test:run
308
+
309
+ # Build for production
310
+ npm run build
311
+
312
+ # Preview production build
313
+ npm run preview
314
+ ```
315
+
316
+ ## Build Output
317
+
318
+ The build generates two bundle formats:
319
+
320
+ - `dist/vaniy.es.js` - ES module
321
+ - `dist/vaniy.umd.js` - UMD bundle
322
+
323
+ Both include sourcemaps for debugging.
324
+
325
+ ## License
326
+
327
+ MIT
328
+
329
+ ## Author
330
+
331
+ TekSoftGroup
@@ -0,0 +1,615 @@
1
+ const b = {
2
+ listeners: /* @__PURE__ */ new Map(),
3
+ sub: function(e, t) {
4
+ let r = this.listeners.get(e);
5
+ r || (r = /* @__PURE__ */ new Set(), this.listeners.set(e, r)), r.add(t);
6
+ },
7
+ once: function(e, t) {
8
+ const r = (...n) => {
9
+ t(...n), this.unsub(e, r);
10
+ };
11
+ this.sub(e, r);
12
+ },
13
+ unsub: function(e, t) {
14
+ let r = this.listeners.get(e);
15
+ r && r.delete(t);
16
+ },
17
+ pub: function(e, ...t) {
18
+ let r = this.listeners.get(e);
19
+ r && r.forEach((n) => {
20
+ try {
21
+ n(...t);
22
+ } catch (s) {
23
+ console.error(`Error in event "${e}" listener: `, s);
24
+ }
25
+ });
26
+ },
27
+ has: function(e) {
28
+ return this.listeners.has(e) && this.listeners.get(e).size > 0;
29
+ },
30
+ clear: function(e) {
31
+ e ? this.listeners.delete(e) : this.listeners.clear();
32
+ },
33
+ ping: () => console.log("PONG!"),
34
+ description: "EVT is for Event publishing and emitting"
35
+ }, B = {
36
+ required: {
37
+ method: (e) => e.trim() !== "",
38
+ message: "This field is required"
39
+ },
40
+ email: {
41
+ method: (e) => /\S+@\S+\.\S+/.test(e),
42
+ message: "Email is invalid"
43
+ },
44
+ min: {
45
+ method: (e) => (t) => t.length >= e,
46
+ message: (e) => `Must be at least ${e} characters`
47
+ },
48
+ max: {
49
+ method: (e) => (t) => t.length <= e,
50
+ message: (e) => `Must be at most ${e} characters`
51
+ },
52
+ date: {
53
+ method: (e) => {
54
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(e)) return !1;
55
+ const [r, n, s] = e.split("-").map(Number), o = new Date(r, n - 1, s);
56
+ return o.getFullYear() === r && o.getMonth() === n - 1 && o.getDate() === s;
57
+ },
58
+ message: "Date is invalid. Use the format YYYY-MM-DD."
59
+ },
60
+ currency: {
61
+ method: (e) => /^\$?\d{1,3}((,\d{3})*|\d*)(\.\d{2})?$/.test(e),
62
+ message: "Currency is invalid. Use the format $123,456.78 or 123456.78."
63
+ }
64
+ };
65
+ function J(e) {
66
+ const [t, r] = e.split(":");
67
+ return { name: t, param: r ? parseInt(r, 10) : void 0 };
68
+ }
69
+ function j(e, t) {
70
+ let r = !0;
71
+ const n = {};
72
+ for (const s in e) {
73
+ const o = e[s];
74
+ for (const i of o) {
75
+ const { name: u, param: h } = J(i), p = B[u];
76
+ if (!(h !== void 0 ? p.method(h)(t[s]) : p.method(t[s]))) {
77
+ r = !1, n[s] || (n[s] = []);
78
+ const d = h !== void 0 ? p.message(h) : p.message;
79
+ n[s].push(d);
80
+ }
81
+ }
82
+ }
83
+ return { isValid: r, errors: n };
84
+ }
85
+ const U = {
86
+ run: j,
87
+ ping: () => console.log("PONG"),
88
+ version: "1.0.0",
89
+ description: "V is for validating forms"
90
+ }, D = (e) => ({
91
+ on: (t, r) => e.addEventListener(t, r),
92
+ off: (t, r) => e.removeEventListener(t, r)
93
+ }), x = (e, t) => {
94
+ if (!e) return;
95
+ const r = "innerText" in e ? "innerText" : "textContent";
96
+ return t != null && (e[r] = t), e[r];
97
+ }, M = (e, t) => {
98
+ if (e)
99
+ return t != null && (e.innerHTML = t), e.innerHTML;
100
+ }, P = (e) => document.createElement(e), Y = (e) => {
101
+ let t = "";
102
+ const r = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", n = r.length;
103
+ for (let s = 0; s < e; s++)
104
+ t += r.charAt(Math.floor(Math.random() * n));
105
+ return t;
106
+ }, z = (e) => {
107
+ const t = document.implementation.createHTMLDocument("");
108
+ return t.body.innerHTML = e, [...t.body.childNodes];
109
+ }, K = (e) => {
110
+ document.readyState !== "loading" ? e() : document.addEventListener("DOMContentLoaded", e);
111
+ }, Q = (e) => {
112
+ window.onload = e;
113
+ }, N = (e) => {
114
+ const t = document.querySelector(e), r = {
115
+ elt: t,
116
+ value: t?.value,
117
+ text: (n) => n != null ? (x(t, n), r) : x(t),
118
+ print: () => t,
119
+ html: (n) => n != null ? (M(t, n), r) : M(t),
120
+ val: () => t.options && t.multiple ? Array.from(t.options).filter((n) => n.selected).map((n) => n.value) : t.value,
121
+ addClass: (n) => (t.classList.add(n), r),
122
+ removeClass: (n) => (t.classList.remove(n), r),
123
+ hasClass: (n) => t.classList.contains(n),
124
+ hide: () => {
125
+ t.style.display = "none";
126
+ },
127
+ show: () => {
128
+ t.style.display = "";
129
+ },
130
+ prop: (n) => t[n],
131
+ attr: (n) => t.getAttribute(n),
132
+ removeAttr: (n) => {
133
+ t.removeAttribute(n);
134
+ },
135
+ toggle: () => {
136
+ t.style.display == "none" ? r.show() : r.hide();
137
+ },
138
+ css: (n) => (Object.entries(n).forEach(([s, o]) => {
139
+ t.style[s] = o;
140
+ }), r),
141
+ on: D(t).on,
142
+ off: D(t).off
143
+ };
144
+ return r;
145
+ }, F = (e) => document.querySelectorAll(e), ut = {
146
+ Q: N,
147
+ $: N,
148
+ all: F,
149
+ $$: F,
150
+ make: P,
151
+ makeId: Y,
152
+ parseHtml: z,
153
+ onPageLoad: K,
154
+ onWindowLoad: Q,
155
+ ping: () => console.log("PONG!"),
156
+ description: "DOM is for dom manipulation"
157
+ };
158
+ let w = "", H = 8e3, T = null, A = null;
159
+ const C = /* @__PURE__ */ new Map(), v = () => Date.now();
160
+ function _(e) {
161
+ const t = typeof window < "u" ? window[e] : null;
162
+ return t ? {
163
+ get(r) {
164
+ const n = t.getItem(r);
165
+ if (!n) return null;
166
+ try {
167
+ const s = JSON.parse(n);
168
+ return s.exp && s.exp < v() ? (t.removeItem(r), null) : s.val;
169
+ } catch {
170
+ return null;
171
+ }
172
+ },
173
+ set(r, n, s) {
174
+ const o = s ? v() + s : null;
175
+ t.setItem(r, JSON.stringify({ val: n, exp: o }));
176
+ },
177
+ del(r) {
178
+ t && t.removeItem(r);
179
+ },
180
+ clear() {
181
+ t && t.clear();
182
+ }
183
+ } : null;
184
+ }
185
+ const V = {
186
+ memory: {
187
+ get(e) {
188
+ const t = C.get(e);
189
+ return t ? t.exp && t.exp < v() ? (C.delete(e), null) : t.val : null;
190
+ },
191
+ set(e, t, r) {
192
+ const n = r ? v() + r : null;
193
+ C.set(e, { val: t, exp: n });
194
+ },
195
+ del(e) {
196
+ C.delete(e);
197
+ },
198
+ clear() {
199
+ C.clear();
200
+ }
201
+ },
202
+ local: _("localStorage"),
203
+ session: _("sessionStorage")
204
+ };
205
+ function L(e) {
206
+ return e === null || typeof e != "object" ? String(e) : Array.isArray(e) ? `[${e.map(L).join(",")}]` : `{${Object.keys(e).sort().map((t) => `${JSON.stringify(t)}:${L(e[t])}`).join(",")}}`;
207
+ }
208
+ function W(e = "memory") {
209
+ return V[e] || V.memory;
210
+ }
211
+ function X(e, t, r, n) {
212
+ const s = r ? `?${new URLSearchParams(r).toString()}` : "", o = n && e !== "GET" ? `#${L(n)}` : "";
213
+ return `H|${e}|${t}${s}${o}`;
214
+ }
215
+ function Z({ files: e, fieldName: t = "file", fields: r = {} }) {
216
+ const n = new FormData(), s = Array.isArray(e) ? e : [e];
217
+ return s.forEach((o, i) => {
218
+ const u = s.length > 1 ? `${t}[${i}]` : t;
219
+ n.append(u, o);
220
+ }), Object.entries(r).forEach(([o, i]) => {
221
+ n.append(
222
+ o,
223
+ i instanceof Blob || i instanceof File ? i : typeof i == "object" ? JSON.stringify(i) : String(i)
224
+ );
225
+ }), n;
226
+ }
227
+ const k = (e, t) => setTimeout(() => t.abort(), e);
228
+ async function $(e, t, r = {}) {
229
+ const { params: n, body: s, headers: o = {}, cache: i } = r;
230
+ let u = w + t;
231
+ if (n) {
232
+ const l = new URLSearchParams(n).toString();
233
+ u += (u.includes("?") ? "&" : "?") + l;
234
+ }
235
+ const h = new AbortController(), p = k(H, h), m = !!i, d = i?.strategy, g = i?.ttl ?? 0, a = W(i?.storage), f = i?.key || X(e, u, n, s);
236
+ if (m && !i?.forceRefresh && d === "cache-first") {
237
+ const l = a.get(f);
238
+ if (l !== null) return l;
239
+ }
240
+ let c = {
241
+ method: e,
242
+ headers: o,
243
+ signal: h.signal
244
+ };
245
+ s !== void 0 && (s instanceof FormData ? c.body = s : (c.headers["Content-Type"] = "application/json", c.body = JSON.stringify(s))), T && (c = T(c) || c);
246
+ try {
247
+ let l = await fetch(u, c);
248
+ clearTimeout(p), A && (l = A(l) || l);
249
+ let y;
250
+ try {
251
+ y = await l.json();
252
+ } catch {
253
+ y = await l.text();
254
+ }
255
+ if (!l.ok) {
256
+ const S = {
257
+ status: l.status,
258
+ data: y,
259
+ url: u,
260
+ method: e
261
+ };
262
+ if (m && d === "network-first") {
263
+ const I = a.get(f);
264
+ if (I !== null) return I;
265
+ }
266
+ throw S;
267
+ }
268
+ return m && a.set(f, y, g), y;
269
+ } catch (l) {
270
+ if (clearTimeout(p), m && d === "network-first") {
271
+ const y = a.get(f);
272
+ if (y !== null) return y;
273
+ }
274
+ throw l;
275
+ }
276
+ }
277
+ async function tt(e, { filename: t, params: r, headers: n = {}, method: s = "GET", body: o, onProgress: i } = {}) {
278
+ let u = w + e;
279
+ if (r) {
280
+ const c = new URLSearchParams(r).toString();
281
+ u += (u.includes("?") ? "&" : "?") + c;
282
+ }
283
+ const h = new AbortController(), p = k(H, h), m = {
284
+ method: s,
285
+ headers: { ...n },
286
+ signal: h.signal
287
+ };
288
+ o !== void 0 && (o instanceof FormData ? m.body = o : (m.headers["Content-Type"] = m.headers["Content-Type"] || "application/json", m.body = typeof o == "string" ? o : JSON.stringify(o)));
289
+ const d = await fetch(u, m);
290
+ if (clearTimeout(p), !d.ok) {
291
+ let c = "";
292
+ try {
293
+ c = await d.text();
294
+ } catch {
295
+ }
296
+ throw new Error(
297
+ `Download failed ${d.status}: ${c || d.statusText}`
298
+ );
299
+ }
300
+ if (!t) {
301
+ const c = d.headers.get("Content-Disposition") || "", l = /filename\*=UTF-8''([^;]+)|filename="?([^"]+)"?/i.exec(c);
302
+ t = decodeURIComponent(l?.[1] || l?.[2] || "download");
303
+ }
304
+ let g;
305
+ if (d.body && "getReader" in d.body) {
306
+ const c = d.body.getReader(), l = Number(d.headers.get("Content-Length")) || null, y = [];
307
+ let S = 0;
308
+ for (; ; ) {
309
+ const { done: I, value: O } = await c.read();
310
+ if (I) break;
311
+ if (y.push(O), S += O.length, typeof i == "function") {
312
+ const q = l ? Math.round(S / l * 100) : null;
313
+ i(S, l, q);
314
+ }
315
+ }
316
+ g = new Blob(y);
317
+ } else
318
+ g = await d.blob(), typeof i == "function" && i(1, 1, 100);
319
+ const a = URL.createObjectURL(g), f = document.createElement("a");
320
+ return f.href = a, f.download = t, f.style.display = "none", document.body.appendChild(f), f.click(), document.body.removeChild(f), URL.revokeObjectURL(a), { filename: t, size: g.size, type: g.type };
321
+ }
322
+ function et(e, {
323
+ files: t,
324
+ // File | Blob | File[] | Blob[]
325
+ fieldName: r = "file",
326
+ // form field name(s)
327
+ fields: n = {},
328
+ // additional form fields (e.g., { name: "Pascal" })
329
+ headers: s = {},
330
+ // extra headers (don't set Content-Type yourself)
331
+ method: o = "POST",
332
+ onProgress: i,
333
+ // (sentBytes, totalBytes, percent) => void
334
+ signal: u
335
+ // AbortSignal
336
+ } = {}) {
337
+ return new Promise((p, m) => {
338
+ const d = Z({ files: t, fieldName: r, fields: n }), g = `${w}${e}`, a = new XMLHttpRequest();
339
+ a.open(o, g, !0);
340
+ let f = { method: o, headers: { ...s } };
341
+ if (T && (f = T(f) || f), Object.entries(f.headers).forEach(([c, l]) => a.setRequestHeader(c, l)), a.timeout = H, u) {
342
+ const c = () => {
343
+ try {
344
+ a.abort();
345
+ } catch {
346
+ }
347
+ };
348
+ u.aborted && c(), u.addEventListener("abort", c, { once: !0 });
349
+ }
350
+ a.upload && typeof i == "function" && (a.upload.onprogress = (c) => {
351
+ if (!c.lengthComputable) {
352
+ i(c.loaded, null, null);
353
+ return;
354
+ }
355
+ const l = Math.round(c.loaded / c.total * 100);
356
+ i(c.loaded, c.total, l);
357
+ }), a.onreadystatechange = async () => {
358
+ if (a.readyState !== 4) return;
359
+ if (A) {
360
+ const S = {
361
+ status: a.status,
362
+ ok: a.status >= 200 && a.status < 300,
363
+ headers: new Headers(),
364
+ // not fully accurate; fine for logging/hook
365
+ text: async () => a.responseText,
366
+ json: async () => JSON.parse(a.responseText || "null")
367
+ };
368
+ A(S);
369
+ }
370
+ const y = (a.getResponseHeader("Content-Type") || "").includes("application/json") ? h(a.responseText) : a.responseText;
371
+ a.status >= 200 && a.status < 300 ? p(y) : m({
372
+ status: a.status,
373
+ data: y,
374
+ url: g,
375
+ method: o
376
+ });
377
+ }, a.onerror = () => m({
378
+ status: 0,
379
+ data: "Network error",
380
+ url: `${w}${e}`,
381
+ method: o
382
+ }), a.ontimeout = () => m({
383
+ status: 0,
384
+ data: "Timeout",
385
+ url: `${w}${e}`,
386
+ method: o
387
+ }), a.send(d);
388
+ });
389
+ function h(p) {
390
+ try {
391
+ return JSON.parse(p || "null");
392
+ } catch {
393
+ return p;
394
+ }
395
+ }
396
+ }
397
+ const rt = (e, t) => $("GET", e, t), nt = (e, t, r = {}) => $("POST", e, { ...r, body: t }), st = (e, t, r = {}) => $("PUT", e, { ...r, body: t }), ot = (e, t = {}) => $("DELETE", e, t), it = (e, t) => fetch(w + e, t), R = {
398
+ base(e) {
399
+ return w = e, R;
400
+ },
401
+ timeout(e) {
402
+ return H = e, R;
403
+ },
404
+ interceptRequest(e) {
405
+ return T = e, R;
406
+ },
407
+ interceptResponse(e) {
408
+ return A = e, R;
409
+ },
410
+ get: rt,
411
+ post: nt,
412
+ put: st,
413
+ delete: ot,
414
+ raw: it,
415
+ download: tt,
416
+ upload: et,
417
+ ping: () => console.log("PONG"),
418
+ description: "H is for Http"
419
+ }, E = {
420
+ STATE_CHANGE: "form:state:change",
421
+ ERRORS_CHANGE: "form:errors:change",
422
+ SUBMIT_SUCCESS: "form:submit:success",
423
+ SUBMIT_ERROR: "form:submit:error",
424
+ RESET: "form:reset",
425
+ VALIDATED: "form:validated"
426
+ };
427
+ class at {
428
+ constructor(t, r, n) {
429
+ this.formId = t, this.schema = r, this.onSubmit = n, this.form = null, this.formState = {}, this.errors = {}, this.initialValues = {}, this._boundHandleSubmit = this.#o.bind(this), this._boundHandleInput = this.#s.bind(this), this.#r();
430
+ }
431
+ #r() {
432
+ if (this.form = document.getElementById(this.formId), !this.form) {
433
+ console.error(`Form with id ${this.formId} not found`);
434
+ return;
435
+ }
436
+ this.#n(), this.form.addEventListener("submit", this._boundHandleSubmit), this.form.addEventListener("input", this._boundHandleInput), this.#e();
437
+ }
438
+ #n() {
439
+ const t = this.form.elements;
440
+ for (const r of Array.from(t))
441
+ r.name && (this.initialValues[r.name] = r.value, this.formState[r.name] = r.value);
442
+ }
443
+ #s(t) {
444
+ const { name: r, value: n } = t.target;
445
+ r && (this.formState[r] = n, this.#e(), this.errors[r] && (delete this.errors[r], this.#t()));
446
+ }
447
+ #o(t) {
448
+ t.preventDefault();
449
+ const r = new FormData(this.form), n = {};
450
+ r.forEach((i, u) => {
451
+ n[u] = i;
452
+ }), this.formState = n, this.#e();
453
+ const { isValid: s, errors: o } = U.run(this.schema, n);
454
+ b.pub(E.VALIDATED, {
455
+ formId: this.formId,
456
+ isValid: s,
457
+ errors: o,
458
+ data: n
459
+ }), s ? (this.errors = {}, this.#t(), b.pub(E.SUBMIT_SUCCESS, {
460
+ formId: this.formId,
461
+ data: n
462
+ }), this.onSubmit(n)) : (this.errors = o, this.#t(), b.pub(E.SUBMIT_ERROR, {
463
+ formId: this.formId,
464
+ errors: o
465
+ }));
466
+ }
467
+ #e() {
468
+ b.pub(E.STATE_CHANGE, {
469
+ formId: this.formId,
470
+ state: { ...this.formState }
471
+ });
472
+ }
473
+ #t() {
474
+ b.pub(E.ERRORS_CHANGE, {
475
+ formId: this.formId,
476
+ errors: { ...this.errors }
477
+ });
478
+ }
479
+ getFormState() {
480
+ return { ...this.formState };
481
+ }
482
+ getErrors() {
483
+ return { ...this.errors };
484
+ }
485
+ reset() {
486
+ this.formState = { ...this.initialValues }, this.errors = {}, this.form && this.form.reset(), this.#e(), this.#t(), b.pub(E.RESET, { formId: this.formId });
487
+ }
488
+ validateNow() {
489
+ const t = new FormData(this.form), r = {};
490
+ t.forEach((s, o) => {
491
+ r[o] = s;
492
+ });
493
+ const n = U.run(this.schema, r);
494
+ return this.errors = n.errors, this.#t(), b.pub(E.VALIDATED, {
495
+ formId: this.formId,
496
+ isValid: n.isValid,
497
+ errors: n.errors,
498
+ data: r
499
+ }), n;
500
+ }
501
+ destroy() {
502
+ this.form && (this.form.removeEventListener("submit", this._boundHandleSubmit), this.form.removeEventListener("input", this._boundHandleInput));
503
+ }
504
+ }
505
+ class ct {
506
+ constructor(t, r = {}) {
507
+ this.formId = t, this.options = {
508
+ containerClass: "form-error-container",
509
+ errorClass: "text-danger",
510
+ insertAfterField: !0,
511
+ ...r
512
+ }, this.customContainers = {}, this._boundHandleErrors = this.#r.bind(this), b.sub(E.ERRORS_CHANGE, this._boundHandleErrors);
513
+ }
514
+ #r({ formId: t, errors: r }) {
515
+ t === this.formId && (this.clearAll(), this.renderAll(r));
516
+ }
517
+ setContainer(t, r) {
518
+ this.customContainers[t] = typeof r == "string" ? document.querySelector(r) : r;
519
+ }
520
+ renderAll(t) {
521
+ for (const r in t)
522
+ this.render(r, t[r]);
523
+ }
524
+ render(t, r) {
525
+ if (!r || r.length === 0) return null;
526
+ const n = document.createElement("span");
527
+ n.className = `${this.options.containerClass} ${this.options.errorClass}`, n.dataset.field = t;
528
+ const s = document.createElement("ul");
529
+ r.forEach((i) => {
530
+ const u = document.createElement("li"), h = document.createElement("i");
531
+ h.textContent = i, u.appendChild(h), s.appendChild(u);
532
+ }), n.appendChild(s);
533
+ const o = this.customContainers[t];
534
+ if (o)
535
+ o.innerHTML = "", o.appendChild(n);
536
+ else if (this.options.insertAfterField) {
537
+ const u = document.getElementById(this.formId)?.querySelector(`[name="${t}"]`);
538
+ u && u.insertAdjacentElement("afterend", n);
539
+ }
540
+ return n;
541
+ }
542
+ clearAll() {
543
+ const t = document.getElementById(this.formId);
544
+ if (!t) return;
545
+ t.querySelectorAll(`.${this.options.containerClass}`).forEach((n) => n.remove());
546
+ for (const n in this.customContainers)
547
+ this.customContainers[n] && (this.customContainers[n].innerHTML = "");
548
+ }
549
+ destroy() {
550
+ b.unsub(E.ERRORS_CHANGE, this._boundHandleErrors), this.clearAll();
551
+ }
552
+ }
553
+ function dt(e, t, r) {
554
+ const n = new at(e, t, r), s = new ct(e);
555
+ return {
556
+ reset: () => n.reset(),
557
+ validate: () => n.validateNow(),
558
+ destroy: () => {
559
+ s.destroy(), n.destroy();
560
+ },
561
+ setContainer: (o, i) => s.setContainer(o, i)
562
+ };
563
+ }
564
+ const ft = (e) => window.location.href = e, ht = (e) => Array.isArray(e), mt = (e) => !(Array.isArray(e) && e.length > 0), pt = (e) => e == document.activeElement, G = {
565
+ US: { locale: "en-US", currency: "USD" },
566
+ CA: { locale: "en-CA", currency: "CAD" },
567
+ FR: { locale: "fr-FR", currency: "EUR" },
568
+ HT: { locale: "ht-HT", currency: "HTG" },
569
+ GB: { locale: "en-GB", currency: "GBP" },
570
+ AU: { locale: "en-AU", currency: "AUD" }
571
+ }, lt = (e, { locale: t = "en-US", currency: r = "USD" } = {}) => Intl.NumberFormat(t, {
572
+ style: "currency",
573
+ currency: r
574
+ }).format(e), yt = (e, t) => {
575
+ const r = G[t] ?? G.US;
576
+ return lt(e, r);
577
+ }, gt = (e) => {
578
+ if (!/^\d{9}$/.test(e))
579
+ return !1;
580
+ const t = e.split("").map(Number);
581
+ return (7 * (t[0] + t[3] + t[6]) + 3 * (t[1] + t[4] + t[7]) + 1 * (t[2] + t[5] + t[8])) % 10 === 0;
582
+ };
583
+ export {
584
+ ut as DOM,
585
+ b as EVT,
586
+ ct as FormErrorRenderer,
587
+ E as FormEvents,
588
+ at as FormHandler,
589
+ R as HTTP,
590
+ N as Q,
591
+ U as V,
592
+ F as all,
593
+ ot as del,
594
+ tt as download,
595
+ yt as formatByCountry,
596
+ rt as get,
597
+ ht as isArray,
598
+ mt as isArrayEmpty,
599
+ pt as isFocus,
600
+ gt as isValidRoutingNumber,
601
+ P as make,
602
+ Y as makeId,
603
+ K as onPageLoad,
604
+ Q as onWindowLoad,
605
+ z as parseHtml,
606
+ nt as post,
607
+ st as put,
608
+ it as raw,
609
+ ft as redirect,
610
+ $ as request,
611
+ lt as toCurrency,
612
+ et as upload,
613
+ dt as useFormHandler
614
+ };
615
+ //# sourceMappingURL=vaniy.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vaniy.es.js","sources":["../src/evt.js","../src/validator.js","../src/dom.js","../src/http.js","../src/form.js","../src/utils.js"],"sourcesContent":["\"use strict\";\n\nconst EVT = {\n listeners: new Map(),\n sub: function (name, callback) {\n let handlers = this.listeners.get(name);\n if (!handlers) {\n handlers = new Set();\n this.listeners.set(name, handlers);\n }\n handlers.add(callback);\n },\n once: function (name, callback) {\n const onceCallback = (...args) => {\n callback(...args);\n this.unsub(name, onceCallback);\n };\n this.sub(name, onceCallback);\n },\n unsub: function (name, cb) {\n let handlers = this.listeners.get(name);\n if (!handlers) return;\n handlers.delete(cb);\n },\n pub: function (name, ...data) {\n let handlers = this.listeners.get(name);\n if (!handlers) return;\n handlers.forEach((cb) => {\n try {\n cb(...data);\n } catch (e) {\n console.error(`Error in event \"${name}\" listener: `, e);\n }\n });\n },\n has: function (name) {\n return this.listeners.has(name) && this.listeners.get(name).size > 0;\n },\n clear: function (name) {\n if (name) {\n this.listeners.delete(name);\n } else {\n this.listeners.clear();\n }\n },\n ping: () => console.log(\"PONG!\"),\n description: \"EVT is for Event publishing and emitting\",\n};\n\nexport default EVT;\n","\"use strict\";\n\nconst methods = {\n required: {\n method: (value) => value.trim() !== \"\",\n message: \"This field is required\",\n },\n email: {\n method: (value) => /\\S+@\\S+\\.\\S+/.test(value),\n message: \"Email is invalid\",\n },\n min: {\n method: (length) => (value) => value.length >= length,\n message: (length) => `Must be at least ${length} characters`,\n },\n max: {\n method: (length) => (value) => value.length <= length,\n message: (length) => `Must be at most ${length} characters`,\n },\n date: {\n method: (value) => {\n const dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n if (!dateRegex.test(value)) return false;\n const [year, month, day] = value.split(\"-\").map(Number);\n const date = new Date(year, month - 1, day);\n return (\n date.getFullYear() === year &&\n date.getMonth() === month - 1 &&\n date.getDate() === day\n );\n },\n message: \"Date is invalid. Use the format YYYY-MM-DD.\",\n },\n currency: {\n method: (value) => /^\\$?\\d{1,3}((,\\d{3})*|\\d*)(\\.\\d{2})?$/.test(value),\n message: \"Currency is invalid. Use the format $123,456.78 or 123456.78.\",\n },\n};\n\nfunction parseRule(rule) {\n const [name, param] = rule.split(\":\");\n return { name, param: param ? parseInt(param, 10) : undefined };\n}\n\nfunction run(schema, formData) {\n let isValid = true;\n const errors = {};\n\n for (const field in schema) {\n const rules = schema[field];\n\n for (const ruleString of rules) {\n const { name, param } = parseRule(ruleString);\n const validationMethod = methods[name];\n\n const isFieldValid =\n param !== undefined\n ? validationMethod.method(param)(formData[field])\n : validationMethod.method(formData[field]);\n\n if (!isFieldValid) {\n isValid = false;\n if (!errors[field]) {\n errors[field] = [];\n }\n const errorMessage =\n param !== undefined\n ? validationMethod.message(param)\n : validationMethod.message;\n\n errors[field].push(errorMessage);\n }\n }\n }\n return { isValid, errors };\n}\n\nconst V = {\n run,\n ping: () => console.log(\"PONG\"),\n version: \"1.0.0\",\n description: \"V is for validating forms\",\n};\n\nexport default V;\n","\"use strict\";\n\nconst hook = (element) => ({\n on: (event, callback) => element.addEventListener(event, callback),\n off: (event, callback) => element.removeEventListener(event, callback),\n});\n\nconst text = (element, value) => {\n if (!element) return undefined;\n const prop = \"innerText\" in element ? \"innerText\" : \"textContent\";\n if (value != null) element[prop] = value; // allows empty string\n return element[prop];\n};\n\nconst html = (element, value) => {\n if (!element) return undefined;\n if (value != null) element.innerHTML = value;\n return element.innerHTML;\n};\n\nexport const make = (name) => document.createElement(name);\n\nexport const makeId = (length) => {\n let result = \"\";\n const alphaNum =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n const alphaNumLength = alphaNum.length;\n\n for (let i = 0; i < length; i++) {\n result += alphaNum.charAt(Math.floor(Math.random() * alphaNumLength));\n }\n return result;\n};\n\nexport const parseHtml = (source) => {\n const tmp = document.implementation.createHTMLDocument(\"\");\n tmp.body.innerHTML = source;\n return [...tmp.body.childNodes];\n};\n\nexport const onPageLoad = (callback) => {\n if (document.readyState !== \"loading\") callback();\n else document.addEventListener(\"DOMContentLoaded\", callback);\n};\n\nexport const onWindowLoad = (callback) => {\n window.onload = callback;\n};\n\nexport const Q = (selector) => {\n const selectedElement = document.querySelector(selector);\n\n const wrapper = {\n elt: selectedElement,\n value: selectedElement?.value,\n text: (val) => {\n if (val != null) {\n text(selectedElement, val);\n return wrapper;\n }\n return text(selectedElement);\n },\n print: () => {\n return selectedElement;\n },\n html: (val) => {\n if (val != null) {\n html(selectedElement, val);\n return wrapper;\n }\n return html(selectedElement);\n },\n val: () => {\n if (selectedElement.options && selectedElement.multiple) {\n return Array.from(selectedElement.options)\n .filter((opt) => opt.selected)\n .map((opt) => opt.value);\n }\n return selectedElement.value;\n },\n addClass: (className) => {\n selectedElement.classList.add(className);\n return wrapper;\n },\n removeClass: (className) => {\n selectedElement.classList.remove(className);\n return wrapper;\n },\n hasClass: (className) => {\n return selectedElement.classList.contains(className);\n },\n hide: () => {\n selectedElement.style.display = \"none\";\n },\n show: () => {\n selectedElement.style.display = \"\";\n },\n prop: (propertyName) => {\n return selectedElement[propertyName];\n },\n attr: (attributeName) => {\n return selectedElement.getAttribute(attributeName);\n },\n removeAttr: (attributeName) => {\n selectedElement.removeAttribute(attributeName);\n },\n toggle: () => {\n if (selectedElement.style.display == \"none\") wrapper.show();\n else wrapper.hide();\n },\n css: (styleObject) => {\n Object.entries(styleObject).forEach(([key, value]) => {\n selectedElement.style[key] = value;\n });\n return wrapper;\n },\n on: hook(selectedElement).on,\n off: hook(selectedElement).off,\n };\n return wrapper;\n};\n\nexport const all = (selector) => {\n const selectedElements = document.querySelectorAll(selector);\n return selectedElements;\n};\n\nconst DOM = {\n Q,\n $: Q,\n all,\n $$: all,\n make,\n makeId,\n parseHtml,\n onPageLoad,\n onWindowLoad,\n ping: () => console.log(\"PONG!\"),\n description: \"DOM is for dom manipulation\",\n};\n\nexport default DOM;\n","\"use strict\";\n\nlet _base = \"\";\nlet _timeout = 8000;\nlet _requestInterceptor = null;\nlet _responseInterceptor = null;\n\nconst memoryStore = new Map();\nconst now = () => Date.now();\n\nfunction makeStorageAdapter(kind) {\n const store = typeof window !== \"undefined\" ? window[kind] : null;\n if (!store) return null;\n return {\n get(key) {\n const raw = store.getItem(key);\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw);\n if (parsed.exp && parsed.exp < now()) {\n store.removeItem(key);\n return null;\n }\n return parsed.val;\n } catch {\n return null;\n }\n },\n set(key, val, ttl) {\n const exp = ttl ? now() + ttl : null;\n store.setItem(key, JSON.stringify({ val, exp }));\n },\n del(key) {\n if (store) store.removeItem(key);\n },\n clear() {\n if (store) store.clear();\n },\n };\n}\n\nconst storages = {\n memory: {\n get(key) {\n const hit = memoryStore.get(key);\n if (!hit) return null;\n if (hit.exp && hit.exp < now()) {\n memoryStore.delete(key);\n return null;\n }\n return hit.val;\n },\n set(key, val, ttl) {\n const exp = ttl ? now() + ttl : null;\n memoryStore.set(key, { val, exp });\n },\n del(key) {\n memoryStore.delete(key);\n },\n clear() {\n memoryStore.clear();\n },\n },\n local: makeStorageAdapter(\"localStorage\"),\n session: makeStorageAdapter(\"sessionStorage\"),\n};\n\nfunction stableStringify(obj) {\n if (obj === null || typeof obj !== \"object\") return String(obj);\n if (Array.isArray(obj)) return `[${obj.map(stableStringify).join(\",\")}]`;\n return `{${Object.keys(obj)\n .sort()\n .map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`)\n .join(\",\")}}`;\n}\n\nfunction getStorage(storageKind = \"memory\") {\n return storages[storageKind] || storages.memory;\n}\n\nfunction buildCacheKey(method, url, params, body) {\n const p = params ? `?${new URLSearchParams(params).toString()}` : \"\";\n const b = body && method !== \"GET\" ? `#${stableStringify(body)}` : \"\";\n return `H|${method}|${url}${p}${b}`;\n}\n\nfunction buildFormData({ files, fieldName = \"file\", fields = {} }) {\n const fd = new FormData();\n\n const list = Array.isArray(files) ? files : [files];\n list.forEach((f, i) => {\n const name = list.length > 1 ? `${fieldName}[${i}]` : fieldName;\n fd.append(name, f);\n });\n\n Object.entries(fields).forEach(([k, v]) => {\n fd.append(\n k,\n v instanceof Blob || v instanceof File\n ? v\n : typeof v === \"object\"\n ? JSON.stringify(v)\n : String(v),\n );\n });\n\n return fd;\n}\n\nconst applyTimeout = (ms, controller) =>\n setTimeout(() => controller.abort(), ms);\n\nexport async function request(method, url, opts = {}) {\n const { params, body, headers = {}, cache } = opts;\n\n let finalUrl = _base + url;\n if (params) {\n const qs = new URLSearchParams(params).toString();\n finalUrl += (finalUrl.includes(\"?\") ? \"&\" : \"?\") + qs;\n }\n\n const controller = new AbortController();\n const timeoutId = applyTimeout(_timeout, controller);\n const useCache = !!cache;\n const strategy = cache?.strategy; // 'cache-first' | 'network-first'\n const ttl = cache?.ttl ?? 0;\n const storage = getStorage(cache?.storage);\n const cacheKey = cache?.key || buildCacheKey(method, finalUrl, params, body);\n\n if (useCache && !cache?.forceRefresh && strategy === \"cache-first\") {\n const hit = storage.get(cacheKey);\n if (hit !== null) return hit;\n }\n\n // Build URL with base + query params\n\n let config = {\n method,\n headers,\n signal: controller.signal,\n };\n\n if (body !== undefined) {\n if (body instanceof FormData) {\n config.body = body;\n } else {\n config.headers[\"Content-Type\"] = \"application/json\";\n config.body = JSON.stringify(body);\n }\n }\n\n if (_requestInterceptor) {\n config = _requestInterceptor(config) || config;\n }\n\n try {\n let res = await fetch(finalUrl, config);\n clearTimeout(timeoutId);\n\n if (_responseInterceptor) {\n res = _responseInterceptor(res) || res;\n }\n\n // Try to parse JSON but fallback to text\n let data;\n try {\n data = await res.json();\n } catch {\n data = await res.text();\n }\n\n if (!res.ok) {\n const err = {\n status: res.status,\n data,\n url: finalUrl,\n method,\n };\n //for network-first with cache fallback on error, try cached value\n if (useCache && strategy === \"network-first\") {\n const cached = storage.get(cacheKey);\n if (cached !== null) return cached;\n }\n throw err;\n }\n\n if (useCache) {\n storage.set(cacheKey, data, ttl);\n }\n return data;\n } catch (err) {\n clearTimeout(timeoutId);\n if (useCache && strategy === \"network-first\") {\n const cached = storage.get(cacheKey);\n if (cached !== null) return cached;\n }\n throw err;\n }\n}\n\nexport async function download(\n url,\n { filename, params, headers = {}, method = \"GET\", body, onProgress } = {},\n) {\n // Build URL w/ base + params\n let finalUrl = _base + url;\n if (params) {\n const qs = new URLSearchParams(params).toString();\n finalUrl += (finalUrl.includes(\"?\") ? \"&\" : \"?\") + qs;\n }\n\n const controller = new AbortController();\n const timeoutId = applyTimeout(_timeout, controller);\n\n // Prepare request\n const init = {\n method,\n headers: { ...headers },\n signal: controller.signal,\n };\n if (body !== undefined) {\n if (body instanceof FormData) {\n init.body = body;\n } else {\n init.headers[\"Content-Type\"] =\n init.headers[\"Content-Type\"] || \"application/json\";\n init.body = typeof body === \"string\" ? body : JSON.stringify(body);\n }\n }\n\n const res = await fetch(finalUrl, init);\n clearTimeout(timeoutId);\n if (!res.ok) {\n let errText = \"\";\n try {\n errText = await res.text();\n } catch {}\n throw new Error(\n `Download failed ${res.status}: ${errText || res.statusText}`,\n );\n }\n\n // Try to infer filename from Content-Disposition\n if (!filename) {\n const cd = res.headers.get(\"Content-Disposition\") || \"\";\n const match = /filename\\*=UTF-8''([^;]+)|filename=\"?([^\"]+)\"?/i.exec(cd);\n filename = decodeURIComponent(match?.[1] || match?.[2] || \"download\");\n }\n\n // Stream with progress if possible\n let blob;\n if (res.body && \"getReader\" in res.body) {\n const reader = res.body.getReader();\n const contentLength = Number(res.headers.get(\"Content-Length\")) || null;\n const chunks = [];\n let received = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n received += value.length;\n if (typeof onProgress === \"function\") {\n const percent = contentLength\n ? Math.round((received / contentLength) * 100)\n : null;\n onProgress(received, contentLength, percent);\n }\n }\n blob = new Blob(chunks);\n } else {\n blob = await res.blob();\n if (typeof onProgress === \"function\") onProgress(1, 1, 100);\n }\n\n // Trigger browser download\n const href = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = href;\n a.download = filename;\n a.style.display = \"none\";\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(href);\n\n return { filename, size: blob.size, type: blob.type };\n}\n\nexport function upload(\n url,\n {\n files, // File | Blob | File[] | Blob[]\n fieldName = \"file\", // form field name(s)\n fields = {}, // additional form fields (e.g., { name: \"Pascal\" })\n headers = {}, // extra headers (don't set Content-Type yourself)\n method = \"POST\",\n onProgress, // (sentBytes, totalBytes, percent) => void\n signal, // AbortSignal\n } = {},\n) {\n return new Promise((resolve, reject) => {\n const fd = buildFormData({ files, fieldName, fields });\n\n // Build URL with base\n const finalUrl = `${_base}${url}`;\n\n // Use XHR for upload progress\n const xhr = new XMLHttpRequest();\n xhr.open(method, finalUrl, true);\n\n // apply interceptors (request)\n let cfg = { method, headers: { ...headers } };\n if (_requestInterceptor) {\n cfg = _requestInterceptor(cfg) || cfg;\n }\n\n // set headers AFTER interceptor (never set Content-Type for FormData manually)\n Object.entries(cfg.headers).forEach(([k, v]) => xhr.setRequestHeader(k, v));\n\n // timeout (ms)\n xhr.timeout = _timeout;\n\n // abort support\n if (signal) {\n const onAbort = () => {\n try {\n xhr.abort();\n } catch {}\n };\n if (signal.aborted) onAbort();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n // progress\n if (xhr.upload && typeof onProgress === \"function\") {\n xhr.upload.onprogress = (e) => {\n if (!e.lengthComputable) {\n onProgress(e.loaded, null, null);\n return;\n }\n const percent = Math.round((e.loaded / e.total) * 100);\n onProgress(e.loaded, e.total, percent);\n };\n }\n\n xhr.onreadystatechange = async () => {\n if (xhr.readyState !== 4) return;\n\n // apply interceptor (response-like)\n if (_responseInterceptor) {\n // minimal fake Response compatible object\n const fakeRes = {\n status: xhr.status,\n ok: xhr.status >= 200 && xhr.status < 300,\n headers: new Headers(), // not fully accurate; fine for logging/hook\n text: async () => xhr.responseText,\n json: async () => JSON.parse(xhr.responseText || \"null\"),\n };\n _responseInterceptor(fakeRes);\n }\n\n // parse JSON or text\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n const isJson = contentType.includes(\"application/json\");\n const payload = isJson ? safeJson(xhr.responseText) : xhr.responseText;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n resolve(payload);\n } else {\n reject({\n status: xhr.status,\n data: payload,\n url: finalUrl,\n method,\n });\n }\n };\n\n xhr.onerror = () =>\n reject({\n status: 0,\n data: \"Network error\",\n url: `${_base}${url}`,\n method,\n });\n xhr.ontimeout = () =>\n reject({\n status: 0,\n data: \"Timeout\",\n url: `${_base}${url}`,\n method,\n });\n\n xhr.send(fd);\n });\n\n function safeJson(t) {\n try {\n return JSON.parse(t || \"null\");\n } catch {\n return t;\n }\n }\n}\n\nexport const get = (url, opts) => request(\"GET\", url, opts);\nexport const post = (url, body, opts = {}) =>\n request(\"POST\", url, { ...opts, body });\nexport const put = (url, body, opts = {}) =>\n request(\"PUT\", url, { ...opts, body });\nexport const del = (url, opts = {}) => request(\"DELETE\", url, opts);\nexport const raw = (url, opts) => fetch(_base + url, opts);\n\nconst HTTP = {\n base(url) {\n _base = url;\n return HTTP;\n },\n timeout(ms) {\n _timeout = ms;\n return HTTP;\n },\n interceptRequest(fn) {\n _requestInterceptor = fn;\n return HTTP;\n },\n interceptResponse(fn) {\n _responseInterceptor = fn;\n return HTTP;\n },\n\n get,\n post,\n put,\n delete: del,\n raw,\n download,\n upload,\n ping: () => console.log(\"PONG\"),\n description: \"H is for Http\",\n};\n\nexport default HTTP;\n","\"use strict\";\n\nimport EVT from \"./evt.js\";\nimport V from \"./validator.js\";\n\nconst FormEvents = {\n STATE_CHANGE: \"form:state:change\",\n ERRORS_CHANGE: \"form:errors:change\",\n SUBMIT_SUCCESS: \"form:submit:success\",\n SUBMIT_ERROR: \"form:submit:error\",\n RESET: \"form:reset\",\n VALIDATED: \"form:validated\",\n};\n\nclass FormHandler {\n constructor(formId, schema, onSubmit) {\n this.formId = formId;\n this.schema = schema;\n this.onSubmit = onSubmit;\n this.form = null;\n this.formState = {};\n this.errors = {};\n this.initialValues = {};\n\n this._boundHandleSubmit = this.#handleSubmit.bind(this);\n this._boundHandleInput = this.#handleInput.bind(this);\n\n this.#init();\n }\n\n #init() {\n this.form = document.getElementById(this.formId);\n\n if (!this.form) {\n console.error(`Form with id ${this.formId} not found`);\n return;\n }\n\n this.#captureInitialValues();\n this.form.addEventListener(\"submit\", this._boundHandleSubmit);\n this.form.addEventListener(\"input\", this._boundHandleInput);\n\n this.#publishState();\n }\n\n #captureInitialValues() {\n const formElements = this.form.elements;\n\n for (const element of Array.from(formElements)) {\n if (element.name) {\n this.initialValues[element.name] = element.value;\n this.formState[element.name] = element.value;\n }\n }\n }\n\n #handleInput(event) {\n const { name, value } = event.target;\n if (!name) return;\n\n this.formState[name] = value;\n this.#publishState();\n\n if (this.errors[name]) {\n delete this.errors[name];\n this.#publishErrors();\n }\n }\n\n #handleSubmit(event) {\n event.preventDefault();\n\n const data = new FormData(this.form);\n const formObject = {};\n\n data.forEach((value, key) => {\n formObject[key] = value;\n });\n\n this.formState = formObject;\n this.#publishState();\n\n const { isValid, errors: validateErrors } = V.run(this.schema, formObject);\n\n EVT.pub(FormEvents.VALIDATED, {\n formId: this.formId,\n isValid,\n errors: validateErrors,\n data: formObject,\n });\n\n if (isValid) {\n this.errors = {};\n this.#publishErrors();\n\n EVT.pub(FormEvents.SUBMIT_SUCCESS, {\n formId: this.formId,\n data: formObject,\n });\n\n this.onSubmit(formObject);\n } else {\n this.errors = validateErrors;\n this.#publishErrors();\n\n EVT.pub(FormEvents.SUBMIT_ERROR, {\n formId: this.formId,\n errors: validateErrors,\n });\n }\n }\n\n #publishState() {\n EVT.pub(FormEvents.STATE_CHANGE, {\n formId: this.formId,\n state: { ...this.formState },\n });\n }\n\n #publishErrors() {\n EVT.pub(FormEvents.ERRORS_CHANGE, {\n formId: this.formId,\n errors: { ...this.errors },\n });\n }\n\n getFormState() {\n return { ...this.formState };\n }\n\n getErrors() {\n return { ...this.errors };\n }\n\n reset() {\n this.formState = { ...this.initialValues };\n this.errors = {};\n\n if (this.form) {\n this.form.reset();\n }\n\n this.#publishState();\n this.#publishErrors();\n\n EVT.pub(FormEvents.RESET, { formId: this.formId });\n }\n\n validateNow() {\n const data = new FormData(this.form);\n const formObject = {};\n\n data.forEach((value, key) => {\n formObject[key] = value;\n });\n\n const result = V.run(this.schema, formObject);\n this.errors = result.errors;\n this.#publishErrors();\n\n EVT.pub(FormEvents.VALIDATED, {\n formId: this.formId,\n isValid: result.isValid,\n errors: result.errors,\n data: formObject,\n });\n\n return result;\n }\n\n destroy() {\n if (this.form) {\n this.form.removeEventListener(\"submit\", this._boundHandleSubmit);\n this.form.removeEventListener(\"input\", this._boundHandleInput);\n }\n }\n}\n\nclass FormErrorRenderer {\n constructor(formId, options = {}) {\n this.formId = formId;\n this.options = {\n containerClass: \"form-error-container\",\n errorClass: \"text-danger\",\n insertAfterField: true,\n ...options,\n };\n\n this.customContainers = {};\n\n this._boundHandleErrors = this.#handleErrors.bind(this);\n EVT.sub(FormEvents.ERRORS_CHANGE, this._boundHandleErrors);\n }\n\n #handleErrors({ formId, errors }) {\n if (formId !== this.formId) return;\n\n this.clearAll();\n this.renderAll(errors);\n }\n\n setContainer(fieldName, container) {\n this.customContainers[fieldName] =\n typeof container === \"string\"\n ? document.querySelector(container)\n : container;\n }\n\n renderAll(errors) {\n for (const field in errors) {\n this.render(field, errors[field]);\n }\n }\n\n render(fieldName, errorList) {\n if (!errorList || errorList.length === 0) return null;\n\n const errorSpan = document.createElement(\"span\");\n errorSpan.className = `${this.options.containerClass} ${this.options.errorClass}`;\n errorSpan.dataset.field = fieldName;\n\n const ul = document.createElement(\"ul\");\n errorList.forEach((item) => {\n const li = document.createElement(\"li\");\n const i = document.createElement(\"i\");\n i.textContent = item;\n li.appendChild(i);\n ul.appendChild(li);\n });\n errorSpan.appendChild(ul);\n\n const targetContainer = this.customContainers[fieldName];\n\n if (targetContainer) {\n targetContainer.innerHTML = \"\";\n targetContainer.appendChild(errorSpan);\n } else if (this.options.insertAfterField) {\n const form = document.getElementById(this.formId);\n const field = form?.querySelector(`[name=\"${fieldName}\"]`);\n if (field) {\n field.insertAdjacentElement(\"afterend\", errorSpan);\n }\n }\n return errorSpan;\n }\n\n clearAll() {\n const form = document.getElementById(this.formId);\n if (!form) return;\n\n const errors = form.querySelectorAll(`.${this.options.containerClass}`);\n errors.forEach((el) => el.remove());\n\n for (const key in this.customContainers) {\n if (this.customContainers[key]) {\n this.customContainers[key].innerHTML = \"\";\n }\n }\n }\n\n destroy() {\n EVT.unsub(FormEvents.ERRORS_CHANGE, this._boundHandleErrors);\n this.clearAll();\n }\n}\n\nexport { FormEvents, FormHandler, FormErrorRenderer };\n\nexport function useFormHandler(formId, schema, onSubmit) {\n const h = new FormHandler(formId, schema, onSubmit);\n const r = new FormErrorRenderer(formId);\n return {\n reset: () => h.reset(),\n validate: () => h.validateNow(),\n destroy: () => {\n r.destroy();\n h.destroy();\n },\n setContainer: (fieldName, container) =>\n r.setContainer(fieldName, container),\n };\n}\n","\"use strict\";\n\nexport const redirect = (url) => (window.location.href = url);\n\nexport const isArray = (arr) => Array.isArray(arr);\nexport const isArrayEmpty = (arr) => !(Array.isArray(arr) && arr.length > 0);\n\nexport const isFocus = (element) => element == document.activeElement;\n\nconst currencyMap = {\n US: { locale: \"en-US\", currency: \"USD\" },\n CA: { locale: \"en-CA\", currency: \"CAD\" },\n FR: { locale: \"fr-FR\", currency: \"EUR\" },\n HT: { locale: \"ht-HT\", currency: \"HTG\" },\n GB: { locale: \"en-GB\", currency: \"GBP\" },\n AU: { locale: \"en-AU\", currency: \"AUD\" },\n};\n\nexport const toCurrency = (\n value,\n { locale = \"en-US\", currency = \"USD\" } = {},\n) =>\n Intl.NumberFormat(locale, {\n style: \"currency\",\n currency: currency,\n }).format(value);\n\nexport const formatByCountry = (value, countryCode) => {\n const config = currencyMap[countryCode] ?? currencyMap[\"US\"];\n return toCurrency(value, config);\n};\n\nexport const isValidRoutingNumber = (routingNumber) => {\n if (!/^\\d{9}$/.test(routingNumber)) {\n return false;\n }\n\n // Split the routing number into individual digits\n const digits = routingNumber.split(\"\").map(Number);\n\n // Calculate the weighted sum\n const sum =\n 7 * (digits[0] + digits[3] + digits[6]) +\n 3 * (digits[1] + digits[4] + digits[7]) +\n 1 * (digits[2] + digits[5] + digits[8]);\n\n // Check if the sum is a multiple of 10\n return sum % 10 === 0;\n};\n"],"names":["EVT","name","callback","handlers","onceCallback","args","cb","data","e","methods","value","length","year","month","day","date","parseRule","rule","param","run","schema","formData","isValid","errors","field","rules","ruleString","validationMethod","errorMessage","V","hook","element","event","text","prop","html","make","makeId","result","alphaNum","alphaNumLength","i","parseHtml","source","tmp","onPageLoad","onWindowLoad","Q","selector","selectedElement","wrapper","val","opt","className","propertyName","attributeName","styleObject","key","all","DOM","_base","_timeout","_requestInterceptor","_responseInterceptor","memoryStore","now","makeStorageAdapter","kind","store","raw","parsed","ttl","exp","storages","hit","stableStringify","obj","k","getStorage","storageKind","buildCacheKey","method","url","params","body","p","b","buildFormData","files","fieldName","fields","fd","list","f","v","applyTimeout","ms","controller","request","opts","headers","cache","finalUrl","qs","timeoutId","useCache","strategy","storage","cacheKey","config","res","err","cached","download","filename","onProgress","init","errText","cd","match","blob","reader","contentLength","chunks","received","done","percent","href","a","upload","signal","resolve","reject","xhr","cfg","onAbort","fakeRes","payload","safeJson","t","get","post","put","del","HTTP","fn","FormEvents","FormHandler","formId","onSubmit","#handleSubmit","#handleInput","#init","#captureInitialValues","#publishState","formElements","#publishErrors","formObject","validateErrors","FormErrorRenderer","options","#handleErrors","container","errorList","errorSpan","ul","item","li","targetContainer","form","el","useFormHandler","h","r","redirect","isArray","arr","isArrayEmpty","isFocus","currencyMap","toCurrency","locale","currency","formatByCountry","countryCode","isValidRoutingNumber","routingNumber","digits"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ (function(i,y){typeof exports=="object"&&typeof module<"u"?y(exports):typeof define=="function"&&define.amd?define(["exports"],y):(i=typeof globalThis<"u"?globalThis:i||self,y(i.vaniy={}))})(this,(function(i){"use strict";const y={listeners:new Map,sub:function(e,t){let n=this.listeners.get(e);n||(n=new Set,this.listeners.set(e,n)),n.add(t)},once:function(e,t){const n=(...r)=>{t(...r),this.unsub(e,n)};this.sub(e,n)},unsub:function(e,t){let n=this.listeners.get(e);n&&n.delete(t)},pub:function(e,...t){let n=this.listeners.get(e);n&&n.forEach(r=>{try{r(...t)}catch(s){console.error(`Error in event "${e}" listener: `,s)}})},has:function(e){return this.listeners.has(e)&&this.listeners.get(e).size>0},clear:function(e){e?this.listeners.delete(e):this.listeners.clear()},ping:()=>console.log("PONG!"),description:"EVT is for Event publishing and emitting"},st={required:{method:e=>e.trim()!=="",message:"This field is required"},email:{method:e=>/\S+@\S+\.\S+/.test(e),message:"Email is invalid"},min:{method:e=>t=>t.length>=e,message:e=>`Must be at least ${e} characters`},max:{method:e=>t=>t.length<=e,message:e=>`Must be at most ${e} characters`},date:{method:e=>{if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;const[n,r,s]=e.split("-").map(Number),o=new Date(n,r-1,s);return o.getFullYear()===n&&o.getMonth()===r-1&&o.getDate()===s},message:"Date is invalid. Use the format YYYY-MM-DD."},currency:{method:e=>/^\$?\d{1,3}((,\d{3})*|\d*)(\.\d{2})?$/.test(e),message:"Currency is invalid. Use the format $123,456.78 or 123456.78."}};function ot(e){const[t,n]=e.split(":");return{name:t,param:n?parseInt(n,10):void 0}}function it(e,t){let n=!0;const r={};for(const s in e){const o=e[s];for(const a of o){const{name:d,param:h}=ot(a),g=st[d];if(!(h!==void 0?g.method(h)(t[s]):g.method(t[s]))){n=!1,r[s]||(r[s]=[]);const f=h!==void 0?g.message(h):g.message;r[s].push(f)}}}return{isValid:n,errors:r}}const O={run:it,ping:()=>console.log("PONG"),version:"1.0.0",description:"V is for validating forms"},F=e=>({on:(t,n)=>e.addEventListener(t,n),off:(t,n)=>e.removeEventListener(t,n)}),N=(e,t)=>{if(!e)return;const n="innerText"in e?"innerText":"textContent";return t!=null&&(e[n]=t),e[n]},_=(e,t)=>{if(e)return t!=null&&(e.innerHTML=t),e.innerHTML},V=e=>document.createElement(e),k=e=>{let t="";const n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",r=n.length;for(let s=0;s<e;s++)t+=n.charAt(Math.floor(Math.random()*r));return t},G=e=>{const t=document.implementation.createHTMLDocument("");return t.body.innerHTML=e,[...t.body.childNodes]},q=e=>{document.readyState!=="loading"?e():document.addEventListener("DOMContentLoaded",e)},B=e=>{window.onload=e},U=e=>{const t=document.querySelector(e),n={elt:t,value:t?.value,text:r=>r!=null?(N(t,r),n):N(t),print:()=>t,html:r=>r!=null?(_(t,r),n):_(t),val:()=>t.options&&t.multiple?Array.from(t.options).filter(r=>r.selected).map(r=>r.value):t.value,addClass:r=>(t.classList.add(r),n),removeClass:r=>(t.classList.remove(r),n),hasClass:r=>t.classList.contains(r),hide:()=>{t.style.display="none"},show:()=>{t.style.display=""},prop:r=>t[r],attr:r=>t.getAttribute(r),removeAttr:r=>{t.removeAttribute(r)},toggle:()=>{t.style.display=="none"?n.show():n.hide()},css:r=>(Object.entries(r).forEach(([s,o])=>{t.style[s]=o}),n),on:F(t).on,off:F(t).off};return n},D=e=>document.querySelectorAll(e),at={Q:U,$:U,all:D,$$:D,make:V,makeId:k,parseHtml:G,onPageLoad:q,onWindowLoad:B,ping:()=>console.log("PONG!"),description:"DOM is for dom manipulation"};let T="",H=8e3,C=null,A=null;const I=new Map,L=()=>Date.now();function j(e){const t=typeof window<"u"?window[e]:null;return t?{get(n){const r=t.getItem(n);if(!r)return null;try{const s=JSON.parse(r);return s.exp&&s.exp<L()?(t.removeItem(n),null):s.val}catch{return null}},set(n,r,s){const o=s?L()+s:null;t.setItem(n,JSON.stringify({val:r,exp:o}))},del(n){t&&t.removeItem(n)},clear(){t&&t.clear()}}:null}const P={memory:{get(e){const t=I.get(e);return t?t.exp&&t.exp<L()?(I.delete(e),null):t.val:null},set(e,t,n){const r=n?L()+n:null;I.set(e,{val:t,exp:r})},del(e){I.delete(e)},clear(){I.clear()}},local:j("localStorage"),session:j("sessionStorage")};function M(e){return e===null||typeof e!="object"?String(e):Array.isArray(e)?`[${e.map(M).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${M(e[t])}`).join(",")}}`}function lt(e="memory"){return P[e]||P.memory}function ct(e,t,n,r){const s=n?`?${new URLSearchParams(n).toString()}`:"",o=r&&e!=="GET"?`#${M(r)}`:"";return`H|${e}|${t}${s}${o}`}function ut({files:e,fieldName:t="file",fields:n={}}){const r=new FormData,s=Array.isArray(e)?e:[e];return s.forEach((o,a)=>{const d=s.length>1?`${t}[${a}]`:t;r.append(d,o)}),Object.entries(n).forEach(([o,a])=>{r.append(o,a instanceof Blob||a instanceof File?a:typeof a=="object"?JSON.stringify(a):String(a))}),r}const J=(e,t)=>setTimeout(()=>t.abort(),e);async function R(e,t,n={}){const{params:r,body:s,headers:o={},cache:a}=n;let d=T+t;if(r){const u=new URLSearchParams(r).toString();d+=(d.includes("?")?"&":"?")+u}const h=new AbortController,g=J(H,h),p=!!a,f=a?.strategy,S=a?.ttl??0,l=lt(a?.storage),m=a?.key||ct(e,d,r,s);if(p&&!a?.forceRefresh&&f==="cache-first"){const u=l.get(m);if(u!==null)return u}let c={method:e,headers:o,signal:h.signal};s!==void 0&&(s instanceof FormData?c.body=s:(c.headers["Content-Type"]="application/json",c.body=JSON.stringify(s))),C&&(c=C(c)||c);try{let u=await fetch(d,c);clearTimeout(g),A&&(u=A(u)||u);let b;try{b=await u.json()}catch{b=await u.text()}if(!u.ok){const w={status:u.status,data:b,url:d,method:e};if(p&&f==="network-first"){const $=l.get(m);if($!==null)return $}throw w}return p&&l.set(m,b,S),b}catch(u){if(clearTimeout(g),p&&f==="network-first"){const b=l.get(m);if(b!==null)return b}throw u}}async function Y(e,{filename:t,params:n,headers:r={},method:s="GET",body:o,onProgress:a}={}){let d=T+e;if(n){const c=new URLSearchParams(n).toString();d+=(d.includes("?")?"&":"?")+c}const h=new AbortController,g=J(H,h),p={method:s,headers:{...r},signal:h.signal};o!==void 0&&(o instanceof FormData?p.body=o:(p.headers["Content-Type"]=p.headers["Content-Type"]||"application/json",p.body=typeof o=="string"?o:JSON.stringify(o)));const f=await fetch(d,p);if(clearTimeout(g),!f.ok){let c="";try{c=await f.text()}catch{}throw new Error(`Download failed ${f.status}: ${c||f.statusText}`)}if(!t){const c=f.headers.get("Content-Disposition")||"",u=/filename\*=UTF-8''([^;]+)|filename="?([^"]+)"?/i.exec(c);t=decodeURIComponent(u?.[1]||u?.[2]||"download")}let S;if(f.body&&"getReader"in f.body){const c=f.body.getReader(),u=Number(f.headers.get("Content-Length"))||null,b=[];let w=0;for(;;){const{done:$,value:rt}=await c.read();if($)break;if(b.push(rt),w+=rt.length,typeof a=="function"){const bt=u?Math.round(w/u*100):null;a(w,u,bt)}}S=new Blob(b)}else S=await f.blob(),typeof a=="function"&&a(1,1,100);const l=URL.createObjectURL(S),m=document.createElement("a");return m.href=l,m.download=t,m.style.display="none",document.body.appendChild(m),m.click(),document.body.removeChild(m),URL.revokeObjectURL(l),{filename:t,size:S.size,type:S.type}}function z(e,{files:t,fieldName:n="file",fields:r={},headers:s={},method:o="POST",onProgress:a,signal:d}={}){return new Promise((g,p)=>{const f=ut({files:t,fieldName:n,fields:r}),S=`${T}${e}`,l=new XMLHttpRequest;l.open(o,S,!0);let m={method:o,headers:{...s}};if(C&&(m=C(m)||m),Object.entries(m.headers).forEach(([c,u])=>l.setRequestHeader(c,u)),l.timeout=H,d){const c=()=>{try{l.abort()}catch{}};d.aborted&&c(),d.addEventListener("abort",c,{once:!0})}l.upload&&typeof a=="function"&&(l.upload.onprogress=c=>{if(!c.lengthComputable){a(c.loaded,null,null);return}const u=Math.round(c.loaded/c.total*100);a(c.loaded,c.total,u)}),l.onreadystatechange=async()=>{if(l.readyState!==4)return;if(A){const w={status:l.status,ok:l.status>=200&&l.status<300,headers:new Headers,text:async()=>l.responseText,json:async()=>JSON.parse(l.responseText||"null")};A(w)}const b=(l.getResponseHeader("Content-Type")||"").includes("application/json")?h(l.responseText):l.responseText;l.status>=200&&l.status<300?g(b):p({status:l.status,data:b,url:S,method:o})},l.onerror=()=>p({status:0,data:"Network error",url:`${T}${e}`,method:o}),l.ontimeout=()=>p({status:0,data:"Timeout",url:`${T}${e}`,method:o}),l.send(f)});function h(g){try{return JSON.parse(g||"null")}catch{return g}}}const K=(e,t)=>R("GET",e,t),Q=(e,t,n={})=>R("POST",e,{...n,body:t}),W=(e,t,n={})=>R("PUT",e,{...n,body:t}),X=(e,t={})=>R("DELETE",e,t),x=(e,t)=>fetch(T+e,t),v={base(e){return T=e,v},timeout(e){return H=e,v},interceptRequest(e){return C=e,v},interceptResponse(e){return A=e,v},get:K,post:Q,put:W,delete:X,raw:x,download:Y,upload:z,ping:()=>console.log("PONG"),description:"H is for Http"},E={STATE_CHANGE:"form:state:change",ERRORS_CHANGE:"form:errors:change",SUBMIT_SUCCESS:"form:submit:success",SUBMIT_ERROR:"form:submit:error",RESET:"form:reset",VALIDATED:"form:validated"};class Z{constructor(t,n,r){this.formId=t,this.schema=n,this.onSubmit=r,this.form=null,this.formState={},this.errors={},this.initialValues={},this._boundHandleSubmit=this.#o.bind(this),this._boundHandleInput=this.#s.bind(this),this.#n()}#n(){if(this.form=document.getElementById(this.formId),!this.form){console.error(`Form with id ${this.formId} not found`);return}this.#r(),this.form.addEventListener("submit",this._boundHandleSubmit),this.form.addEventListener("input",this._boundHandleInput),this.#e()}#r(){const t=this.form.elements;for(const n of Array.from(t))n.name&&(this.initialValues[n.name]=n.value,this.formState[n.name]=n.value)}#s(t){const{name:n,value:r}=t.target;n&&(this.formState[n]=r,this.#e(),this.errors[n]&&(delete this.errors[n],this.#t()))}#o(t){t.preventDefault();const n=new FormData(this.form),r={};n.forEach((a,d)=>{r[d]=a}),this.formState=r,this.#e();const{isValid:s,errors:o}=O.run(this.schema,r);y.pub(E.VALIDATED,{formId:this.formId,isValid:s,errors:o,data:r}),s?(this.errors={},this.#t(),y.pub(E.SUBMIT_SUCCESS,{formId:this.formId,data:r}),this.onSubmit(r)):(this.errors=o,this.#t(),y.pub(E.SUBMIT_ERROR,{formId:this.formId,errors:o}))}#e(){y.pub(E.STATE_CHANGE,{formId:this.formId,state:{...this.formState}})}#t(){y.pub(E.ERRORS_CHANGE,{formId:this.formId,errors:{...this.errors}})}getFormState(){return{...this.formState}}getErrors(){return{...this.errors}}reset(){this.formState={...this.initialValues},this.errors={},this.form&&this.form.reset(),this.#e(),this.#t(),y.pub(E.RESET,{formId:this.formId})}validateNow(){const t=new FormData(this.form),n={};t.forEach((s,o)=>{n[o]=s});const r=O.run(this.schema,n);return this.errors=r.errors,this.#t(),y.pub(E.VALIDATED,{formId:this.formId,isValid:r.isValid,errors:r.errors,data:n}),r}destroy(){this.form&&(this.form.removeEventListener("submit",this._boundHandleSubmit),this.form.removeEventListener("input",this._boundHandleInput))}}class tt{constructor(t,n={}){this.formId=t,this.options={containerClass:"form-error-container",errorClass:"text-danger",insertAfterField:!0,...n},this.customContainers={},this._boundHandleErrors=this.#n.bind(this),y.sub(E.ERRORS_CHANGE,this._boundHandleErrors)}#n({formId:t,errors:n}){t===this.formId&&(this.clearAll(),this.renderAll(n))}setContainer(t,n){this.customContainers[t]=typeof n=="string"?document.querySelector(n):n}renderAll(t){for(const n in t)this.render(n,t[n])}render(t,n){if(!n||n.length===0)return null;const r=document.createElement("span");r.className=`${this.options.containerClass} ${this.options.errorClass}`,r.dataset.field=t;const s=document.createElement("ul");n.forEach(a=>{const d=document.createElement("li"),h=document.createElement("i");h.textContent=a,d.appendChild(h),s.appendChild(d)}),r.appendChild(s);const o=this.customContainers[t];if(o)o.innerHTML="",o.appendChild(r);else if(this.options.insertAfterField){const d=document.getElementById(this.formId)?.querySelector(`[name="${t}"]`);d&&d.insertAdjacentElement("afterend",r)}return r}clearAll(){const t=document.getElementById(this.formId);if(!t)return;t.querySelectorAll(`.${this.options.containerClass}`).forEach(r=>r.remove());for(const r in this.customContainers)this.customContainers[r]&&(this.customContainers[r].innerHTML="")}destroy(){y.unsub(E.ERRORS_CHANGE,this._boundHandleErrors),this.clearAll()}}function dt(e,t,n){const r=new Z(e,t,n),s=new tt(e);return{reset:()=>r.reset(),validate:()=>r.validateNow(),destroy:()=>{s.destroy(),r.destroy()},setContainer:(o,a)=>s.setContainer(o,a)}}const ft=e=>window.location.href=e,mt=e=>Array.isArray(e),ht=e=>!(Array.isArray(e)&&e.length>0),pt=e=>e==document.activeElement,et={US:{locale:"en-US",currency:"USD"},CA:{locale:"en-CA",currency:"CAD"},FR:{locale:"fr-FR",currency:"EUR"},HT:{locale:"ht-HT",currency:"HTG"},GB:{locale:"en-GB",currency:"GBP"},AU:{locale:"en-AU",currency:"AUD"}},nt=(e,{locale:t="en-US",currency:n="USD"}={})=>Intl.NumberFormat(t,{style:"currency",currency:n}).format(e),yt=(e,t)=>{const n=et[t]??et.US;return nt(e,n)},gt=e=>{if(!/^\d{9}$/.test(e))return!1;const t=e.split("").map(Number);return(7*(t[0]+t[3]+t[6])+3*(t[1]+t[4]+t[7])+1*(t[2]+t[5]+t[8]))%10===0};i.DOM=at,i.EVT=y,i.FormErrorRenderer=tt,i.FormEvents=E,i.FormHandler=Z,i.HTTP=v,i.Q=U,i.V=O,i.all=D,i.del=X,i.download=Y,i.formatByCountry=yt,i.get=K,i.isArray=mt,i.isArrayEmpty=ht,i.isFocus=pt,i.isValidRoutingNumber=gt,i.make=V,i.makeId=k,i.onPageLoad=q,i.onWindowLoad=B,i.parseHtml=G,i.post=Q,i.put=W,i.raw=x,i.redirect=ft,i.request=R,i.toCurrency=nt,i.upload=z,i.useFormHandler=dt,Object.defineProperty(i,Symbol.toStringTag,{value:"Module"})}));
2
+ //# sourceMappingURL=vaniy.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vaniy.umd.js","sources":["../src/evt.js","../src/validator.js","../src/dom.js","../src/http.js","../src/form.js","../src/utils.js"],"sourcesContent":["\"use strict\";\n\nconst EVT = {\n listeners: new Map(),\n sub: function (name, callback) {\n let handlers = this.listeners.get(name);\n if (!handlers) {\n handlers = new Set();\n this.listeners.set(name, handlers);\n }\n handlers.add(callback);\n },\n once: function (name, callback) {\n const onceCallback = (...args) => {\n callback(...args);\n this.unsub(name, onceCallback);\n };\n this.sub(name, onceCallback);\n },\n unsub: function (name, cb) {\n let handlers = this.listeners.get(name);\n if (!handlers) return;\n handlers.delete(cb);\n },\n pub: function (name, ...data) {\n let handlers = this.listeners.get(name);\n if (!handlers) return;\n handlers.forEach((cb) => {\n try {\n cb(...data);\n } catch (e) {\n console.error(`Error in event \"${name}\" listener: `, e);\n }\n });\n },\n has: function (name) {\n return this.listeners.has(name) && this.listeners.get(name).size > 0;\n },\n clear: function (name) {\n if (name) {\n this.listeners.delete(name);\n } else {\n this.listeners.clear();\n }\n },\n ping: () => console.log(\"PONG!\"),\n description: \"EVT is for Event publishing and emitting\",\n};\n\nexport default EVT;\n","\"use strict\";\n\nconst methods = {\n required: {\n method: (value) => value.trim() !== \"\",\n message: \"This field is required\",\n },\n email: {\n method: (value) => /\\S+@\\S+\\.\\S+/.test(value),\n message: \"Email is invalid\",\n },\n min: {\n method: (length) => (value) => value.length >= length,\n message: (length) => `Must be at least ${length} characters`,\n },\n max: {\n method: (length) => (value) => value.length <= length,\n message: (length) => `Must be at most ${length} characters`,\n },\n date: {\n method: (value) => {\n const dateRegex = /^\\d{4}-\\d{2}-\\d{2}$/;\n if (!dateRegex.test(value)) return false;\n const [year, month, day] = value.split(\"-\").map(Number);\n const date = new Date(year, month - 1, day);\n return (\n date.getFullYear() === year &&\n date.getMonth() === month - 1 &&\n date.getDate() === day\n );\n },\n message: \"Date is invalid. Use the format YYYY-MM-DD.\",\n },\n currency: {\n method: (value) => /^\\$?\\d{1,3}((,\\d{3})*|\\d*)(\\.\\d{2})?$/.test(value),\n message: \"Currency is invalid. Use the format $123,456.78 or 123456.78.\",\n },\n};\n\nfunction parseRule(rule) {\n const [name, param] = rule.split(\":\");\n return { name, param: param ? parseInt(param, 10) : undefined };\n}\n\nfunction run(schema, formData) {\n let isValid = true;\n const errors = {};\n\n for (const field in schema) {\n const rules = schema[field];\n\n for (const ruleString of rules) {\n const { name, param } = parseRule(ruleString);\n const validationMethod = methods[name];\n\n const isFieldValid =\n param !== undefined\n ? validationMethod.method(param)(formData[field])\n : validationMethod.method(formData[field]);\n\n if (!isFieldValid) {\n isValid = false;\n if (!errors[field]) {\n errors[field] = [];\n }\n const errorMessage =\n param !== undefined\n ? validationMethod.message(param)\n : validationMethod.message;\n\n errors[field].push(errorMessage);\n }\n }\n }\n return { isValid, errors };\n}\n\nconst V = {\n run,\n ping: () => console.log(\"PONG\"),\n version: \"1.0.0\",\n description: \"V is for validating forms\",\n};\n\nexport default V;\n","\"use strict\";\n\nconst hook = (element) => ({\n on: (event, callback) => element.addEventListener(event, callback),\n off: (event, callback) => element.removeEventListener(event, callback),\n});\n\nconst text = (element, value) => {\n if (!element) return undefined;\n const prop = \"innerText\" in element ? \"innerText\" : \"textContent\";\n if (value != null) element[prop] = value; // allows empty string\n return element[prop];\n};\n\nconst html = (element, value) => {\n if (!element) return undefined;\n if (value != null) element.innerHTML = value;\n return element.innerHTML;\n};\n\nexport const make = (name) => document.createElement(name);\n\nexport const makeId = (length) => {\n let result = \"\";\n const alphaNum =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n const alphaNumLength = alphaNum.length;\n\n for (let i = 0; i < length; i++) {\n result += alphaNum.charAt(Math.floor(Math.random() * alphaNumLength));\n }\n return result;\n};\n\nexport const parseHtml = (source) => {\n const tmp = document.implementation.createHTMLDocument(\"\");\n tmp.body.innerHTML = source;\n return [...tmp.body.childNodes];\n};\n\nexport const onPageLoad = (callback) => {\n if (document.readyState !== \"loading\") callback();\n else document.addEventListener(\"DOMContentLoaded\", callback);\n};\n\nexport const onWindowLoad = (callback) => {\n window.onload = callback;\n};\n\nexport const Q = (selector) => {\n const selectedElement = document.querySelector(selector);\n\n const wrapper = {\n elt: selectedElement,\n value: selectedElement?.value,\n text: (val) => {\n if (val != null) {\n text(selectedElement, val);\n return wrapper;\n }\n return text(selectedElement);\n },\n print: () => {\n return selectedElement;\n },\n html: (val) => {\n if (val != null) {\n html(selectedElement, val);\n return wrapper;\n }\n return html(selectedElement);\n },\n val: () => {\n if (selectedElement.options && selectedElement.multiple) {\n return Array.from(selectedElement.options)\n .filter((opt) => opt.selected)\n .map((opt) => opt.value);\n }\n return selectedElement.value;\n },\n addClass: (className) => {\n selectedElement.classList.add(className);\n return wrapper;\n },\n removeClass: (className) => {\n selectedElement.classList.remove(className);\n return wrapper;\n },\n hasClass: (className) => {\n return selectedElement.classList.contains(className);\n },\n hide: () => {\n selectedElement.style.display = \"none\";\n },\n show: () => {\n selectedElement.style.display = \"\";\n },\n prop: (propertyName) => {\n return selectedElement[propertyName];\n },\n attr: (attributeName) => {\n return selectedElement.getAttribute(attributeName);\n },\n removeAttr: (attributeName) => {\n selectedElement.removeAttribute(attributeName);\n },\n toggle: () => {\n if (selectedElement.style.display == \"none\") wrapper.show();\n else wrapper.hide();\n },\n css: (styleObject) => {\n Object.entries(styleObject).forEach(([key, value]) => {\n selectedElement.style[key] = value;\n });\n return wrapper;\n },\n on: hook(selectedElement).on,\n off: hook(selectedElement).off,\n };\n return wrapper;\n};\n\nexport const all = (selector) => {\n const selectedElements = document.querySelectorAll(selector);\n return selectedElements;\n};\n\nconst DOM = {\n Q,\n $: Q,\n all,\n $$: all,\n make,\n makeId,\n parseHtml,\n onPageLoad,\n onWindowLoad,\n ping: () => console.log(\"PONG!\"),\n description: \"DOM is for dom manipulation\",\n};\n\nexport default DOM;\n","\"use strict\";\n\nlet _base = \"\";\nlet _timeout = 8000;\nlet _requestInterceptor = null;\nlet _responseInterceptor = null;\n\nconst memoryStore = new Map();\nconst now = () => Date.now();\n\nfunction makeStorageAdapter(kind) {\n const store = typeof window !== \"undefined\" ? window[kind] : null;\n if (!store) return null;\n return {\n get(key) {\n const raw = store.getItem(key);\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw);\n if (parsed.exp && parsed.exp < now()) {\n store.removeItem(key);\n return null;\n }\n return parsed.val;\n } catch {\n return null;\n }\n },\n set(key, val, ttl) {\n const exp = ttl ? now() + ttl : null;\n store.setItem(key, JSON.stringify({ val, exp }));\n },\n del(key) {\n if (store) store.removeItem(key);\n },\n clear() {\n if (store) store.clear();\n },\n };\n}\n\nconst storages = {\n memory: {\n get(key) {\n const hit = memoryStore.get(key);\n if (!hit) return null;\n if (hit.exp && hit.exp < now()) {\n memoryStore.delete(key);\n return null;\n }\n return hit.val;\n },\n set(key, val, ttl) {\n const exp = ttl ? now() + ttl : null;\n memoryStore.set(key, { val, exp });\n },\n del(key) {\n memoryStore.delete(key);\n },\n clear() {\n memoryStore.clear();\n },\n },\n local: makeStorageAdapter(\"localStorage\"),\n session: makeStorageAdapter(\"sessionStorage\"),\n};\n\nfunction stableStringify(obj) {\n if (obj === null || typeof obj !== \"object\") return String(obj);\n if (Array.isArray(obj)) return `[${obj.map(stableStringify).join(\",\")}]`;\n return `{${Object.keys(obj)\n .sort()\n .map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`)\n .join(\",\")}}`;\n}\n\nfunction getStorage(storageKind = \"memory\") {\n return storages[storageKind] || storages.memory;\n}\n\nfunction buildCacheKey(method, url, params, body) {\n const p = params ? `?${new URLSearchParams(params).toString()}` : \"\";\n const b = body && method !== \"GET\" ? `#${stableStringify(body)}` : \"\";\n return `H|${method}|${url}${p}${b}`;\n}\n\nfunction buildFormData({ files, fieldName = \"file\", fields = {} }) {\n const fd = new FormData();\n\n const list = Array.isArray(files) ? files : [files];\n list.forEach((f, i) => {\n const name = list.length > 1 ? `${fieldName}[${i}]` : fieldName;\n fd.append(name, f);\n });\n\n Object.entries(fields).forEach(([k, v]) => {\n fd.append(\n k,\n v instanceof Blob || v instanceof File\n ? v\n : typeof v === \"object\"\n ? JSON.stringify(v)\n : String(v),\n );\n });\n\n return fd;\n}\n\nconst applyTimeout = (ms, controller) =>\n setTimeout(() => controller.abort(), ms);\n\nexport async function request(method, url, opts = {}) {\n const { params, body, headers = {}, cache } = opts;\n\n let finalUrl = _base + url;\n if (params) {\n const qs = new URLSearchParams(params).toString();\n finalUrl += (finalUrl.includes(\"?\") ? \"&\" : \"?\") + qs;\n }\n\n const controller = new AbortController();\n const timeoutId = applyTimeout(_timeout, controller);\n const useCache = !!cache;\n const strategy = cache?.strategy; // 'cache-first' | 'network-first'\n const ttl = cache?.ttl ?? 0;\n const storage = getStorage(cache?.storage);\n const cacheKey = cache?.key || buildCacheKey(method, finalUrl, params, body);\n\n if (useCache && !cache?.forceRefresh && strategy === \"cache-first\") {\n const hit = storage.get(cacheKey);\n if (hit !== null) return hit;\n }\n\n // Build URL with base + query params\n\n let config = {\n method,\n headers,\n signal: controller.signal,\n };\n\n if (body !== undefined) {\n if (body instanceof FormData) {\n config.body = body;\n } else {\n config.headers[\"Content-Type\"] = \"application/json\";\n config.body = JSON.stringify(body);\n }\n }\n\n if (_requestInterceptor) {\n config = _requestInterceptor(config) || config;\n }\n\n try {\n let res = await fetch(finalUrl, config);\n clearTimeout(timeoutId);\n\n if (_responseInterceptor) {\n res = _responseInterceptor(res) || res;\n }\n\n // Try to parse JSON but fallback to text\n let data;\n try {\n data = await res.json();\n } catch {\n data = await res.text();\n }\n\n if (!res.ok) {\n const err = {\n status: res.status,\n data,\n url: finalUrl,\n method,\n };\n //for network-first with cache fallback on error, try cached value\n if (useCache && strategy === \"network-first\") {\n const cached = storage.get(cacheKey);\n if (cached !== null) return cached;\n }\n throw err;\n }\n\n if (useCache) {\n storage.set(cacheKey, data, ttl);\n }\n return data;\n } catch (err) {\n clearTimeout(timeoutId);\n if (useCache && strategy === \"network-first\") {\n const cached = storage.get(cacheKey);\n if (cached !== null) return cached;\n }\n throw err;\n }\n}\n\nexport async function download(\n url,\n { filename, params, headers = {}, method = \"GET\", body, onProgress } = {},\n) {\n // Build URL w/ base + params\n let finalUrl = _base + url;\n if (params) {\n const qs = new URLSearchParams(params).toString();\n finalUrl += (finalUrl.includes(\"?\") ? \"&\" : \"?\") + qs;\n }\n\n const controller = new AbortController();\n const timeoutId = applyTimeout(_timeout, controller);\n\n // Prepare request\n const init = {\n method,\n headers: { ...headers },\n signal: controller.signal,\n };\n if (body !== undefined) {\n if (body instanceof FormData) {\n init.body = body;\n } else {\n init.headers[\"Content-Type\"] =\n init.headers[\"Content-Type\"] || \"application/json\";\n init.body = typeof body === \"string\" ? body : JSON.stringify(body);\n }\n }\n\n const res = await fetch(finalUrl, init);\n clearTimeout(timeoutId);\n if (!res.ok) {\n let errText = \"\";\n try {\n errText = await res.text();\n } catch {}\n throw new Error(\n `Download failed ${res.status}: ${errText || res.statusText}`,\n );\n }\n\n // Try to infer filename from Content-Disposition\n if (!filename) {\n const cd = res.headers.get(\"Content-Disposition\") || \"\";\n const match = /filename\\*=UTF-8''([^;]+)|filename=\"?([^\"]+)\"?/i.exec(cd);\n filename = decodeURIComponent(match?.[1] || match?.[2] || \"download\");\n }\n\n // Stream with progress if possible\n let blob;\n if (res.body && \"getReader\" in res.body) {\n const reader = res.body.getReader();\n const contentLength = Number(res.headers.get(\"Content-Length\")) || null;\n const chunks = [];\n let received = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n chunks.push(value);\n received += value.length;\n if (typeof onProgress === \"function\") {\n const percent = contentLength\n ? Math.round((received / contentLength) * 100)\n : null;\n onProgress(received, contentLength, percent);\n }\n }\n blob = new Blob(chunks);\n } else {\n blob = await res.blob();\n if (typeof onProgress === \"function\") onProgress(1, 1, 100);\n }\n\n // Trigger browser download\n const href = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = href;\n a.download = filename;\n a.style.display = \"none\";\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(href);\n\n return { filename, size: blob.size, type: blob.type };\n}\n\nexport function upload(\n url,\n {\n files, // File | Blob | File[] | Blob[]\n fieldName = \"file\", // form field name(s)\n fields = {}, // additional form fields (e.g., { name: \"Pascal\" })\n headers = {}, // extra headers (don't set Content-Type yourself)\n method = \"POST\",\n onProgress, // (sentBytes, totalBytes, percent) => void\n signal, // AbortSignal\n } = {},\n) {\n return new Promise((resolve, reject) => {\n const fd = buildFormData({ files, fieldName, fields });\n\n // Build URL with base\n const finalUrl = `${_base}${url}`;\n\n // Use XHR for upload progress\n const xhr = new XMLHttpRequest();\n xhr.open(method, finalUrl, true);\n\n // apply interceptors (request)\n let cfg = { method, headers: { ...headers } };\n if (_requestInterceptor) {\n cfg = _requestInterceptor(cfg) || cfg;\n }\n\n // set headers AFTER interceptor (never set Content-Type for FormData manually)\n Object.entries(cfg.headers).forEach(([k, v]) => xhr.setRequestHeader(k, v));\n\n // timeout (ms)\n xhr.timeout = _timeout;\n\n // abort support\n if (signal) {\n const onAbort = () => {\n try {\n xhr.abort();\n } catch {}\n };\n if (signal.aborted) onAbort();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n // progress\n if (xhr.upload && typeof onProgress === \"function\") {\n xhr.upload.onprogress = (e) => {\n if (!e.lengthComputable) {\n onProgress(e.loaded, null, null);\n return;\n }\n const percent = Math.round((e.loaded / e.total) * 100);\n onProgress(e.loaded, e.total, percent);\n };\n }\n\n xhr.onreadystatechange = async () => {\n if (xhr.readyState !== 4) return;\n\n // apply interceptor (response-like)\n if (_responseInterceptor) {\n // minimal fake Response compatible object\n const fakeRes = {\n status: xhr.status,\n ok: xhr.status >= 200 && xhr.status < 300,\n headers: new Headers(), // not fully accurate; fine for logging/hook\n text: async () => xhr.responseText,\n json: async () => JSON.parse(xhr.responseText || \"null\"),\n };\n _responseInterceptor(fakeRes);\n }\n\n // parse JSON or text\n const contentType = xhr.getResponseHeader(\"Content-Type\") || \"\";\n const isJson = contentType.includes(\"application/json\");\n const payload = isJson ? safeJson(xhr.responseText) : xhr.responseText;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n resolve(payload);\n } else {\n reject({\n status: xhr.status,\n data: payload,\n url: finalUrl,\n method,\n });\n }\n };\n\n xhr.onerror = () =>\n reject({\n status: 0,\n data: \"Network error\",\n url: `${_base}${url}`,\n method,\n });\n xhr.ontimeout = () =>\n reject({\n status: 0,\n data: \"Timeout\",\n url: `${_base}${url}`,\n method,\n });\n\n xhr.send(fd);\n });\n\n function safeJson(t) {\n try {\n return JSON.parse(t || \"null\");\n } catch {\n return t;\n }\n }\n}\n\nexport const get = (url, opts) => request(\"GET\", url, opts);\nexport const post = (url, body, opts = {}) =>\n request(\"POST\", url, { ...opts, body });\nexport const put = (url, body, opts = {}) =>\n request(\"PUT\", url, { ...opts, body });\nexport const del = (url, opts = {}) => request(\"DELETE\", url, opts);\nexport const raw = (url, opts) => fetch(_base + url, opts);\n\nconst HTTP = {\n base(url) {\n _base = url;\n return HTTP;\n },\n timeout(ms) {\n _timeout = ms;\n return HTTP;\n },\n interceptRequest(fn) {\n _requestInterceptor = fn;\n return HTTP;\n },\n interceptResponse(fn) {\n _responseInterceptor = fn;\n return HTTP;\n },\n\n get,\n post,\n put,\n delete: del,\n raw,\n download,\n upload,\n ping: () => console.log(\"PONG\"),\n description: \"H is for Http\",\n};\n\nexport default HTTP;\n","\"use strict\";\n\nimport EVT from \"./evt.js\";\nimport V from \"./validator.js\";\n\nconst FormEvents = {\n STATE_CHANGE: \"form:state:change\",\n ERRORS_CHANGE: \"form:errors:change\",\n SUBMIT_SUCCESS: \"form:submit:success\",\n SUBMIT_ERROR: \"form:submit:error\",\n RESET: \"form:reset\",\n VALIDATED: \"form:validated\",\n};\n\nclass FormHandler {\n constructor(formId, schema, onSubmit) {\n this.formId = formId;\n this.schema = schema;\n this.onSubmit = onSubmit;\n this.form = null;\n this.formState = {};\n this.errors = {};\n this.initialValues = {};\n\n this._boundHandleSubmit = this.#handleSubmit.bind(this);\n this._boundHandleInput = this.#handleInput.bind(this);\n\n this.#init();\n }\n\n #init() {\n this.form = document.getElementById(this.formId);\n\n if (!this.form) {\n console.error(`Form with id ${this.formId} not found`);\n return;\n }\n\n this.#captureInitialValues();\n this.form.addEventListener(\"submit\", this._boundHandleSubmit);\n this.form.addEventListener(\"input\", this._boundHandleInput);\n\n this.#publishState();\n }\n\n #captureInitialValues() {\n const formElements = this.form.elements;\n\n for (const element of Array.from(formElements)) {\n if (element.name) {\n this.initialValues[element.name] = element.value;\n this.formState[element.name] = element.value;\n }\n }\n }\n\n #handleInput(event) {\n const { name, value } = event.target;\n if (!name) return;\n\n this.formState[name] = value;\n this.#publishState();\n\n if (this.errors[name]) {\n delete this.errors[name];\n this.#publishErrors();\n }\n }\n\n #handleSubmit(event) {\n event.preventDefault();\n\n const data = new FormData(this.form);\n const formObject = {};\n\n data.forEach((value, key) => {\n formObject[key] = value;\n });\n\n this.formState = formObject;\n this.#publishState();\n\n const { isValid, errors: validateErrors } = V.run(this.schema, formObject);\n\n EVT.pub(FormEvents.VALIDATED, {\n formId: this.formId,\n isValid,\n errors: validateErrors,\n data: formObject,\n });\n\n if (isValid) {\n this.errors = {};\n this.#publishErrors();\n\n EVT.pub(FormEvents.SUBMIT_SUCCESS, {\n formId: this.formId,\n data: formObject,\n });\n\n this.onSubmit(formObject);\n } else {\n this.errors = validateErrors;\n this.#publishErrors();\n\n EVT.pub(FormEvents.SUBMIT_ERROR, {\n formId: this.formId,\n errors: validateErrors,\n });\n }\n }\n\n #publishState() {\n EVT.pub(FormEvents.STATE_CHANGE, {\n formId: this.formId,\n state: { ...this.formState },\n });\n }\n\n #publishErrors() {\n EVT.pub(FormEvents.ERRORS_CHANGE, {\n formId: this.formId,\n errors: { ...this.errors },\n });\n }\n\n getFormState() {\n return { ...this.formState };\n }\n\n getErrors() {\n return { ...this.errors };\n }\n\n reset() {\n this.formState = { ...this.initialValues };\n this.errors = {};\n\n if (this.form) {\n this.form.reset();\n }\n\n this.#publishState();\n this.#publishErrors();\n\n EVT.pub(FormEvents.RESET, { formId: this.formId });\n }\n\n validateNow() {\n const data = new FormData(this.form);\n const formObject = {};\n\n data.forEach((value, key) => {\n formObject[key] = value;\n });\n\n const result = V.run(this.schema, formObject);\n this.errors = result.errors;\n this.#publishErrors();\n\n EVT.pub(FormEvents.VALIDATED, {\n formId: this.formId,\n isValid: result.isValid,\n errors: result.errors,\n data: formObject,\n });\n\n return result;\n }\n\n destroy() {\n if (this.form) {\n this.form.removeEventListener(\"submit\", this._boundHandleSubmit);\n this.form.removeEventListener(\"input\", this._boundHandleInput);\n }\n }\n}\n\nclass FormErrorRenderer {\n constructor(formId, options = {}) {\n this.formId = formId;\n this.options = {\n containerClass: \"form-error-container\",\n errorClass: \"text-danger\",\n insertAfterField: true,\n ...options,\n };\n\n this.customContainers = {};\n\n this._boundHandleErrors = this.#handleErrors.bind(this);\n EVT.sub(FormEvents.ERRORS_CHANGE, this._boundHandleErrors);\n }\n\n #handleErrors({ formId, errors }) {\n if (formId !== this.formId) return;\n\n this.clearAll();\n this.renderAll(errors);\n }\n\n setContainer(fieldName, container) {\n this.customContainers[fieldName] =\n typeof container === \"string\"\n ? document.querySelector(container)\n : container;\n }\n\n renderAll(errors) {\n for (const field in errors) {\n this.render(field, errors[field]);\n }\n }\n\n render(fieldName, errorList) {\n if (!errorList || errorList.length === 0) return null;\n\n const errorSpan = document.createElement(\"span\");\n errorSpan.className = `${this.options.containerClass} ${this.options.errorClass}`;\n errorSpan.dataset.field = fieldName;\n\n const ul = document.createElement(\"ul\");\n errorList.forEach((item) => {\n const li = document.createElement(\"li\");\n const i = document.createElement(\"i\");\n i.textContent = item;\n li.appendChild(i);\n ul.appendChild(li);\n });\n errorSpan.appendChild(ul);\n\n const targetContainer = this.customContainers[fieldName];\n\n if (targetContainer) {\n targetContainer.innerHTML = \"\";\n targetContainer.appendChild(errorSpan);\n } else if (this.options.insertAfterField) {\n const form = document.getElementById(this.formId);\n const field = form?.querySelector(`[name=\"${fieldName}\"]`);\n if (field) {\n field.insertAdjacentElement(\"afterend\", errorSpan);\n }\n }\n return errorSpan;\n }\n\n clearAll() {\n const form = document.getElementById(this.formId);\n if (!form) return;\n\n const errors = form.querySelectorAll(`.${this.options.containerClass}`);\n errors.forEach((el) => el.remove());\n\n for (const key in this.customContainers) {\n if (this.customContainers[key]) {\n this.customContainers[key].innerHTML = \"\";\n }\n }\n }\n\n destroy() {\n EVT.unsub(FormEvents.ERRORS_CHANGE, this._boundHandleErrors);\n this.clearAll();\n }\n}\n\nexport { FormEvents, FormHandler, FormErrorRenderer };\n\nexport function useFormHandler(formId, schema, onSubmit) {\n const h = new FormHandler(formId, schema, onSubmit);\n const r = new FormErrorRenderer(formId);\n return {\n reset: () => h.reset(),\n validate: () => h.validateNow(),\n destroy: () => {\n r.destroy();\n h.destroy();\n },\n setContainer: (fieldName, container) =>\n r.setContainer(fieldName, container),\n };\n}\n","\"use strict\";\n\nexport const redirect = (url) => (window.location.href = url);\n\nexport const isArray = (arr) => Array.isArray(arr);\nexport const isArrayEmpty = (arr) => !(Array.isArray(arr) && arr.length > 0);\n\nexport const isFocus = (element) => element == document.activeElement;\n\nconst currencyMap = {\n US: { locale: \"en-US\", currency: \"USD\" },\n CA: { locale: \"en-CA\", currency: \"CAD\" },\n FR: { locale: \"fr-FR\", currency: \"EUR\" },\n HT: { locale: \"ht-HT\", currency: \"HTG\" },\n GB: { locale: \"en-GB\", currency: \"GBP\" },\n AU: { locale: \"en-AU\", currency: \"AUD\" },\n};\n\nexport const toCurrency = (\n value,\n { locale = \"en-US\", currency = \"USD\" } = {},\n) =>\n Intl.NumberFormat(locale, {\n style: \"currency\",\n currency: currency,\n }).format(value);\n\nexport const formatByCountry = (value, countryCode) => {\n const config = currencyMap[countryCode] ?? currencyMap[\"US\"];\n return toCurrency(value, config);\n};\n\nexport const isValidRoutingNumber = (routingNumber) => {\n if (!/^\\d{9}$/.test(routingNumber)) {\n return false;\n }\n\n // Split the routing number into individual digits\n const digits = routingNumber.split(\"\").map(Number);\n\n // Calculate the weighted sum\n const sum =\n 7 * (digits[0] + digits[3] + digits[6]) +\n 3 * (digits[1] + digits[4] + digits[7]) +\n 1 * (digits[2] + digits[5] + digits[8]);\n\n // Check if the sum is a multiple of 10\n return sum % 10 === 0;\n};\n"],"names":["EVT","name","callback","handlers","onceCallback","args","cb","data","e","methods","value","length","year","month","day","date","parseRule","rule","param","run","schema","formData","isValid","errors","field","rules","ruleString","validationMethod","errorMessage","V","hook","element","event","text","prop","html","make","makeId","result","alphaNum","alphaNumLength","i","parseHtml","source","tmp","onPageLoad","onWindowLoad","Q","selector","selectedElement","wrapper","val","opt","className","propertyName","attributeName","styleObject","key","all","DOM","_base","_timeout","_requestInterceptor","_responseInterceptor","memoryStore","now","makeStorageAdapter","kind","store","raw","parsed","ttl","exp","storages","hit","stableStringify","obj","k","getStorage","storageKind","buildCacheKey","method","url","params","body","p","b","buildFormData","files","fieldName","fields","fd","list","f","v","applyTimeout","ms","controller","request","opts","headers","cache","finalUrl","qs","timeoutId","useCache","strategy","storage","cacheKey","config","res","err","cached","download","filename","onProgress","init","errText","cd","match","blob","reader","contentLength","chunks","received","done","percent","href","a","upload","signal","resolve","reject","xhr","cfg","onAbort","fakeRes","payload","safeJson","t","get","post","put","del","HTTP","fn","FormEvents","FormHandler","formId","onSubmit","#handleSubmit","#handleInput","#init","#captureInitialValues","#publishState","formElements","#publishErrors","formObject","validateErrors","FormErrorRenderer","options","#handleErrors","container","errorList","errorSpan","ul","item","li","targetContainer","form","el","useFormHandler","h","r","redirect","isArray","arr","isArrayEmpty","isFocus","currencyMap","toCurrency","locale","currency","formatByCountry","countryCode","isValidRoutingNumber","routingNumber","digits"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "vaniy",
3
+ "version": "0.1.0",
4
+ "description": "A lightweight, modular JavaScript utility library for common web development tasks.",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/vaniy.umd.js",
8
+ "module": "./dist/vaniy.es.js",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/vanity.es.js",
12
+ "require": "./dist/vanity.umd.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "dev": "vite",
22
+ "build": "vite build",
23
+ "full": "npm run build && npm run test:run",
24
+ "preview": "vite preview",
25
+ "test": "vitest",
26
+ "test:run": "vitest run",
27
+ "coverage": "npx vitest --coverage.enabled --coverage.provider=istanbul"
28
+ },
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "git+https://github.com/teksoftgroup/vaniy.git"
32
+ },
33
+ "keywords": [
34
+ "VanillaJS",
35
+ "vanilla",
36
+ "JS",
37
+ "Javascript",
38
+ "PureJS",
39
+ "SimpleJS"
40
+ ],
41
+ "author": "Teksoftgroup",
42
+ "license": "MIT",
43
+ "bugs": {
44
+ "url": "https://github.com/teksoftgroup/vaniy/issues"
45
+ },
46
+ "homepage": "https://github.com/teksoftgroup/vaniy#readme",
47
+ "devDependencies": {
48
+ "@vitest/coverage-istanbul": "^4.0.17",
49
+ "jsdom": "^27.4.0",
50
+ "vite": "^7.3.1",
51
+ "vitest": "^4.0.17"
52
+ }
53
+ }