sibujs 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -119
- package/dist/browser.cjs +53 -14
- package/dist/browser.d.cts +14 -9
- package/dist/browser.d.ts +14 -9
- package/dist/browser.js +4 -4
- package/dist/build.cjs +124 -42
- package/dist/build.d.cts +1 -1
- package/dist/build.d.ts +1 -1
- package/dist/build.js +10 -10
- package/dist/cdn.global.js +7 -7
- package/dist/chunk-5ZYQ6KDD.js +154 -0
- package/dist/chunk-6BMPXPUW.js +26 -0
- package/dist/chunk-7GRNSCFT.js +1097 -0
- package/dist/chunk-BGTHZHJ5.js +1016 -0
- package/dist/chunk-BMPL52BF.js +654 -0
- package/dist/chunk-GJPXRJ45.js +37 -0
- package/dist/chunk-JCDUJN2F.js +2779 -0
- package/dist/chunk-K4G4ZQNR.js +286 -0
- package/dist/chunk-MB6QFH3I.js +2776 -0
- package/dist/chunk-MYRV7VDM.js +742 -0
- package/dist/chunk-NZIIMDWI.js +84 -0
- package/dist/chunk-P3XWXJZU.js +282 -0
- package/dist/chunk-PDZQY43A.js +616 -0
- package/dist/chunk-RJ46C3CS.js +1293 -0
- package/dist/chunk-SFKNRVCU.js +292 -0
- package/dist/chunk-TDGZL5CU.js +365 -0
- package/dist/chunk-VAPYJN4X.js +368 -0
- package/dist/chunk-VQDZK23A.js +1023 -0
- package/dist/chunk-VQNQZCWJ.js +61 -0
- package/dist/chunk-XHK6BDAJ.js +76 -0
- package/dist/chunk-XUEEGU5O.js +409 -0
- package/dist/contracts-ey_Qh8ef.d.cts +239 -0
- package/dist/contracts-ey_Qh8ef.d.ts +239 -0
- package/dist/customElement-BL3Uo8dL.d.cts +318 -0
- package/dist/customElement-BL3Uo8dL.d.ts +318 -0
- package/dist/data.cjs +52 -11
- package/dist/data.js +6 -6
- package/dist/devtools.cjs +22 -24
- package/dist/devtools.js +26 -28
- package/dist/ecosystem.cjs +31 -6
- package/dist/ecosystem.d.cts +4 -4
- package/dist/ecosystem.d.ts +4 -4
- package/dist/ecosystem.js +7 -7
- package/dist/extras.cjs +304 -108
- package/dist/extras.d.cts +3 -3
- package/dist/extras.d.ts +3 -3
- package/dist/extras.js +19 -19
- package/dist/index.cjs +124 -42
- package/dist/index.d.cts +58 -48
- package/dist/index.d.ts +58 -48
- package/dist/index.js +10 -10
- package/dist/motion.cjs +13 -2
- package/dist/motion.d.cts +1 -1
- package/dist/motion.d.ts +1 -1
- package/dist/motion.js +3 -3
- package/dist/patterns.cjs +91 -24
- package/dist/patterns.d.cts +46 -12
- package/dist/patterns.d.ts +46 -12
- package/dist/patterns.js +5 -5
- package/dist/performance.cjs +97 -12
- package/dist/performance.d.cts +6 -1
- package/dist/performance.d.ts +6 -1
- package/dist/performance.js +5 -3
- package/dist/plugins.cjs +19 -13
- package/dist/plugins.d.cts +3 -3
- package/dist/plugins.d.ts +3 -3
- package/dist/plugins.js +16 -18
- package/dist/ssr.cjs +9 -0
- package/dist/ssr.d.cts +1 -1
- package/dist/ssr.d.ts +1 -1
- package/dist/ssr.js +7 -7
- package/dist/testing.js +2 -2
- package/dist/ui.cjs +130 -48
- package/dist/ui.d.cts +13 -16
- package/dist/ui.d.ts +13 -16
- package/dist/ui.js +6 -6
- package/dist/widgets.cjs +31 -6
- package/dist/widgets.js +5 -5
- package/package.json +1 -1
package/dist/plugins.cjs
CHANGED
|
@@ -1014,7 +1014,15 @@ function dispose(node) {
|
|
|
1014
1014
|
const disposers = elementDisposers.get(current);
|
|
1015
1015
|
if (disposers) {
|
|
1016
1016
|
if (_isDev5) activeBindingCount -= disposers.length;
|
|
1017
|
-
for (const d of disposers)
|
|
1017
|
+
for (const d of disposers) {
|
|
1018
|
+
try {
|
|
1019
|
+
d();
|
|
1020
|
+
} catch (err) {
|
|
1021
|
+
if (_isDev5 && typeof console !== "undefined") {
|
|
1022
|
+
console.warn("[SibuJS] Disposer threw during cleanup:", err);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1018
1026
|
elementDisposers.delete(current);
|
|
1019
1027
|
}
|
|
1020
1028
|
}
|
|
@@ -1425,9 +1433,7 @@ function t(key, params) {
|
|
|
1425
1433
|
return params ? message.replace(/\{(\w+)\}/g, (_, p2) => String(params[p2] ?? "")) : message;
|
|
1426
1434
|
}
|
|
1427
1435
|
function Trans(key, params) {
|
|
1428
|
-
return span(
|
|
1429
|
-
nodes: () => t(key, params)
|
|
1430
|
-
});
|
|
1436
|
+
return span(() => t(key, params));
|
|
1431
1437
|
}
|
|
1432
1438
|
function hasTranslation(key) {
|
|
1433
1439
|
const locale = currentLocale();
|
|
@@ -1598,9 +1604,12 @@ var RouteMatcher = class {
|
|
|
1598
1604
|
return this.namedRoutes.get(name) || null;
|
|
1599
1605
|
}
|
|
1600
1606
|
matchPattern(path2, routePath) {
|
|
1601
|
-
if (routePath === "*"
|
|
1607
|
+
if (routePath === "*") {
|
|
1608
|
+
return { params: { pathMatch: path2 } };
|
|
1609
|
+
}
|
|
1610
|
+
if (routePath.endsWith("/*")) {
|
|
1602
1611
|
const basePath = routePath.slice(0, -2);
|
|
1603
|
-
if (path2.startsWith(basePath)) {
|
|
1612
|
+
if (path2 === basePath || path2.startsWith(`${basePath}/`)) {
|
|
1604
1613
|
return { params: { pathMatch: path2.slice(basePath.length) } };
|
|
1605
1614
|
}
|
|
1606
1615
|
return null;
|
|
@@ -1719,6 +1728,8 @@ var GuardManager = class {
|
|
|
1719
1728
|
const next = (result) => {
|
|
1720
1729
|
if (resolved || signal2.aborted) return;
|
|
1721
1730
|
resolved = true;
|
|
1731
|
+
clearTimeout(timeoutId);
|
|
1732
|
+
signal2.removeEventListener("abort", abortHandler);
|
|
1722
1733
|
if (result instanceof Error) {
|
|
1723
1734
|
reject(result);
|
|
1724
1735
|
} else if (result === false) {
|
|
@@ -1732,10 +1743,10 @@ var GuardManager = class {
|
|
|
1732
1743
|
const abortHandler = () => {
|
|
1733
1744
|
if (!resolved) {
|
|
1734
1745
|
resolved = true;
|
|
1746
|
+
clearTimeout(timeoutId);
|
|
1735
1747
|
reject(new Error("Navigation aborted"));
|
|
1736
1748
|
}
|
|
1737
1749
|
};
|
|
1738
|
-
signal2.addEventListener("abort", abortHandler);
|
|
1739
1750
|
const timeoutId = setTimeout(() => {
|
|
1740
1751
|
if (!resolved) {
|
|
1741
1752
|
resolved = true;
|
|
@@ -1743,6 +1754,7 @@ var GuardManager = class {
|
|
|
1743
1754
|
reject(new Error("Guard timeout"));
|
|
1744
1755
|
}
|
|
1745
1756
|
}, this.timeout);
|
|
1757
|
+
signal2.addEventListener("abort", abortHandler);
|
|
1746
1758
|
try {
|
|
1747
1759
|
guard(to, from, next);
|
|
1748
1760
|
} catch (error) {
|
|
@@ -1753,12 +1765,6 @@ var GuardManager = class {
|
|
|
1753
1765
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
1754
1766
|
}
|
|
1755
1767
|
}
|
|
1756
|
-
Promise.resolve().then(() => {
|
|
1757
|
-
if (resolved) {
|
|
1758
|
-
clearTimeout(timeoutId);
|
|
1759
|
-
signal2.removeEventListener("abort", abortHandler);
|
|
1760
|
-
}
|
|
1761
|
-
});
|
|
1762
1768
|
});
|
|
1763
1769
|
}
|
|
1764
1770
|
addBeforeEach(guard) {
|
package/dist/plugins.d.cts
CHANGED
|
@@ -24,7 +24,7 @@ declare function t(key: string, params?: Params$1): string;
|
|
|
24
24
|
* registerTranslations("en", { greeting: "Hello, {name}!" });
|
|
25
25
|
* registerTranslations("es", { greeting: "Hola, {name}!" });
|
|
26
26
|
*
|
|
27
|
-
* div(
|
|
27
|
+
* div([Trans("greeting", { name: "World" })]);
|
|
28
28
|
* // When locale changes, the text updates automatically
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
@@ -235,11 +235,11 @@ declare function Route(): Node;
|
|
|
235
235
|
* ```ts
|
|
236
236
|
* // Cache all routes (max 10)
|
|
237
237
|
* createRouter(routes, { keepAlive: 10 });
|
|
238
|
-
* mount(() => div(
|
|
238
|
+
* mount(() => div([nav, KeepAliveRoute()]), root);
|
|
239
239
|
*
|
|
240
240
|
* // Or cache specific routes by name
|
|
241
241
|
* createRouter(routes, { keepAlive: ["dashboard", "settings"] });
|
|
242
|
-
* mount(() => div(
|
|
242
|
+
* mount(() => div([nav, KeepAliveRoute()]), root);
|
|
243
243
|
*
|
|
244
244
|
* // Or override per-outlet
|
|
245
245
|
* KeepAliveRoute({ max: 5, include: ["dashboard"] })
|
package/dist/plugins.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ declare function t(key: string, params?: Params$1): string;
|
|
|
24
24
|
* registerTranslations("en", { greeting: "Hello, {name}!" });
|
|
25
25
|
* registerTranslations("es", { greeting: "Hola, {name}!" });
|
|
26
26
|
*
|
|
27
|
-
* div(
|
|
27
|
+
* div([Trans("greeting", { name: "World" })]);
|
|
28
28
|
* // When locale changes, the text updates automatically
|
|
29
29
|
* ```
|
|
30
30
|
*/
|
|
@@ -235,11 +235,11 @@ declare function Route(): Node;
|
|
|
235
235
|
* ```ts
|
|
236
236
|
* // Cache all routes (max 10)
|
|
237
237
|
* createRouter(routes, { keepAlive: 10 });
|
|
238
|
-
* mount(() => div(
|
|
238
|
+
* mount(() => div([nav, KeepAliveRoute()]), root);
|
|
239
239
|
*
|
|
240
240
|
* // Or cache specific routes by name
|
|
241
241
|
* createRouter(routes, { keepAlive: ["dashboard", "settings"] });
|
|
242
|
-
* mount(() => div(
|
|
242
|
+
* mount(() => div([nav, KeepAliveRoute()]), root);
|
|
243
243
|
*
|
|
244
244
|
* // Or override per-outlet
|
|
245
245
|
* KeepAliveRoute({ max: 5, include: ["dashboard"] })
|
package/dist/plugins.js
CHANGED
|
@@ -34,25 +34,25 @@ import {
|
|
|
34
34
|
} from "./chunk-K5ZUMYVS.js";
|
|
35
35
|
import {
|
|
36
36
|
span
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import "./chunk-
|
|
37
|
+
} from "./chunk-P3XWXJZU.js";
|
|
38
|
+
import "./chunk-SFKNRVCU.js";
|
|
39
39
|
import {
|
|
40
40
|
dispose,
|
|
41
41
|
registerDisposer
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-5ZYQ6KDD.js";
|
|
43
43
|
import {
|
|
44
44
|
sanitizeUrl
|
|
45
45
|
} from "./chunk-CMBFNA7L.js";
|
|
46
46
|
import {
|
|
47
47
|
effect
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-VQNQZCWJ.js";
|
|
49
49
|
import "./chunk-EUZND3CB.js";
|
|
50
50
|
import {
|
|
51
51
|
signal
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-NZIIMDWI.js";
|
|
53
53
|
import {
|
|
54
54
|
track
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-K4G4ZQNR.js";
|
|
56
56
|
import "./chunk-5X6PP2UK.js";
|
|
57
57
|
|
|
58
58
|
// src/plugins/i18n.ts
|
|
@@ -73,9 +73,7 @@ function t(key, params) {
|
|
|
73
73
|
return params ? message.replace(/\{(\w+)\}/g, (_, p) => String(params[p] ?? "")) : message;
|
|
74
74
|
}
|
|
75
75
|
function Trans(key, params) {
|
|
76
|
-
return span(
|
|
77
|
-
nodes: () => t(key, params)
|
|
78
|
-
});
|
|
76
|
+
return span(() => t(key, params));
|
|
79
77
|
}
|
|
80
78
|
function hasTranslation(key) {
|
|
81
79
|
const locale = currentLocale();
|
|
@@ -206,9 +204,12 @@ var RouteMatcher = class {
|
|
|
206
204
|
return this.namedRoutes.get(name) || null;
|
|
207
205
|
}
|
|
208
206
|
matchPattern(path, routePath) {
|
|
209
|
-
if (routePath === "*"
|
|
207
|
+
if (routePath === "*") {
|
|
208
|
+
return { params: { pathMatch: path } };
|
|
209
|
+
}
|
|
210
|
+
if (routePath.endsWith("/*")) {
|
|
210
211
|
const basePath = routePath.slice(0, -2);
|
|
211
|
-
if (path.startsWith(basePath)) {
|
|
212
|
+
if (path === basePath || path.startsWith(`${basePath}/`)) {
|
|
212
213
|
return { params: { pathMatch: path.slice(basePath.length) } };
|
|
213
214
|
}
|
|
214
215
|
return null;
|
|
@@ -327,6 +328,8 @@ var GuardManager = class {
|
|
|
327
328
|
const next = (result) => {
|
|
328
329
|
if (resolved || signal2.aborted) return;
|
|
329
330
|
resolved = true;
|
|
331
|
+
clearTimeout(timeoutId);
|
|
332
|
+
signal2.removeEventListener("abort", abortHandler);
|
|
330
333
|
if (result instanceof Error) {
|
|
331
334
|
reject(result);
|
|
332
335
|
} else if (result === false) {
|
|
@@ -340,10 +343,10 @@ var GuardManager = class {
|
|
|
340
343
|
const abortHandler = () => {
|
|
341
344
|
if (!resolved) {
|
|
342
345
|
resolved = true;
|
|
346
|
+
clearTimeout(timeoutId);
|
|
343
347
|
reject(new Error("Navigation aborted"));
|
|
344
348
|
}
|
|
345
349
|
};
|
|
346
|
-
signal2.addEventListener("abort", abortHandler);
|
|
347
350
|
const timeoutId = setTimeout(() => {
|
|
348
351
|
if (!resolved) {
|
|
349
352
|
resolved = true;
|
|
@@ -351,6 +354,7 @@ var GuardManager = class {
|
|
|
351
354
|
reject(new Error("Guard timeout"));
|
|
352
355
|
}
|
|
353
356
|
}, this.timeout);
|
|
357
|
+
signal2.addEventListener("abort", abortHandler);
|
|
354
358
|
try {
|
|
355
359
|
guard(to, from, next);
|
|
356
360
|
} catch (error) {
|
|
@@ -361,12 +365,6 @@ var GuardManager = class {
|
|
|
361
365
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
362
366
|
}
|
|
363
367
|
}
|
|
364
|
-
Promise.resolve().then(() => {
|
|
365
|
-
if (resolved) {
|
|
366
|
-
clearTimeout(timeoutId);
|
|
367
|
-
signal2.removeEventListener("abort", abortHandler);
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
368
|
});
|
|
371
369
|
}
|
|
372
370
|
addBeforeEach(guard) {
|
package/dist/ssr.cjs
CHANGED
|
@@ -658,12 +658,21 @@ function queueSignalNotification(signal2) {
|
|
|
658
658
|
}
|
|
659
659
|
}
|
|
660
660
|
}
|
|
661
|
+
var MAX_DRAIN_ITERATIONS = 1e3;
|
|
661
662
|
function drainNotificationQueue() {
|
|
662
663
|
if (notifyDepth > 0) return;
|
|
663
664
|
notifyDepth++;
|
|
664
665
|
try {
|
|
665
666
|
let i2 = 0;
|
|
666
667
|
while (i2 < pendingQueue.length) {
|
|
668
|
+
if (i2 >= MAX_DRAIN_ITERATIONS) {
|
|
669
|
+
if (typeof console !== "undefined") {
|
|
670
|
+
console.error(
|
|
671
|
+
`[SibuJS] Notification queue exceeded ${MAX_DRAIN_ITERATIONS} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
break;
|
|
675
|
+
}
|
|
667
676
|
safeInvoke(pendingQueue[i2]);
|
|
668
677
|
i2++;
|
|
669
678
|
}
|
package/dist/ssr.d.cts
CHANGED
|
@@ -217,7 +217,7 @@ interface SharedScope<T extends Record<string, unknown>> {
|
|
|
217
217
|
* const app = createMicroApp({ name: "widget", shadow: true });
|
|
218
218
|
* document.body.appendChild(app.element);
|
|
219
219
|
*
|
|
220
|
-
* app.mount(() => div(
|
|
220
|
+
* app.mount(() => div("Hello from micro-app!"));
|
|
221
221
|
*
|
|
222
222
|
* // Later, tear it down:
|
|
223
223
|
* app.unmount();
|
package/dist/ssr.d.ts
CHANGED
|
@@ -217,7 +217,7 @@ interface SharedScope<T extends Record<string, unknown>> {
|
|
|
217
217
|
* const app = createMicroApp({ name: "widget", shadow: true });
|
|
218
218
|
* document.body.appendChild(app.element);
|
|
219
219
|
*
|
|
220
|
-
* app.mount(() => div(
|
|
220
|
+
* app.mount(() => div("Hello from micro-app!"));
|
|
221
221
|
*
|
|
222
222
|
* // Later, tear it down:
|
|
223
223
|
* app.unmount();
|
package/dist/ssr.js
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
wasm,
|
|
23
23
|
worker,
|
|
24
24
|
workerFn
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-MYRV7VDM.js";
|
|
26
26
|
import {
|
|
27
27
|
collectStream,
|
|
28
28
|
deserializeState,
|
|
@@ -42,14 +42,14 @@ import {
|
|
|
42
42
|
suspenseSwapScript,
|
|
43
43
|
trustHTML
|
|
44
44
|
} from "./chunk-3X2YG6YM.js";
|
|
45
|
-
import "./chunk-
|
|
46
|
-
import "./chunk-
|
|
47
|
-
import "./chunk-
|
|
45
|
+
import "./chunk-P3XWXJZU.js";
|
|
46
|
+
import "./chunk-SFKNRVCU.js";
|
|
47
|
+
import "./chunk-5ZYQ6KDD.js";
|
|
48
48
|
import "./chunk-CMBFNA7L.js";
|
|
49
|
-
import "./chunk-
|
|
49
|
+
import "./chunk-VQNQZCWJ.js";
|
|
50
50
|
import "./chunk-EUZND3CB.js";
|
|
51
|
-
import "./chunk-
|
|
52
|
-
import "./chunk-
|
|
51
|
+
import "./chunk-NZIIMDWI.js";
|
|
52
|
+
import "./chunk-K4G4ZQNR.js";
|
|
53
53
|
import "./chunk-5X6PP2UK.js";
|
|
54
54
|
export {
|
|
55
55
|
Head,
|
package/dist/testing.js
CHANGED
package/dist/ui.cjs
CHANGED
|
@@ -324,21 +324,37 @@ function derived(getter, options) {
|
|
|
324
324
|
cs._v = getter();
|
|
325
325
|
}, markDirty);
|
|
326
326
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
327
|
+
let evaluating = false;
|
|
327
328
|
function computedGetter() {
|
|
329
|
+
if (evaluating) {
|
|
330
|
+
throw new Error(
|
|
331
|
+
`[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
328
334
|
if (trackingSuspended) {
|
|
329
335
|
if (cs._d) {
|
|
330
|
-
|
|
331
|
-
|
|
336
|
+
evaluating = true;
|
|
337
|
+
try {
|
|
338
|
+
cs._d = false;
|
|
339
|
+
cs._v = getter();
|
|
340
|
+
} finally {
|
|
341
|
+
evaluating = false;
|
|
342
|
+
}
|
|
332
343
|
}
|
|
333
344
|
return cs._v;
|
|
334
345
|
}
|
|
335
346
|
recordDependency(cs);
|
|
336
347
|
if (cs._d) {
|
|
337
348
|
const oldValue = cs._v;
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
349
|
+
evaluating = true;
|
|
350
|
+
try {
|
|
351
|
+
track(() => {
|
|
352
|
+
cs._d = false;
|
|
353
|
+
cs._v = getter();
|
|
354
|
+
}, markDirty);
|
|
355
|
+
} finally {
|
|
356
|
+
evaluating = false;
|
|
357
|
+
}
|
|
342
358
|
if (hook && oldValue !== cs._v) {
|
|
343
359
|
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
344
360
|
}
|
|
@@ -477,7 +493,7 @@ function bindField(field, extras) {
|
|
|
477
493
|
blur: () => field.touch()
|
|
478
494
|
};
|
|
479
495
|
const { on: extraOn, value: _ignoreValue, ...restExtras } = extras ?? {};
|
|
480
|
-
const mergedOn = extraOn && typeof extraOn === "object" ? { ...
|
|
496
|
+
const mergedOn = extraOn && typeof extraOn === "object" ? { ...extraOn, ...fieldOn } : fieldOn;
|
|
481
497
|
return {
|
|
482
498
|
value: field.value,
|
|
483
499
|
on: mergedOn,
|
|
@@ -548,14 +564,23 @@ function form(config) {
|
|
|
548
564
|
}
|
|
549
565
|
return result;
|
|
550
566
|
});
|
|
567
|
+
const [submitting, setSubmitting] = signal(false);
|
|
551
568
|
function handleSubmit(onSubmit) {
|
|
552
569
|
return (e) => {
|
|
553
570
|
if (e) e.preventDefault();
|
|
571
|
+
if (submitting()) return;
|
|
554
572
|
for (const field of Object.values(fieldMap)) {
|
|
555
573
|
field.touch();
|
|
556
574
|
}
|
|
557
575
|
if (isValid()) {
|
|
558
|
-
onSubmit(values());
|
|
576
|
+
const result = onSubmit(values());
|
|
577
|
+
if (result && typeof result.then === "function") {
|
|
578
|
+
setSubmitting(true);
|
|
579
|
+
result.then(
|
|
580
|
+
() => setSubmitting(false),
|
|
581
|
+
() => setSubmitting(false)
|
|
582
|
+
);
|
|
583
|
+
}
|
|
559
584
|
}
|
|
560
585
|
};
|
|
561
586
|
}
|
|
@@ -572,6 +597,7 @@ function form(config) {
|
|
|
572
597
|
errors,
|
|
573
598
|
isValid,
|
|
574
599
|
isDirty,
|
|
600
|
+
submitting,
|
|
575
601
|
touched: touchedState,
|
|
576
602
|
values,
|
|
577
603
|
handleSubmit,
|
|
@@ -615,6 +641,20 @@ function formAction(fn) {
|
|
|
615
641
|
return { run, pending, error, result, reset, onSubmit };
|
|
616
642
|
}
|
|
617
643
|
|
|
644
|
+
// src/core/rendering/dispose.ts
|
|
645
|
+
var elementDisposers = /* @__PURE__ */ new WeakMap();
|
|
646
|
+
var _isDev4 = isDev();
|
|
647
|
+
var activeBindingCount = 0;
|
|
648
|
+
function registerDisposer(node, teardown) {
|
|
649
|
+
let disposers = elementDisposers.get(node);
|
|
650
|
+
if (!disposers) {
|
|
651
|
+
disposers = [];
|
|
652
|
+
elementDisposers.set(node, disposers);
|
|
653
|
+
}
|
|
654
|
+
disposers.push(teardown);
|
|
655
|
+
if (_isDev4) activeBindingCount++;
|
|
656
|
+
}
|
|
657
|
+
|
|
618
658
|
// src/core/ssr-context.ts
|
|
619
659
|
var ssrMode = false;
|
|
620
660
|
function isSSR() {
|
|
@@ -668,9 +708,9 @@ function VirtualList(props) {
|
|
|
668
708
|
content.style.right = "0";
|
|
669
709
|
spacer.appendChild(content);
|
|
670
710
|
container.appendChild(spacer);
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
711
|
+
const onScroll = () => setScrollTop(container.scrollTop);
|
|
712
|
+
container.addEventListener("scroll", onScroll);
|
|
713
|
+
registerDisposer(container, () => container.removeEventListener("scroll", onScroll));
|
|
674
714
|
const update = () => {
|
|
675
715
|
const items = props.items();
|
|
676
716
|
const totalHeight = items.length * props.itemHeight;
|
|
@@ -778,13 +818,52 @@ function inputMask(options) {
|
|
|
778
818
|
}
|
|
779
819
|
return raw;
|
|
780
820
|
}
|
|
821
|
+
function isSlot(c) {
|
|
822
|
+
return c === "9" || c === "A" || c === "*";
|
|
823
|
+
}
|
|
824
|
+
function buildStripRegex() {
|
|
825
|
+
const hasDigit = options.pattern.includes("9");
|
|
826
|
+
const hasLetter = options.pattern.includes("A");
|
|
827
|
+
const hasAny = options.pattern.includes("*");
|
|
828
|
+
if (hasAny) {
|
|
829
|
+
const literals = /* @__PURE__ */ new Set();
|
|
830
|
+
for (const c of options.pattern) {
|
|
831
|
+
if (!isSlot(c)) literals.add(c.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
832
|
+
}
|
|
833
|
+
return literals.size > 0 ? new RegExp(`[${Array.from(literals).join("")}]`, "g") : /(?!)/g;
|
|
834
|
+
}
|
|
835
|
+
if (hasDigit && hasLetter) return /[^a-zA-Z0-9]/g;
|
|
836
|
+
if (hasDigit) return /[^0-9]/g;
|
|
837
|
+
if (hasLetter) return /[^a-zA-Z]/g;
|
|
838
|
+
return /[^a-zA-Z0-9]/g;
|
|
839
|
+
}
|
|
840
|
+
const stripRegex = buildStripRegex();
|
|
841
|
+
const rawCharTest = options.pattern.includes("*") ? () => true : (c) => /[a-zA-Z0-9]/.test(c);
|
|
781
842
|
function bind(input) {
|
|
782
843
|
input.addEventListener("input", () => {
|
|
783
|
-
const
|
|
844
|
+
const cursorBefore = input.selectionStart ?? input.value.length;
|
|
845
|
+
const oldValue = input.value;
|
|
846
|
+
const raw = oldValue.replace(stripRegex, "");
|
|
784
847
|
const masked = applyMask(raw);
|
|
785
848
|
setValue(masked);
|
|
786
849
|
setRawValue(extractRaw(masked));
|
|
787
850
|
input.value = masked;
|
|
851
|
+
let rawBefore = 0;
|
|
852
|
+
for (let i = 0; i < cursorBefore && i < oldValue.length; i++) {
|
|
853
|
+
if (rawCharTest(oldValue[i])) rawBefore++;
|
|
854
|
+
}
|
|
855
|
+
let newCursor = 0;
|
|
856
|
+
let counted = 0;
|
|
857
|
+
for (; newCursor < masked.length; newCursor++) {
|
|
858
|
+
if (newCursor < options.pattern.length && isSlot(options.pattern[newCursor])) {
|
|
859
|
+
counted++;
|
|
860
|
+
if (counted >= rawBefore) {
|
|
861
|
+
newCursor++;
|
|
862
|
+
break;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
input.setSelectionRange(newCursor, newCursor);
|
|
788
867
|
});
|
|
789
868
|
input.addEventListener("focus", () => {
|
|
790
869
|
if (!input.value) {
|
|
@@ -854,7 +933,10 @@ function FocusTrap(nodes, options = {}) {
|
|
|
854
933
|
const focusable = container.querySelectorAll(
|
|
855
934
|
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
856
935
|
);
|
|
857
|
-
if (focusable.length === 0)
|
|
936
|
+
if (focusable.length === 0) {
|
|
937
|
+
e.preventDefault();
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
858
940
|
const first = focusable[0];
|
|
859
941
|
const last = focusable[focusable.length - 1];
|
|
860
942
|
if (e.shiftKey) {
|
|
@@ -877,24 +959,27 @@ function FocusTrap(nodes, options = {}) {
|
|
|
877
959
|
first?.focus();
|
|
878
960
|
});
|
|
879
961
|
}
|
|
962
|
+
let trapObserver = null;
|
|
963
|
+
function restoreFocusAndCleanup() {
|
|
964
|
+
if (options.restoreFocus !== false) previouslyFocused?.focus();
|
|
965
|
+
if (trapObserver) {
|
|
966
|
+
trapObserver.disconnect();
|
|
967
|
+
trapObserver = null;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
880
970
|
if (options.restoreFocus !== false) {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
if (removed === container || removed.contains(container)) {
|
|
885
|
-
previouslyFocused?.focus();
|
|
886
|
-
observer.disconnect();
|
|
887
|
-
return;
|
|
888
|
-
}
|
|
889
|
-
}
|
|
971
|
+
trapObserver = new MutationObserver(() => {
|
|
972
|
+
if (!container.isConnected) {
|
|
973
|
+
restoreFocusAndCleanup();
|
|
890
974
|
}
|
|
891
975
|
});
|
|
892
976
|
queueMicrotask(() => {
|
|
893
|
-
if (container.
|
|
894
|
-
|
|
977
|
+
if (container.isConnected) {
|
|
978
|
+
trapObserver.observe(document.body, { childList: true, subtree: true });
|
|
895
979
|
}
|
|
896
980
|
});
|
|
897
981
|
}
|
|
982
|
+
registerDisposer(container, restoreFocusAndCleanup);
|
|
898
983
|
return container;
|
|
899
984
|
}
|
|
900
985
|
function hotkey(combo, handler, options = {}) {
|
|
@@ -951,20 +1036,6 @@ function createId(prefix = "sibu") {
|
|
|
951
1036
|
return `${prefix}-${idCounter}`;
|
|
952
1037
|
}
|
|
953
1038
|
|
|
954
|
-
// src/core/rendering/dispose.ts
|
|
955
|
-
var elementDisposers = /* @__PURE__ */ new WeakMap();
|
|
956
|
-
var _isDev4 = isDev();
|
|
957
|
-
var activeBindingCount = 0;
|
|
958
|
-
function registerDisposer(node, teardown) {
|
|
959
|
-
let disposers = elementDisposers.get(node);
|
|
960
|
-
if (!disposers) {
|
|
961
|
-
disposers = [];
|
|
962
|
-
elementDisposers.set(node, disposers);
|
|
963
|
-
}
|
|
964
|
-
disposers.push(teardown);
|
|
965
|
-
if (_isDev4) activeBindingCount++;
|
|
966
|
-
}
|
|
967
|
-
|
|
968
1039
|
// src/ui/a11yPrimitives.ts
|
|
969
1040
|
var DEFAULT_FOCUS_SELECTOR = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
|
|
970
1041
|
function createFocusManager(container, options = {}) {
|
|
@@ -1177,6 +1248,10 @@ function scopedStyle(css) {
|
|
|
1177
1248
|
if (trimmed.startsWith("@") || trimmed.startsWith("from") || trimmed.startsWith("to") || /^\d+%$/.test(trimmed)) {
|
|
1178
1249
|
return match;
|
|
1179
1250
|
}
|
|
1251
|
+
const pseudoIdx = trimmed.indexOf("::");
|
|
1252
|
+
if (pseudoIdx >= 0) {
|
|
1253
|
+
return `${trimmed.slice(0, pseudoIdx)}[${attr}]${trimmed.slice(pseudoIdx)}${delimiter}`;
|
|
1254
|
+
}
|
|
1180
1255
|
return `${trimmed}[${attr}]${delimiter}`;
|
|
1181
1256
|
});
|
|
1182
1257
|
if (typeof document !== "undefined") {
|
|
@@ -1341,28 +1416,35 @@ function dialog() {
|
|
|
1341
1416
|
close();
|
|
1342
1417
|
}
|
|
1343
1418
|
}
|
|
1344
|
-
function
|
|
1345
|
-
setIsOpen(true);
|
|
1419
|
+
function attachListener() {
|
|
1346
1420
|
if (typeof window !== "undefined" && !listenerAttached) {
|
|
1347
1421
|
window.addEventListener("keydown", handleKeydown);
|
|
1348
1422
|
listenerAttached = true;
|
|
1349
1423
|
}
|
|
1350
1424
|
}
|
|
1351
|
-
function
|
|
1352
|
-
setIsOpen(false);
|
|
1425
|
+
function detachListener() {
|
|
1353
1426
|
if (typeof window !== "undefined" && listenerAttached) {
|
|
1354
1427
|
window.removeEventListener("keydown", handleKeydown);
|
|
1355
1428
|
listenerAttached = false;
|
|
1356
1429
|
}
|
|
1357
1430
|
}
|
|
1431
|
+
function open() {
|
|
1432
|
+
setIsOpen(true);
|
|
1433
|
+
attachListener();
|
|
1434
|
+
}
|
|
1435
|
+
function close() {
|
|
1436
|
+
setIsOpen(false);
|
|
1437
|
+
detachListener();
|
|
1438
|
+
}
|
|
1358
1439
|
function toggle() {
|
|
1359
|
-
if (isOpen())
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1440
|
+
if (isOpen()) close();
|
|
1441
|
+
else open();
|
|
1442
|
+
}
|
|
1443
|
+
function dispose() {
|
|
1444
|
+
detachListener();
|
|
1445
|
+
setIsOpen(false);
|
|
1364
1446
|
}
|
|
1365
|
-
return { open, close, isOpen, toggle };
|
|
1447
|
+
return { open, close, isOpen, toggle, dispose };
|
|
1366
1448
|
}
|
|
1367
1449
|
|
|
1368
1450
|
// src/ui/toast.ts
|
package/dist/ui.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { B as BoundFieldProps, C as CustomElementOptions, F as FieldConfig, a as FocusTrap, b as FormConfig, c as FormField, d as FormReturn, I as IntersectionResult, M as MaskOptions, T as Toast, e as ToastInstance, V as ValidatorFn, f as VirtualList, g as VirtualListProps, h as announce, i as aria, j as bindAttrs, k as bindBoolAttr, l as bindData, m as bindField, n as creditCardMask, o as custom, p as dateMask, q as defineElement, r as dialog, s as email, t as eventBus, u as focus, v as form, w as hotkey, x as infiniteScroll, y as inputMask, z as intersection, A as lazyLoad, D as matchesPattern, E as max, G as maxLength, H as min, J as minLength, K as pagination, L as phoneMask, N as removeScopedStyle, O as required, P as scopedStyle, Q as ssnMask, R as svgElement, S as timeMask, U as toast, W as withScopedStyle, X as zipMask } from './customElement-
|
|
2
|
-
export { C as ComponentProps, P as PropDef, a as PropSchema, R as RenderProp, V as Validator, b as assertType, c as compose, d as createGuard, e as createSlots, f as defineComponent, g as defineSlottedComponent, h as defineStrictComponent, v as validateProps, i as validators, w as withBoundary, j as withDefaults, k as withProps, l as withWrapper } from './contracts-
|
|
1
|
+
export { B as BoundFieldProps, C as CustomElementOptions, F as FieldConfig, a as FocusTrap, b as FormConfig, c as FormField, d as FormReturn, I as IntersectionResult, M as MaskOptions, T as Toast, e as ToastInstance, V as ValidatorFn, f as VirtualList, g as VirtualListProps, h as announce, i as aria, j as bindAttrs, k as bindBoolAttr, l as bindData, m as bindField, n as creditCardMask, o as custom, p as dateMask, q as defineElement, r as dialog, s as email, t as eventBus, u as focus, v as form, w as hotkey, x as infiniteScroll, y as inputMask, z as intersection, A as lazyLoad, D as matchesPattern, E as max, G as maxLength, H as min, J as minLength, K as pagination, L as phoneMask, N as removeScopedStyle, O as required, P as scopedStyle, Q as ssnMask, R as svgElement, S as timeMask, U as toast, W as withScopedStyle, X as zipMask } from './customElement-BL3Uo8dL.cjs';
|
|
2
|
+
export { C as ComponentProps, P as PropDef, a as PropSchema, R as RenderProp, V as Validator, b as assertType, c as compose, d as createGuard, e as createSlots, f as defineComponent, g as defineSlottedComponent, h as defineStrictComponent, v as validateProps, i as validators, w as withBoundary, j as withDefaults, k as withProps, l as withWrapper } from './contracts-ey_Qh8ef.cjs';
|
|
3
3
|
|
|
4
4
|
interface FormActionHandle<TArgs extends unknown[], TResult> {
|
|
5
5
|
/** Invoke the action. Rejections become `error()`, resolutions `result()`. */
|
|
@@ -30,14 +30,11 @@ interface FormActionHandle<TArgs extends unknown[], TResult> {
|
|
|
30
30
|
* return res.json();
|
|
31
31
|
* });
|
|
32
32
|
*
|
|
33
|
-
* form({
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* when(() => save.error() != null, () => div({ class: "error", nodes: () => String(save.error()) })),
|
|
39
|
-
* ],
|
|
40
|
-
* });
|
|
33
|
+
* form({ on: { submit: save.onSubmit } }, [
|
|
34
|
+
* input({ name: "title" }),
|
|
35
|
+
* button({ disabled: save.pending }, () => (save.pending() ? "Saving..." : "Save")),
|
|
36
|
+
* when(() => save.error() != null, () => div("error", () => String(save.error()))),
|
|
37
|
+
* ]);
|
|
41
38
|
* ```
|
|
42
39
|
*/
|
|
43
40
|
declare function formAction<TArgs extends unknown[], TResult>(fn: (...args: TArgs) => Promise<TResult>): FormActionHandle<TArgs, TResult>;
|
|
@@ -102,10 +99,10 @@ interface ListboxHandle {
|
|
|
102
99
|
*
|
|
103
100
|
* @example
|
|
104
101
|
* ```ts
|
|
105
|
-
* const container = ul(
|
|
106
|
-
* li({ role: "option", "data-value": "a",
|
|
107
|
-
* li({ role: "option", "data-value": "b",
|
|
108
|
-
* ]
|
|
102
|
+
* const container = ul([
|
|
103
|
+
* li({ role: "option", "data-value": "a" }, "Apple"),
|
|
104
|
+
* li({ role: "option", "data-value": "b" }, "Banana"),
|
|
105
|
+
* ]) as HTMLElement;
|
|
109
106
|
*
|
|
110
107
|
* const lb = createListbox(container, { onSelect: v => console.log(v) });
|
|
111
108
|
* ```
|
|
@@ -142,8 +139,8 @@ interface DialogAriaHandle {
|
|
|
142
139
|
* const dlg = document.createElement("div");
|
|
143
140
|
* const aria = createDialogAria(dlg, { alert: false });
|
|
144
141
|
* dlg.append(
|
|
145
|
-
* h2({ id: aria.titleId,
|
|
146
|
-
* p({ id: aria.descriptionId,
|
|
142
|
+
* h2({ id: aria.titleId }, "Delete?"),
|
|
143
|
+
* p({ id: aria.descriptionId }, "This cannot be undone."),
|
|
147
144
|
* );
|
|
148
145
|
* ```
|
|
149
146
|
*/
|