vaniy 0.1.9 → 0.1.11
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 +364 -0
- package/dist/vaniy.es.js +215 -102
- package/dist/vaniy.iife.min.js +1 -1
- package/dist/vaniy.min.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,9 @@ Vaniy is how we say vanilla in my language.
|
|
|
9
9
|
- **HTTP Client** - Full-featured HTTP client with caching, interceptors, and file upload/download
|
|
10
10
|
- **Event System** - Pub/Sub event emitter for decoupled communication
|
|
11
11
|
- **Form Handling** - Validation engine with error rendering
|
|
12
|
+
- **Reactivity** - Fine-grained signals, effects, computed values, and batching
|
|
13
|
+
- **DOM Bindings** - Declaratively bind signals to DOM elements
|
|
14
|
+
- **Query Cache** - Configurable async data cache with signals, polling, and DOM bindings
|
|
12
15
|
- **Zero Dependencies** - Pure vanilla JavaScript
|
|
13
16
|
|
|
14
17
|
## Installation
|
|
@@ -281,6 +284,367 @@ form.destroy();
|
|
|
281
284
|
| `form:reset` | Form was reset |
|
|
282
285
|
| `form:validated` | Validation completed |
|
|
283
286
|
|
|
287
|
+
### Reactivity
|
|
288
|
+
|
|
289
|
+
Fine-grained reactive primitives — signals, effects, computed values, and batching.
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
import { signal, effect, computed, batch, when } from "vaniy";
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**`signal(initial)`**
|
|
296
|
+
|
|
297
|
+
Holds a reactive value. Reading `.val` inside an `effect` tracks the dependency; writing `.val` triggers all dependents.
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
const count = signal(0);
|
|
301
|
+
|
|
302
|
+
count.val; // read → 0
|
|
303
|
+
count.val = 1; // write → triggers effects
|
|
304
|
+
count.peek(); // read without tracking
|
|
305
|
+
String(count); // "1" (toString)
|
|
306
|
+
count + 0; // 1 (valueOf)
|
|
307
|
+
|
|
308
|
+
// Subscribe manually
|
|
309
|
+
const unsub = count.subscribe(() => console.log(count.val));
|
|
310
|
+
unsub(); // stop
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**`effect(fn)`**
|
|
314
|
+
|
|
315
|
+
Runs `fn` immediately and re-runs it whenever any signal read inside it changes.
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
const name = signal("Alice");
|
|
319
|
+
|
|
320
|
+
effect(() => {
|
|
321
|
+
console.log("Name:", name.val); // runs now and on every change
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
name.val = "Bob"; // → logs "Name: Bob"
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**`computed(fn)`**
|
|
328
|
+
|
|
329
|
+
Derives a read-only signal from other signals.
|
|
330
|
+
|
|
331
|
+
```javascript
|
|
332
|
+
const price = signal(10);
|
|
333
|
+
const qty = signal(3);
|
|
334
|
+
const total = computed(() => price.val * qty.val);
|
|
335
|
+
|
|
336
|
+
console.log(total.val); // 30
|
|
337
|
+
|
|
338
|
+
price.val = 20;
|
|
339
|
+
console.log(total.val); // 60
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**`batch(fn)`**
|
|
343
|
+
|
|
344
|
+
Groups multiple signal writes so effects only run once after all updates.
|
|
345
|
+
|
|
346
|
+
```javascript
|
|
347
|
+
const x = signal(1);
|
|
348
|
+
const y = signal(2);
|
|
349
|
+
|
|
350
|
+
effect(() => console.log(x.val, y.val)); // logs: 1 2
|
|
351
|
+
|
|
352
|
+
batch(() => {
|
|
353
|
+
x.val = 10;
|
|
354
|
+
y.val = 20;
|
|
355
|
+
// effect has not run yet
|
|
356
|
+
});
|
|
357
|
+
// effect runs once here → logs: 10 20
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**`when(signal, fn)`**
|
|
361
|
+
|
|
362
|
+
Runs `fn` whenever `signal.val` is truthy, passing the current value.
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
const user = signal(null);
|
|
366
|
+
|
|
367
|
+
when(user, (u) => console.log("Logged in:", u.name));
|
|
368
|
+
|
|
369
|
+
user.val = { name: "Alice" }; // → logs "Logged in: Alice"
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### DOM Bindings
|
|
373
|
+
|
|
374
|
+
Declaratively bind signals to DOM elements. Each function returns the underlying `effect` — call it to stop the binding.
|
|
375
|
+
|
|
376
|
+
```javascript
|
|
377
|
+
import { bind, bindText, bindHtml, bindValue, bindList, bindOptions, bindClass, bindAttr } from "vaniy";
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
All functions accept a CSS selector string or a `Q`-wrapped element as `target`.
|
|
381
|
+
|
|
382
|
+
**`bind(target, prop, signal)`**
|
|
383
|
+
|
|
384
|
+
Syncs a signal to a named property on an element.
|
|
385
|
+
|
|
386
|
+
| `prop` | Behavior |
|
|
387
|
+
| --- | --- |
|
|
388
|
+
| `"text"` | Sets element text content |
|
|
389
|
+
| `"html"` | Sets element inner HTML |
|
|
390
|
+
| `"value"` | Sets input value |
|
|
391
|
+
| `"show"` | Shows element when truthy, hides when falsy |
|
|
392
|
+
| `"hide"` | Hides element when truthy, shows when falsy |
|
|
393
|
+
| `"disabled"` | Sets `disabled` attribute |
|
|
394
|
+
| anything else | Assigned directly as `element[prop]` |
|
|
395
|
+
|
|
396
|
+
```javascript
|
|
397
|
+
const username = signal("Alice");
|
|
398
|
+
const isAdmin = signal(false);
|
|
399
|
+
const bio = signal("<p>Hello</p>");
|
|
400
|
+
|
|
401
|
+
bind("#name", "text", username);
|
|
402
|
+
bind("#bio", "html", bio);
|
|
403
|
+
bind("#role-badge", "show", isAdmin);
|
|
404
|
+
bind("#submit", "disabled", isAdmin);
|
|
405
|
+
|
|
406
|
+
username.val = "Bob"; // → #name text updates instantly
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
**`bindText(target, signal)`**
|
|
410
|
+
|
|
411
|
+
Shorthand for `bind(target, "text", signal)`.
|
|
412
|
+
|
|
413
|
+
```javascript
|
|
414
|
+
const title = signal("Hello");
|
|
415
|
+
bindText("#heading", title);
|
|
416
|
+
|
|
417
|
+
title.val = "World"; // → #heading text content updates
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**`bindHtml(target, signal)`**
|
|
421
|
+
|
|
422
|
+
Shorthand for `bind(target, "html", signal)`.
|
|
423
|
+
|
|
424
|
+
```javascript
|
|
425
|
+
const content = signal("<p>Loading...</p>");
|
|
426
|
+
bindHtml("#panel", content);
|
|
427
|
+
|
|
428
|
+
content.val = "<p>Done</p>"; // → #panel innerHTML updates
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
**`bindValue(target, signal)`**
|
|
432
|
+
|
|
433
|
+
Shorthand for `bind(target, "value", signal)`.
|
|
434
|
+
|
|
435
|
+
```javascript
|
|
436
|
+
const query = signal("");
|
|
437
|
+
bindValue("#search", query);
|
|
438
|
+
|
|
439
|
+
query.val = "vaniy"; // → #search input value updates
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
**`bindList(target, signal, template, empty?)`**
|
|
443
|
+
|
|
444
|
+
Renders an array signal as a list. Re-renders the entire list on every change.
|
|
445
|
+
|
|
446
|
+
```javascript
|
|
447
|
+
const users = signal([]);
|
|
448
|
+
|
|
449
|
+
const stop = bindList(
|
|
450
|
+
"#user-list",
|
|
451
|
+
users,
|
|
452
|
+
(user) => `<li>${user.name}</li>`,
|
|
453
|
+
"<li>No users found.</li>", // optional fallback for empty/null
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
users.val = [{ name: "Alice" }, { name: "Bob" }];
|
|
457
|
+
// → #user-list innerHTML: <li>Alice</li><li>Bob</li>
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
**`bindOptions(target, signal, opts?)`**
|
|
461
|
+
|
|
462
|
+
Populates a `<select>` element from an array signal.
|
|
463
|
+
|
|
464
|
+
```javascript
|
|
465
|
+
const roles = signal([]);
|
|
466
|
+
|
|
467
|
+
bindOptions("#role-select", roles, {
|
|
468
|
+
value: "id", // item property used as <option value> (default: "id")
|
|
469
|
+
label: "name", // item property used as <option> text (default: "name")
|
|
470
|
+
placeholder: "Pick a role", // first empty option text (default: "Select ...")
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
roles.val = [
|
|
474
|
+
{ id: 1, name: "Admin" },
|
|
475
|
+
{ id: 2, name: "Editor" },
|
|
476
|
+
];
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
**`bindClass(target, className, signal)`**
|
|
480
|
+
|
|
481
|
+
Adds a class when the signal is truthy, removes it when falsy.
|
|
482
|
+
|
|
483
|
+
```javascript
|
|
484
|
+
const isActive = signal(false);
|
|
485
|
+
|
|
486
|
+
bindClass("#card", "active", isActive);
|
|
487
|
+
|
|
488
|
+
isActive.val = true; // → adds class "active"
|
|
489
|
+
isActive.val = false; // → removes class "active"
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
**`bindAttr(target, attr, signal)`**
|
|
493
|
+
|
|
494
|
+
Sets an HTML attribute to the signal's value on every change.
|
|
495
|
+
|
|
496
|
+
```javascript
|
|
497
|
+
const progress = signal(0);
|
|
498
|
+
|
|
499
|
+
bindAttr("#bar", "aria-valuenow", progress);
|
|
500
|
+
|
|
501
|
+
progress.val = 75; // → <div id="bar" aria-valuenow="75">
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Query Cache
|
|
505
|
+
|
|
506
|
+
Async data cache with deduplication, stale-while-revalidate, persistence, and reactive signals.
|
|
507
|
+
|
|
508
|
+
Use `createQuery` to create a fully configured client. `queryClient` is a zero-config default export for quick use.
|
|
509
|
+
|
|
510
|
+
```javascript
|
|
511
|
+
import { createQuery, queryClient } from "vaniy";
|
|
512
|
+
|
|
513
|
+
// Create your own configured client
|
|
514
|
+
const client = createQuery({
|
|
515
|
+
persistKey: "my-app-cache", // localStorage key (default: "query-cache")
|
|
516
|
+
persistedKeys: ["user", "settings"], // cache key prefixes to persist (default: null = none)
|
|
517
|
+
defaultTtl: 60000, // entry lifetime in ms (default: 60000)
|
|
518
|
+
defaultStaleTime: 5000, // freshness window in ms (default: 5000)
|
|
519
|
+
defaultRetries: 3, // retry attempts on failure (default: 3)
|
|
520
|
+
defaultRetryDelay: 1000, // base retry delay in ms, doubles each attempt (default: 1000)
|
|
521
|
+
});
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
**Core cache methods:**
|
|
525
|
+
|
|
526
|
+
```javascript
|
|
527
|
+
// Fetch and cache data
|
|
528
|
+
const data = await client.query("users", () => fetch("/api/users").then(r => r.json()));
|
|
529
|
+
|
|
530
|
+
// Per-query overrides
|
|
531
|
+
const data = await client.query("users", fetcher, { ttl: 30000, staleTime: 0 });
|
|
532
|
+
|
|
533
|
+
// Set data manually (e.g. after a mutation)
|
|
534
|
+
client.setQueryData("users", updatedList);
|
|
535
|
+
|
|
536
|
+
// Optimistic update — returns previous value
|
|
537
|
+
const previous = client.mutate("users", (prev) => [...prev, newUser]);
|
|
538
|
+
|
|
539
|
+
// Invalidate (remove from cache)
|
|
540
|
+
client.invalidate("users");
|
|
541
|
+
|
|
542
|
+
// Invalidate and immediately refetch
|
|
543
|
+
client.invalidate("users", { refetch: true, fetcher });
|
|
544
|
+
|
|
545
|
+
// Invalidate all keys matching a pattern
|
|
546
|
+
client.invalidateMatching((key) => key.startsWith("users"));
|
|
547
|
+
|
|
548
|
+
// Prefetch into cache without blocking
|
|
549
|
+
client.prefetch("users", fetcher);
|
|
550
|
+
|
|
551
|
+
// Read cache entry directly
|
|
552
|
+
const entry = client.getEntry("users"); // { data, staleAt, expiry, error, promise }
|
|
553
|
+
|
|
554
|
+
// Subscribe to cache updates for a key
|
|
555
|
+
const unsub = client.subscribe("users", (entry) => console.log(entry?.data));
|
|
556
|
+
|
|
557
|
+
// Clear all cache and storage
|
|
558
|
+
client.clear();
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Polling:**
|
|
562
|
+
|
|
563
|
+
```javascript
|
|
564
|
+
// Start polling every 5 seconds — returns a stop function
|
|
565
|
+
const stop = client.startPolling("price", fetcher, 5000);
|
|
566
|
+
|
|
567
|
+
// Stop a specific poll
|
|
568
|
+
client.stopPolling("price");
|
|
569
|
+
|
|
570
|
+
// Stop all active polls
|
|
571
|
+
client.stopAllPolling();
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
**Reactive signals (`querySignal`):**
|
|
575
|
+
|
|
576
|
+
Wraps a query in reactive signals — ideal for use with Vaniy's reactive system.
|
|
577
|
+
|
|
578
|
+
```javascript
|
|
579
|
+
const { data, loading, error, fetch, refetch, mutate, unsubscribe } =
|
|
580
|
+
client.querySignal("users", () => fetch("/api/users").then(r => r.json()));
|
|
581
|
+
|
|
582
|
+
// data.val, loading.val, error.val update automatically
|
|
583
|
+
console.log(data.val); // fetched array or null
|
|
584
|
+
console.log(loading.val); // true while fetching
|
|
585
|
+
console.log(error.val); // Error instance or null
|
|
586
|
+
|
|
587
|
+
// Skip auto-fetch, call manually
|
|
588
|
+
const qs = client.querySignal("users", fetcher, { enabled: false });
|
|
589
|
+
await qs.fetch();
|
|
590
|
+
|
|
591
|
+
// Refetch (invalidates then fetches)
|
|
592
|
+
await qs.refetch();
|
|
593
|
+
|
|
594
|
+
// Optimistic update
|
|
595
|
+
qs.mutate((prev) => [...prev, newUser]);
|
|
596
|
+
|
|
597
|
+
// Stop listening
|
|
598
|
+
qs.unsubscribe();
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
**Polling signals (`pollingSignal`):**
|
|
602
|
+
|
|
603
|
+
```javascript
|
|
604
|
+
const { data, loading, error, stop } =
|
|
605
|
+
client.pollingSignal("price", fetcher, 5000);
|
|
606
|
+
|
|
607
|
+
// stop polling
|
|
608
|
+
stop();
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
**DOM binding (`bindQuery`):**
|
|
612
|
+
|
|
613
|
+
Automatically renders data into a DOM element when the cache updates.
|
|
614
|
+
|
|
615
|
+
```javascript
|
|
616
|
+
client.bindQuery("users", fetcher, {
|
|
617
|
+
target: "#user-list", // CSS selector or element reference
|
|
618
|
+
render: (data) => data.map(u => `<li>${u.name}</li>`).join(""),
|
|
619
|
+
onLoading: (el) => el.innerHTML = "Loading...",
|
|
620
|
+
onError: (err, staleData, el) => el.innerHTML = "Failed to load",
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// With polling — returns a stop function
|
|
624
|
+
const stop = client.bindQuery("users", fetcher, {
|
|
625
|
+
target: "#user-list",
|
|
626
|
+
render: (data) => data.map(u => `<li>${u.name}</li>`).join(""),
|
|
627
|
+
poll: 10000,
|
|
628
|
+
});
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**Query events (via `EVT`):**
|
|
632
|
+
|
|
633
|
+
| Event | Description |
|
|
634
|
+
| ----- | ----------- |
|
|
635
|
+
| `query:fetch` | Fetch started |
|
|
636
|
+
| `query:success` | Fetch succeeded |
|
|
637
|
+
| `query:error` | Fetch failed |
|
|
638
|
+
| `query:retry` | Fetch retrying |
|
|
639
|
+
| `query:mutate` | Cache mutated |
|
|
640
|
+
| `query:set` | Cache set manually |
|
|
641
|
+
| `query:invalidate` | Entry invalidated |
|
|
642
|
+
| `query:hydrated` | Cache loaded from storage |
|
|
643
|
+
| `query:gc` | Expired entries collected |
|
|
644
|
+
| `query:cleared` | All cache cleared |
|
|
645
|
+
|
|
646
|
+
Each event also fires as `query:<key>:<event>` for key-specific subscriptions.
|
|
647
|
+
|
|
284
648
|
### Utilities
|
|
285
649
|
|
|
286
650
|
Additional helper functions.
|
package/dist/vaniy.es.js
CHANGED
|
@@ -970,6 +970,144 @@ const HTTP = {
|
|
|
970
970
|
ping: () => console.log("PONG"),
|
|
971
971
|
description: "H is for Http"
|
|
972
972
|
};
|
|
973
|
+
let _tracking = null;
|
|
974
|
+
let _pending = /* @__PURE__ */ new Set();
|
|
975
|
+
function signal(initial) {
|
|
976
|
+
let _val = initial;
|
|
977
|
+
const subs = /* @__PURE__ */ new Set();
|
|
978
|
+
const s = {
|
|
979
|
+
get val() {
|
|
980
|
+
if (_tracking) subs.add(_tracking);
|
|
981
|
+
return _val;
|
|
982
|
+
},
|
|
983
|
+
set val(v) {
|
|
984
|
+
if (v === _val) return;
|
|
985
|
+
_val = v;
|
|
986
|
+
for (const fn of subs) fn();
|
|
987
|
+
},
|
|
988
|
+
peek: () => _val,
|
|
989
|
+
subscribe: (fn) => {
|
|
990
|
+
subs.add(fn);
|
|
991
|
+
return () => subs.delete(fn);
|
|
992
|
+
},
|
|
993
|
+
toString: () => String(_val),
|
|
994
|
+
valueOf: () => _val
|
|
995
|
+
};
|
|
996
|
+
return s;
|
|
997
|
+
}
|
|
998
|
+
function effect(fn) {
|
|
999
|
+
const run2 = () => {
|
|
1000
|
+
const prev = _tracking;
|
|
1001
|
+
_tracking = run2;
|
|
1002
|
+
try {
|
|
1003
|
+
fn();
|
|
1004
|
+
} finally {
|
|
1005
|
+
_tracking = prev;
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
run2();
|
|
1009
|
+
return run2;
|
|
1010
|
+
}
|
|
1011
|
+
function computed(fn) {
|
|
1012
|
+
const s = signal(void 0);
|
|
1013
|
+
effect(() => {
|
|
1014
|
+
s.val = fn();
|
|
1015
|
+
});
|
|
1016
|
+
return s;
|
|
1017
|
+
}
|
|
1018
|
+
function batch(fn) {
|
|
1019
|
+
fn();
|
|
1020
|
+
_pending.forEach((f) => f());
|
|
1021
|
+
_pending.clear();
|
|
1022
|
+
}
|
|
1023
|
+
function when(sig, fn) {
|
|
1024
|
+
return effect(() => {
|
|
1025
|
+
if (sig.val) fn(sig.val);
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
function getElement(target) {
|
|
1029
|
+
return typeof target === "string" ? Q(target) : target;
|
|
1030
|
+
}
|
|
1031
|
+
function bind(target, prop, sig) {
|
|
1032
|
+
const el = getElement(target);
|
|
1033
|
+
return effect(() => {
|
|
1034
|
+
const val = sig.val;
|
|
1035
|
+
switch (prop) {
|
|
1036
|
+
case "text":
|
|
1037
|
+
el.text(val);
|
|
1038
|
+
break;
|
|
1039
|
+
case "html":
|
|
1040
|
+
el.html(val);
|
|
1041
|
+
break;
|
|
1042
|
+
case "value":
|
|
1043
|
+
el.val(val);
|
|
1044
|
+
break;
|
|
1045
|
+
case "show":
|
|
1046
|
+
val ? el.show() : el.hide();
|
|
1047
|
+
break;
|
|
1048
|
+
case "hide":
|
|
1049
|
+
val ? el.hide() : el.show();
|
|
1050
|
+
break;
|
|
1051
|
+
case "disabled":
|
|
1052
|
+
el.elt.disabled = !!val;
|
|
1053
|
+
break;
|
|
1054
|
+
default:
|
|
1055
|
+
el.elt[prop] = val;
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
function bindText(target, sig) {
|
|
1060
|
+
const el = getElement(target);
|
|
1061
|
+
return effect(() => {
|
|
1062
|
+
const val = sig.val;
|
|
1063
|
+
el.text(val);
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
function bindHtml(target, sig) {
|
|
1067
|
+
const el = getElement(target);
|
|
1068
|
+
return effect(() => {
|
|
1069
|
+
const val = sig.val;
|
|
1070
|
+
el.html(val);
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
function bindValue(target, sig) {
|
|
1074
|
+
const el = getElement(target);
|
|
1075
|
+
return effect(() => {
|
|
1076
|
+
const val = sig.val;
|
|
1077
|
+
el.val(val);
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
function bindList(target, sig, template, empty = "") {
|
|
1081
|
+
const el = getElement(target);
|
|
1082
|
+
return effect(() => {
|
|
1083
|
+
const items = sig.val;
|
|
1084
|
+
el.html(items?.length ? items.map(template).join("") : empty);
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
function bindOptions(target, sig, opts = {}) {
|
|
1088
|
+
const { value = "id", label = "name", placeholder = "Select ..." } = opts;
|
|
1089
|
+
const el = getElement(target);
|
|
1090
|
+
return effect(() => {
|
|
1091
|
+
const items = sig.val || [];
|
|
1092
|
+
el.html(
|
|
1093
|
+
`<option value="">${placeholder}</option>` + items.map(
|
|
1094
|
+
(item) => `<option value="${item[value]}">${item[label]}</option>`
|
|
1095
|
+
).join("")
|
|
1096
|
+
);
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
function bindClass(target, className, sig) {
|
|
1100
|
+
const el = getElement(target);
|
|
1101
|
+
return effect(() => {
|
|
1102
|
+
sig.val ? el.addClass(className) : el.removeClass(className);
|
|
1103
|
+
});
|
|
1104
|
+
}
|
|
1105
|
+
function bindAttr(target, attr, sig) {
|
|
1106
|
+
const el = getElement(target);
|
|
1107
|
+
return effect(() => {
|
|
1108
|
+
el.elt.setAttribute(attr, sig.val);
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
973
1111
|
const FormEvents = {
|
|
974
1112
|
STATE_CHANGE: "form:state:change",
|
|
975
1113
|
ERRORS_CHANGE: "form:errors:change",
|
|
@@ -1275,28 +1413,6 @@ function parseTTL(str) {
|
|
|
1275
1413
|
};
|
|
1276
1414
|
return num * (map[unit] || 1);
|
|
1277
1415
|
}
|
|
1278
|
-
function signal(initial) {
|
|
1279
|
-
let _val = initial;
|
|
1280
|
-
const subs = /* @__PURE__ */ new Set();
|
|
1281
|
-
const s = {
|
|
1282
|
-
get val() {
|
|
1283
|
-
return _val;
|
|
1284
|
-
},
|
|
1285
|
-
set val(v) {
|
|
1286
|
-
if (v === _val) return;
|
|
1287
|
-
_val = v;
|
|
1288
|
-
for (const fn of subs) fn();
|
|
1289
|
-
},
|
|
1290
|
-
peek: () => _val,
|
|
1291
|
-
subscribe: (fn) => {
|
|
1292
|
-
subs.add(fn);
|
|
1293
|
-
return () => subs.delete(fn);
|
|
1294
|
-
},
|
|
1295
|
-
toString: () => String(_val),
|
|
1296
|
-
valueOf: () => _val
|
|
1297
|
-
};
|
|
1298
|
-
return s;
|
|
1299
|
-
}
|
|
1300
1416
|
const createQuery = (options = {}) => {
|
|
1301
1417
|
const {
|
|
1302
1418
|
persistKey = "query-cache",
|
|
@@ -1539,6 +1655,64 @@ const createQuery = (options = {}) => {
|
|
|
1539
1655
|
stopAllPolling();
|
|
1540
1656
|
saveToStorage();
|
|
1541
1657
|
});
|
|
1658
|
+
const querySignal = (key, fetcher, options2 = {}) => {
|
|
1659
|
+
const data = signal(options2.inital ?? null);
|
|
1660
|
+
const loading = signal(false);
|
|
1661
|
+
const error = signal(null);
|
|
1662
|
+
const unsubscribe = subscribe(key, (entry) => {
|
|
1663
|
+
if (entry?.data) data.val = entry.data;
|
|
1664
|
+
if (entry?.error) error.val = entry.error;
|
|
1665
|
+
loading.val = !!entry?.promise && !entry?.data;
|
|
1666
|
+
});
|
|
1667
|
+
const fetch2 = () => {
|
|
1668
|
+
loading.val = true;
|
|
1669
|
+
return query(key, fetcher, options2);
|
|
1670
|
+
};
|
|
1671
|
+
const mutateFn = (updater) => {
|
|
1672
|
+
const prev = mutate(key, updater);
|
|
1673
|
+
data.val = getEntry(key)?.data;
|
|
1674
|
+
return prev;
|
|
1675
|
+
};
|
|
1676
|
+
const refetch = () => {
|
|
1677
|
+
invalidate(key);
|
|
1678
|
+
return fetch2();
|
|
1679
|
+
};
|
|
1680
|
+
if (options2.enabled !== false) fetch2().catch(() => {
|
|
1681
|
+
});
|
|
1682
|
+
return { data, loading, error, fetch: fetch2, refetch, unsubscribe, mutate: mutateFn };
|
|
1683
|
+
};
|
|
1684
|
+
const pollingSignal = (key, fetcher, interval, options2 = {}) => {
|
|
1685
|
+
const qs = querySignal(key, fetcher, { ...options2, enabled: false });
|
|
1686
|
+
const stop = startPolling(key, fetcher, interval, options2);
|
|
1687
|
+
return { ...qs, stop };
|
|
1688
|
+
};
|
|
1689
|
+
const bindQuery = (key, fetcher, options2 = {}) => {
|
|
1690
|
+
const { target, render, onLoading, onError, poll = null, ...queryOptions } = options2;
|
|
1691
|
+
const el = typeof target === "string" ? document.querySelector(target) : target;
|
|
1692
|
+
const renderData = (data) => {
|
|
1693
|
+
const html2 = render(data);
|
|
1694
|
+
if (typeof html2 === "string") el.innerHTML = html2;
|
|
1695
|
+
};
|
|
1696
|
+
EVT.sub(`query:${key}:success`, ({ data }) => renderData(data));
|
|
1697
|
+
EVT.sub(`query:${key}:set`, ({ data }) => renderData(data));
|
|
1698
|
+
EVT.sub(`query:${key}:mutate`, ({ data }) => renderData(data));
|
|
1699
|
+
if (onError) {
|
|
1700
|
+
EVT.sub(
|
|
1701
|
+
`query:${key}:error`,
|
|
1702
|
+
({ error, staleData }) => onError(error, staleData, el)
|
|
1703
|
+
);
|
|
1704
|
+
}
|
|
1705
|
+
if (onLoading) {
|
|
1706
|
+
EVT.sub(`query:${key}:fetch`, ({ hasCache }) => {
|
|
1707
|
+
if (!hasCache) onLoading(el);
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
query(key, fetcher, queryOptions).catch(() => {
|
|
1711
|
+
});
|
|
1712
|
+
if (poll) {
|
|
1713
|
+
return startPolling(key, fetcher, poll, queryOptions);
|
|
1714
|
+
}
|
|
1715
|
+
};
|
|
1542
1716
|
return {
|
|
1543
1717
|
query,
|
|
1544
1718
|
mutate,
|
|
@@ -1552,6 +1726,9 @@ const createQuery = (options = {}) => {
|
|
|
1552
1726
|
stopAllPolling,
|
|
1553
1727
|
getEntry,
|
|
1554
1728
|
gc,
|
|
1729
|
+
querySignal,
|
|
1730
|
+
pollingSignal,
|
|
1731
|
+
bindQuery,
|
|
1555
1732
|
clear: () => {
|
|
1556
1733
|
cache2.clear();
|
|
1557
1734
|
localStorage.removeItem(persistKey);
|
|
@@ -1559,82 +1736,7 @@ const createQuery = (options = {}) => {
|
|
|
1559
1736
|
}
|
|
1560
1737
|
};
|
|
1561
1738
|
};
|
|
1562
|
-
const queryClient = createQuery(
|
|
1563
|
-
persistKey: "teksoft-cache",
|
|
1564
|
-
persistedKeys: ["user", "settings"]
|
|
1565
|
-
});
|
|
1566
|
-
const querySignal = (key, fetcher, options = {}) => {
|
|
1567
|
-
const data = signal(options.inital ?? null);
|
|
1568
|
-
const loading = signal(false);
|
|
1569
|
-
const error = signal(null);
|
|
1570
|
-
const unsubscribe = queryClient.subscribe(key, (entry) => {
|
|
1571
|
-
if (entry?.data) data.val = entry.data;
|
|
1572
|
-
if (entry?.error) error.val = entry.error;
|
|
1573
|
-
loading.val = !!entry?.promise && !entry?.data;
|
|
1574
|
-
});
|
|
1575
|
-
const fetch2 = () => {
|
|
1576
|
-
loading.val = true;
|
|
1577
|
-
return queryClient.query(key, fetcher, options);
|
|
1578
|
-
};
|
|
1579
|
-
const mutate = (updater) => {
|
|
1580
|
-
const prev = queryClient.mutate(key, updater);
|
|
1581
|
-
data.val = queryClient.getEntry(key)?.data;
|
|
1582
|
-
return prev;
|
|
1583
|
-
};
|
|
1584
|
-
const refetch = () => {
|
|
1585
|
-
queryClient.invalidate(key);
|
|
1586
|
-
return fetch2();
|
|
1587
|
-
};
|
|
1588
|
-
if (options.enabled !== false) fetch2();
|
|
1589
|
-
return {
|
|
1590
|
-
data,
|
|
1591
|
-
loading,
|
|
1592
|
-
error,
|
|
1593
|
-
fetch: fetch2,
|
|
1594
|
-
refetch,
|
|
1595
|
-
unsubscribe,
|
|
1596
|
-
mutate
|
|
1597
|
-
};
|
|
1598
|
-
};
|
|
1599
|
-
const pollingSignal = (key, fetcher, interval, options = {}) => {
|
|
1600
|
-
const qs = querySignal(key, fetcher, { ...options, enabled: false });
|
|
1601
|
-
const stop = queryClient.startPolling(key, fetcher, interval, options);
|
|
1602
|
-
return { ...qs, stop };
|
|
1603
|
-
};
|
|
1604
|
-
const bindQuery = (key, fetcher, options = {}) => {
|
|
1605
|
-
const {
|
|
1606
|
-
target,
|
|
1607
|
-
render,
|
|
1608
|
-
onLoading,
|
|
1609
|
-
onError,
|
|
1610
|
-
poll = null,
|
|
1611
|
-
...queryOptions
|
|
1612
|
-
} = options;
|
|
1613
|
-
const el = typeof target === "string" ? document.querySelector(target) : target;
|
|
1614
|
-
const renderData = (data) => {
|
|
1615
|
-
const html2 = render(data);
|
|
1616
|
-
if (typeof html2 === "string") el.innerHTML = html2;
|
|
1617
|
-
};
|
|
1618
|
-
EVT.sub(`query:${key}:success`, ({ data }) => renderData(data));
|
|
1619
|
-
EVT.sub(`query:${key}:set`, ({ data }) => renderData(data));
|
|
1620
|
-
EVT.sub(`query:${key}:mutate`, ({ data }) => renderData(data));
|
|
1621
|
-
if (onError) {
|
|
1622
|
-
EVT.sub(
|
|
1623
|
-
`query:${key}:error`,
|
|
1624
|
-
({ error, staleData }) => onError(error, staleData, el)
|
|
1625
|
-
);
|
|
1626
|
-
}
|
|
1627
|
-
if (onLoading) {
|
|
1628
|
-
EVT.sub(`query:${key}:fetch`, ({ hasCache }) => {
|
|
1629
|
-
if (!hasCache) onLoading(el);
|
|
1630
|
-
});
|
|
1631
|
-
}
|
|
1632
|
-
queryClient.query(key, fetcher, queryOptions).catch(() => {
|
|
1633
|
-
});
|
|
1634
|
-
if (poll) {
|
|
1635
|
-
return queryClient.startPolling(key, fetcher, poll, queryOptions);
|
|
1636
|
-
}
|
|
1637
|
-
};
|
|
1739
|
+
const queryClient = createQuery();
|
|
1638
1740
|
export {
|
|
1639
1741
|
DOM,
|
|
1640
1742
|
EVT,
|
|
@@ -1645,10 +1747,21 @@ export {
|
|
|
1645
1747
|
Q,
|
|
1646
1748
|
V,
|
|
1647
1749
|
all,
|
|
1648
|
-
|
|
1750
|
+
batch,
|
|
1751
|
+
bind,
|
|
1752
|
+
bindAttr,
|
|
1753
|
+
bindClass,
|
|
1754
|
+
bindHtml,
|
|
1755
|
+
bindList,
|
|
1756
|
+
bindOptions,
|
|
1757
|
+
bindText,
|
|
1758
|
+
bindValue,
|
|
1649
1759
|
cache,
|
|
1760
|
+
computed,
|
|
1761
|
+
createQuery,
|
|
1650
1762
|
del,
|
|
1651
1763
|
download,
|
|
1764
|
+
effect,
|
|
1652
1765
|
formatByCountry,
|
|
1653
1766
|
get,
|
|
1654
1767
|
isArray,
|
|
@@ -1660,15 +1773,15 @@ export {
|
|
|
1660
1773
|
onPageLoad,
|
|
1661
1774
|
onWindowLoad,
|
|
1662
1775
|
parseHtml,
|
|
1663
|
-
pollingSignal,
|
|
1664
1776
|
post,
|
|
1665
1777
|
put,
|
|
1666
1778
|
queryClient,
|
|
1667
|
-
querySignal,
|
|
1668
1779
|
raw,
|
|
1669
1780
|
redirect,
|
|
1670
1781
|
request,
|
|
1782
|
+
signal,
|
|
1671
1783
|
toCurrency,
|
|
1672
1784
|
upload,
|
|
1673
|
-
useFormHandler
|
|
1785
|
+
useFormHandler,
|
|
1786
|
+
when
|
|
1674
1787
|
};
|
package/dist/vaniy.iife.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var vaniy=function(e){"use strict";const t={listeners:new Map,sub:function(e,t){let r=this.listeners.get(e);r||(r=new Set,this.listeners.set(e,r)),r.add(t)},once:function(e,t){const r=(...n)=>{t(...n),this.unsub(e,r)};this.sub(e,r)},unsub:function(e,t){let r=this.listeners.get(e);r&&r.delete(t)},pub:function(e,...t){let r=this.listeners.get(e);r&&r.forEach(r=>{try{r(...t)}catch(t){console.error(`Error in event "${e}" listener: `,t)}})},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"},r={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"}},n=(e,{locale:t="en-US",currency:r="USD"}={})=>Intl.NumberFormat(t,{style:"currency",currency:r}).format(e);function s(e){return Array.isArray(e)?e.length:function(e){if("number"==typeof e)return Number.isFinite(e);if("string"!=typeof e)return!1;const t=e.trim();return!!t&&/^-?\d+(\.\d+)?$/.test(t)}(e)?Number(String(e).trim()):String(e??"").length}function o(e){const[t,r]=String(e??"").split(",").map(e=>e.trim()),n=Number(t),s=Number(r);return Number.isFinite(n)&&Number.isFinite(s)?{min:n,max:s}:null}const a=e=>new Promise(t=>setTimeout(t,e));function i(e,t){const r=String(e??"").trim();if(!r)return null;if("YYYY-MM-DD"===t){const e=r.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!e)return null;const t=Number(e[1]),n=Number(e[2]),s=Number(e[3]);return!t||n<1||n>12||s<1||s>31?null:{year:t,month:n,day:s}}return null}function l(e,t,r="en-US"){const n=new Intl.DateTimeFormat(r,{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(e),s=Object.fromEntries(n.map(e=>[e.type,e.value]));return{year:Number(s.year),month:Number(s.month),day:Number(s.day),hour:Number(s.hour),minute:Number(s.minute),second:Number(s.second)}}function u({year:e,month:t,day:r},n){const s=new Date(Date.UTC(e,t-1,r));return s.setUTCDate(s.getUTCDate()+n),{year:s.getUTCFullYear(),month:s.getUTCMonth()+1,day:s.getUTCDate()}}function c(e,t,r){const{base:n,offsetDays:s}=function(e){const t=String(e).trim().match(/^(.+?)([+-]\d+)?$/);return t?{base:t[1].trim(),offsetDays:t[2]?Number(t[2]):0}:{base:String(e).trim(),offsetDays:0}}(e);let o=function(e,t){const r=new Date,{year:n,month:s,day:o}=l(r,t);return"today"===e?{year:n,month:s,day:o}:"tomorrow"===e?u({year:n,month:s,day:o},1):"yesterday"===e?u({year:n,month:s,day:o},-1):null}(n,r.timezone);if(!o){const e=t?.[n];o=d(e,r)}return o||(o=i(n,r.dateFormat)),o?(s&&(o=u(o,s)),o):null}function d(e,t){if(null==(r=e)||""===String(r??"").trim())return null;var r;const n=String(e).trim();let s=i(n,t.dateFormat);if(s)return s;if(!/^\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}(:\d{2}(\.\d{1,3})?)?(Z|[+-]\d{2}:\d{2})?$/.test(n))return null;const o=new Date(n);if(isNaN(o.getTime()))return null;const a=l(o,t.timezone);return{year:a.year,month:a.month,day:a.day}}function m(e,t,r,n){let s=null;return s="value"===n?d(e,r):c(e,t,r),s?function({year:e,month:t,day:r},n){let s=Date.UTC(e,t-1,r,0,0,0);for(let o=0;o<2;o++){const o=l(new Date(s),n),a=Date.UTC(o.year,o.month-1,o.day,o.hour,o.minute,o.second)-Date.UTC(e,t-1,r,0,0,0);if(0===a)break;s-=a}return s}(s,r.timezone):null}function f(e,t){return{method:t=>(r,n,s)=>{const o=m(r,n,s,"value"),a=m(t,n,s,"target");return null!=o&&null!=a&&e(o,a)},message:t}}const h={required:{method:e=>""!==String(e??"").trim(),message:"This field is required"},requiredIf:{method:e=>(t,r)=>{const[n,s]=String(e).split("="),o=r?.[n];return!(null!=s?String(o??"")===s:""!==String(o??"").trim())||""!==String(t??"").trim()},message:e=>{const[t,r]=String(e).split("=");return null!=r?`This field is requied when ${t} is ${r}`:`This field is required when ${t} has a value`}},email:{method:e=>/\S+@\S+\.\S+/.test(e),message:"Email is invalid"},min:{method:e=>t=>String(t??"").length>=Number(e),message:e=>`Must be at least ${e} characters`},max:{method:e=>t=>String(t??"").length<=Number(e),message:e=>`Must be at most ${e} characters`},date:{method:e=>{if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;const[t,r,n]=e.split("-").map(Number),s=new Date(t,r-1,n);return s.getFullYear()===t&&s.getMonth()===r-1&&s.getDate()===n},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."},same:{method:e=>(t,r)=>String(t??"")===String(r?.[e]??""),message:e=>`Must match ${e}`},in:{method:e=>t=>(Array.isArray(e)?e:String(e??"").split(",").map(e=>e.trim()).filter(Boolean)).includes(String(t??"").trim()),message:e=>`Must be one of the following: ${(Array.isArray(e)?e:String(e??"").split(",").map(e=>e.trim())).filter(Boolean).join(",")}`},before:f((e,t)=>e<t,e=>`Must be before ${e}`),beforeOrEqual:f((e,t)=>e<=t,e=>`Must be before or equal to ${e}`),after:f((e,t)=>e>t,e=>`Must be after ${e}`),afterOrEqual:f((e,t)=>e>=t,e=>`Must be after or equal to ${e}`),between:{method:e=>t=>{const r=o(e);if(!r)return!1;const n=s(t);return r.min<=n&&n<=r.max},message:e=>{const t=o(e);return t?`Must be between ${t.min} and ${t.max}`:"Between rule is invalid. Use between:min,max"}}};function y(e){const t=e.indexOf(":");return-1===t?{name:e,param:void 0}:{name:e.slice(0,t),param:e.slice(t+1)}}const p={run:function(e,t){let r=!0;const n={};for(const s in e){const o=e[s]||[];for(const e of o){const{name:o,param:a}=y(e),i=h[o];if(!i)continue;const l=t?.[s];if(!(void 0!==a?i.method(a)(l,t):i.method(l,t))){r=!1,n[s]||(n[s]=[]);const e="function"==typeof i.message?i.message(a):i.message;n[s].push(e)}}}return{isValid:r,errors:n}},ping:()=>console.log("PONG"),description:"V is for validating forms"},g=e=>({on:(t,r)=>e?.addEventListener(t,r),off:(t,r)=>e?.removeEventListener(t,r)}),b=(e,t)=>{if(!e)return;const r="innerText"in e?"innerText":"textContent";return null!=t&&(e[r]=t),e[r]},S=(e,t)=>{if(e)return null!=t&&(e.innerHTML=t),e.innerHTML},w=e=>document.createElement(e),E=e=>{let t="";const r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let n=0;n<e;n++)t+=r.charAt(Math.floor(62*Math.random()));return t},v=e=>{const t=document.implementation.createHTMLDocument("");return t.body.innerHTML=e,[...t.body.childNodes]},A=e=>{"loading"!==document.readyState?e():document.addEventListener("DOMContentLoaded",e)},T=e=>{window.onload=e},$=e=>{const t="string"==typeof e?document.querySelector(e):e,r=e=>(...r)=>{if(t)return e(...r)},n={elt:t,value:t?.value,text:e=>null!=e?(b(t,e),n):b(t),html:e=>null!=e?(S(t,e),n):S(t),val:r(e=>{if(null!=e){if(t.opt&&t.multiple){const r=new Set(Array.isArray(e)?e:[e]);Array.from(t.options).forEach(e=>{e.selected=r.has(e.value)})}else t.value=e;return n.value=t.value,n}return t.options&&t.multiple?Array.from(t.options).filter(e=>e.selected).map(e=>e.value):t.value}),addClass:r(e=>(t.classList.add(e),n)),removeClass:r(e=>(t.classList.remove(e),n)),hasClass:r(e=>t.classList.contains(e)),hide:r(()=>(t.style.display="none",n)),show:r(()=>(t.style.display="",n)),prop:r(e=>t[e]),attr:r(e=>t.getAttribute(e)),removeAttr:e=>{t.removeAttribute(e)},toggle:r(()=>("none"==t.style.display?n.show():n.hide(),n)),css:r(e=>(Object.entries(e).forEach(([e,r])=>{t.style[e]=r}),n)),on:g(t).on,off:g(t).off};return n},C=e=>document.querySelectorAll(e),D={Q:$,$:$,all:C,$$:C,scan:(e,t={})=>{const r=t.refAttr||"v-ref",n="string"==typeof e?document.querySelector(e):e||document;if(!n)throw new Error(`Dom.scan: root "${e}" not found`);const s=Object.create(null);return n.querySelectorAll(`[${r}]`).forEach(e=>{const t=e.getAttribute(r);if(!t)return;const n=$(e);s[t]?Array.isArray(s[t])?s[t].push(n):s[t]=[s[t],n]:s[t]=n}),new Proxy({},{get(e,t){if("_"===t)return s;if("get"===t)return e=>s[e];if("all"===t)return e=>s[e]?Array.isArray(s[e])?s[e]:[s[e]]:[];if("on"===t)return(e,t,r)=>{const n=s[e];(Array.isArray(n)?n:[n]).forEach(e=>e?.on(t,r))};if("string"!=typeof t)return;const r=s[t];return r||(console.warn(`DOM.scan: ref "${t}" not found`),$(null))}})},make:w,makeId:E,parseHtml:v,onPageLoad:A,onWindowLoad:T,ping:()=>console.log("PONG!"),description:"DOM is for dom manipulation"};let I="",N=8e3,q=null,R=null,M=null;const L=new Map,O=new Map,U=()=>Date.now();function x(e){const t="undefined"!=typeof window?window[e]:null;return t?{get(e){const r=t.getItem(e);if(!r)return null;try{const n=JSON.parse(r);return n.exp&&n.exp<U()?(t.removeItem(e),null):n.val}catch{return null}},set(e,r,n){const s=n?U()+n:null;t.setItem(e,JSON.stringify({val:r,exp:s}))},del(e){t&&t.removeItem(e)},clear(){t&&t.clear()}}:null}const H={memory:{get(e){const t=O.get(e);return t?t.exp&&t.exp<U()?(O.delete(e),null):t.val:null},set(e,t,r){const n=r?U()+r:null;O.set(e,{val:t,exp:n})},del(e){O.delete(e)},clear(){O.clear()}},local:x("localStorage"),session:x("sessionStorage")};function k(e){return null===e||"object"!=typeof e?String(e):Array.isArray(e)?`[${e.map(k).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${k(e[t])}`).join(",")}}`}const F=(e,t)=>setTimeout(()=>t.abort(),e);async function P(e,t,r={}){const{params:n,body:s,headers:o={},cache:a}=r;let i=I+t;if(n){const e=new URLSearchParams(n).toString();i+=(i.includes("?")?"&":"?")+e}const l=new AbortController,u=F(N,l),c=!!a,d=a?.strategy,m=a?.ttl??0,f=function(e="memory"){return H[e]||H.memory}(a?.storage),h=a?.key||function(e,t,r,n){return`H|${e}|${t}${r?`?${new URLSearchParams(r).toString()}`:""}${n&&"GET"!==e?`#${k(n)}`:""}`}(e,i,n,s);if(c&&!a?.forceRefresh&&"cache-first"===d){const e=f.get(h);if(null!==e)return e}let y={method:e,headers:o,signal:l.signal};if(M){const{token:e,headerName:t}=M,r="function"==typeof e?e():e;if(r){const e="Authorization"===t?"Bearer ":"";y.headers[t]=`${e}${r}`}}void 0!==s&&(s instanceof FormData?y.body=s:(y.headers["Content-Type"]="application/json",y.body=JSON.stringify(s))),q&&(y=q(y)||y);try{let t,r=await fetch(i,y);L.has(r.status)&&L.get(r.status)(r,{method:e,url:i}),clearTimeout(u),R&&(r=R(r)||r);try{t=await r.json()}catch{t=await r.text()}if(!r.ok){const n={status:r.status,data:t,url:i,method:e};if(c&&"network-first"===d){const e=f.get(h);if(null!==e)return e}throw n}return c&&f.set(h,t,m),t}catch(e){if(clearTimeout(u),c&&"network-first"===d){const e=f.get(h);if(null!==e)return e}throw e}}async function j(e,{filename:t,params:r,headers:n={},method:s="GET",body:o,onProgress:a}={}){let i=I+e;if(r){const e=new URLSearchParams(r).toString();i+=(i.includes("?")?"&":"?")+e}const l=new AbortController,u=F(N,l),c={method:s,headers:{...n},signal:l.signal};void 0!==o&&(o instanceof FormData?c.body=o:(c.headers["Content-Type"]=c.headers["Content-Type"]||"application/json",c.body="string"==typeof o?o:JSON.stringify(o)));const d=await fetch(i,c);if(clearTimeout(u),!d.ok){let e="";try{e=await d.text()}catch{}throw new Error(`Download failed ${d.status}: ${e||d.statusText}`)}if(!t){const e=d.headers.get("Content-Disposition")||"",r=/filename\*=UTF-8''([^;]+)|filename="?([^"]+)"?/i.exec(e);t=decodeURIComponent(r?.[1]||r?.[2]||"download")}let m;if(d.body&&"getReader"in d.body){const e=d.body.getReader(),t=Number(d.headers.get("Content-Length"))||null,r=[];let n=0;for(;;){const{done:s,value:o}=await e.read();if(s)break;if(r.push(o),n+=o.length,"function"==typeof a){a(n,t,t?Math.round(n/t*100):null)}}m=new Blob(r)}else m=await d.blob(),"function"==typeof a&&a(1,1,100);const f=URL.createObjectURL(m),h=document.createElement("a");return h.href=f,h.download=t,h.style.display="none",document.body.appendChild(h),h.click(),document.body.removeChild(h),URL.revokeObjectURL(f),{filename:t,size:m.size,type:m.type}}function _(e,{files:t,fieldName:r="file",fields:n={},headers:s={},method:o="POST",onProgress:a,signal:i}={}){return new Promise((l,u)=>{const c=function({files:e,fieldName:t="file",fields:r={}}){const n=new FormData,s=Array.isArray(e)?e:[e];return s.forEach((e,r)=>{const o=s.length>1?`${t}[${r}]`:t;n.append(o,e)}),Object.entries(r).forEach(([e,t])=>{n.append(e,t instanceof Blob||t instanceof File?t:"object"==typeof t?JSON.stringify(t):String(t))}),n}({files:t,fieldName:r,fields:n}),d=`${I}${e}`,m=new XMLHttpRequest;m.open(o,d,!0);let f={method:o,headers:{...s}};if(M){const{token:e,headerName:t}=M,r="function"==typeof e?e():e;if(r){const e="Authorization"===t?"Bearer ":"";f.headers[t]=`${e}${r}`}}if(q&&(f=q(f)||f),Object.entries(f.headers).forEach(([e,t])=>m.setRequestHeader(e,t)),m.timeout=N,i){const e=()=>{try{m.abort()}catch{}};i.aborted&&e(),i.addEventListener("abort",e,{once:!0})}m.upload&&"function"==typeof a&&(m.upload.onprogress=e=>{if(!e.lengthComputable)return void a(e.loaded,null,null);const t=Math.round(e.loaded/e.total*100);a(e.loaded,e.total,t)}),m.onreadystatechange=async()=>{if(4!==m.readyState)return;if(R){const e={status:m.status,ok:m.status>=200&&m.status<300,headers:new Headers,text:async()=>m.responseText,json:async()=>JSON.parse(m.responseText||"null")};R(e)}const e=(m.getResponseHeader("Content-Type")||"").includes("application/json")?function(e){try{return JSON.parse(e||"null")}catch{return e}}(m.responseText):m.responseText;m.status>=200&&m.status<300?l(e):u({status:m.status,data:e,url:d,method:o})},m.onerror=()=>u({status:0,data:"Network error",url:`${I}${e}`,method:o}),m.ontimeout=()=>u({status:0,data:"Timeout",url:`${I}${e}`,method:o}),m.send(c)})}const B=(e,t)=>P("GET",e,t),V=(e,t,r={})=>P("POST",e,{...r,body:t}),G=(e,t,r={})=>P("PUT",e,{...r,body:t}),z=(e,t={})=>P("DELETE",e,t),J=(e,t)=>fetch(I+e,t),Y={base:e=>(I=e,Y),timeout:e=>(N=e,Y),bearer:(e,t="Authorization")=>(M={token:e,headerName:t},Y),onStatus:(e,t)=>(L.set(e,t),Y),onUnauthorized:e=>Y.onStatus(401,e),onForbidden:e=>Y.onStatus(403,e),onInternalServerError:e=>Y.onStatus(500,e),interceptRequest:e=>(q=e,Y),interceptResponse:e=>(R=e,Y),get:B,post:V,put:G,delete:z,raw:J,download:j,upload:_,ping:()=>console.log("PONG"),description:"H is for Http"},K={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 Q{constructor(e,t,r,n={}){this.formId=e,this.schema=t,this.onSubmit=r,this.preSubmit=n.preSubmit||null,this.form=null,this.formState={},this.errors={},this.initialValues={},this._boundHandleSubmit=this.#e.bind(this),this._boundHandleInput=this.#t.bind(this),this.#r()}#r(){this.form=document.getElementById(this.formId),this.form?(this.#n(),this.form.addEventListener("submit",this._boundHandleSubmit),this.form.addEventListener("input",this._boundHandleInput),this.#s()):console.error(`Form with id ${this.formId} not found`)}#n(){const e=this.form.elements;for(const t of Array.from(e))t.name&&(this.initialValues[t.name]=t.value,this.formState[t.name]=t.value)}#t(e){const{name:t,value:r}=e.target;t&&(this.formState[t]=r,this.#s(),this.errors[t]&&(delete this.errors[t],this.#o()))}async#e(e){e.preventDefault();const r=new FormData(this.form);let n={};r.forEach((e,t)=>{n[t]=e}),this.formState=n,this.#s();const{isValid:s,errors:o}=p.run(this.schema,n);if(t.pub(K.VALIDATED,{formId:this.formId,isValid:s,errors:o,data:n}),!s)return this.errors=o,this.#o(),void t.pub(K.SUBMIT_ERROR,{formId:this.formId,errors:o});if(this.errors={},this.#o(),this.preSubmit)try{n=await this.preSubmit(n)}catch(e){return void t.pub(K.SUBMIT_ERROR,{formId:this.formId,errors:{_preSubmit:[e.message]}})}t.pub(K.SUBMIT_SUCCESS,{formId:this.formId,data:n}),this.onSubmit(n)}#s(){t.pub(K.STATE_CHANGE,{formId:this.formId,state:{...this.formState}})}#o(){t.pub(K.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.#s(),this.#o(),t.pub(K.RESET,{formId:this.formId})}validateNow(){const e=new FormData(this.form),r={};e.forEach((e,t)=>{r[t]=e});const n=p.run(this.schema,r);return this.errors=n.errors,this.#o(),t.pub(K.VALIDATED,{formId:this.formId,isValid:n.isValid,errors:n.errors,data:r}),n}destroy(){this.form&&(this.form.removeEventListener("submit",this._boundHandleSubmit),this.form.removeEventListener("input",this._boundHandleInput))}}class W{constructor(e,r={}){this.formId=e,this.options={containerClass:"form-error-container",errorClass:"text-danger",insertAfterField:!0,...r},this.customContainers={},this._boundHandleErrors=this.#a.bind(this),t.sub(K.ERRORS_CHANGE,this._boundHandleErrors)}#a({formId:e,errors:t}){e===this.formId&&(this.clearAll(),this.renderAll(t))}setContainer(e,t){this.customContainers[e]="string"==typeof t?document.querySelector(t):t}renderAll(e){for(const t in e)this.render(t,e[t])}render(e,t){if(!t||0===t.length)return null;const r=document.createElement("span");r.className=`${this.options.containerClass} ${this.options.errorClass}`,r.dataset.field=e;const n=document.createElement("ul");t.forEach(e=>{const t=document.createElement("li"),r=document.createElement("i");r.textContent=e,t.appendChild(r),n.appendChild(t)}),r.appendChild(n);const s=this.customContainers[e];if(s)s.innerHTML="",s.appendChild(r);else if(this.options.insertAfterField){const t=document.getElementById(this.formId),n=t?.querySelector(`[name="${e}"]`);n&&n.insertAdjacentElement("afterend",r)}return r}clearAll(){const e=document.getElementById(this.formId);if(!e)return;e.querySelectorAll(`.${this.options.containerClass}`).forEach(e=>e.remove());for(const e in this.customContainers)this.customContainers[e]&&(this.customContainers[e].innerHTML="")}destroy(){t.unsub(K.ERRORS_CHANGE,this._boundHandleErrors),this.clearAll()}}function Z(e){let t=e;const r=new Set;return{get val(){return t},set val(e){if(e!==t){t=e;for(const e of r)e()}},peek:()=>t,subscribe:e=>(r.add(e),()=>r.delete(e)),toString:()=>String(t),valueOf:()=>t}}const X=((e={})=>{const{persistKey:r="query-cache",persistedKeys:n=null,defaultTtl:s=6e4,defaultStaleTime:o=5e3,defaultRetries:i=3,defaultRetryDelay:l=1e3}=e,u=new Map,c=new Map,d=(e,r,n)=>{t.pub(`query:${e}`,{key:r,...n}),t.pub(`query:${r}:${e}`,n)},m=()=>{try{const e=localStorage.getItem(r);if(!e)return;const n=JSON.parse(e),s=Date.now();for(const[e,t]of Object.entries(n))s<t.expiry&&u.set(e,{...t,promise:null});t.pub("query:hydrated",{keys:[...u.keys()]})}catch(e){console.warn("Failed to load query cache: ",e)}},f=()=>{try{const e={};for(const[t,r]of u.entries())void 0!==r.data&&(n&&!n.some(e=>t.startsWith(e))||(e[t]={data:r.data,staleAt:r.staleAt,expiry:r.expiry}));localStorage.setItem(r,JSON.stringify(e))}catch(e){console.warn("Failed to persist query cache: ",e)}};let h=null;const y=()=>{h&&clearTimeout(h),h=setTimeout(f,1e3)},p=e=>u.get(e)??null,g=async(e,t,r={})=>{const{ttl:n=s,staleTime:c=o,retries:m=i,retryDelay:f=l}=r,h=Date.now(),g=p(e);if(g&&h<g.staleAt)return d("hit",e,{data:g.data}),g.data;if(g?.promise)return g.promise;const b=g&&h<g.expiry;d("fetch",e,{isStale:b,hasCache:!!g});const S=(async(e,t,r,n)=>{let s;for(let o=0;o<=r;o++)try{return await t()}catch(t){if(s=t,o<r){const s=n*Math.pow(2,o);d("retry",e,{attempt:o+1,maxRetries:r,delay:s,error:t}),await a(s)}}throw s})(e,t,m,f).then(t=>(u.set(e,{data:t,staleAt:Date.now()+c,expiry:Date.now()+n,promise:null,error:null}),d("success",e,{data:t}),y(),t)).catch(t=>{throw u.set(e,{data:g?.data??null,staleAt:g?.staleAt??0,expiry:g?.expiry??0,promise:null,error:t}),d("error",e,{error:t,staleData:g?.data??null}),t});return u.set(e,{...g,promise:S}),b?g.data:S},b=e=>{const t=c.get(e);t&&(clearInterval(t),c.delete(e),d("polling:stop",e,{}))},S=()=>{for(const e of c.keys())b(e)},w=()=>{const e=Date.now(),r=[];for(const[n,s]of u.entries())e>s.expiry&&!t.has(`query:${n}:success`)&&(u.delete(n),r.push(n));r.length&&(y(),t.pub("query:gc",{collected:r}))};return m(),setInterval(w,6e4),window.addEventListener("storage",e=>{if(e.key===r){m();for(const e of u.keys())d("sync",e,{data:u.get(e)?.data})}}),window.addEventListener("beforeunload",()=>{S(),f()}),{query:g,mutate:(e,t)=>{const r=p(e);if(!r)return null;const n=r.data,s="function"==typeof t?t(n):t;return u.set(e,{...r,data:s}),d("mutate",e,{data:s,previous:n}),y(),n},setQueryData:(e,t,r={})=>{const{ttl:n=s,staleTime:a=o}=r,i=Date.now();u.set(e,{data:t,staleAt:i+a,expiry:i+n,promise:null,error:null}),d("set",e,{data:t}),y()},invalidate:(e,t={})=>{const{refetch:r,fetcher:n}=t;if(u.delete(e),d("invalidate",e,{}),y(),r&&n)return g(e,n)},invalidateMatching:e=>{const t=[];for(const r of u.keys())e(r)&&(u.delete(r),t.push(r),d("invalidate",r,{}));return y(),t},subscribe:(e,r)=>{const n=t=>r({...p(e),...t});t.sub(`query:${e}:success`,n),t.sub(`query:${e}:error`,n),t.sub(`query:${e}:mutate`,n),t.sub(`query:${e}:set`,n),t.sub(`query:${e}:invalidate`,()=>r(null));const s=p(e);return s&&r(s),()=>{t.unsub(`query:${e}:success`,n),t.unsub(`query:${e}:error`,n),t.unsub(`query:${e}:mutate`,n),t.unsub(`query:${e}:set`,n),t.unsub(`query:${e}:invalidate`,n)}},prefetch:(e,t,r)=>{const n=p(e);n&&Date.now()<n.staleAt||g(e,t,r).catch(()=>{})},startPolling:(e,t,r,n={})=>{b(e),g(e,t,n).catch(()=>{});const s=setInterval(()=>{const r=p(e);r&&u.set(e,{...r,staleAt:0}),g(e,t,n).catch(()=>{})},r);return c.set(e,s),d("polling:start",e,{interval:r}),()=>b(e)},stopPolling:b,stopAllPolling:S,getEntry:p,gc:w,clear:()=>{u.clear(),localStorage.removeItem(r),t.pub("query:cleared",{})}}})({persistKey:"teksoft-cache",persistedKeys:["user","settings"]}),ee=(e,t,r={})=>{const n=Z(r.inital??null),s=Z(!1),o=Z(null),a=X.subscribe(e,e=>{e?.data&&(n.val=e.data),e?.error&&(o.val=e.error),s.val=!!e?.promise&&!e?.data}),i=()=>(s.val=!0,X.query(e,t,r));return!1!==r.enabled&&i(),{data:n,loading:s,error:o,fetch:i,refetch:()=>(X.invalidate(e),i()),unsubscribe:a,mutate:t=>{const r=X.mutate(e,t);return n.val=X.getEntry(e)?.data,r}}};return e.DOM=D,e.EVT=t,e.FormErrorRenderer=W,e.FormEvents=K,e.FormHandler=Q,e.HTTP=Y,e.Q=$,e.V=p,e.all=C,e.bindQuery=(e,r,n={})=>{const{target:s,render:o,onLoading:a,onError:i,poll:l=null,...u}=n,c="string"==typeof s?document.querySelector(s):s,d=e=>{const t=o(e);"string"==typeof t&&(c.innerHTML=t)};if(t.sub(`query:${e}:success`,({data:e})=>d(e)),t.sub(`query:${e}:set`,({data:e})=>d(e)),t.sub(`query:${e}:mutate`,({data:e})=>d(e)),i&&t.sub(`query:${e}:error`,({error:e,staleData:t})=>i(e,t,c)),a&&t.sub(`query:${e}:fetch`,({hasCache:e})=>{e||a(c)}),X.query(e,r,u).catch(()=>{}),l)return X.startPolling(e,r,l,u)},e.cache=function(e){if(null==e)return{cache:{strategy:"cache-first",storage:"local",ttl:6e4}};if("object"==typeof e)return{cache:e};const t=e.toLowerCase(),r={cfl:{strategy:"cache-first",storage:"local"},cfs:{strategy:"cache-first",storage:"session"},cfm:{strategy:"cache-first",storage:"memory"},nfl:{strategy:"network-first",storage:"local"},nfs:{strategy:"network-first",storage:"session"},nfm:{strategy:"network-first",storage:"memory"}},n=t.match(/cfl|cfs|cfm|nfl|nfs|nfm/),s=n?r[n[0]]:r.cfl,o=t.match(/(\d+)\s*(s|sec|secs|second|seconds|min|m|mins|minute|minutes|h|hr|hours)?/),a=o?function(e){const t=e.replace(/[0-9]/g,"").trim().toLowerCase(),r=parseInt(e,10),n={s:1e3,sec:1e3,secs:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,mins:6e4,minute:6e4,minutes:6e4,h:36e5,hr:36e5,hrs:36e5,hours:36e5};return r*(n[t]||1)}(o[0]):6e4;return{cache:{strategy:s.strategy,storage:s.storage,ttl:a}}},e.del=z,e.download=j,e.formatByCountry=(e,t)=>n(e,r[t]??r.US),e.get=B,e.isArray=e=>Array.isArray(e),e.isArrayEmpty=e=>!(Array.isArray(e)&&e.length>0),e.isFocus=e=>e==document.activeElement,e.isValidRoutingNumber=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},e.make=w,e.makeId=E,e.onPageLoad=A,e.onWindowLoad=T,e.parseHtml=v,e.pollingSignal=(e,t,r,n={})=>({...ee(e,t,{...n,enabled:!1}),stop:X.startPolling(e,t,r,n)}),e.post=V,e.put=G,e.queryClient=X,e.querySignal=ee,e.raw=J,e.redirect=e=>window.location.href=e,e.request=P,e.toCurrency=n,e.upload=_,e.useFormHandler=function(e,t,r,n){const s=new Q(e,t,r,n),o=new W(e,n);return{reset:()=>s.reset(),validate:()=>s.validateNow(),destroy:()=>{o.destroy(),s.destroy()},setContainer:(e,t)=>o.setContainer(e,t)}},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),e}({});
|
|
1
|
+
var vaniy=function(e){"use strict";const t={listeners:new Map,sub:function(e,t){let r=this.listeners.get(e);r||(r=new Set,this.listeners.set(e,r)),r.add(t)},once:function(e,t){const r=(...n)=>{t(...n),this.unsub(e,r)};this.sub(e,r)},unsub:function(e,t){let r=this.listeners.get(e);r&&r.delete(t)},pub:function(e,...t){let r=this.listeners.get(e);r&&r.forEach(r=>{try{r(...t)}catch(t){console.error(`Error in event "${e}" listener: `,t)}})},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"},r={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"}},n=(e,{locale:t="en-US",currency:r="USD"}={})=>Intl.NumberFormat(t,{style:"currency",currency:r}).format(e);function s(e){return Array.isArray(e)?e.length:function(e){if("number"==typeof e)return Number.isFinite(e);if("string"!=typeof e)return!1;const t=e.trim();return!!t&&/^-?\d+(\.\d+)?$/.test(t)}(e)?Number(String(e).trim()):String(e??"").length}function o(e){const[t,r]=String(e??"").split(",").map(e=>e.trim()),n=Number(t),s=Number(r);return Number.isFinite(n)&&Number.isFinite(s)?{min:n,max:s}:null}const a=e=>new Promise(t=>setTimeout(t,e));function i(e,t){const r=String(e??"").trim();if(!r)return null;if("YYYY-MM-DD"===t){const e=r.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!e)return null;const t=Number(e[1]),n=Number(e[2]),s=Number(e[3]);return!t||n<1||n>12||s<1||s>31?null:{year:t,month:n,day:s}}return null}function l(e,t,r="en-US"){const n=new Intl.DateTimeFormat(r,{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(e),s=Object.fromEntries(n.map(e=>[e.type,e.value]));return{year:Number(s.year),month:Number(s.month),day:Number(s.day),hour:Number(s.hour),minute:Number(s.minute),second:Number(s.second)}}function u({year:e,month:t,day:r},n){const s=new Date(Date.UTC(e,t-1,r));return s.setUTCDate(s.getUTCDate()+n),{year:s.getUTCFullYear(),month:s.getUTCMonth()+1,day:s.getUTCDate()}}function c(e,t,r){const{base:n,offsetDays:s}=function(e){const t=String(e).trim().match(/^(.+?)([+-]\d+)?$/);return t?{base:t[1].trim(),offsetDays:t[2]?Number(t[2]):0}:{base:String(e).trim(),offsetDays:0}}(e);let o=function(e,t){const r=new Date,{year:n,month:s,day:o}=l(r,t);return"today"===e?{year:n,month:s,day:o}:"tomorrow"===e?u({year:n,month:s,day:o},1):"yesterday"===e?u({year:n,month:s,day:o},-1):null}(n,r.timezone);if(!o){const e=t?.[n];o=d(e,r)}return o||(o=i(n,r.dateFormat)),o?(s&&(o=u(o,s)),o):null}function d(e,t){if(null==(r=e)||""===String(r??"").trim())return null;var r;const n=String(e).trim();let s=i(n,t.dateFormat);if(s)return s;if(!/^\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}(:\d{2}(\.\d{1,3})?)?(Z|[+-]\d{2}:\d{2})?$/.test(n))return null;const o=new Date(n);if(isNaN(o.getTime()))return null;const a=l(o,t.timezone);return{year:a.year,month:a.month,day:a.day}}function m(e,t,r,n){let s=null;return s="value"===n?d(e,r):c(e,t,r),s?function({year:e,month:t,day:r},n){let s=Date.UTC(e,t-1,r,0,0,0);for(let o=0;o<2;o++){const o=l(new Date(s),n),a=Date.UTC(o.year,o.month-1,o.day,o.hour,o.minute,o.second)-Date.UTC(e,t-1,r,0,0,0);if(0===a)break;s-=a}return s}(s,r.timezone):null}function f(e,t){return{method:t=>(r,n,s)=>{const o=m(r,n,s,"value"),a=m(t,n,s,"target");return null!=o&&null!=a&&e(o,a)},message:t}}const h={required:{method:e=>""!==String(e??"").trim(),message:"This field is required"},requiredIf:{method:e=>(t,r)=>{const[n,s]=String(e).split("="),o=r?.[n];return!(null!=s?String(o??"")===s:""!==String(o??"").trim())||""!==String(t??"").trim()},message:e=>{const[t,r]=String(e).split("=");return null!=r?`This field is requied when ${t} is ${r}`:`This field is required when ${t} has a value`}},email:{method:e=>/\S+@\S+\.\S+/.test(e),message:"Email is invalid"},min:{method:e=>t=>String(t??"").length>=Number(e),message:e=>`Must be at least ${e} characters`},max:{method:e=>t=>String(t??"").length<=Number(e),message:e=>`Must be at most ${e} characters`},date:{method:e=>{if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;const[t,r,n]=e.split("-").map(Number),s=new Date(t,r-1,n);return s.getFullYear()===t&&s.getMonth()===r-1&&s.getDate()===n},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."},same:{method:e=>(t,r)=>String(t??"")===String(r?.[e]??""),message:e=>`Must match ${e}`},in:{method:e=>t=>(Array.isArray(e)?e:String(e??"").split(",").map(e=>e.trim()).filter(Boolean)).includes(String(t??"").trim()),message:e=>`Must be one of the following: ${(Array.isArray(e)?e:String(e??"").split(",").map(e=>e.trim())).filter(Boolean).join(",")}`},before:f((e,t)=>e<t,e=>`Must be before ${e}`),beforeOrEqual:f((e,t)=>e<=t,e=>`Must be before or equal to ${e}`),after:f((e,t)=>e>t,e=>`Must be after ${e}`),afterOrEqual:f((e,t)=>e>=t,e=>`Must be after or equal to ${e}`),between:{method:e=>t=>{const r=o(e);if(!r)return!1;const n=s(t);return r.min<=n&&n<=r.max},message:e=>{const t=o(e);return t?`Must be between ${t.min} and ${t.max}`:"Between rule is invalid. Use between:min,max"}}};function y(e){const t=e.indexOf(":");return-1===t?{name:e,param:void 0}:{name:e.slice(0,t),param:e.slice(t+1)}}const p={run:function(e,t){let r=!0;const n={};for(const s in e){const o=e[s]||[];for(const e of o){const{name:o,param:a}=y(e),i=h[o];if(!i)continue;const l=t?.[s];if(!(void 0!==a?i.method(a)(l,t):i.method(l,t))){r=!1,n[s]||(n[s]=[]);const e="function"==typeof i.message?i.message(a):i.message;n[s].push(e)}}}return{isValid:r,errors:n}},ping:()=>console.log("PONG"),description:"V is for validating forms"},b=e=>({on:(t,r)=>e?.addEventListener(t,r),off:(t,r)=>e?.removeEventListener(t,r)}),g=(e,t)=>{if(!e)return;const r="innerText"in e?"innerText":"textContent";return null!=t&&(e[r]=t),e[r]},S=(e,t)=>{if(e)return null!=t&&(e.innerHTML=t),e.innerHTML},v=e=>document.createElement(e),w=e=>{let t="";const r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let n=0;n<e;n++)t+=r.charAt(Math.floor(62*Math.random()));return t},E=e=>{const t=document.implementation.createHTMLDocument("");return t.body.innerHTML=e,[...t.body.childNodes]},A=e=>{"loading"!==document.readyState?e():document.addEventListener("DOMContentLoaded",e)},$=e=>{window.onload=e},T=e=>{const t="string"==typeof e?document.querySelector(e):e,r=e=>(...r)=>{if(t)return e(...r)},n={elt:t,value:t?.value,text:e=>null!=e?(g(t,e),n):g(t),html:e=>null!=e?(S(t,e),n):S(t),val:r(e=>{if(null!=e){if(t.opt&&t.multiple){const r=new Set(Array.isArray(e)?e:[e]);Array.from(t.options).forEach(e=>{e.selected=r.has(e.value)})}else t.value=e;return n.value=t.value,n}return t.options&&t.multiple?Array.from(t.options).filter(e=>e.selected).map(e=>e.value):t.value}),addClass:r(e=>(t.classList.add(e),n)),removeClass:r(e=>(t.classList.remove(e),n)),hasClass:r(e=>t.classList.contains(e)),hide:r(()=>(t.style.display="none",n)),show:r(()=>(t.style.display="",n)),prop:r(e=>t[e]),attr:r(e=>t.getAttribute(e)),removeAttr:e=>{t.removeAttribute(e)},toggle:r(()=>("none"==t.style.display?n.show():n.hide(),n)),css:r(e=>(Object.entries(e).forEach(([e,r])=>{t.style[e]=r}),n)),on:b(t).on,off:b(t).off};return n},C=e=>document.querySelectorAll(e),D={Q:T,$:T,all:C,$$:C,scan:(e,t={})=>{const r=t.refAttr||"v-ref",n="string"==typeof e?document.querySelector(e):e||document;if(!n)throw new Error(`Dom.scan: root "${e}" not found`);const s=Object.create(null);return n.querySelectorAll(`[${r}]`).forEach(e=>{const t=e.getAttribute(r);if(!t)return;const n=T(e);s[t]?Array.isArray(s[t])?s[t].push(n):s[t]=[s[t],n]:s[t]=n}),new Proxy({},{get(e,t){if("_"===t)return s;if("get"===t)return e=>s[e];if("all"===t)return e=>s[e]?Array.isArray(s[e])?s[e]:[s[e]]:[];if("on"===t)return(e,t,r)=>{const n=s[e];(Array.isArray(n)?n:[n]).forEach(e=>e?.on(t,r))};if("string"!=typeof t)return;const r=s[t];return r||(console.warn(`DOM.scan: ref "${t}" not found`),T(null))}})},make:v,makeId:w,parseHtml:E,onPageLoad:A,onWindowLoad:$,ping:()=>console.log("PONG!"),description:"DOM is for dom manipulation"};let I="",N=8e3,q=null,R=null,M=null;const x=new Map,L=new Map,O=()=>Date.now();function U(e){const t="undefined"!=typeof window?window[e]:null;return t?{get(e){const r=t.getItem(e);if(!r)return null;try{const n=JSON.parse(r);return n.exp&&n.exp<O()?(t.removeItem(e),null):n.val}catch{return null}},set(e,r,n){const s=n?O()+n:null;t.setItem(e,JSON.stringify({val:r,exp:s}))},del(e){t&&t.removeItem(e)},clear(){t&&t.clear()}}:null}const H={memory:{get(e){const t=L.get(e);return t?t.exp&&t.exp<O()?(L.delete(e),null):t.val:null},set(e,t,r){const n=r?O()+r:null;L.set(e,{val:t,exp:n})},del(e){L.delete(e)},clear(){L.clear()}},local:U("localStorage"),session:U("sessionStorage")};function k(e){return null===e||"object"!=typeof e?String(e):Array.isArray(e)?`[${e.map(k).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${k(e[t])}`).join(",")}}`}const F=(e,t)=>setTimeout(()=>t.abort(),e);async function j(e,t,r={}){const{params:n,body:s,headers:o={},cache:a}=r;let i=I+t;if(n){const e=new URLSearchParams(n).toString();i+=(i.includes("?")?"&":"?")+e}const l=new AbortController,u=F(N,l),c=!!a,d=a?.strategy,m=a?.ttl??0,f=function(e="memory"){return H[e]||H.memory}(a?.storage),h=a?.key||function(e,t,r,n){return`H|${e}|${t}${r?`?${new URLSearchParams(r).toString()}`:""}${n&&"GET"!==e?`#${k(n)}`:""}`}(e,i,n,s);if(c&&!a?.forceRefresh&&"cache-first"===d){const e=f.get(h);if(null!==e)return e}let y={method:e,headers:o,signal:l.signal};if(M){const{token:e,headerName:t}=M,r="function"==typeof e?e():e;if(r){const e="Authorization"===t?"Bearer ":"";y.headers[t]=`${e}${r}`}}void 0!==s&&(s instanceof FormData?y.body=s:(y.headers["Content-Type"]="application/json",y.body=JSON.stringify(s))),q&&(y=q(y)||y);try{let t,r=await fetch(i,y);x.has(r.status)&&x.get(r.status)(r,{method:e,url:i}),clearTimeout(u),R&&(r=R(r)||r);try{t=await r.json()}catch{t=await r.text()}if(!r.ok){const n={status:r.status,data:t,url:i,method:e};if(c&&"network-first"===d){const e=f.get(h);if(null!==e)return e}throw n}return c&&f.set(h,t,m),t}catch(e){if(clearTimeout(u),c&&"network-first"===d){const e=f.get(h);if(null!==e)return e}throw e}}async function P(e,{filename:t,params:r,headers:n={},method:s="GET",body:o,onProgress:a}={}){let i=I+e;if(r){const e=new URLSearchParams(r).toString();i+=(i.includes("?")?"&":"?")+e}const l=new AbortController,u=F(N,l),c={method:s,headers:{...n},signal:l.signal};void 0!==o&&(o instanceof FormData?c.body=o:(c.headers["Content-Type"]=c.headers["Content-Type"]||"application/json",c.body="string"==typeof o?o:JSON.stringify(o)));const d=await fetch(i,c);if(clearTimeout(u),!d.ok){let e="";try{e=await d.text()}catch{}throw new Error(`Download failed ${d.status}: ${e||d.statusText}`)}if(!t){const e=d.headers.get("Content-Disposition")||"",r=/filename\*=UTF-8''([^;]+)|filename="?([^"]+)"?/i.exec(e);t=decodeURIComponent(r?.[1]||r?.[2]||"download")}let m;if(d.body&&"getReader"in d.body){const e=d.body.getReader(),t=Number(d.headers.get("Content-Length"))||null,r=[];let n=0;for(;;){const{done:s,value:o}=await e.read();if(s)break;if(r.push(o),n+=o.length,"function"==typeof a){a(n,t,t?Math.round(n/t*100):null)}}m=new Blob(r)}else m=await d.blob(),"function"==typeof a&&a(1,1,100);const f=URL.createObjectURL(m),h=document.createElement("a");return h.href=f,h.download=t,h.style.display="none",document.body.appendChild(h),h.click(),document.body.removeChild(h),URL.revokeObjectURL(f),{filename:t,size:m.size,type:m.type}}function _(e,{files:t,fieldName:r="file",fields:n={},headers:s={},method:o="POST",onProgress:a,signal:i}={}){return new Promise((l,u)=>{const c=function({files:e,fieldName:t="file",fields:r={}}){const n=new FormData,s=Array.isArray(e)?e:[e];return s.forEach((e,r)=>{const o=s.length>1?`${t}[${r}]`:t;n.append(o,e)}),Object.entries(r).forEach(([e,t])=>{n.append(e,t instanceof Blob||t instanceof File?t:"object"==typeof t?JSON.stringify(t):String(t))}),n}({files:t,fieldName:r,fields:n}),d=`${I}${e}`,m=new XMLHttpRequest;m.open(o,d,!0);let f={method:o,headers:{...s}};if(M){const{token:e,headerName:t}=M,r="function"==typeof e?e():e;if(r){const e="Authorization"===t?"Bearer ":"";f.headers[t]=`${e}${r}`}}if(q&&(f=q(f)||f),Object.entries(f.headers).forEach(([e,t])=>m.setRequestHeader(e,t)),m.timeout=N,i){const e=()=>{try{m.abort()}catch{}};i.aborted&&e(),i.addEventListener("abort",e,{once:!0})}m.upload&&"function"==typeof a&&(m.upload.onprogress=e=>{if(!e.lengthComputable)return void a(e.loaded,null,null);const t=Math.round(e.loaded/e.total*100);a(e.loaded,e.total,t)}),m.onreadystatechange=async()=>{if(4!==m.readyState)return;if(R){const e={status:m.status,ok:m.status>=200&&m.status<300,headers:new Headers,text:async()=>m.responseText,json:async()=>JSON.parse(m.responseText||"null")};R(e)}const e=(m.getResponseHeader("Content-Type")||"").includes("application/json")?function(e){try{return JSON.parse(e||"null")}catch{return e}}(m.responseText):m.responseText;m.status>=200&&m.status<300?l(e):u({status:m.status,data:e,url:d,method:o})},m.onerror=()=>u({status:0,data:"Network error",url:`${I}${e}`,method:o}),m.ontimeout=()=>u({status:0,data:"Timeout",url:`${I}${e}`,method:o}),m.send(c)})}const B=(e,t)=>j("GET",e,t),V=(e,t,r={})=>j("POST",e,{...r,body:t}),G=(e,t,r={})=>j("PUT",e,{...r,body:t}),z=(e,t={})=>j("DELETE",e,t),J=(e,t)=>fetch(I+e,t),Y={base:e=>(I=e,Y),timeout:e=>(N=e,Y),bearer:(e,t="Authorization")=>(M={token:e,headerName:t},Y),onStatus:(e,t)=>(x.set(e,t),Y),onUnauthorized:e=>Y.onStatus(401,e),onForbidden:e=>Y.onStatus(403,e),onInternalServerError:e=>Y.onStatus(500,e),interceptRequest:e=>(q=e,Y),interceptResponse:e=>(R=e,Y),get:B,post:V,put:G,delete:z,raw:J,download:P,upload:_,ping:()=>console.log("PONG"),description:"H is for Http"};let Q=null,W=new Set;function K(e){let t=e;const r=new Set;return{get val(){return Q&&r.add(Q),t},set val(e){if(e!==t){t=e;for(const e of r)e()}},peek:()=>t,subscribe:e=>(r.add(e),()=>r.delete(e)),toString:()=>String(t),valueOf:()=>t}}function Z(e){const t=()=>{const r=Q;Q=t;try{e()}finally{Q=r}};return t(),t}function X(e){return"string"==typeof e?T(e):e}const ee={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 te{constructor(e,t,r,n={}){this.formId=e,this.schema=t,this.onSubmit=r,this.preSubmit=n.preSubmit||null,this.form=null,this.formState={},this.errors={},this.initialValues={},this._boundHandleSubmit=this.#e.bind(this),this._boundHandleInput=this.#t.bind(this),this.#r()}#r(){this.form=document.getElementById(this.formId),this.form?(this.#n(),this.form.addEventListener("submit",this._boundHandleSubmit),this.form.addEventListener("input",this._boundHandleInput),this.#s()):console.error(`Form with id ${this.formId} not found`)}#n(){const e=this.form.elements;for(const t of Array.from(e))t.name&&(this.initialValues[t.name]=t.value,this.formState[t.name]=t.value)}#t(e){const{name:t,value:r}=e.target;t&&(this.formState[t]=r,this.#s(),this.errors[t]&&(delete this.errors[t],this.#o()))}async#e(e){e.preventDefault();const r=new FormData(this.form);let n={};r.forEach((e,t)=>{n[t]=e}),this.formState=n,this.#s();const{isValid:s,errors:o}=p.run(this.schema,n);if(t.pub(ee.VALIDATED,{formId:this.formId,isValid:s,errors:o,data:n}),!s)return this.errors=o,this.#o(),void t.pub(ee.SUBMIT_ERROR,{formId:this.formId,errors:o});if(this.errors={},this.#o(),this.preSubmit)try{n=await this.preSubmit(n)}catch(e){return void t.pub(ee.SUBMIT_ERROR,{formId:this.formId,errors:{_preSubmit:[e.message]}})}t.pub(ee.SUBMIT_SUCCESS,{formId:this.formId,data:n}),this.onSubmit(n)}#s(){t.pub(ee.STATE_CHANGE,{formId:this.formId,state:{...this.formState}})}#o(){t.pub(ee.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.#s(),this.#o(),t.pub(ee.RESET,{formId:this.formId})}validateNow(){const e=new FormData(this.form),r={};e.forEach((e,t)=>{r[t]=e});const n=p.run(this.schema,r);return this.errors=n.errors,this.#o(),t.pub(ee.VALIDATED,{formId:this.formId,isValid:n.isValid,errors:n.errors,data:r}),n}destroy(){this.form&&(this.form.removeEventListener("submit",this._boundHandleSubmit),this.form.removeEventListener("input",this._boundHandleInput))}}class re{constructor(e,r={}){this.formId=e,this.options={containerClass:"form-error-container",errorClass:"text-danger",insertAfterField:!0,...r},this.customContainers={},this._boundHandleErrors=this.#a.bind(this),t.sub(ee.ERRORS_CHANGE,this._boundHandleErrors)}#a({formId:e,errors:t}){e===this.formId&&(this.clearAll(),this.renderAll(t))}setContainer(e,t){this.customContainers[e]="string"==typeof t?document.querySelector(t):t}renderAll(e){for(const t in e)this.render(t,e[t])}render(e,t){if(!t||0===t.length)return null;const r=document.createElement("span");r.className=`${this.options.containerClass} ${this.options.errorClass}`,r.dataset.field=e;const n=document.createElement("ul");t.forEach(e=>{const t=document.createElement("li"),r=document.createElement("i");r.textContent=e,t.appendChild(r),n.appendChild(t)}),r.appendChild(n);const s=this.customContainers[e];if(s)s.innerHTML="",s.appendChild(r);else if(this.options.insertAfterField){const t=document.getElementById(this.formId),n=t?.querySelector(`[name="${e}"]`);n&&n.insertAdjacentElement("afterend",r)}return r}clearAll(){const e=document.getElementById(this.formId);if(!e)return;e.querySelectorAll(`.${this.options.containerClass}`).forEach(e=>e.remove());for(const e in this.customContainers)this.customContainers[e]&&(this.customContainers[e].innerHTML="")}destroy(){t.unsub(ee.ERRORS_CHANGE,this._boundHandleErrors),this.clearAll()}}const ne=(e={})=>{const{persistKey:r="query-cache",persistedKeys:n=null,defaultTtl:s=6e4,defaultStaleTime:o=5e3,defaultRetries:i=3,defaultRetryDelay:l=1e3}=e,u=new Map,c=new Map,d=(e,r,n)=>{t.pub(`query:${e}`,{key:r,...n}),t.pub(`query:${r}:${e}`,n)},m=()=>{try{const e=localStorage.getItem(r);if(!e)return;const n=JSON.parse(e),s=Date.now();for(const[e,t]of Object.entries(n))s<t.expiry&&u.set(e,{...t,promise:null});t.pub("query:hydrated",{keys:[...u.keys()]})}catch(e){console.warn("Failed to load query cache: ",e)}},f=()=>{try{const e={};for(const[t,r]of u.entries())void 0!==r.data&&(n&&!n.some(e=>t.startsWith(e))||(e[t]={data:r.data,staleAt:r.staleAt,expiry:r.expiry}));localStorage.setItem(r,JSON.stringify(e))}catch(e){console.warn("Failed to persist query cache: ",e)}};let h=null;const y=()=>{h&&clearTimeout(h),h=setTimeout(f,1e3)},p=e=>u.get(e)??null,b=async(e,t,r={})=>{const{ttl:n=s,staleTime:c=o,retries:m=i,retryDelay:f=l}=r,h=Date.now(),b=p(e);if(b&&h<b.staleAt)return d("hit",e,{data:b.data}),b.data;if(b?.promise)return b.promise;const g=b&&h<b.expiry;d("fetch",e,{isStale:g,hasCache:!!b});const S=(async(e,t,r,n)=>{let s;for(let o=0;o<=r;o++)try{return await t()}catch(t){if(s=t,o<r){const s=n*Math.pow(2,o);d("retry",e,{attempt:o+1,maxRetries:r,delay:s,error:t}),await a(s)}}throw s})(e,t,m,f).then(t=>(u.set(e,{data:t,staleAt:Date.now()+c,expiry:Date.now()+n,promise:null,error:null}),d("success",e,{data:t}),y(),t)).catch(t=>{throw u.set(e,{data:b?.data??null,staleAt:b?.staleAt??0,expiry:b?.expiry??0,promise:null,error:t}),d("error",e,{error:t,staleData:b?.data??null}),t});return u.set(e,{...b,promise:S}),g?b.data:S},g=(e,t)=>{const r=p(e);if(!r)return null;const n=r.data,s="function"==typeof t?t(n):t;return u.set(e,{...r,data:s}),d("mutate",e,{data:s,previous:n}),y(),n},S=(e,t={})=>{const{refetch:r,fetcher:n}=t;if(u.delete(e),d("invalidate",e,{}),y(),r&&n)return b(e,n)},v=e=>{const t=c.get(e);t&&(clearInterval(t),c.delete(e),d("polling:stop",e,{}))},w=()=>{for(const e of c.keys())v(e)},E=(e,t,r,n={})=>{v(e),b(e,t,n).catch(()=>{});const s=setInterval(()=>{const r=p(e);r&&u.set(e,{...r,staleAt:0}),b(e,t,n).catch(()=>{})},r);return c.set(e,s),d("polling:start",e,{interval:r}),()=>v(e)},A=()=>{const e=Date.now(),r=[];for(const[n,s]of u.entries())e>s.expiry&&!t.has(`query:${n}:success`)&&(u.delete(n),r.push(n));r.length&&(y(),t.pub("query:gc",{collected:r}))},$=(e,r)=>{const n=t=>r({...p(e),...t});t.sub(`query:${e}:success`,n),t.sub(`query:${e}:error`,n),t.sub(`query:${e}:mutate`,n),t.sub(`query:${e}:set`,n),t.sub(`query:${e}:invalidate`,()=>r(null));const s=p(e);return s&&r(s),()=>{t.unsub(`query:${e}:success`,n),t.unsub(`query:${e}:error`,n),t.unsub(`query:${e}:mutate`,n),t.unsub(`query:${e}:set`,n),t.unsub(`query:${e}:invalidate`,n)}};m(),setInterval(A,6e4),window.addEventListener("storage",e=>{if(e.key===r){m();for(const e of u.keys())d("sync",e,{data:u.get(e)?.data})}}),window.addEventListener("beforeunload",()=>{w(),f()});const T=(e,t,r={})=>{const n=K(r.inital??null),s=K(!1),o=K(null),a=$(e,e=>{e?.data&&(n.val=e.data),e?.error&&(o.val=e.error),s.val=!!e?.promise&&!e?.data}),i=()=>(s.val=!0,b(e,t,r));return!1!==r.enabled&&i().catch(()=>{}),{data:n,loading:s,error:o,fetch:i,refetch:()=>(S(e),i()),unsubscribe:a,mutate:t=>{const r=g(e,t);return n.val=p(e)?.data,r}}};return{query:b,mutate:g,setQueryData:(e,t,r={})=>{const{ttl:n=s,staleTime:a=o}=r,i=Date.now();u.set(e,{data:t,staleAt:i+a,expiry:i+n,promise:null,error:null}),d("set",e,{data:t}),y()},invalidate:S,invalidateMatching:e=>{const t=[];for(const r of u.keys())e(r)&&(u.delete(r),t.push(r),d("invalidate",r,{}));return y(),t},subscribe:$,prefetch:(e,t,r)=>{const n=p(e);n&&Date.now()<n.staleAt||b(e,t,r).catch(()=>{})},startPolling:E,stopPolling:v,stopAllPolling:w,getEntry:p,gc:A,querySignal:T,pollingSignal:(e,t,r,n={})=>({...T(e,t,{...n,enabled:!1}),stop:E(e,t,r,n)}),bindQuery:(e,r,n={})=>{const{target:s,render:o,onLoading:a,onError:i,poll:l=null,...u}=n,c="string"==typeof s?document.querySelector(s):s,d=e=>{const t=o(e);"string"==typeof t&&(c.innerHTML=t)};if(t.sub(`query:${e}:success`,({data:e})=>d(e)),t.sub(`query:${e}:set`,({data:e})=>d(e)),t.sub(`query:${e}:mutate`,({data:e})=>d(e)),i&&t.sub(`query:${e}:error`,({error:e,staleData:t})=>i(e,t,c)),a&&t.sub(`query:${e}:fetch`,({hasCache:e})=>{e||a(c)}),b(e,r,u).catch(()=>{}),l)return E(e,r,l,u)},clear:()=>{u.clear(),localStorage.removeItem(r),t.pub("query:cleared",{})}}},se=ne();return e.DOM=D,e.EVT=t,e.FormErrorRenderer=re,e.FormEvents=ee,e.FormHandler=te,e.HTTP=Y,e.Q=T,e.V=p,e.all=C,e.batch=function(e){e(),W.forEach(e=>e()),W.clear()},e.bind=function(e,t,r){const n=X(e);return Z(()=>{const e=r.val;switch(t){case"text":n.text(e);break;case"html":n.html(e);break;case"value":n.val(e);break;case"show":e?n.show():n.hide();break;case"hide":e?n.hide():n.show();break;case"disabled":n.elt.disabled=!!e;break;default:n.elt[t]=e}})},e.bindAttr=function(e,t,r){const n=X(e);return Z(()=>{n.elt.setAttribute(t,r.val)})},e.bindClass=function(e,t,r){const n=X(e);return Z(()=>{r.val?n.addClass(t):n.removeClass(t)})},e.bindHtml=function(e,t){const r=X(e);return Z(()=>{const e=t.val;r.html(e)})},e.bindList=function(e,t,r,n=""){const s=X(e);return Z(()=>{const e=t.val;s.html(e?.length?e.map(r).join(""):n)})},e.bindOptions=function(e,t,r={}){const{value:n="id",label:s="name",placeholder:o="Select ..."}=r,a=X(e);return Z(()=>{const e=t.val||[];a.html(`<option value="">${o}</option>`+e.map(e=>`<option value="${e[n]}">${e[s]}</option>`).join(""))})},e.bindText=function(e,t){const r=X(e);return Z(()=>{const e=t.val;r.text(e)})},e.bindValue=function(e,t){const r=X(e);return Z(()=>{const e=t.val;r.val(e)})},e.cache=function(e){if(null==e)return{cache:{strategy:"cache-first",storage:"local",ttl:6e4}};if("object"==typeof e)return{cache:e};const t=e.toLowerCase(),r={cfl:{strategy:"cache-first",storage:"local"},cfs:{strategy:"cache-first",storage:"session"},cfm:{strategy:"cache-first",storage:"memory"},nfl:{strategy:"network-first",storage:"local"},nfs:{strategy:"network-first",storage:"session"},nfm:{strategy:"network-first",storage:"memory"}},n=t.match(/cfl|cfs|cfm|nfl|nfs|nfm/),s=n?r[n[0]]:r.cfl,o=t.match(/(\d+)\s*(s|sec|secs|second|seconds|min|m|mins|minute|minutes|h|hr|hours)?/),a=o?function(e){const t=e.replace(/[0-9]/g,"").trim().toLowerCase(),r=parseInt(e,10),n={s:1e3,sec:1e3,secs:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,mins:6e4,minute:6e4,minutes:6e4,h:36e5,hr:36e5,hrs:36e5,hours:36e5};return r*(n[t]||1)}(o[0]):6e4;return{cache:{strategy:s.strategy,storage:s.storage,ttl:a}}},e.computed=function(e){const t=K(void 0);return Z(()=>{t.val=e()}),t},e.createQuery=ne,e.del=z,e.download=P,e.effect=Z,e.formatByCountry=(e,t)=>n(e,r[t]??r.US),e.get=B,e.isArray=e=>Array.isArray(e),e.isArrayEmpty=e=>!(Array.isArray(e)&&e.length>0),e.isFocus=e=>e==document.activeElement,e.isValidRoutingNumber=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},e.make=v,e.makeId=w,e.onPageLoad=A,e.onWindowLoad=$,e.parseHtml=E,e.post=V,e.put=G,e.queryClient=se,e.raw=J,e.redirect=e=>window.location.href=e,e.request=j,e.signal=K,e.toCurrency=n,e.upload=_,e.useFormHandler=function(e,t,r,n){const s=new te(e,t,r,n),o=new re(e,n);return{reset:()=>s.reset(),validate:()=>s.validateNow(),destroy:()=>{o.destroy(),s.destroy()},setContainer:(e,t)=>o.setContainer(e,t)}},e.when=function(e,t){return Z(()=>{e.val&&t(e.val)})},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),e}({});
|
package/dist/vaniy.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vaniy={})}(this,function(e){"use strict";const t={listeners:new Map,sub:function(e,t){let r=this.listeners.get(e);r||(r=new Set,this.listeners.set(e,r)),r.add(t)},once:function(e,t){const r=(...n)=>{t(...n),this.unsub(e,r)};this.sub(e,r)},unsub:function(e,t){let r=this.listeners.get(e);r&&r.delete(t)},pub:function(e,...t){let r=this.listeners.get(e);r&&r.forEach(r=>{try{r(...t)}catch(t){console.error(`Error in event "${e}" listener: `,t)}})},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"},r={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"}},n=(e,{locale:t="en-US",currency:r="USD"}={})=>Intl.NumberFormat(t,{style:"currency",currency:r}).format(e);function s(e){return Array.isArray(e)?e.length:function(e){if("number"==typeof e)return Number.isFinite(e);if("string"!=typeof e)return!1;const t=e.trim();return!!t&&/^-?\d+(\.\d+)?$/.test(t)}(e)?Number(String(e).trim()):String(e??"").length}function o(e){const[t,r]=String(e??"").split(",").map(e=>e.trim()),n=Number(t),s=Number(r);return Number.isFinite(n)&&Number.isFinite(s)?{min:n,max:s}:null}const a=e=>new Promise(t=>setTimeout(t,e));function i(e,t){const r=String(e??"").trim();if(!r)return null;if("YYYY-MM-DD"===t){const e=r.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!e)return null;const t=Number(e[1]),n=Number(e[2]),s=Number(e[3]);return!t||n<1||n>12||s<1||s>31?null:{year:t,month:n,day:s}}return null}function l(e,t,r="en-US"){const n=new Intl.DateTimeFormat(r,{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(e),s=Object.fromEntries(n.map(e=>[e.type,e.value]));return{year:Number(s.year),month:Number(s.month),day:Number(s.day),hour:Number(s.hour),minute:Number(s.minute),second:Number(s.second)}}function u({year:e,month:t,day:r},n){const s=new Date(Date.UTC(e,t-1,r));return s.setUTCDate(s.getUTCDate()+n),{year:s.getUTCFullYear(),month:s.getUTCMonth()+1,day:s.getUTCDate()}}function c(e,t,r){const{base:n,offsetDays:s}=function(e){const t=String(e).trim().match(/^(.+?)([+-]\d+)?$/);return t?{base:t[1].trim(),offsetDays:t[2]?Number(t[2]):0}:{base:String(e).trim(),offsetDays:0}}(e);let o=function(e,t){const r=new Date,{year:n,month:s,day:o}=l(r,t);return"today"===e?{year:n,month:s,day:o}:"tomorrow"===e?u({year:n,month:s,day:o},1):"yesterday"===e?u({year:n,month:s,day:o},-1):null}(n,r.timezone);if(!o){const e=t?.[n];o=d(e,r)}return o||(o=i(n,r.dateFormat)),o?(s&&(o=u(o,s)),o):null}function d(e,t){if(null==(r=e)||""===String(r??"").trim())return null;var r;const n=String(e).trim();let s=i(n,t.dateFormat);if(s)return s;if(!/^\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}(:\d{2}(\.\d{1,3})?)?(Z|[+-]\d{2}:\d{2})?$/.test(n))return null;const o=new Date(n);if(isNaN(o.getTime()))return null;const a=l(o,t.timezone);return{year:a.year,month:a.month,day:a.day}}function m(e,t,r,n){let s=null;return s="value"===n?d(e,r):c(e,t,r),s?function({year:e,month:t,day:r},n){let s=Date.UTC(e,t-1,r,0,0,0);for(let o=0;o<2;o++){const o=l(new Date(s),n),a=Date.UTC(o.year,o.month-1,o.day,o.hour,o.minute,o.second)-Date.UTC(e,t-1,r,0,0,0);if(0===a)break;s-=a}return s}(s,r.timezone):null}function f(e,t){return{method:t=>(r,n,s)=>{const o=m(r,n,s,"value"),a=m(t,n,s,"target");return null!=o&&null!=a&&e(o,a)},message:t}}const h={required:{method:e=>""!==String(e??"").trim(),message:"This field is required"},requiredIf:{method:e=>(t,r)=>{const[n,s]=String(e).split("="),o=r?.[n];return!(null!=s?String(o??"")===s:""!==String(o??"").trim())||""!==String(t??"").trim()},message:e=>{const[t,r]=String(e).split("=");return null!=r?`This field is requied when ${t} is ${r}`:`This field is required when ${t} has a value`}},email:{method:e=>/\S+@\S+\.\S+/.test(e),message:"Email is invalid"},min:{method:e=>t=>String(t??"").length>=Number(e),message:e=>`Must be at least ${e} characters`},max:{method:e=>t=>String(t??"").length<=Number(e),message:e=>`Must be at most ${e} characters`},date:{method:e=>{if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;const[t,r,n]=e.split("-").map(Number),s=new Date(t,r-1,n);return s.getFullYear()===t&&s.getMonth()===r-1&&s.getDate()===n},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."},same:{method:e=>(t,r)=>String(t??"")===String(r?.[e]??""),message:e=>`Must match ${e}`},in:{method:e=>t=>(Array.isArray(e)?e:String(e??"").split(",").map(e=>e.trim()).filter(Boolean)).includes(String(t??"").trim()),message:e=>`Must be one of the following: ${(Array.isArray(e)?e:String(e??"").split(",").map(e=>e.trim())).filter(Boolean).join(",")}`},before:f((e,t)=>e<t,e=>`Must be before ${e}`),beforeOrEqual:f((e,t)=>e<=t,e=>`Must be before or equal to ${e}`),after:f((e,t)=>e>t,e=>`Must be after ${e}`),afterOrEqual:f((e,t)=>e>=t,e=>`Must be after or equal to ${e}`),between:{method:e=>t=>{const r=o(e);if(!r)return!1;const n=s(t);return r.min<=n&&n<=r.max},message:e=>{const t=o(e);return t?`Must be between ${t.min} and ${t.max}`:"Between rule is invalid. Use between:min,max"}}};function y(e){const t=e.indexOf(":");return-1===t?{name:e,param:void 0}:{name:e.slice(0,t),param:e.slice(t+1)}}const p={run:function(e,t){let r=!0;const n={};for(const s in e){const o=e[s]||[];for(const e of o){const{name:o,param:a}=y(e),i=h[o];if(!i)continue;const l=t?.[s];if(!(void 0!==a?i.method(a)(l,t):i.method(l,t))){r=!1,n[s]||(n[s]=[]);const e="function"==typeof i.message?i.message(a):i.message;n[s].push(e)}}}return{isValid:r,errors:n}},ping:()=>console.log("PONG"),description:"V is for validating forms"},g=e=>({on:(t,r)=>e?.addEventListener(t,r),off:(t,r)=>e?.removeEventListener(t,r)}),b=(e,t)=>{if(!e)return;const r="innerText"in e?"innerText":"textContent";return null!=t&&(e[r]=t),e[r]},S=(e,t)=>{if(e)return null!=t&&(e.innerHTML=t),e.innerHTML},w=e=>document.createElement(e),E=e=>{let t="";const r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let n=0;n<e;n++)t+=r.charAt(Math.floor(62*Math.random()));return t},v=e=>{const t=document.implementation.createHTMLDocument("");return t.body.innerHTML=e,[...t.body.childNodes]},A=e=>{"loading"!==document.readyState?e():document.addEventListener("DOMContentLoaded",e)},T=e=>{window.onload=e},$=e=>{const t="string"==typeof e?document.querySelector(e):e,r=e=>(...r)=>{if(t)return e(...r)},n={elt:t,value:t?.value,text:e=>null!=e?(b(t,e),n):b(t),html:e=>null!=e?(S(t,e),n):S(t),val:r(e=>{if(null!=e){if(t.opt&&t.multiple){const r=new Set(Array.isArray(e)?e:[e]);Array.from(t.options).forEach(e=>{e.selected=r.has(e.value)})}else t.value=e;return n.value=t.value,n}return t.options&&t.multiple?Array.from(t.options).filter(e=>e.selected).map(e=>e.value):t.value}),addClass:r(e=>(t.classList.add(e),n)),removeClass:r(e=>(t.classList.remove(e),n)),hasClass:r(e=>t.classList.contains(e)),hide:r(()=>(t.style.display="none",n)),show:r(()=>(t.style.display="",n)),prop:r(e=>t[e]),attr:r(e=>t.getAttribute(e)),removeAttr:e=>{t.removeAttribute(e)},toggle:r(()=>("none"==t.style.display?n.show():n.hide(),n)),css:r(e=>(Object.entries(e).forEach(([e,r])=>{t.style[e]=r}),n)),on:g(t).on,off:g(t).off};return n},C=e=>document.querySelectorAll(e),D={Q:$,$:$,all:C,$$:C,scan:(e,t={})=>{const r=t.refAttr||"v-ref",n="string"==typeof e?document.querySelector(e):e||document;if(!n)throw new Error(`Dom.scan: root "${e}" not found`);const s=Object.create(null);return n.querySelectorAll(`[${r}]`).forEach(e=>{const t=e.getAttribute(r);if(!t)return;const n=$(e);s[t]?Array.isArray(s[t])?s[t].push(n):s[t]=[s[t],n]:s[t]=n}),new Proxy({},{get(e,t){if("_"===t)return s;if("get"===t)return e=>s[e];if("all"===t)return e=>s[e]?Array.isArray(s[e])?s[e]:[s[e]]:[];if("on"===t)return(e,t,r)=>{const n=s[e];(Array.isArray(n)?n:[n]).forEach(e=>e?.on(t,r))};if("string"!=typeof t)return;const r=s[t];return r||(console.warn(`DOM.scan: ref "${t}" not found`),$(null))}})},make:w,makeId:E,parseHtml:v,onPageLoad:A,onWindowLoad:T,ping:()=>console.log("PONG!"),description:"DOM is for dom manipulation"};let I="",N=8e3,q=null,R=null,M=null;const x=new Map,L=new Map,O=()=>Date.now();function U(e){const t="undefined"!=typeof window?window[e]:null;return t?{get(e){const r=t.getItem(e);if(!r)return null;try{const n=JSON.parse(r);return n.exp&&n.exp<O()?(t.removeItem(e),null):n.val}catch{return null}},set(e,r,n){const s=n?O()+n:null;t.setItem(e,JSON.stringify({val:r,exp:s}))},del(e){t&&t.removeItem(e)},clear(){t&&t.clear()}}:null}const H={memory:{get(e){const t=L.get(e);return t?t.exp&&t.exp<O()?(L.delete(e),null):t.val:null},set(e,t,r){const n=r?O()+r:null;L.set(e,{val:t,exp:n})},del(e){L.delete(e)},clear(){L.clear()}},local:U("localStorage"),session:U("sessionStorage")};function k(e){return null===e||"object"!=typeof e?String(e):Array.isArray(e)?`[${e.map(k).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${k(e[t])}`).join(",")}}`}const F=(e,t)=>setTimeout(()=>t.abort(),e);async function P(e,t,r={}){const{params:n,body:s,headers:o={},cache:a}=r;let i=I+t;if(n){const e=new URLSearchParams(n).toString();i+=(i.includes("?")?"&":"?")+e}const l=new AbortController,u=F(N,l),c=!!a,d=a?.strategy,m=a?.ttl??0,f=function(e="memory"){return H[e]||H.memory}(a?.storage),h=a?.key||function(e,t,r,n){return`H|${e}|${t}${r?`?${new URLSearchParams(r).toString()}`:""}${n&&"GET"!==e?`#${k(n)}`:""}`}(e,i,n,s);if(c&&!a?.forceRefresh&&"cache-first"===d){const e=f.get(h);if(null!==e)return e}let y={method:e,headers:o,signal:l.signal};if(M){const{token:e,headerName:t}=M,r="function"==typeof e?e():e;if(r){const e="Authorization"===t?"Bearer ":"";y.headers[t]=`${e}${r}`}}void 0!==s&&(s instanceof FormData?y.body=s:(y.headers["Content-Type"]="application/json",y.body=JSON.stringify(s))),q&&(y=q(y)||y);try{let t,r=await fetch(i,y);x.has(r.status)&&x.get(r.status)(r,{method:e,url:i}),clearTimeout(u),R&&(r=R(r)||r);try{t=await r.json()}catch{t=await r.text()}if(!r.ok){const n={status:r.status,data:t,url:i,method:e};if(c&&"network-first"===d){const e=f.get(h);if(null!==e)return e}throw n}return c&&f.set(h,t,m),t}catch(e){if(clearTimeout(u),c&&"network-first"===d){const e=f.get(h);if(null!==e)return e}throw e}}async function j(e,{filename:t,params:r,headers:n={},method:s="GET",body:o,onProgress:a}={}){let i=I+e;if(r){const e=new URLSearchParams(r).toString();i+=(i.includes("?")?"&":"?")+e}const l=new AbortController,u=F(N,l),c={method:s,headers:{...n},signal:l.signal};void 0!==o&&(o instanceof FormData?c.body=o:(c.headers["Content-Type"]=c.headers["Content-Type"]||"application/json",c.body="string"==typeof o?o:JSON.stringify(o)));const d=await fetch(i,c);if(clearTimeout(u),!d.ok){let e="";try{e=await d.text()}catch{}throw new Error(`Download failed ${d.status}: ${e||d.statusText}`)}if(!t){const e=d.headers.get("Content-Disposition")||"",r=/filename\*=UTF-8''([^;]+)|filename="?([^"]+)"?/i.exec(e);t=decodeURIComponent(r?.[1]||r?.[2]||"download")}let m;if(d.body&&"getReader"in d.body){const e=d.body.getReader(),t=Number(d.headers.get("Content-Length"))||null,r=[];let n=0;for(;;){const{done:s,value:o}=await e.read();if(s)break;if(r.push(o),n+=o.length,"function"==typeof a){a(n,t,t?Math.round(n/t*100):null)}}m=new Blob(r)}else m=await d.blob(),"function"==typeof a&&a(1,1,100);const f=URL.createObjectURL(m),h=document.createElement("a");return h.href=f,h.download=t,h.style.display="none",document.body.appendChild(h),h.click(),document.body.removeChild(h),URL.revokeObjectURL(f),{filename:t,size:m.size,type:m.type}}function _(e,{files:t,fieldName:r="file",fields:n={},headers:s={},method:o="POST",onProgress:a,signal:i}={}){return new Promise((l,u)=>{const c=function({files:e,fieldName:t="file",fields:r={}}){const n=new FormData,s=Array.isArray(e)?e:[e];return s.forEach((e,r)=>{const o=s.length>1?`${t}[${r}]`:t;n.append(o,e)}),Object.entries(r).forEach(([e,t])=>{n.append(e,t instanceof Blob||t instanceof File?t:"object"==typeof t?JSON.stringify(t):String(t))}),n}({files:t,fieldName:r,fields:n}),d=`${I}${e}`,m=new XMLHttpRequest;m.open(o,d,!0);let f={method:o,headers:{...s}};if(M){const{token:e,headerName:t}=M,r="function"==typeof e?e():e;if(r){const e="Authorization"===t?"Bearer ":"";f.headers[t]=`${e}${r}`}}if(q&&(f=q(f)||f),Object.entries(f.headers).forEach(([e,t])=>m.setRequestHeader(e,t)),m.timeout=N,i){const e=()=>{try{m.abort()}catch{}};i.aborted&&e(),i.addEventListener("abort",e,{once:!0})}m.upload&&"function"==typeof a&&(m.upload.onprogress=e=>{if(!e.lengthComputable)return void a(e.loaded,null,null);const t=Math.round(e.loaded/e.total*100);a(e.loaded,e.total,t)}),m.onreadystatechange=async()=>{if(4!==m.readyState)return;if(R){const e={status:m.status,ok:m.status>=200&&m.status<300,headers:new Headers,text:async()=>m.responseText,json:async()=>JSON.parse(m.responseText||"null")};R(e)}const e=(m.getResponseHeader("Content-Type")||"").includes("application/json")?function(e){try{return JSON.parse(e||"null")}catch{return e}}(m.responseText):m.responseText;m.status>=200&&m.status<300?l(e):u({status:m.status,data:e,url:d,method:o})},m.onerror=()=>u({status:0,data:"Network error",url:`${I}${e}`,method:o}),m.ontimeout=()=>u({status:0,data:"Timeout",url:`${I}${e}`,method:o}),m.send(c)})}const B=(e,t)=>P("GET",e,t),V=(e,t,r={})=>P("POST",e,{...r,body:t}),G=(e,t,r={})=>P("PUT",e,{...r,body:t}),z=(e,t={})=>P("DELETE",e,t),J=(e,t)=>fetch(I+e,t),Y={base:e=>(I=e,Y),timeout:e=>(N=e,Y),bearer:(e,t="Authorization")=>(M={token:e,headerName:t},Y),onStatus:(e,t)=>(x.set(e,t),Y),onUnauthorized:e=>Y.onStatus(401,e),onForbidden:e=>Y.onStatus(403,e),onInternalServerError:e=>Y.onStatus(500,e),interceptRequest:e=>(q=e,Y),interceptResponse:e=>(R=e,Y),get:B,post:V,put:G,delete:z,raw:J,download:j,upload:_,ping:()=>console.log("PONG"),description:"H is for Http"},K={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 Q{constructor(e,t,r,n={}){this.formId=e,this.schema=t,this.onSubmit=r,this.preSubmit=n.preSubmit||null,this.form=null,this.formState={},this.errors={},this.initialValues={},this._boundHandleSubmit=this.#e.bind(this),this._boundHandleInput=this.#t.bind(this),this.#r()}#r(){this.form=document.getElementById(this.formId),this.form?(this.#n(),this.form.addEventListener("submit",this._boundHandleSubmit),this.form.addEventListener("input",this._boundHandleInput),this.#s()):console.error(`Form with id ${this.formId} not found`)}#n(){const e=this.form.elements;for(const t of Array.from(e))t.name&&(this.initialValues[t.name]=t.value,this.formState[t.name]=t.value)}#t(e){const{name:t,value:r}=e.target;t&&(this.formState[t]=r,this.#s(),this.errors[t]&&(delete this.errors[t],this.#o()))}async#e(e){e.preventDefault();const r=new FormData(this.form);let n={};r.forEach((e,t)=>{n[t]=e}),this.formState=n,this.#s();const{isValid:s,errors:o}=p.run(this.schema,n);if(t.pub(K.VALIDATED,{formId:this.formId,isValid:s,errors:o,data:n}),!s)return this.errors=o,this.#o(),void t.pub(K.SUBMIT_ERROR,{formId:this.formId,errors:o});if(this.errors={},this.#o(),this.preSubmit)try{n=await this.preSubmit(n)}catch(e){return void t.pub(K.SUBMIT_ERROR,{formId:this.formId,errors:{_preSubmit:[e.message]}})}t.pub(K.SUBMIT_SUCCESS,{formId:this.formId,data:n}),this.onSubmit(n)}#s(){t.pub(K.STATE_CHANGE,{formId:this.formId,state:{...this.formState}})}#o(){t.pub(K.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.#s(),this.#o(),t.pub(K.RESET,{formId:this.formId})}validateNow(){const e=new FormData(this.form),r={};e.forEach((e,t)=>{r[t]=e});const n=p.run(this.schema,r);return this.errors=n.errors,this.#o(),t.pub(K.VALIDATED,{formId:this.formId,isValid:n.isValid,errors:n.errors,data:r}),n}destroy(){this.form&&(this.form.removeEventListener("submit",this._boundHandleSubmit),this.form.removeEventListener("input",this._boundHandleInput))}}class W{constructor(e,r={}){this.formId=e,this.options={containerClass:"form-error-container",errorClass:"text-danger",insertAfterField:!0,...r},this.customContainers={},this._boundHandleErrors=this.#a.bind(this),t.sub(K.ERRORS_CHANGE,this._boundHandleErrors)}#a({formId:e,errors:t}){e===this.formId&&(this.clearAll(),this.renderAll(t))}setContainer(e,t){this.customContainers[e]="string"==typeof t?document.querySelector(t):t}renderAll(e){for(const t in e)this.render(t,e[t])}render(e,t){if(!t||0===t.length)return null;const r=document.createElement("span");r.className=`${this.options.containerClass} ${this.options.errorClass}`,r.dataset.field=e;const n=document.createElement("ul");t.forEach(e=>{const t=document.createElement("li"),r=document.createElement("i");r.textContent=e,t.appendChild(r),n.appendChild(t)}),r.appendChild(n);const s=this.customContainers[e];if(s)s.innerHTML="",s.appendChild(r);else if(this.options.insertAfterField){const t=document.getElementById(this.formId),n=t?.querySelector(`[name="${e}"]`);n&&n.insertAdjacentElement("afterend",r)}return r}clearAll(){const e=document.getElementById(this.formId);if(!e)return;e.querySelectorAll(`.${this.options.containerClass}`).forEach(e=>e.remove());for(const e in this.customContainers)this.customContainers[e]&&(this.customContainers[e].innerHTML="")}destroy(){t.unsub(K.ERRORS_CHANGE,this._boundHandleErrors),this.clearAll()}}function Z(e){let t=e;const r=new Set;return{get val(){return t},set val(e){if(e!==t){t=e;for(const e of r)e()}},peek:()=>t,subscribe:e=>(r.add(e),()=>r.delete(e)),toString:()=>String(t),valueOf:()=>t}}const X=((e={})=>{const{persistKey:r="query-cache",persistedKeys:n=null,defaultTtl:s=6e4,defaultStaleTime:o=5e3,defaultRetries:i=3,defaultRetryDelay:l=1e3}=e,u=new Map,c=new Map,d=(e,r,n)=>{t.pub(`query:${e}`,{key:r,...n}),t.pub(`query:${r}:${e}`,n)},m=()=>{try{const e=localStorage.getItem(r);if(!e)return;const n=JSON.parse(e),s=Date.now();for(const[e,t]of Object.entries(n))s<t.expiry&&u.set(e,{...t,promise:null});t.pub("query:hydrated",{keys:[...u.keys()]})}catch(e){console.warn("Failed to load query cache: ",e)}},f=()=>{try{const e={};for(const[t,r]of u.entries())void 0!==r.data&&(n&&!n.some(e=>t.startsWith(e))||(e[t]={data:r.data,staleAt:r.staleAt,expiry:r.expiry}));localStorage.setItem(r,JSON.stringify(e))}catch(e){console.warn("Failed to persist query cache: ",e)}};let h=null;const y=()=>{h&&clearTimeout(h),h=setTimeout(f,1e3)},p=e=>u.get(e)??null,g=async(e,t,r={})=>{const{ttl:n=s,staleTime:c=o,retries:m=i,retryDelay:f=l}=r,h=Date.now(),g=p(e);if(g&&h<g.staleAt)return d("hit",e,{data:g.data}),g.data;if(g?.promise)return g.promise;const b=g&&h<g.expiry;d("fetch",e,{isStale:b,hasCache:!!g});const S=(async(e,t,r,n)=>{let s;for(let o=0;o<=r;o++)try{return await t()}catch(t){if(s=t,o<r){const s=n*Math.pow(2,o);d("retry",e,{attempt:o+1,maxRetries:r,delay:s,error:t}),await a(s)}}throw s})(e,t,m,f).then(t=>(u.set(e,{data:t,staleAt:Date.now()+c,expiry:Date.now()+n,promise:null,error:null}),d("success",e,{data:t}),y(),t)).catch(t=>{throw u.set(e,{data:g?.data??null,staleAt:g?.staleAt??0,expiry:g?.expiry??0,promise:null,error:t}),d("error",e,{error:t,staleData:g?.data??null}),t});return u.set(e,{...g,promise:S}),b?g.data:S},b=e=>{const t=c.get(e);t&&(clearInterval(t),c.delete(e),d("polling:stop",e,{}))},S=()=>{for(const e of c.keys())b(e)},w=()=>{const e=Date.now(),r=[];for(const[n,s]of u.entries())e>s.expiry&&!t.has(`query:${n}:success`)&&(u.delete(n),r.push(n));r.length&&(y(),t.pub("query:gc",{collected:r}))};return m(),setInterval(w,6e4),window.addEventListener("storage",e=>{if(e.key===r){m();for(const e of u.keys())d("sync",e,{data:u.get(e)?.data})}}),window.addEventListener("beforeunload",()=>{S(),f()}),{query:g,mutate:(e,t)=>{const r=p(e);if(!r)return null;const n=r.data,s="function"==typeof t?t(n):t;return u.set(e,{...r,data:s}),d("mutate",e,{data:s,previous:n}),y(),n},setQueryData:(e,t,r={})=>{const{ttl:n=s,staleTime:a=o}=r,i=Date.now();u.set(e,{data:t,staleAt:i+a,expiry:i+n,promise:null,error:null}),d("set",e,{data:t}),y()},invalidate:(e,t={})=>{const{refetch:r,fetcher:n}=t;if(u.delete(e),d("invalidate",e,{}),y(),r&&n)return g(e,n)},invalidateMatching:e=>{const t=[];for(const r of u.keys())e(r)&&(u.delete(r),t.push(r),d("invalidate",r,{}));return y(),t},subscribe:(e,r)=>{const n=t=>r({...p(e),...t});t.sub(`query:${e}:success`,n),t.sub(`query:${e}:error`,n),t.sub(`query:${e}:mutate`,n),t.sub(`query:${e}:set`,n),t.sub(`query:${e}:invalidate`,()=>r(null));const s=p(e);return s&&r(s),()=>{t.unsub(`query:${e}:success`,n),t.unsub(`query:${e}:error`,n),t.unsub(`query:${e}:mutate`,n),t.unsub(`query:${e}:set`,n),t.unsub(`query:${e}:invalidate`,n)}},prefetch:(e,t,r)=>{const n=p(e);n&&Date.now()<n.staleAt||g(e,t,r).catch(()=>{})},startPolling:(e,t,r,n={})=>{b(e),g(e,t,n).catch(()=>{});const s=setInterval(()=>{const r=p(e);r&&u.set(e,{...r,staleAt:0}),g(e,t,n).catch(()=>{})},r);return c.set(e,s),d("polling:start",e,{interval:r}),()=>b(e)},stopPolling:b,stopAllPolling:S,getEntry:p,gc:w,clear:()=>{u.clear(),localStorage.removeItem(r),t.pub("query:cleared",{})}}})({persistKey:"teksoft-cache",persistedKeys:["user","settings"]}),ee=(e,t,r={})=>{const n=Z(r.inital??null),s=Z(!1),o=Z(null),a=X.subscribe(e,e=>{e?.data&&(n.val=e.data),e?.error&&(o.val=e.error),s.val=!!e?.promise&&!e?.data}),i=()=>(s.val=!0,X.query(e,t,r));return!1!==r.enabled&&i(),{data:n,loading:s,error:o,fetch:i,refetch:()=>(X.invalidate(e),i()),unsubscribe:a,mutate:t=>{const r=X.mutate(e,t);return n.val=X.getEntry(e)?.data,r}}};e.DOM=D,e.EVT=t,e.FormErrorRenderer=W,e.FormEvents=K,e.FormHandler=Q,e.HTTP=Y,e.Q=$,e.V=p,e.all=C,e.bindQuery=(e,r,n={})=>{const{target:s,render:o,onLoading:a,onError:i,poll:l=null,...u}=n,c="string"==typeof s?document.querySelector(s):s,d=e=>{const t=o(e);"string"==typeof t&&(c.innerHTML=t)};if(t.sub(`query:${e}:success`,({data:e})=>d(e)),t.sub(`query:${e}:set`,({data:e})=>d(e)),t.sub(`query:${e}:mutate`,({data:e})=>d(e)),i&&t.sub(`query:${e}:error`,({error:e,staleData:t})=>i(e,t,c)),a&&t.sub(`query:${e}:fetch`,({hasCache:e})=>{e||a(c)}),X.query(e,r,u).catch(()=>{}),l)return X.startPolling(e,r,l,u)},e.cache=function(e){if(null==e)return{cache:{strategy:"cache-first",storage:"local",ttl:6e4}};if("object"==typeof e)return{cache:e};const t=e.toLowerCase(),r={cfl:{strategy:"cache-first",storage:"local"},cfs:{strategy:"cache-first",storage:"session"},cfm:{strategy:"cache-first",storage:"memory"},nfl:{strategy:"network-first",storage:"local"},nfs:{strategy:"network-first",storage:"session"},nfm:{strategy:"network-first",storage:"memory"}},n=t.match(/cfl|cfs|cfm|nfl|nfs|nfm/),s=n?r[n[0]]:r.cfl,o=t.match(/(\d+)\s*(s|sec|secs|second|seconds|min|m|mins|minute|minutes|h|hr|hours)?/),a=o?function(e){const t=e.replace(/[0-9]/g,"").trim().toLowerCase(),r=parseInt(e,10),n={s:1e3,sec:1e3,secs:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,mins:6e4,minute:6e4,minutes:6e4,h:36e5,hr:36e5,hrs:36e5,hours:36e5};return r*(n[t]||1)}(o[0]):6e4;return{cache:{strategy:s.strategy,storage:s.storage,ttl:a}}},e.del=z,e.download=j,e.formatByCountry=(e,t)=>n(e,r[t]??r.US),e.get=B,e.isArray=e=>Array.isArray(e),e.isArrayEmpty=e=>!(Array.isArray(e)&&e.length>0),e.isFocus=e=>e==document.activeElement,e.isValidRoutingNumber=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},e.make=w,e.makeId=E,e.onPageLoad=A,e.onWindowLoad=T,e.parseHtml=v,e.pollingSignal=(e,t,r,n={})=>({...ee(e,t,{...n,enabled:!1}),stop:X.startPolling(e,t,r,n)}),e.post=V,e.put=G,e.queryClient=X,e.querySignal=ee,e.raw=J,e.redirect=e=>window.location.href=e,e.request=P,e.toCurrency=n,e.upload=_,e.useFormHandler=function(e,t,r,n){const s=new Q(e,t,r,n),o=new W(e,n);return{reset:()=>s.reset(),validate:()=>s.validateNow(),destroy:()=>{o.destroy(),s.destroy()},setContainer:(e,t)=>o.setContainer(e,t)}},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vaniy={})}(this,function(e){"use strict";const t={listeners:new Map,sub:function(e,t){let r=this.listeners.get(e);r||(r=new Set,this.listeners.set(e,r)),r.add(t)},once:function(e,t){const r=(...n)=>{t(...n),this.unsub(e,r)};this.sub(e,r)},unsub:function(e,t){let r=this.listeners.get(e);r&&r.delete(t)},pub:function(e,...t){let r=this.listeners.get(e);r&&r.forEach(r=>{try{r(...t)}catch(t){console.error(`Error in event "${e}" listener: `,t)}})},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"},r={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"}},n=(e,{locale:t="en-US",currency:r="USD"}={})=>Intl.NumberFormat(t,{style:"currency",currency:r}).format(e);function s(e){return Array.isArray(e)?e.length:function(e){if("number"==typeof e)return Number.isFinite(e);if("string"!=typeof e)return!1;const t=e.trim();return!!t&&/^-?\d+(\.\d+)?$/.test(t)}(e)?Number(String(e).trim()):String(e??"").length}function o(e){const[t,r]=String(e??"").split(",").map(e=>e.trim()),n=Number(t),s=Number(r);return Number.isFinite(n)&&Number.isFinite(s)?{min:n,max:s}:null}const a=e=>new Promise(t=>setTimeout(t,e));function i(e,t){const r=String(e??"").trim();if(!r)return null;if("YYYY-MM-DD"===t){const e=r.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!e)return null;const t=Number(e[1]),n=Number(e[2]),s=Number(e[3]);return!t||n<1||n>12||s<1||s>31?null:{year:t,month:n,day:s}}return null}function l(e,t,r="en-US"){const n=new Intl.DateTimeFormat(r,{timeZone:t,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1}).formatToParts(e),s=Object.fromEntries(n.map(e=>[e.type,e.value]));return{year:Number(s.year),month:Number(s.month),day:Number(s.day),hour:Number(s.hour),minute:Number(s.minute),second:Number(s.second)}}function u({year:e,month:t,day:r},n){const s=new Date(Date.UTC(e,t-1,r));return s.setUTCDate(s.getUTCDate()+n),{year:s.getUTCFullYear(),month:s.getUTCMonth()+1,day:s.getUTCDate()}}function c(e,t,r){const{base:n,offsetDays:s}=function(e){const t=String(e).trim().match(/^(.+?)([+-]\d+)?$/);return t?{base:t[1].trim(),offsetDays:t[2]?Number(t[2]):0}:{base:String(e).trim(),offsetDays:0}}(e);let o=function(e,t){const r=new Date,{year:n,month:s,day:o}=l(r,t);return"today"===e?{year:n,month:s,day:o}:"tomorrow"===e?u({year:n,month:s,day:o},1):"yesterday"===e?u({year:n,month:s,day:o},-1):null}(n,r.timezone);if(!o){const e=t?.[n];o=d(e,r)}return o||(o=i(n,r.dateFormat)),o?(s&&(o=u(o,s)),o):null}function d(e,t){if(null==(r=e)||""===String(r??"").trim())return null;var r;const n=String(e).trim();let s=i(n,t.dateFormat);if(s)return s;if(!/^\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}(:\d{2}(\.\d{1,3})?)?(Z|[+-]\d{2}:\d{2})?$/.test(n))return null;const o=new Date(n);if(isNaN(o.getTime()))return null;const a=l(o,t.timezone);return{year:a.year,month:a.month,day:a.day}}function m(e,t,r,n){let s=null;return s="value"===n?d(e,r):c(e,t,r),s?function({year:e,month:t,day:r},n){let s=Date.UTC(e,t-1,r,0,0,0);for(let o=0;o<2;o++){const o=l(new Date(s),n),a=Date.UTC(o.year,o.month-1,o.day,o.hour,o.minute,o.second)-Date.UTC(e,t-1,r,0,0,0);if(0===a)break;s-=a}return s}(s,r.timezone):null}function f(e,t){return{method:t=>(r,n,s)=>{const o=m(r,n,s,"value"),a=m(t,n,s,"target");return null!=o&&null!=a&&e(o,a)},message:t}}const h={required:{method:e=>""!==String(e??"").trim(),message:"This field is required"},requiredIf:{method:e=>(t,r)=>{const[n,s]=String(e).split("="),o=r?.[n];return!(null!=s?String(o??"")===s:""!==String(o??"").trim())||""!==String(t??"").trim()},message:e=>{const[t,r]=String(e).split("=");return null!=r?`This field is requied when ${t} is ${r}`:`This field is required when ${t} has a value`}},email:{method:e=>/\S+@\S+\.\S+/.test(e),message:"Email is invalid"},min:{method:e=>t=>String(t??"").length>=Number(e),message:e=>`Must be at least ${e} characters`},max:{method:e=>t=>String(t??"").length<=Number(e),message:e=>`Must be at most ${e} characters`},date:{method:e=>{if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;const[t,r,n]=e.split("-").map(Number),s=new Date(t,r-1,n);return s.getFullYear()===t&&s.getMonth()===r-1&&s.getDate()===n},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."},same:{method:e=>(t,r)=>String(t??"")===String(r?.[e]??""),message:e=>`Must match ${e}`},in:{method:e=>t=>(Array.isArray(e)?e:String(e??"").split(",").map(e=>e.trim()).filter(Boolean)).includes(String(t??"").trim()),message:e=>`Must be one of the following: ${(Array.isArray(e)?e:String(e??"").split(",").map(e=>e.trim())).filter(Boolean).join(",")}`},before:f((e,t)=>e<t,e=>`Must be before ${e}`),beforeOrEqual:f((e,t)=>e<=t,e=>`Must be before or equal to ${e}`),after:f((e,t)=>e>t,e=>`Must be after ${e}`),afterOrEqual:f((e,t)=>e>=t,e=>`Must be after or equal to ${e}`),between:{method:e=>t=>{const r=o(e);if(!r)return!1;const n=s(t);return r.min<=n&&n<=r.max},message:e=>{const t=o(e);return t?`Must be between ${t.min} and ${t.max}`:"Between rule is invalid. Use between:min,max"}}};function y(e){const t=e.indexOf(":");return-1===t?{name:e,param:void 0}:{name:e.slice(0,t),param:e.slice(t+1)}}const p={run:function(e,t){let r=!0;const n={};for(const s in e){const o=e[s]||[];for(const e of o){const{name:o,param:a}=y(e),i=h[o];if(!i)continue;const l=t?.[s];if(!(void 0!==a?i.method(a)(l,t):i.method(l,t))){r=!1,n[s]||(n[s]=[]);const e="function"==typeof i.message?i.message(a):i.message;n[s].push(e)}}}return{isValid:r,errors:n}},ping:()=>console.log("PONG"),description:"V is for validating forms"},b=e=>({on:(t,r)=>e?.addEventListener(t,r),off:(t,r)=>e?.removeEventListener(t,r)}),g=(e,t)=>{if(!e)return;const r="innerText"in e?"innerText":"textContent";return null!=t&&(e[r]=t),e[r]},S=(e,t)=>{if(e)return null!=t&&(e.innerHTML=t),e.innerHTML},v=e=>document.createElement(e),w=e=>{let t="";const r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";for(let n=0;n<e;n++)t+=r.charAt(Math.floor(62*Math.random()));return t},E=e=>{const t=document.implementation.createHTMLDocument("");return t.body.innerHTML=e,[...t.body.childNodes]},A=e=>{"loading"!==document.readyState?e():document.addEventListener("DOMContentLoaded",e)},T=e=>{window.onload=e},$=e=>{const t="string"==typeof e?document.querySelector(e):e,r=e=>(...r)=>{if(t)return e(...r)},n={elt:t,value:t?.value,text:e=>null!=e?(g(t,e),n):g(t),html:e=>null!=e?(S(t,e),n):S(t),val:r(e=>{if(null!=e){if(t.opt&&t.multiple){const r=new Set(Array.isArray(e)?e:[e]);Array.from(t.options).forEach(e=>{e.selected=r.has(e.value)})}else t.value=e;return n.value=t.value,n}return t.options&&t.multiple?Array.from(t.options).filter(e=>e.selected).map(e=>e.value):t.value}),addClass:r(e=>(t.classList.add(e),n)),removeClass:r(e=>(t.classList.remove(e),n)),hasClass:r(e=>t.classList.contains(e)),hide:r(()=>(t.style.display="none",n)),show:r(()=>(t.style.display="",n)),prop:r(e=>t[e]),attr:r(e=>t.getAttribute(e)),removeAttr:e=>{t.removeAttribute(e)},toggle:r(()=>("none"==t.style.display?n.show():n.hide(),n)),css:r(e=>(Object.entries(e).forEach(([e,r])=>{t.style[e]=r}),n)),on:b(t).on,off:b(t).off};return n},C=e=>document.querySelectorAll(e),D={Q:$,$:$,all:C,$$:C,scan:(e,t={})=>{const r=t.refAttr||"v-ref",n="string"==typeof e?document.querySelector(e):e||document;if(!n)throw new Error(`Dom.scan: root "${e}" not found`);const s=Object.create(null);return n.querySelectorAll(`[${r}]`).forEach(e=>{const t=e.getAttribute(r);if(!t)return;const n=$(e);s[t]?Array.isArray(s[t])?s[t].push(n):s[t]=[s[t],n]:s[t]=n}),new Proxy({},{get(e,t){if("_"===t)return s;if("get"===t)return e=>s[e];if("all"===t)return e=>s[e]?Array.isArray(s[e])?s[e]:[s[e]]:[];if("on"===t)return(e,t,r)=>{const n=s[e];(Array.isArray(n)?n:[n]).forEach(e=>e?.on(t,r))};if("string"!=typeof t)return;const r=s[t];return r||(console.warn(`DOM.scan: ref "${t}" not found`),$(null))}})},make:v,makeId:w,parseHtml:E,onPageLoad:A,onWindowLoad:T,ping:()=>console.log("PONG!"),description:"DOM is for dom manipulation"};let I="",N=8e3,q=null,R=null,x=null;const M=new Map,L=new Map,O=()=>Date.now();function U(e){const t="undefined"!=typeof window?window[e]:null;return t?{get(e){const r=t.getItem(e);if(!r)return null;try{const n=JSON.parse(r);return n.exp&&n.exp<O()?(t.removeItem(e),null):n.val}catch{return null}},set(e,r,n){const s=n?O()+n:null;t.setItem(e,JSON.stringify({val:r,exp:s}))},del(e){t&&t.removeItem(e)},clear(){t&&t.clear()}}:null}const H={memory:{get(e){const t=L.get(e);return t?t.exp&&t.exp<O()?(L.delete(e),null):t.val:null},set(e,t,r){const n=r?O()+r:null;L.set(e,{val:t,exp:n})},del(e){L.delete(e)},clear(){L.clear()}},local:U("localStorage"),session:U("sessionStorage")};function k(e){return null===e||"object"!=typeof e?String(e):Array.isArray(e)?`[${e.map(k).join(",")}]`:`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${k(e[t])}`).join(",")}}`}const F=(e,t)=>setTimeout(()=>t.abort(),e);async function j(e,t,r={}){const{params:n,body:s,headers:o={},cache:a}=r;let i=I+t;if(n){const e=new URLSearchParams(n).toString();i+=(i.includes("?")?"&":"?")+e}const l=new AbortController,u=F(N,l),c=!!a,d=a?.strategy,m=a?.ttl??0,f=function(e="memory"){return H[e]||H.memory}(a?.storage),h=a?.key||function(e,t,r,n){return`H|${e}|${t}${r?`?${new URLSearchParams(r).toString()}`:""}${n&&"GET"!==e?`#${k(n)}`:""}`}(e,i,n,s);if(c&&!a?.forceRefresh&&"cache-first"===d){const e=f.get(h);if(null!==e)return e}let y={method:e,headers:o,signal:l.signal};if(x){const{token:e,headerName:t}=x,r="function"==typeof e?e():e;if(r){const e="Authorization"===t?"Bearer ":"";y.headers[t]=`${e}${r}`}}void 0!==s&&(s instanceof FormData?y.body=s:(y.headers["Content-Type"]="application/json",y.body=JSON.stringify(s))),q&&(y=q(y)||y);try{let t,r=await fetch(i,y);M.has(r.status)&&M.get(r.status)(r,{method:e,url:i}),clearTimeout(u),R&&(r=R(r)||r);try{t=await r.json()}catch{t=await r.text()}if(!r.ok){const n={status:r.status,data:t,url:i,method:e};if(c&&"network-first"===d){const e=f.get(h);if(null!==e)return e}throw n}return c&&f.set(h,t,m),t}catch(e){if(clearTimeout(u),c&&"network-first"===d){const e=f.get(h);if(null!==e)return e}throw e}}async function P(e,{filename:t,params:r,headers:n={},method:s="GET",body:o,onProgress:a}={}){let i=I+e;if(r){const e=new URLSearchParams(r).toString();i+=(i.includes("?")?"&":"?")+e}const l=new AbortController,u=F(N,l),c={method:s,headers:{...n},signal:l.signal};void 0!==o&&(o instanceof FormData?c.body=o:(c.headers["Content-Type"]=c.headers["Content-Type"]||"application/json",c.body="string"==typeof o?o:JSON.stringify(o)));const d=await fetch(i,c);if(clearTimeout(u),!d.ok){let e="";try{e=await d.text()}catch{}throw new Error(`Download failed ${d.status}: ${e||d.statusText}`)}if(!t){const e=d.headers.get("Content-Disposition")||"",r=/filename\*=UTF-8''([^;]+)|filename="?([^"]+)"?/i.exec(e);t=decodeURIComponent(r?.[1]||r?.[2]||"download")}let m;if(d.body&&"getReader"in d.body){const e=d.body.getReader(),t=Number(d.headers.get("Content-Length"))||null,r=[];let n=0;for(;;){const{done:s,value:o}=await e.read();if(s)break;if(r.push(o),n+=o.length,"function"==typeof a){a(n,t,t?Math.round(n/t*100):null)}}m=new Blob(r)}else m=await d.blob(),"function"==typeof a&&a(1,1,100);const f=URL.createObjectURL(m),h=document.createElement("a");return h.href=f,h.download=t,h.style.display="none",document.body.appendChild(h),h.click(),document.body.removeChild(h),URL.revokeObjectURL(f),{filename:t,size:m.size,type:m.type}}function _(e,{files:t,fieldName:r="file",fields:n={},headers:s={},method:o="POST",onProgress:a,signal:i}={}){return new Promise((l,u)=>{const c=function({files:e,fieldName:t="file",fields:r={}}){const n=new FormData,s=Array.isArray(e)?e:[e];return s.forEach((e,r)=>{const o=s.length>1?`${t}[${r}]`:t;n.append(o,e)}),Object.entries(r).forEach(([e,t])=>{n.append(e,t instanceof Blob||t instanceof File?t:"object"==typeof t?JSON.stringify(t):String(t))}),n}({files:t,fieldName:r,fields:n}),d=`${I}${e}`,m=new XMLHttpRequest;m.open(o,d,!0);let f={method:o,headers:{...s}};if(x){const{token:e,headerName:t}=x,r="function"==typeof e?e():e;if(r){const e="Authorization"===t?"Bearer ":"";f.headers[t]=`${e}${r}`}}if(q&&(f=q(f)||f),Object.entries(f.headers).forEach(([e,t])=>m.setRequestHeader(e,t)),m.timeout=N,i){const e=()=>{try{m.abort()}catch{}};i.aborted&&e(),i.addEventListener("abort",e,{once:!0})}m.upload&&"function"==typeof a&&(m.upload.onprogress=e=>{if(!e.lengthComputable)return void a(e.loaded,null,null);const t=Math.round(e.loaded/e.total*100);a(e.loaded,e.total,t)}),m.onreadystatechange=async()=>{if(4!==m.readyState)return;if(R){const e={status:m.status,ok:m.status>=200&&m.status<300,headers:new Headers,text:async()=>m.responseText,json:async()=>JSON.parse(m.responseText||"null")};R(e)}const e=(m.getResponseHeader("Content-Type")||"").includes("application/json")?function(e){try{return JSON.parse(e||"null")}catch{return e}}(m.responseText):m.responseText;m.status>=200&&m.status<300?l(e):u({status:m.status,data:e,url:d,method:o})},m.onerror=()=>u({status:0,data:"Network error",url:`${I}${e}`,method:o}),m.ontimeout=()=>u({status:0,data:"Timeout",url:`${I}${e}`,method:o}),m.send(c)})}const B=(e,t)=>j("GET",e,t),V=(e,t,r={})=>j("POST",e,{...r,body:t}),G=(e,t,r={})=>j("PUT",e,{...r,body:t}),z=(e,t={})=>j("DELETE",e,t),J=(e,t)=>fetch(I+e,t),Y={base:e=>(I=e,Y),timeout:e=>(N=e,Y),bearer:(e,t="Authorization")=>(x={token:e,headerName:t},Y),onStatus:(e,t)=>(M.set(e,t),Y),onUnauthorized:e=>Y.onStatus(401,e),onForbidden:e=>Y.onStatus(403,e),onInternalServerError:e=>Y.onStatus(500,e),interceptRequest:e=>(q=e,Y),interceptResponse:e=>(R=e,Y),get:B,post:V,put:G,delete:z,raw:J,download:P,upload:_,ping:()=>console.log("PONG"),description:"H is for Http"};let Q=null,W=new Set;function K(e){let t=e;const r=new Set;return{get val(){return Q&&r.add(Q),t},set val(e){if(e!==t){t=e;for(const e of r)e()}},peek:()=>t,subscribe:e=>(r.add(e),()=>r.delete(e)),toString:()=>String(t),valueOf:()=>t}}function Z(e){const t=()=>{const r=Q;Q=t;try{e()}finally{Q=r}};return t(),t}function X(e){return"string"==typeof e?$(e):e}const ee={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 te{constructor(e,t,r,n={}){this.formId=e,this.schema=t,this.onSubmit=r,this.preSubmit=n.preSubmit||null,this.form=null,this.formState={},this.errors={},this.initialValues={},this._boundHandleSubmit=this.#e.bind(this),this._boundHandleInput=this.#t.bind(this),this.#r()}#r(){this.form=document.getElementById(this.formId),this.form?(this.#n(),this.form.addEventListener("submit",this._boundHandleSubmit),this.form.addEventListener("input",this._boundHandleInput),this.#s()):console.error(`Form with id ${this.formId} not found`)}#n(){const e=this.form.elements;for(const t of Array.from(e))t.name&&(this.initialValues[t.name]=t.value,this.formState[t.name]=t.value)}#t(e){const{name:t,value:r}=e.target;t&&(this.formState[t]=r,this.#s(),this.errors[t]&&(delete this.errors[t],this.#o()))}async#e(e){e.preventDefault();const r=new FormData(this.form);let n={};r.forEach((e,t)=>{n[t]=e}),this.formState=n,this.#s();const{isValid:s,errors:o}=p.run(this.schema,n);if(t.pub(ee.VALIDATED,{formId:this.formId,isValid:s,errors:o,data:n}),!s)return this.errors=o,this.#o(),void t.pub(ee.SUBMIT_ERROR,{formId:this.formId,errors:o});if(this.errors={},this.#o(),this.preSubmit)try{n=await this.preSubmit(n)}catch(e){return void t.pub(ee.SUBMIT_ERROR,{formId:this.formId,errors:{_preSubmit:[e.message]}})}t.pub(ee.SUBMIT_SUCCESS,{formId:this.formId,data:n}),this.onSubmit(n)}#s(){t.pub(ee.STATE_CHANGE,{formId:this.formId,state:{...this.formState}})}#o(){t.pub(ee.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.#s(),this.#o(),t.pub(ee.RESET,{formId:this.formId})}validateNow(){const e=new FormData(this.form),r={};e.forEach((e,t)=>{r[t]=e});const n=p.run(this.schema,r);return this.errors=n.errors,this.#o(),t.pub(ee.VALIDATED,{formId:this.formId,isValid:n.isValid,errors:n.errors,data:r}),n}destroy(){this.form&&(this.form.removeEventListener("submit",this._boundHandleSubmit),this.form.removeEventListener("input",this._boundHandleInput))}}class re{constructor(e,r={}){this.formId=e,this.options={containerClass:"form-error-container",errorClass:"text-danger",insertAfterField:!0,...r},this.customContainers={},this._boundHandleErrors=this.#a.bind(this),t.sub(ee.ERRORS_CHANGE,this._boundHandleErrors)}#a({formId:e,errors:t}){e===this.formId&&(this.clearAll(),this.renderAll(t))}setContainer(e,t){this.customContainers[e]="string"==typeof t?document.querySelector(t):t}renderAll(e){for(const t in e)this.render(t,e[t])}render(e,t){if(!t||0===t.length)return null;const r=document.createElement("span");r.className=`${this.options.containerClass} ${this.options.errorClass}`,r.dataset.field=e;const n=document.createElement("ul");t.forEach(e=>{const t=document.createElement("li"),r=document.createElement("i");r.textContent=e,t.appendChild(r),n.appendChild(t)}),r.appendChild(n);const s=this.customContainers[e];if(s)s.innerHTML="",s.appendChild(r);else if(this.options.insertAfterField){const t=document.getElementById(this.formId),n=t?.querySelector(`[name="${e}"]`);n&&n.insertAdjacentElement("afterend",r)}return r}clearAll(){const e=document.getElementById(this.formId);if(!e)return;e.querySelectorAll(`.${this.options.containerClass}`).forEach(e=>e.remove());for(const e in this.customContainers)this.customContainers[e]&&(this.customContainers[e].innerHTML="")}destroy(){t.unsub(ee.ERRORS_CHANGE,this._boundHandleErrors),this.clearAll()}}const ne=(e={})=>{const{persistKey:r="query-cache",persistedKeys:n=null,defaultTtl:s=6e4,defaultStaleTime:o=5e3,defaultRetries:i=3,defaultRetryDelay:l=1e3}=e,u=new Map,c=new Map,d=(e,r,n)=>{t.pub(`query:${e}`,{key:r,...n}),t.pub(`query:${r}:${e}`,n)},m=()=>{try{const e=localStorage.getItem(r);if(!e)return;const n=JSON.parse(e),s=Date.now();for(const[e,t]of Object.entries(n))s<t.expiry&&u.set(e,{...t,promise:null});t.pub("query:hydrated",{keys:[...u.keys()]})}catch(e){console.warn("Failed to load query cache: ",e)}},f=()=>{try{const e={};for(const[t,r]of u.entries())void 0!==r.data&&(n&&!n.some(e=>t.startsWith(e))||(e[t]={data:r.data,staleAt:r.staleAt,expiry:r.expiry}));localStorage.setItem(r,JSON.stringify(e))}catch(e){console.warn("Failed to persist query cache: ",e)}};let h=null;const y=()=>{h&&clearTimeout(h),h=setTimeout(f,1e3)},p=e=>u.get(e)??null,b=async(e,t,r={})=>{const{ttl:n=s,staleTime:c=o,retries:m=i,retryDelay:f=l}=r,h=Date.now(),b=p(e);if(b&&h<b.staleAt)return d("hit",e,{data:b.data}),b.data;if(b?.promise)return b.promise;const g=b&&h<b.expiry;d("fetch",e,{isStale:g,hasCache:!!b});const S=(async(e,t,r,n)=>{let s;for(let o=0;o<=r;o++)try{return await t()}catch(t){if(s=t,o<r){const s=n*Math.pow(2,o);d("retry",e,{attempt:o+1,maxRetries:r,delay:s,error:t}),await a(s)}}throw s})(e,t,m,f).then(t=>(u.set(e,{data:t,staleAt:Date.now()+c,expiry:Date.now()+n,promise:null,error:null}),d("success",e,{data:t}),y(),t)).catch(t=>{throw u.set(e,{data:b?.data??null,staleAt:b?.staleAt??0,expiry:b?.expiry??0,promise:null,error:t}),d("error",e,{error:t,staleData:b?.data??null}),t});return u.set(e,{...b,promise:S}),g?b.data:S},g=(e,t)=>{const r=p(e);if(!r)return null;const n=r.data,s="function"==typeof t?t(n):t;return u.set(e,{...r,data:s}),d("mutate",e,{data:s,previous:n}),y(),n},S=(e,t={})=>{const{refetch:r,fetcher:n}=t;if(u.delete(e),d("invalidate",e,{}),y(),r&&n)return b(e,n)},v=e=>{const t=c.get(e);t&&(clearInterval(t),c.delete(e),d("polling:stop",e,{}))},w=()=>{for(const e of c.keys())v(e)},E=(e,t,r,n={})=>{v(e),b(e,t,n).catch(()=>{});const s=setInterval(()=>{const r=p(e);r&&u.set(e,{...r,staleAt:0}),b(e,t,n).catch(()=>{})},r);return c.set(e,s),d("polling:start",e,{interval:r}),()=>v(e)},A=()=>{const e=Date.now(),r=[];for(const[n,s]of u.entries())e>s.expiry&&!t.has(`query:${n}:success`)&&(u.delete(n),r.push(n));r.length&&(y(),t.pub("query:gc",{collected:r}))},T=(e,r)=>{const n=t=>r({...p(e),...t});t.sub(`query:${e}:success`,n),t.sub(`query:${e}:error`,n),t.sub(`query:${e}:mutate`,n),t.sub(`query:${e}:set`,n),t.sub(`query:${e}:invalidate`,()=>r(null));const s=p(e);return s&&r(s),()=>{t.unsub(`query:${e}:success`,n),t.unsub(`query:${e}:error`,n),t.unsub(`query:${e}:mutate`,n),t.unsub(`query:${e}:set`,n),t.unsub(`query:${e}:invalidate`,n)}};m(),setInterval(A,6e4),window.addEventListener("storage",e=>{if(e.key===r){m();for(const e of u.keys())d("sync",e,{data:u.get(e)?.data})}}),window.addEventListener("beforeunload",()=>{w(),f()});const $=(e,t,r={})=>{const n=K(r.inital??null),s=K(!1),o=K(null),a=T(e,e=>{e?.data&&(n.val=e.data),e?.error&&(o.val=e.error),s.val=!!e?.promise&&!e?.data}),i=()=>(s.val=!0,b(e,t,r));return!1!==r.enabled&&i().catch(()=>{}),{data:n,loading:s,error:o,fetch:i,refetch:()=>(S(e),i()),unsubscribe:a,mutate:t=>{const r=g(e,t);return n.val=p(e)?.data,r}}};return{query:b,mutate:g,setQueryData:(e,t,r={})=>{const{ttl:n=s,staleTime:a=o}=r,i=Date.now();u.set(e,{data:t,staleAt:i+a,expiry:i+n,promise:null,error:null}),d("set",e,{data:t}),y()},invalidate:S,invalidateMatching:e=>{const t=[];for(const r of u.keys())e(r)&&(u.delete(r),t.push(r),d("invalidate",r,{}));return y(),t},subscribe:T,prefetch:(e,t,r)=>{const n=p(e);n&&Date.now()<n.staleAt||b(e,t,r).catch(()=>{})},startPolling:E,stopPolling:v,stopAllPolling:w,getEntry:p,gc:A,querySignal:$,pollingSignal:(e,t,r,n={})=>({...$(e,t,{...n,enabled:!1}),stop:E(e,t,r,n)}),bindQuery:(e,r,n={})=>{const{target:s,render:o,onLoading:a,onError:i,poll:l=null,...u}=n,c="string"==typeof s?document.querySelector(s):s,d=e=>{const t=o(e);"string"==typeof t&&(c.innerHTML=t)};if(t.sub(`query:${e}:success`,({data:e})=>d(e)),t.sub(`query:${e}:set`,({data:e})=>d(e)),t.sub(`query:${e}:mutate`,({data:e})=>d(e)),i&&t.sub(`query:${e}:error`,({error:e,staleData:t})=>i(e,t,c)),a&&t.sub(`query:${e}:fetch`,({hasCache:e})=>{e||a(c)}),b(e,r,u).catch(()=>{}),l)return E(e,r,l,u)},clear:()=>{u.clear(),localStorage.removeItem(r),t.pub("query:cleared",{})}}},se=ne();e.DOM=D,e.EVT=t,e.FormErrorRenderer=re,e.FormEvents=ee,e.FormHandler=te,e.HTTP=Y,e.Q=$,e.V=p,e.all=C,e.batch=function(e){e(),W.forEach(e=>e()),W.clear()},e.bind=function(e,t,r){const n=X(e);return Z(()=>{const e=r.val;switch(t){case"text":n.text(e);break;case"html":n.html(e);break;case"value":n.val(e);break;case"show":e?n.show():n.hide();break;case"hide":e?n.hide():n.show();break;case"disabled":n.elt.disabled=!!e;break;default:n.elt[t]=e}})},e.bindAttr=function(e,t,r){const n=X(e);return Z(()=>{n.elt.setAttribute(t,r.val)})},e.bindClass=function(e,t,r){const n=X(e);return Z(()=>{r.val?n.addClass(t):n.removeClass(t)})},e.bindHtml=function(e,t){const r=X(e);return Z(()=>{const e=t.val;r.html(e)})},e.bindList=function(e,t,r,n=""){const s=X(e);return Z(()=>{const e=t.val;s.html(e?.length?e.map(r).join(""):n)})},e.bindOptions=function(e,t,r={}){const{value:n="id",label:s="name",placeholder:o="Select ..."}=r,a=X(e);return Z(()=>{const e=t.val||[];a.html(`<option value="">${o}</option>`+e.map(e=>`<option value="${e[n]}">${e[s]}</option>`).join(""))})},e.bindText=function(e,t){const r=X(e);return Z(()=>{const e=t.val;r.text(e)})},e.bindValue=function(e,t){const r=X(e);return Z(()=>{const e=t.val;r.val(e)})},e.cache=function(e){if(null==e)return{cache:{strategy:"cache-first",storage:"local",ttl:6e4}};if("object"==typeof e)return{cache:e};const t=e.toLowerCase(),r={cfl:{strategy:"cache-first",storage:"local"},cfs:{strategy:"cache-first",storage:"session"},cfm:{strategy:"cache-first",storage:"memory"},nfl:{strategy:"network-first",storage:"local"},nfs:{strategy:"network-first",storage:"session"},nfm:{strategy:"network-first",storage:"memory"}},n=t.match(/cfl|cfs|cfm|nfl|nfs|nfm/),s=n?r[n[0]]:r.cfl,o=t.match(/(\d+)\s*(s|sec|secs|second|seconds|min|m|mins|minute|minutes|h|hr|hours)?/),a=o?function(e){const t=e.replace(/[0-9]/g,"").trim().toLowerCase(),r=parseInt(e,10),n={s:1e3,sec:1e3,secs:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,mins:6e4,minute:6e4,minutes:6e4,h:36e5,hr:36e5,hrs:36e5,hours:36e5};return r*(n[t]||1)}(o[0]):6e4;return{cache:{strategy:s.strategy,storage:s.storage,ttl:a}}},e.computed=function(e){const t=K(void 0);return Z(()=>{t.val=e()}),t},e.createQuery=ne,e.del=z,e.download=P,e.effect=Z,e.formatByCountry=(e,t)=>n(e,r[t]??r.US),e.get=B,e.isArray=e=>Array.isArray(e),e.isArrayEmpty=e=>!(Array.isArray(e)&&e.length>0),e.isFocus=e=>e==document.activeElement,e.isValidRoutingNumber=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},e.make=v,e.makeId=w,e.onPageLoad=A,e.onWindowLoad=T,e.parseHtml=E,e.post=V,e.put=G,e.queryClient=se,e.raw=J,e.redirect=e=>window.location.href=e,e.request=j,e.signal=K,e.toCurrency=n,e.upload=_,e.useFormHandler=function(e,t,r,n){const s=new te(e,t,r,n),o=new re(e,n);return{reset:()=>s.reset(),validate:()=>s.validateNow(),destroy:()=>{o.destroy(),s.destroy()},setContainer:(e,t)=>o.setContainer(e,t)}},e.when=function(e,t){return Z(()=>{e.val&&t(e.val)})},Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
|