sibujs 4.1.0 → 4.2.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 +24 -0
- package/dist/browser.cjs +13 -21
- package/dist/browser.js +6 -6
- package/dist/build.cjs +278 -104
- package/dist/build.js +15 -15
- package/dist/cdn.dev.global.js +398 -0
- package/dist/cdn.global.js +10 -10
- package/dist/{chunk-DCDS2PQ6.js → chunk-2LOYNGBY.js} +2 -2
- package/dist/{chunk-VPP2FONR.js → chunk-2WLZ6757.js} +17 -10
- package/dist/{chunk-IM7N5WR4.js → chunk-3VTSPNC5.js} +2 -2
- package/dist/{chunk-TIRZCERI.js → chunk-5DXA2J44.js} +1 -1
- package/dist/{chunk-I3VI34DP.js → chunk-6ZGI3RBE.js} +149 -33
- package/dist/{chunk-D3SZ4LVS.js → chunk-7ALC7KGE.js} +5 -6
- package/dist/{chunk-PFTDGEPZ.js → chunk-7VEC3UD2.js} +3 -3
- package/dist/{chunk-KSOEJGFO.js → chunk-BMYYZWHX.js} +3 -3
- package/dist/{chunk-LOFZHP6V.js → chunk-BNKV4REK.js} +7 -8
- package/dist/{chunk-5GJ5RTHA.js → chunk-FOWBJZDL.js} +7 -8
- package/dist/{chunk-FB7KQXZI.js → chunk-GDUNQCCW.js} +4 -4
- package/dist/{chunk-UFSQEO7P.js → chunk-HECVW343.js} +7 -8
- package/dist/{chunk-SHDVWATN.js → chunk-HJEPKZ2O.js} +7 -8
- package/dist/{chunk-ANGSYNPX.js → chunk-HZEBO22J.js} +57 -37
- package/dist/{chunk-5INI7D2L.js → chunk-IXKSNWV5.js} +74 -11
- package/dist/{chunk-DAKLOMKS.js → chunk-KE4KWRDY.js} +3 -3
- package/dist/{chunk-AW6HPJ3L.js → chunk-KKLW7YWL.js} +1 -1
- package/dist/{chunk-BMSN6NWQ.js → chunk-NEYWS4EX.js} +6 -6
- package/dist/{chunk-HYCCIYNS.js → chunk-NIOYEGBQ.js} +13 -14
- package/dist/{chunk-4U7KD3RY.js → chunk-OUWAIXIK.js} +3 -3
- package/dist/{chunk-MRAMKDHQ.js → chunk-P3DHXBR6.js} +1 -1
- package/dist/{chunk-FMHIQNMP.js → chunk-QCFLDD7C.js} +5 -5
- package/dist/{chunk-DHDZ7IVN.js → chunk-QKRPLZ2V.js} +7 -8
- package/dist/{chunk-4RH6D7GR.js → chunk-QL4UREZO.js} +6 -6
- package/dist/{chunk-XIHMS2Y6.js → chunk-SF3TB4K6.js} +8 -8
- package/dist/{chunk-XSZRJW76.js → chunk-XZ2N525U.js} +6 -6
- package/dist/{customElement-CKLoO63w.d.ts → customElement-CNZxEB9G.d.cts} +77 -0
- package/dist/{customElement-CKLoO63w.d.cts → customElement-CNZxEB9G.d.ts} +77 -0
- package/dist/data.cjs +15 -24
- package/dist/data.js +9 -9
- package/dist/devtools.cjs +18 -22
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +8 -8
- package/dist/{dispose-4FZ6OFXR.js → dispose-46BOMMQJ.js} +2 -2
- package/dist/ecosystem.cjs +222 -67
- package/dist/ecosystem.js +11 -11
- package/dist/extras.cjs +243 -86
- package/dist/extras.d.cts +2 -2
- package/dist/extras.d.ts +2 -2
- package/dist/extras.js +25 -25
- package/dist/index.cjs +272 -98
- package/dist/index.d.cts +154 -33
- package/dist/index.d.ts +154 -33
- package/dist/index.js +15 -15
- package/dist/{introspect-RjLfIFpL.d.cts → introspect-D5xF-0Es.d.cts} +7 -0
- package/dist/{introspect-DOZfmC-4.d.ts → introspect-rSBIxEQi.d.ts} +7 -0
- package/dist/motion.cjs +13 -22
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +16 -24
- package/dist/patterns.d.cts +8 -0
- package/dist/patterns.d.ts +8 -0
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +16 -27
- package/dist/performance.js +9 -9
- package/dist/plugins.cjs +260 -86
- package/dist/plugins.d.cts +92 -0
- package/dist/plugins.d.ts +92 -0
- package/dist/plugins.js +18 -17
- package/dist/{ssr-JFP5535P.js → ssr-Y7XOEPEN.js} +5 -5
- package/dist/ssr.cjs +233 -79
- package/dist/ssr.js +12 -12
- package/dist/testing.cjs +11 -19
- package/dist/testing.js +5 -5
- package/dist/ui.cjs +98 -43
- package/dist/ui.d.cts +7 -1
- package/dist/ui.d.ts +7 -1
- package/dist/ui.js +10 -10
- package/dist/widgets.cjs +13 -21
- package/dist/widgets.d.cts +8 -0
- package/dist/widgets.d.ts +8 -0
- package/dist/widgets.js +9 -9
- package/package.json +5 -2
package/dist/build.cjs
CHANGED
|
@@ -161,15 +161,15 @@ function parseTemplateLiteral(code2, openBacktick) {
|
|
|
161
161
|
return null;
|
|
162
162
|
}
|
|
163
163
|
function skipString(code2, start) {
|
|
164
|
-
const
|
|
164
|
+
const quote2 = code2[start];
|
|
165
165
|
let pos = start + 1;
|
|
166
166
|
while (pos < code2.length) {
|
|
167
167
|
if (code2[pos] === "\\") {
|
|
168
168
|
pos += 2;
|
|
169
169
|
continue;
|
|
170
170
|
}
|
|
171
|
-
if (code2[pos] ===
|
|
172
|
-
if (
|
|
171
|
+
if (code2[pos] === quote2) return pos + 1;
|
|
172
|
+
if (quote2 === "`" && code2[pos] === "$" && code2[pos + 1] === "{") {
|
|
173
173
|
pos += 2;
|
|
174
174
|
let depth = 1;
|
|
175
175
|
while (pos < code2.length && depth > 0) {
|
|
@@ -225,12 +225,12 @@ function parseTemplateToAST(strings) {
|
|
|
225
225
|
skipWs();
|
|
226
226
|
const exprIdx = tryExprIdx();
|
|
227
227
|
if (exprIdx >= 0) return { kind: "expr", index: exprIdx };
|
|
228
|
-
const
|
|
229
|
-
if (
|
|
228
|
+
const quote2 = template2[pos];
|
|
229
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
230
230
|
pos++;
|
|
231
231
|
const parts = [];
|
|
232
232
|
let current = "";
|
|
233
|
-
while (pos < len && template2[pos] !==
|
|
233
|
+
while (pos < len && template2[pos] !== quote2) {
|
|
234
234
|
const innerIdx = tryExprIdx();
|
|
235
235
|
if (innerIdx >= 0) {
|
|
236
236
|
if (current) parts.push({ kind: "static", value: current });
|
|
@@ -1382,23 +1382,28 @@ function reportError(error, context2) {
|
|
|
1382
1382
|
}
|
|
1383
1383
|
|
|
1384
1384
|
// src/core/dev.ts
|
|
1385
|
+
var DEV = typeof __SIBU_DEV__ !== "undefined" ? !!__SIBU_DEV__ : typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
|
|
1386
|
+
// safe default: off in browser, on in test/dev Node
|
|
1387
|
+
typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
1388
|
+
);
|
|
1385
1389
|
function isDev() {
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
// this branch is unreachable here.
|
|
1390
|
-
/* v8 ignore next 2 */
|
|
1391
|
-
typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
1392
|
-
);
|
|
1390
|
+
if (typeof globalThis.__SIBU_DEV__ !== "undefined") return !!globalThis.__SIBU_DEV__;
|
|
1391
|
+
if (typeof __SIBU_DEV__ !== "undefined") return !!__SIBU_DEV__;
|
|
1392
|
+
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
1393
1393
|
}
|
|
1394
|
-
var _isDev = isDev();
|
|
1395
1394
|
function devAssert(condition, message) {
|
|
1396
|
-
if (
|
|
1395
|
+
if ((typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) && !condition) {
|
|
1397
1396
|
throw new Error(`[SibuJS] ${message}`);
|
|
1398
1397
|
}
|
|
1399
1398
|
}
|
|
1399
|
+
function devWarnLazy(build) {
|
|
1400
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
1401
|
+
const message = build();
|
|
1402
|
+
if (message) console.warn(`[SibuJS] ${message}`);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1400
1405
|
function devWarn(message) {
|
|
1401
|
-
if (
|
|
1406
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
1402
1407
|
console.warn(`[SibuJS] ${message}`);
|
|
1403
1408
|
}
|
|
1404
1409
|
}
|
|
@@ -1413,7 +1418,6 @@ function reportDrainRunaway(label2, executed, remaining) {
|
|
|
1413
1418
|
{ executed, remaining }
|
|
1414
1419
|
);
|
|
1415
1420
|
}
|
|
1416
|
-
var _isDev2 = isDev();
|
|
1417
1421
|
var activeBindingCount = 0;
|
|
1418
1422
|
function registerDisposer(node, teardown) {
|
|
1419
1423
|
let disposers = elementDisposers.get(node);
|
|
@@ -1422,7 +1426,7 @@ function registerDisposer(node, teardown) {
|
|
|
1422
1426
|
elementDisposers.set(node, disposers);
|
|
1423
1427
|
}
|
|
1424
1428
|
disposers.push(teardown);
|
|
1425
|
-
if (
|
|
1429
|
+
if (DEV) activeBindingCount++;
|
|
1426
1430
|
}
|
|
1427
1431
|
function unregisterDisposer(node, teardown) {
|
|
1428
1432
|
const disposers = elementDisposers.get(node);
|
|
@@ -1430,7 +1434,7 @@ function unregisterDisposer(node, teardown) {
|
|
|
1430
1434
|
const index = disposers.indexOf(teardown);
|
|
1431
1435
|
if (index === -1) return;
|
|
1432
1436
|
disposers.splice(index, 1);
|
|
1433
|
-
if (
|
|
1437
|
+
if (DEV) activeBindingCount--;
|
|
1434
1438
|
if (disposers.length === 0) elementDisposers.delete(node);
|
|
1435
1439
|
}
|
|
1436
1440
|
function dispose(node) {
|
|
@@ -1454,13 +1458,13 @@ function dispose(node) {
|
|
|
1454
1458
|
if (!pending || pending.length === 0) break;
|
|
1455
1459
|
const snapshot = pending.slice();
|
|
1456
1460
|
elementDisposers.delete(current);
|
|
1457
|
-
if (
|
|
1461
|
+
if (DEV) activeBindingCount -= snapshot.length;
|
|
1458
1462
|
for (let i3 = 0; i3 < snapshot.length; i3++) {
|
|
1459
1463
|
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
1460
1464
|
const rest = snapshot.slice(i3);
|
|
1461
1465
|
const added = elementDisposers.get(current);
|
|
1462
1466
|
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
1463
|
-
if (
|
|
1467
|
+
if (DEV) activeBindingCount += rest.length;
|
|
1464
1468
|
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
1465
1469
|
runaway = true;
|
|
1466
1470
|
break;
|
|
@@ -1488,7 +1492,7 @@ function replaceChildrenSafely(parent, ...next) {
|
|
|
1488
1492
|
parent.replaceChildren(...next);
|
|
1489
1493
|
}
|
|
1490
1494
|
function checkLeaks(warnThreshold = 0) {
|
|
1491
|
-
if (!
|
|
1495
|
+
if (!DEV) return 0;
|
|
1492
1496
|
if (warnThreshold > 0 && activeBindingCount > warnThreshold) {
|
|
1493
1497
|
devWarn(
|
|
1494
1498
|
`checkLeaks: ${activeBindingCount} active DOM bindings detected. Expected \u2264${warnThreshold}. This may indicate a component was removed from the DOM without calling dispose().`
|
|
@@ -1590,20 +1594,75 @@ function decodeCssEscapes(value) {
|
|
|
1590
1594
|
}
|
|
1591
1595
|
return out;
|
|
1592
1596
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1597
|
+
var BLOCKED_CSS_NEEDLES = [
|
|
1598
|
+
"url(",
|
|
1599
|
+
"expression(",
|
|
1600
|
+
"javascript:",
|
|
1601
|
+
"vbscript:",
|
|
1602
|
+
"-moz-binding",
|
|
1603
|
+
"behavior:",
|
|
1604
|
+
"@import",
|
|
1605
|
+
"image-set(",
|
|
1606
|
+
"filter:progid"
|
|
1607
|
+
];
|
|
1608
|
+
function describeElement(el) {
|
|
1609
|
+
if (!el) return "an element";
|
|
1610
|
+
let out = el.tagName.toLowerCase();
|
|
1611
|
+
const id = el.getAttribute("id");
|
|
1612
|
+
if (id) out += `#${id}`;
|
|
1613
|
+
const cls = el.getAttribute("class");
|
|
1614
|
+
if (cls) out += `.${cls.trim().split(/\s+/).slice(0, 3).join(".")}`;
|
|
1615
|
+
return `<${out}>`;
|
|
1616
|
+
}
|
|
1617
|
+
var warnedDeclarations = /* @__PURE__ */ new Set();
|
|
1618
|
+
var MAX_WARNED_DECLARATIONS = 100;
|
|
1619
|
+
var declarationCapAnnounced = false;
|
|
1620
|
+
function warnDroppedDeclaration(value, reason, ctx) {
|
|
1621
|
+
devWarnLazy(() => {
|
|
1622
|
+
const reasons = [
|
|
1623
|
+
"url() in an inline style is an exfiltration channel: the browser fetches it immediately and the URL's path or query can carry page data off-origin",
|
|
1624
|
+
"expression() executes arbitrary script in legacy engines",
|
|
1625
|
+
"the javascript: scheme executes script",
|
|
1626
|
+
"the vbscript: scheme executes script",
|
|
1627
|
+
"-moz-binding loads and runs remote XBL",
|
|
1628
|
+
"behavior: loads and runs a remote HTC script",
|
|
1629
|
+
"@import pulls in a remote stylesheet",
|
|
1630
|
+
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
1631
|
+
"filter:progid activates legacy scriptable filters"
|
|
1632
|
+
];
|
|
1633
|
+
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
1634
|
+
const where = describeElement(ctx?.element);
|
|
1635
|
+
const key = `${where}|${declaration}`;
|
|
1636
|
+
if (warnedDeclarations.has(key)) return "";
|
|
1637
|
+
if (warnedDeclarations.size >= MAX_WARNED_DECLARATIONS) {
|
|
1638
|
+
if (declarationCapAnnounced) return "";
|
|
1639
|
+
declarationCapAnnounced = true;
|
|
1640
|
+
return `${MAX_WARNED_DECLARATIONS} distinct dropped style declarations have been reported; suppressing further ones for the rest of this session so they cannot flood the console. The declarations are still dropped \u2014 only the reporting stops. Fix the reported ones and reload to see any that remain.`;
|
|
1641
|
+
}
|
|
1642
|
+
warnedDeclarations.add(key);
|
|
1643
|
+
return `style declaration "${declaration}" was dropped by the style sanitizer on ${where} \u2014 ${reasons[reason]}. The element renders without it, which usually looks like a missing image rather than an error. Sanctioned alternatives: for a content image use an <img> element (or a <picture>); for decoration, put the rule in a stylesheet and set a class instead \u2014 stylesheet CSS is not sanitized, only inline style attributes are. If this declaration is not yours, it came from untrusted data and the drop just prevented an exfiltration.`;
|
|
1644
|
+
});
|
|
1645
|
+
}
|
|
1646
|
+
function blockedCssReason(value) {
|
|
1647
|
+
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
1595
1648
|
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
1596
1649
|
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
1597
|
-
|
|
1598
|
-
return
|
|
1650
|
+
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
1651
|
+
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
1599
1652
|
}
|
|
1600
|
-
return
|
|
1653
|
+
return -1;
|
|
1654
|
+
}
|
|
1655
|
+
function sanitizeCSSValue(value, context2) {
|
|
1656
|
+
const reason = blockedCssReason(value);
|
|
1657
|
+
if (reason === -1) return value;
|
|
1658
|
+
warnDroppedDeclaration(value, reason, context2);
|
|
1659
|
+
return "";
|
|
1601
1660
|
}
|
|
1602
|
-
function sanitizeStyleAttribute(cssText) {
|
|
1661
|
+
function sanitizeStyleAttribute(cssText, context2) {
|
|
1603
1662
|
const input2 = String(cssText);
|
|
1604
1663
|
if (input2.trim() === "") return "";
|
|
1605
1664
|
if (typeof document === "undefined") {
|
|
1606
|
-
return sanitizeCSSValue(input2) === "" ? "" : input2;
|
|
1665
|
+
return sanitizeCSSValue(input2, context2) === "" ? "" : input2;
|
|
1607
1666
|
}
|
|
1608
1667
|
const probe = document.createElement("div");
|
|
1609
1668
|
try {
|
|
@@ -1615,8 +1674,12 @@ function sanitizeStyleAttribute(cssText) {
|
|
|
1615
1674
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
1616
1675
|
const property = probe.style[i2];
|
|
1617
1676
|
const value = probe.style.getPropertyValue(property);
|
|
1618
|
-
|
|
1619
|
-
if (
|
|
1677
|
+
let reason = blockedCssReason(value);
|
|
1678
|
+
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
1679
|
+
if (reason !== -1) {
|
|
1680
|
+
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
1681
|
+
continue;
|
|
1682
|
+
}
|
|
1620
1683
|
const priority = probe.style.getPropertyPriority(property);
|
|
1621
1684
|
declarations.push(`${property}: ${value}${priority ? ` !${priority}` : ""}`);
|
|
1622
1685
|
}
|
|
@@ -1644,16 +1707,15 @@ var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
|
1644
1707
|
function isHtmlContentAttribute(name) {
|
|
1645
1708
|
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
1646
1709
|
}
|
|
1647
|
-
function sanitizeAttributeString(attr, value) {
|
|
1710
|
+
function sanitizeAttributeString(attr, value, context2) {
|
|
1648
1711
|
const lower = attr.toLowerCase();
|
|
1649
1712
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
1650
1713
|
if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
|
|
1651
|
-
if (lower === "style") return sanitizeStyleAttribute(value);
|
|
1714
|
+
if (lower === "style") return sanitizeStyleAttribute(value, context2);
|
|
1652
1715
|
return value;
|
|
1653
1716
|
}
|
|
1654
1717
|
|
|
1655
1718
|
// src/utils/setSafeAttribute.ts
|
|
1656
|
-
var _isDev3 = isDev();
|
|
1657
1719
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
1658
1720
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
1659
1721
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
@@ -1676,7 +1738,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1676
1738
|
const ns = namespaceFor(el, name);
|
|
1677
1739
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
1678
1740
|
if (isEventHandlerAttr(name)) {
|
|
1679
|
-
if (
|
|
1741
|
+
if (DEV) {
|
|
1680
1742
|
devWarn(
|
|
1681
1743
|
`${options.label ?? "setSafeAttribute"}: refusing to set event-handler attribute "${name}". Its value would be evaluated as JavaScript. Use on:{ ${name.slice(2)}: fn } instead.`
|
|
1682
1744
|
);
|
|
@@ -1691,7 +1753,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1691
1753
|
return true;
|
|
1692
1754
|
}
|
|
1693
1755
|
if (isHtmlContentAttribute(name)) {
|
|
1694
|
-
if (
|
|
1756
|
+
if (DEV) {
|
|
1695
1757
|
devWarn(
|
|
1696
1758
|
`${options.label ?? "setSafeAttribute"}: refusing to set "${name}". The browser parses this attribute as a nested HTML document, so a generic string value cannot be made safe \u2014 attribute escaping is undone before the parse. Build the frame's content another way.`
|
|
1697
1759
|
);
|
|
@@ -1720,7 +1782,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1720
1782
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
1721
1783
|
return true;
|
|
1722
1784
|
}
|
|
1723
|
-
const safe = sanitizeAttributeString(name, str);
|
|
1785
|
+
const safe = sanitizeAttributeString(name, str, { element: el });
|
|
1724
1786
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
1725
1787
|
if (current === safe) return true;
|
|
1726
1788
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -2184,17 +2246,16 @@ function forEachSubscriber(signal2, visit) {
|
|
|
2184
2246
|
}
|
|
2185
2247
|
|
|
2186
2248
|
// src/reactivity/track.ts
|
|
2187
|
-
var
|
|
2188
|
-
var _runtimeVersion = true ? "4.1.0" : "dev";
|
|
2249
|
+
var _runtimeVersion = true ? "4.2.0" : "dev";
|
|
2189
2250
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
2190
2251
|
function resolveReactiveApi() {
|
|
2191
2252
|
const g2 = globalThis;
|
|
2192
2253
|
const existing = g2[REGISTRY_KEY];
|
|
2193
2254
|
if (existing) {
|
|
2194
|
-
if (
|
|
2255
|
+
if (DEV && !existing.__dupWarned) {
|
|
2195
2256
|
existing.__dupWarned = true;
|
|
2196
2257
|
devWarn(
|
|
2197
|
-
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity
|
|
2258
|
+
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity is NOT broken and no bundler configuration is required: every copy routes through the first one via a global registry, so signal writes still reach subscribers registered by any copy. This is only a SIZE issue \u2014 the duplicate copy's bytes are downloaded and parsed for nothing. If you want them back, de-duplicate sibujs in your bundler (Vite: resolve.dedupe: ['sibujs']). Mismatched VERSIONS above are worth fixing regardless, since only the first one loaded is used.`
|
|
2198
2259
|
);
|
|
2199
2260
|
}
|
|
2200
2261
|
return existing;
|
|
@@ -2293,8 +2354,101 @@ function bindDynamic(el, nameGetter, valueGetter) {
|
|
|
2293
2354
|
};
|
|
2294
2355
|
}
|
|
2295
2356
|
|
|
2357
|
+
// src/core/rendering/focusPreservation.ts
|
|
2358
|
+
var IDENTITY_ATTRS = ["data-focus-key", "id", "name"];
|
|
2359
|
+
var SELECTABLE_TYPES = /* @__PURE__ */ new Set(["text", "search", "url", "tel", "password", ""]);
|
|
2360
|
+
function selectionOf(el) {
|
|
2361
|
+
const tag = el.tagName;
|
|
2362
|
+
const selectable = tag === "TEXTAREA" || tag === "INPUT" && SELECTABLE_TYPES.has(el.type.toLowerCase());
|
|
2363
|
+
if (!selectable) return { start: null, end: null, direction: null };
|
|
2364
|
+
const field = el;
|
|
2365
|
+
return { start: field.selectionStart, end: field.selectionEnd, direction: field.selectionDirection };
|
|
2366
|
+
}
|
|
2367
|
+
function captureFocusWithin(nodes) {
|
|
2368
|
+
if (nodes.length === 0 || typeof document === "undefined") return null;
|
|
2369
|
+
const active = document.activeElement;
|
|
2370
|
+
if (!active || active === document.body) return null;
|
|
2371
|
+
let inside = false;
|
|
2372
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
2373
|
+
const n = nodes[i2];
|
|
2374
|
+
if (n === active || n.nodeType === 1 && n.contains(active)) {
|
|
2375
|
+
inside = true;
|
|
2376
|
+
break;
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
if (!inside) return null;
|
|
2380
|
+
let attr = null;
|
|
2381
|
+
let value = null;
|
|
2382
|
+
for (let i2 = 0; i2 < IDENTITY_ATTRS.length; i2++) {
|
|
2383
|
+
const candidate = active.getAttribute(IDENTITY_ATTRS[i2]);
|
|
2384
|
+
if (candidate) {
|
|
2385
|
+
attr = IDENTITY_ATTRS[i2];
|
|
2386
|
+
value = candidate;
|
|
2387
|
+
break;
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
return { el: active, attr, value, tag: active.tagName, ...selectionOf(active) };
|
|
2391
|
+
}
|
|
2392
|
+
function quote(value) {
|
|
2393
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
2394
|
+
}
|
|
2395
|
+
function findUniqueByIdentity(nodes, selector) {
|
|
2396
|
+
let el = null;
|
|
2397
|
+
let count = 0;
|
|
2398
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
2399
|
+
const n = nodes[i2];
|
|
2400
|
+
if (n.nodeType !== 1) continue;
|
|
2401
|
+
const root = n;
|
|
2402
|
+
if (root.matches(selector)) {
|
|
2403
|
+
count++;
|
|
2404
|
+
el ?? (el = root);
|
|
2405
|
+
}
|
|
2406
|
+
const inner = root.querySelectorAll(selector);
|
|
2407
|
+
for (let j = 0; j < inner.length; j++) {
|
|
2408
|
+
count++;
|
|
2409
|
+
el ?? (el = inner[j]);
|
|
2410
|
+
}
|
|
2411
|
+
if (count > 1) return { el: null, count };
|
|
2412
|
+
}
|
|
2413
|
+
return count === 1 ? { el, count } : { el: null, count };
|
|
2414
|
+
}
|
|
2415
|
+
function refocus(el, snapshot) {
|
|
2416
|
+
el.focus();
|
|
2417
|
+
if (snapshot.start !== null && typeof el.setSelectionRange === "function") {
|
|
2418
|
+
const field = el;
|
|
2419
|
+
const max = field.value.length;
|
|
2420
|
+
const start = Math.min(snapshot.start, max);
|
|
2421
|
+
const end = Math.min(snapshot.end ?? start, max);
|
|
2422
|
+
field.setSelectionRange(start, end, snapshot.direction ?? "none");
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
function restoreFocusWithin(snapshot, nodes, where) {
|
|
2426
|
+
if (!snapshot) return;
|
|
2427
|
+
if (typeof document === "undefined") return;
|
|
2428
|
+
const active = document.activeElement;
|
|
2429
|
+
if (active === snapshot.el) return;
|
|
2430
|
+
if (active && active !== document.body && active !== document.documentElement) return;
|
|
2431
|
+
if (snapshot.el.isConnected) {
|
|
2432
|
+
refocus(snapshot.el, snapshot);
|
|
2433
|
+
return;
|
|
2434
|
+
}
|
|
2435
|
+
let ambiguous = false;
|
|
2436
|
+
if (snapshot.attr && snapshot.value) {
|
|
2437
|
+
const { el: replacement, count } = findUniqueByIdentity(nodes, `[${snapshot.attr}=${quote(snapshot.value)}]`);
|
|
2438
|
+
if (replacement && replacement.tagName === snapshot.tag) {
|
|
2439
|
+
refocus(replacement, snapshot);
|
|
2440
|
+
return;
|
|
2441
|
+
}
|
|
2442
|
+
ambiguous = count > 1;
|
|
2443
|
+
}
|
|
2444
|
+
devWarnLazy(() => {
|
|
2445
|
+
const id = snapshot.attr ? ` (${snapshot.attr}="${snapshot.value}")` : "";
|
|
2446
|
+
const why = ambiguous ? `several elements in the rebuilt subtree share ${snapshot.attr}="${snapshot.value}", so there is no way to tell which one the user was in \u2014 a shared name (a radio group) identifies a GROUP, not a control. Add a unique id or data-focus-key to each` : "no element in the rebuilt subtree carries the same identity. Give it a stable id, name, or data-focus-key that the rebuild reproduces";
|
|
2447
|
+
return `${where}: a reactive rebuild discarded the focused element <${snapshot.tag.toLowerCase()}>${id} and could not re-establish it, so focus fell back to <body>. An in-progress edit ends here, and an in-progress IME composition is lost outright \u2014 a composition belongs to the DOM node, so it cannot survive the node being destroyed. ${why}, or stop the rebuild from happening: key the subtree with match(() => shapeKey(), { \u2026 }) so it is re-created only when the shape actually changes, and drive the rest with reactive attributes and text children, which mutate nodes in place instead of replacing them.`;
|
|
2448
|
+
});
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2296
2451
|
// src/reactivity/bindChildNode.ts
|
|
2297
|
-
var _isDev5 = isDev();
|
|
2298
2452
|
function bindChildNode(placeholder, getter) {
|
|
2299
2453
|
let lastNodes = [];
|
|
2300
2454
|
function commit() {
|
|
@@ -2305,6 +2459,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2305
2459
|
reportError(err, { phase: "binding", name: "bindChildNode", node: placeholder });
|
|
2306
2460
|
return;
|
|
2307
2461
|
}
|
|
2462
|
+
const focused = captureFocusWithin(lastNodes);
|
|
2308
2463
|
if (result == null || typeof result === "boolean") {
|
|
2309
2464
|
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
2310
2465
|
const node = lastNodes[i2];
|
|
@@ -2312,6 +2467,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2312
2467
|
if (node.parentNode) node.parentNode.removeChild(node);
|
|
2313
2468
|
}
|
|
2314
2469
|
lastNodes.length = 0;
|
|
2470
|
+
restoreFocusWithin(focused, lastNodes, "bindChildNode");
|
|
2315
2471
|
return;
|
|
2316
2472
|
}
|
|
2317
2473
|
const parent = placeholder.parentNode;
|
|
@@ -2328,8 +2484,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2328
2484
|
if (item == null || typeof item === "boolean") continue;
|
|
2329
2485
|
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
2330
2486
|
if (seen.has(node)) {
|
|
2331
|
-
if (
|
|
2332
|
-
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
2487
|
+
if (DEV) devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
2333
2488
|
continue;
|
|
2334
2489
|
}
|
|
2335
2490
|
seen.add(node);
|
|
@@ -2362,13 +2517,13 @@ function bindChildNode(placeholder, getter) {
|
|
|
2362
2517
|
prev = node;
|
|
2363
2518
|
}
|
|
2364
2519
|
lastNodes = newNodes;
|
|
2520
|
+
restoreFocusWithin(focused, newNodes, "bindChildNode");
|
|
2365
2521
|
}
|
|
2366
2522
|
return reactiveBinding2(commit, placeholder);
|
|
2367
2523
|
}
|
|
2368
2524
|
|
|
2369
2525
|
// src/core/rendering/tagFactory.ts
|
|
2370
2526
|
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2371
|
-
var _isDev6 = isDev();
|
|
2372
2527
|
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
2373
2528
|
function isBlockedTag(tag) {
|
|
2374
2529
|
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
@@ -2386,18 +2541,9 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
|
2386
2541
|
"self",
|
|
2387
2542
|
"frames"
|
|
2388
2543
|
]);
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
const tokens = t.split(/\s+/);
|
|
2393
|
-
let sawClassish = false;
|
|
2394
|
-
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
2395
|
-
const tok = tokens[i2];
|
|
2396
|
-
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return false;
|
|
2397
|
-
if (/[-:/0-9]/.test(tok)) sawClassish = true;
|
|
2398
|
-
}
|
|
2399
|
-
return sawClassish;
|
|
2400
|
-
}
|
|
2544
|
+
var warnedLoneStrings = /* @__PURE__ */ new Set();
|
|
2545
|
+
var MAX_WARNED_LONE_STRINGS = 100;
|
|
2546
|
+
var loneStringCapAnnounced = false;
|
|
2401
2547
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
2402
2548
|
function toKebab(prop) {
|
|
2403
2549
|
let cached = kebabCache.get(prop);
|
|
@@ -2409,13 +2555,13 @@ function toKebab(prop) {
|
|
|
2409
2555
|
function applyStyle(el, style2) {
|
|
2410
2556
|
if (typeof style2 === "function") {
|
|
2411
2557
|
const teardown = reactiveBinding2(() => {
|
|
2412
|
-
el.setAttribute("style", sanitizeStyleAttribute(String(style2())));
|
|
2558
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(style2()), { element: el }));
|
|
2413
2559
|
}, el);
|
|
2414
2560
|
registerDisposer(el, teardown);
|
|
2415
2561
|
return;
|
|
2416
2562
|
}
|
|
2417
2563
|
if (typeof style2 === "string") {
|
|
2418
|
-
el.setAttribute("style", sanitizeStyleAttribute(style2));
|
|
2564
|
+
el.setAttribute("style", sanitizeStyleAttribute(style2, { element: el }));
|
|
2419
2565
|
return;
|
|
2420
2566
|
}
|
|
2421
2567
|
const htmlEl = el;
|
|
@@ -2425,11 +2571,11 @@ function applyStyle(el, style2) {
|
|
|
2425
2571
|
if (typeof val === "function") {
|
|
2426
2572
|
const getter = val;
|
|
2427
2573
|
const teardown = reactiveBinding2(() => {
|
|
2428
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
|
|
2574
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter()), { property: name, element: el }));
|
|
2429
2575
|
}, el);
|
|
2430
2576
|
registerDisposer(el, teardown);
|
|
2431
2577
|
} else {
|
|
2432
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
|
|
2578
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
|
|
2433
2579
|
}
|
|
2434
2580
|
}
|
|
2435
2581
|
}
|
|
@@ -2536,11 +2682,26 @@ var tagFactory = (tag, ns) => {
|
|
|
2536
2682
|
appendChildren(el, second);
|
|
2537
2683
|
return el;
|
|
2538
2684
|
}
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2685
|
+
devWarnLazy(() => {
|
|
2686
|
+
const tokens = first.trim().split(/\s+/);
|
|
2687
|
+
if (tokens.length < 2) return "";
|
|
2688
|
+
let utilityTokens = 0;
|
|
2689
|
+
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
2690
|
+
const tok = tokens[i2];
|
|
2691
|
+
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return "";
|
|
2692
|
+
if (/[-:/0-9]/.test(tok)) utilityTokens++;
|
|
2693
|
+
}
|
|
2694
|
+
if (utilityTokens < 2) return "";
|
|
2695
|
+
const key = `${tag}|${first}`;
|
|
2696
|
+
if (warnedLoneStrings.has(key)) return "";
|
|
2697
|
+
if (warnedLoneStrings.size >= MAX_WARNED_LONE_STRINGS) {
|
|
2698
|
+
if (loneStringCapAnnounced) return "";
|
|
2699
|
+
loneStringCapAnnounced = true;
|
|
2700
|
+
return `tagFactory: ${MAX_WARNED_LONE_STRINGS} distinct lone-string class warnings have been reported; suppressing further ones for the rest of this session so they cannot flood the console. Fix the reported ones and reload to see any that remain.`;
|
|
2701
|
+
}
|
|
2702
|
+
warnedLoneStrings.add(key);
|
|
2703
|
+
return `tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`;
|
|
2704
|
+
});
|
|
2544
2705
|
el.textContent = first;
|
|
2545
2706
|
return el;
|
|
2546
2707
|
}
|
|
@@ -2557,7 +2718,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2557
2718
|
if (pClass != null) applyClass(el, pClass);
|
|
2558
2719
|
const pId = props.id;
|
|
2559
2720
|
if (pId != null) {
|
|
2560
|
-
if (
|
|
2721
|
+
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
2561
2722
|
devWarn(
|
|
2562
2723
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
2563
2724
|
);
|
|
@@ -2572,7 +2733,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2572
2733
|
const handler = pOn[ev];
|
|
2573
2734
|
if (typeof handler === "function") {
|
|
2574
2735
|
el.addEventListener(ev, handler);
|
|
2575
|
-
} else if (
|
|
2736
|
+
} else if (DEV) {
|
|
2576
2737
|
devWarn(
|
|
2577
2738
|
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
2578
2739
|
);
|
|
@@ -3371,7 +3532,6 @@ var isBatching = API2.isBatching;
|
|
|
3371
3532
|
|
|
3372
3533
|
// src/core/signals/signal.ts
|
|
3373
3534
|
var _g2 = globalThis;
|
|
3374
|
-
var _isDev7 = isDev();
|
|
3375
3535
|
function signal(initial, options) {
|
|
3376
3536
|
const state2 = {
|
|
3377
3537
|
value: initial,
|
|
@@ -3384,7 +3544,7 @@ function signal(initial, options) {
|
|
|
3384
3544
|
_d: false,
|
|
3385
3545
|
_validate: void 0
|
|
3386
3546
|
};
|
|
3387
|
-
const debugName =
|
|
3547
|
+
const debugName = DEV ? options?.name : void 0;
|
|
3388
3548
|
const equalsFn = options?.equals;
|
|
3389
3549
|
if (debugName) state2.__name = debugName;
|
|
3390
3550
|
function get() {
|
|
@@ -3401,7 +3561,7 @@ function signal(initial, options) {
|
|
|
3401
3561
|
if (equalsFn(prev, newValue)) return;
|
|
3402
3562
|
state2.value = newValue;
|
|
3403
3563
|
state2.__v++;
|
|
3404
|
-
if (
|
|
3564
|
+
if (DEV) {
|
|
3405
3565
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
3406
3566
|
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
3407
3567
|
}
|
|
@@ -3409,7 +3569,7 @@ function signal(initial, options) {
|
|
|
3409
3569
|
notifySubscribers2(state2);
|
|
3410
3570
|
}
|
|
3411
3571
|
};
|
|
3412
|
-
} else if (
|
|
3572
|
+
} else if (DEV) {
|
|
3413
3573
|
set = (next) => {
|
|
3414
3574
|
const prev = state2.value;
|
|
3415
3575
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
@@ -3434,7 +3594,7 @@ function signal(initial, options) {
|
|
|
3434
3594
|
}
|
|
3435
3595
|
};
|
|
3436
3596
|
}
|
|
3437
|
-
if (
|
|
3597
|
+
if (DEV) {
|
|
3438
3598
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
3439
3599
|
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
3440
3600
|
}
|
|
@@ -4426,11 +4586,10 @@ function setGlobalErrorHandler(handler) {
|
|
|
4426
4586
|
}
|
|
4427
4587
|
|
|
4428
4588
|
// src/core/rendering/context.ts
|
|
4429
|
-
var _isDev8 = isDev();
|
|
4430
4589
|
function context(defaultValue) {
|
|
4431
4590
|
const [getValue, setValue] = signal(defaultValue);
|
|
4432
4591
|
const warnIfSSR = (method) => {
|
|
4433
|
-
if (!
|
|
4592
|
+
if (!DEV || !isSSR()) return;
|
|
4434
4593
|
devWarn(
|
|
4435
4594
|
`context.${method}() called during SSR. SibuJS context() is application-global \u2014 it is NOT isolated per request, so a concurrent request can observe this value. Do not use context() for request-specific SSR data; pass it explicitly or use request-scoped storage instead.`
|
|
4436
4595
|
);
|
|
@@ -4458,7 +4617,7 @@ function context(defaultValue) {
|
|
|
4458
4617
|
setValue(value);
|
|
4459
4618
|
try {
|
|
4460
4619
|
const result = fn();
|
|
4461
|
-
if (
|
|
4620
|
+
if (DEV && result !== null && typeof result?.then === "function") {
|
|
4462
4621
|
devWarn(
|
|
4463
4622
|
"context.withContext() received an async callback. Scoping is synchronous only \u2014 the previous value is restored as soon as the callback returns its promise, so anything after an `await` runs outside the scope."
|
|
4464
4623
|
);
|
|
@@ -4485,34 +4644,53 @@ function __resetIdCounter() {
|
|
|
4485
4644
|
|
|
4486
4645
|
// src/core/rendering/directives.ts
|
|
4487
4646
|
function show(condition, element) {
|
|
4647
|
+
const resolved = typeof element === "function" ? element() : element;
|
|
4488
4648
|
const update = () => {
|
|
4489
|
-
|
|
4649
|
+
resolved.style.display = condition() ? "" : "none";
|
|
4490
4650
|
};
|
|
4491
|
-
registerDisposer(
|
|
4492
|
-
return
|
|
4651
|
+
registerDisposer(resolved, track2(update));
|
|
4652
|
+
return resolved;
|
|
4653
|
+
}
|
|
4654
|
+
function attachBranch(parent, anchor, branch, attachedOnce, where) {
|
|
4655
|
+
const result = typeof branch === "function" ? branch() : branch;
|
|
4656
|
+
if (result == null || typeof result === "boolean") return { node: null, owned: false };
|
|
4657
|
+
const node = result instanceof Node ? result : document.createTextNode(String(result));
|
|
4658
|
+
const handedIn = node === branch;
|
|
4659
|
+
const seenBefore = attachedOnce.has(node);
|
|
4660
|
+
const owned = !handedIn && !seenBefore;
|
|
4661
|
+
attachedOnce.add(node);
|
|
4662
|
+
if (seenBefore) {
|
|
4663
|
+
devWarnLazy(
|
|
4664
|
+
() => `${where}: ${handedIn ? "a branch was given as an element rather than a function" : "a branch factory returned a node it had already returned"}, so the SAME node is being re-attached \u2014 any state it accumulated while detached (input value, scroll position, classes set imperatively) comes back with it. Its reactive bindings are left intact rather than disposed, because the node is not this directive's to tear down. Return a FRESH node per call (\`() => div(\u2026)\`) for rebuild semantics, or keep this form deliberately when the reuse is what you want.`
|
|
4665
|
+
);
|
|
4666
|
+
}
|
|
4667
|
+
parent.insertBefore(node, anchor.nextSibling);
|
|
4668
|
+
return { node, owned };
|
|
4493
4669
|
}
|
|
4494
4670
|
function when(condition, thenBranch, elseBranch) {
|
|
4495
4671
|
const anchor = document.createComment("when");
|
|
4496
4672
|
let currentNode = null;
|
|
4497
4673
|
let lastCondition;
|
|
4498
4674
|
let initialized = false;
|
|
4675
|
+
const attachedOnce = /* @__PURE__ */ new WeakSet();
|
|
4676
|
+
let currentNodeOwned = false;
|
|
4499
4677
|
const update = () => {
|
|
4500
4678
|
const show2 = condition();
|
|
4501
4679
|
const parent = anchor.parentNode;
|
|
4502
4680
|
if (!parent) return;
|
|
4503
4681
|
if (initialized && show2 === lastCondition) return;
|
|
4504
4682
|
lastCondition = show2;
|
|
4683
|
+
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
4505
4684
|
if (currentNode?.parentNode) {
|
|
4506
|
-
dispose(currentNode);
|
|
4685
|
+
if (currentNodeOwned) dispose(currentNode);
|
|
4507
4686
|
currentNode.parentNode.removeChild(currentNode);
|
|
4508
4687
|
currentNode = null;
|
|
4509
4688
|
}
|
|
4510
|
-
const
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
}
|
|
4689
|
+
const branch = show2 ? thenBranch : elseBranch !== void 0 ? elseBranch : null;
|
|
4690
|
+
const attached = attachBranch(parent, anchor, branch, attachedOnce, "when");
|
|
4691
|
+
currentNode = attached.node;
|
|
4692
|
+
currentNodeOwned = attached.owned;
|
|
4693
|
+
restoreFocusWithin(focused, currentNode ? [currentNode] : [], "when");
|
|
4516
4694
|
initialized = true;
|
|
4517
4695
|
};
|
|
4518
4696
|
registerDisposer(anchor, track2(update));
|
|
@@ -4528,26 +4706,25 @@ function match(value, cases, fallback) {
|
|
|
4528
4706
|
let currentNode = null;
|
|
4529
4707
|
let lastKey;
|
|
4530
4708
|
let initialized = false;
|
|
4709
|
+
const attachedOnce = /* @__PURE__ */ new WeakSet();
|
|
4710
|
+
let currentNodeOwned = false;
|
|
4531
4711
|
const update = () => {
|
|
4532
4712
|
const key = String(value());
|
|
4533
4713
|
const parent = anchor.parentNode;
|
|
4534
4714
|
if (!parent) return;
|
|
4535
4715
|
if (initialized && key === lastKey) return;
|
|
4536
4716
|
lastKey = key;
|
|
4717
|
+
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
4537
4718
|
if (currentNode?.parentNode) {
|
|
4538
|
-
dispose(currentNode);
|
|
4719
|
+
if (currentNodeOwned) dispose(currentNode);
|
|
4539
4720
|
currentNode.parentNode.removeChild(currentNode);
|
|
4540
4721
|
currentNode = null;
|
|
4541
4722
|
}
|
|
4542
|
-
const
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
parent.insertBefore(node, anchor.nextSibling);
|
|
4548
|
-
currentNode = node;
|
|
4549
|
-
}
|
|
4550
|
-
}
|
|
4723
|
+
const branch = Object.hasOwn(cases, key) ? cases[key] : fallback;
|
|
4724
|
+
const attached = attachBranch(parent, anchor, branch ?? null, attachedOnce, "match");
|
|
4725
|
+
currentNode = attached.node;
|
|
4726
|
+
currentNodeOwned = attached.owned;
|
|
4727
|
+
restoreFocusWithin(focused, currentNode ? [currentNode] : [], "match");
|
|
4551
4728
|
initialized = true;
|
|
4552
4729
|
};
|
|
4553
4730
|
registerDisposer(anchor, track2(update));
|
|
@@ -4592,7 +4769,6 @@ function DynamicComponent(is) {
|
|
|
4592
4769
|
}
|
|
4593
4770
|
|
|
4594
4771
|
// src/core/rendering/each.ts
|
|
4595
|
-
var _isDev9 = isDev();
|
|
4596
4772
|
function resolveNodeChild(child) {
|
|
4597
4773
|
if (typeof child === "function") {
|
|
4598
4774
|
return resolveNodeChild(child());
|
|
@@ -4683,7 +4859,7 @@ function each(getArray, render, options) {
|
|
|
4683
4859
|
workMap.clear();
|
|
4684
4860
|
keyIndexMap.clear();
|
|
4685
4861
|
for (let i2 = 0; i2 < newLen; i2++) {
|
|
4686
|
-
if (
|
|
4862
|
+
if (DEV && keyIndexMap.has(newKeys[i2])) {
|
|
4687
4863
|
devWarn(
|
|
4688
4864
|
`each: duplicate key "${String(newKeys[i2])}" at index ${i2} (first seen at ${keyIndexMap.get(newKeys[i2])}). Keys must be unique \u2014 duplicates cause rows to be dropped or mis-ordered.`
|
|
4689
4865
|
);
|
|
@@ -4867,7 +5043,6 @@ function resolveChild(child) {
|
|
|
4867
5043
|
}
|
|
4868
5044
|
|
|
4869
5045
|
// src/core/rendering/htm.ts
|
|
4870
|
-
var _isDev10 = isDev();
|
|
4871
5046
|
var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
4872
5047
|
var VOID_ELEMENTS3 = /* @__PURE__ */ new Set([
|
|
4873
5048
|
"area",
|
|
@@ -4954,13 +5129,13 @@ function parseTemplate(strings) {
|
|
|
4954
5129
|
skipWs();
|
|
4955
5130
|
const exprIdx = tryExprIdx();
|
|
4956
5131
|
if (exprIdx >= 0) return { kind: "expr", idx: exprIdx };
|
|
4957
|
-
const
|
|
4958
|
-
if (
|
|
5132
|
+
const quote2 = template2[pos];
|
|
5133
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
4959
5134
|
pos++;
|
|
4960
5135
|
const statics = [];
|
|
4961
5136
|
const exprs = [];
|
|
4962
5137
|
let current = "";
|
|
4963
|
-
while (pos < len && template2[pos] !==
|
|
5138
|
+
while (pos < len && template2[pos] !== quote2) {
|
|
4964
5139
|
const innerIdx = tryExprIdx();
|
|
4965
5140
|
if (innerIdx >= 0) {
|
|
4966
5141
|
statics.push(current);
|
|
@@ -5147,7 +5322,7 @@ function executeElement(tmpl, values) {
|
|
|
5147
5322
|
const fn = values[attr.idx];
|
|
5148
5323
|
if (typeof fn === "function") {
|
|
5149
5324
|
el.addEventListener(attr.name, fn);
|
|
5150
|
-
} else if (
|
|
5325
|
+
} else if (DEV) {
|
|
5151
5326
|
devWarn(
|
|
5152
5327
|
`html: on:${attr.name} handler is not a function (got ${typeof fn}). Event listener was not attached.`
|
|
5153
5328
|
);
|
|
@@ -6422,7 +6597,6 @@ function schedule(strategy, el, activate, options) {
|
|
|
6422
6597
|
}
|
|
6423
6598
|
|
|
6424
6599
|
// src/platform/ssr.ts
|
|
6425
|
-
var _isDev11 = isDev();
|
|
6426
6600
|
function trustHTML(html3) {
|
|
6427
6601
|
return html3;
|
|
6428
6602
|
}
|