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 +331 -0
- package/dist/vaniy.es.js +615 -0
- package/dist/vaniy.es.js.map +1 -0
- package/dist/vaniy.umd.js +2 -0
- package/dist/vaniy.umd.js.map +1 -0
- package/package.json +53 -0
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
|
package/dist/vaniy.es.js
ADDED
|
@@ -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
|
+
}
|