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/index.cjs
CHANGED
|
@@ -346,23 +346,28 @@ function reportError(error, context2) {
|
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
// src/core/dev.ts
|
|
349
|
+
var DEV = typeof __SIBU_DEV__ !== "undefined" ? !!__SIBU_DEV__ : typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
|
|
350
|
+
// safe default: off in browser, on in test/dev Node
|
|
351
|
+
typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
352
|
+
);
|
|
349
353
|
function isDev() {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
// this branch is unreachable here.
|
|
354
|
-
/* v8 ignore next 2 */
|
|
355
|
-
typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
356
|
-
);
|
|
354
|
+
if (typeof globalThis.__SIBU_DEV__ !== "undefined") return !!globalThis.__SIBU_DEV__;
|
|
355
|
+
if (typeof __SIBU_DEV__ !== "undefined") return !!__SIBU_DEV__;
|
|
356
|
+
return typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
357
357
|
}
|
|
358
|
-
var _isDev = isDev();
|
|
359
358
|
function devAssert(condition, message) {
|
|
360
|
-
if (
|
|
359
|
+
if ((typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) && !condition) {
|
|
361
360
|
throw new Error(`[SibuJS] ${message}`);
|
|
362
361
|
}
|
|
363
362
|
}
|
|
363
|
+
function devWarnLazy(build) {
|
|
364
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
365
|
+
const message = build();
|
|
366
|
+
if (message) console.warn(`[SibuJS] ${message}`);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
364
369
|
function devWarn(message) {
|
|
365
|
-
if (
|
|
370
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
366
371
|
console.warn(`[SibuJS] ${message}`);
|
|
367
372
|
}
|
|
368
373
|
}
|
|
@@ -377,7 +382,6 @@ function reportDrainRunaway(label2, executed, remaining) {
|
|
|
377
382
|
{ executed, remaining }
|
|
378
383
|
);
|
|
379
384
|
}
|
|
380
|
-
var _isDev2 = isDev();
|
|
381
385
|
var activeBindingCount = 0;
|
|
382
386
|
function registerDisposer(node, teardown) {
|
|
383
387
|
let disposers = elementDisposers.get(node);
|
|
@@ -386,7 +390,7 @@ function registerDisposer(node, teardown) {
|
|
|
386
390
|
elementDisposers.set(node, disposers);
|
|
387
391
|
}
|
|
388
392
|
disposers.push(teardown);
|
|
389
|
-
if (
|
|
393
|
+
if (DEV) activeBindingCount++;
|
|
390
394
|
}
|
|
391
395
|
function unregisterDisposer(node, teardown) {
|
|
392
396
|
const disposers = elementDisposers.get(node);
|
|
@@ -394,7 +398,7 @@ function unregisterDisposer(node, teardown) {
|
|
|
394
398
|
const index = disposers.indexOf(teardown);
|
|
395
399
|
if (index === -1) return;
|
|
396
400
|
disposers.splice(index, 1);
|
|
397
|
-
if (
|
|
401
|
+
if (DEV) activeBindingCount--;
|
|
398
402
|
if (disposers.length === 0) elementDisposers.delete(node);
|
|
399
403
|
}
|
|
400
404
|
function dispose(node) {
|
|
@@ -418,13 +422,13 @@ function dispose(node) {
|
|
|
418
422
|
if (!pending || pending.length === 0) break;
|
|
419
423
|
const snapshot = pending.slice();
|
|
420
424
|
elementDisposers.delete(current);
|
|
421
|
-
if (
|
|
425
|
+
if (DEV) activeBindingCount -= snapshot.length;
|
|
422
426
|
for (let i3 = 0; i3 < snapshot.length; i3++) {
|
|
423
427
|
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
424
428
|
const rest = snapshot.slice(i3);
|
|
425
429
|
const added = elementDisposers.get(current);
|
|
426
430
|
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
427
|
-
if (
|
|
431
|
+
if (DEV) activeBindingCount += rest.length;
|
|
428
432
|
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
429
433
|
runaway = true;
|
|
430
434
|
break;
|
|
@@ -452,7 +456,7 @@ function replaceChildrenSafely(parent, ...next) {
|
|
|
452
456
|
parent.replaceChildren(...next);
|
|
453
457
|
}
|
|
454
458
|
function checkLeaks(warnThreshold = 0) {
|
|
455
|
-
if (!
|
|
459
|
+
if (!DEV) return 0;
|
|
456
460
|
if (warnThreshold > 0 && activeBindingCount > warnThreshold) {
|
|
457
461
|
devWarn(
|
|
458
462
|
`checkLeaks: ${activeBindingCount} active DOM bindings detected. Expected \u2264${warnThreshold}. This may indicate a component was removed from the DOM without calling dispose().`
|
|
@@ -554,20 +558,75 @@ function decodeCssEscapes(value) {
|
|
|
554
558
|
}
|
|
555
559
|
return out;
|
|
556
560
|
}
|
|
557
|
-
|
|
558
|
-
|
|
561
|
+
var BLOCKED_CSS_NEEDLES = [
|
|
562
|
+
"url(",
|
|
563
|
+
"expression(",
|
|
564
|
+
"javascript:",
|
|
565
|
+
"vbscript:",
|
|
566
|
+
"-moz-binding",
|
|
567
|
+
"behavior:",
|
|
568
|
+
"@import",
|
|
569
|
+
"image-set(",
|
|
570
|
+
"filter:progid"
|
|
571
|
+
];
|
|
572
|
+
function describeElement(el) {
|
|
573
|
+
if (!el) return "an element";
|
|
574
|
+
let out = el.tagName.toLowerCase();
|
|
575
|
+
const id = el.getAttribute("id");
|
|
576
|
+
if (id) out += `#${id}`;
|
|
577
|
+
const cls = el.getAttribute("class");
|
|
578
|
+
if (cls) out += `.${cls.trim().split(/\s+/).slice(0, 3).join(".")}`;
|
|
579
|
+
return `<${out}>`;
|
|
580
|
+
}
|
|
581
|
+
var warnedDeclarations = /* @__PURE__ */ new Set();
|
|
582
|
+
var MAX_WARNED_DECLARATIONS = 100;
|
|
583
|
+
var declarationCapAnnounced = false;
|
|
584
|
+
function warnDroppedDeclaration(value, reason, ctx) {
|
|
585
|
+
devWarnLazy(() => {
|
|
586
|
+
const reasons = [
|
|
587
|
+
"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",
|
|
588
|
+
"expression() executes arbitrary script in legacy engines",
|
|
589
|
+
"the javascript: scheme executes script",
|
|
590
|
+
"the vbscript: scheme executes script",
|
|
591
|
+
"-moz-binding loads and runs remote XBL",
|
|
592
|
+
"behavior: loads and runs a remote HTC script",
|
|
593
|
+
"@import pulls in a remote stylesheet",
|
|
594
|
+
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
595
|
+
"filter:progid activates legacy scriptable filters"
|
|
596
|
+
];
|
|
597
|
+
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
598
|
+
const where = describeElement(ctx?.element);
|
|
599
|
+
const key = `${where}|${declaration}`;
|
|
600
|
+
if (warnedDeclarations.has(key)) return "";
|
|
601
|
+
if (warnedDeclarations.size >= MAX_WARNED_DECLARATIONS) {
|
|
602
|
+
if (declarationCapAnnounced) return "";
|
|
603
|
+
declarationCapAnnounced = true;
|
|
604
|
+
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.`;
|
|
605
|
+
}
|
|
606
|
+
warnedDeclarations.add(key);
|
|
607
|
+
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.`;
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
function blockedCssReason(value) {
|
|
611
|
+
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
559
612
|
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
560
613
|
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
561
|
-
|
|
562
|
-
return
|
|
614
|
+
for (let i2 = 0; i2 < BLOCKED_CSS_NEEDLES.length; i2++) {
|
|
615
|
+
if (lower.includes(BLOCKED_CSS_NEEDLES[i2])) return i2;
|
|
563
616
|
}
|
|
564
|
-
return
|
|
617
|
+
return -1;
|
|
618
|
+
}
|
|
619
|
+
function sanitizeCSSValue(value, context2) {
|
|
620
|
+
const reason = blockedCssReason(value);
|
|
621
|
+
if (reason === -1) return value;
|
|
622
|
+
warnDroppedDeclaration(value, reason, context2);
|
|
623
|
+
return "";
|
|
565
624
|
}
|
|
566
|
-
function sanitizeStyleAttribute(cssText) {
|
|
625
|
+
function sanitizeStyleAttribute(cssText, context2) {
|
|
567
626
|
const input2 = String(cssText);
|
|
568
627
|
if (input2.trim() === "") return "";
|
|
569
628
|
if (typeof document === "undefined") {
|
|
570
|
-
return sanitizeCSSValue(input2) === "" ? "" : input2;
|
|
629
|
+
return sanitizeCSSValue(input2, context2) === "" ? "" : input2;
|
|
571
630
|
}
|
|
572
631
|
const probe = document.createElement("div");
|
|
573
632
|
try {
|
|
@@ -579,8 +638,12 @@ function sanitizeStyleAttribute(cssText) {
|
|
|
579
638
|
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
580
639
|
const property = probe.style[i2];
|
|
581
640
|
const value = probe.style.getPropertyValue(property);
|
|
582
|
-
|
|
583
|
-
if (
|
|
641
|
+
let reason = blockedCssReason(value);
|
|
642
|
+
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
643
|
+
if (reason !== -1) {
|
|
644
|
+
warnDroppedDeclaration(value, reason, { property, element: context2?.element });
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
584
647
|
const priority = probe.style.getPropertyPriority(property);
|
|
585
648
|
declarations.push(`${property}: ${value}${priority ? ` !${priority}` : ""}`);
|
|
586
649
|
}
|
|
@@ -608,16 +671,15 @@ var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
|
608
671
|
function isHtmlContentAttribute(name) {
|
|
609
672
|
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
610
673
|
}
|
|
611
|
-
function sanitizeAttributeString(attr, value) {
|
|
674
|
+
function sanitizeAttributeString(attr, value, context2) {
|
|
612
675
|
const lower = attr.toLowerCase();
|
|
613
676
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
614
677
|
if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
|
|
615
|
-
if (lower === "style") return sanitizeStyleAttribute(value);
|
|
678
|
+
if (lower === "style") return sanitizeStyleAttribute(value, context2);
|
|
616
679
|
return value;
|
|
617
680
|
}
|
|
618
681
|
|
|
619
682
|
// src/utils/setSafeAttribute.ts
|
|
620
|
-
var _isDev3 = isDev();
|
|
621
683
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
622
684
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
623
685
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
@@ -640,7 +702,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
640
702
|
const ns = namespaceFor(el, name);
|
|
641
703
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
642
704
|
if (isEventHandlerAttr(name)) {
|
|
643
|
-
if (
|
|
705
|
+
if (DEV) {
|
|
644
706
|
devWarn(
|
|
645
707
|
`${options.label ?? "setSafeAttribute"}: refusing to set event-handler attribute "${name}". Its value would be evaluated as JavaScript. Use on:{ ${name.slice(2)}: fn } instead.`
|
|
646
708
|
);
|
|
@@ -655,7 +717,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
655
717
|
return true;
|
|
656
718
|
}
|
|
657
719
|
if (isHtmlContentAttribute(name)) {
|
|
658
|
-
if (
|
|
720
|
+
if (DEV) {
|
|
659
721
|
devWarn(
|
|
660
722
|
`${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.`
|
|
661
723
|
);
|
|
@@ -684,7 +746,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
684
746
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
685
747
|
return true;
|
|
686
748
|
}
|
|
687
|
-
const safe = sanitizeAttributeString(name, str);
|
|
749
|
+
const safe = sanitizeAttributeString(name, str, { element: el });
|
|
688
750
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
689
751
|
if (current === safe) return true;
|
|
690
752
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -1148,17 +1210,16 @@ function forEachSubscriber(signal2, visit) {
|
|
|
1148
1210
|
}
|
|
1149
1211
|
|
|
1150
1212
|
// src/reactivity/track.ts
|
|
1151
|
-
var
|
|
1152
|
-
var _runtimeVersion = true ? "4.1.0" : "dev";
|
|
1213
|
+
var _runtimeVersion = true ? "4.2.0" : "dev";
|
|
1153
1214
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1154
1215
|
function resolveReactiveApi() {
|
|
1155
1216
|
const g2 = globalThis;
|
|
1156
1217
|
const existing = g2[REGISTRY_KEY];
|
|
1157
1218
|
if (existing) {
|
|
1158
|
-
if (
|
|
1219
|
+
if (DEV && !existing.__dupWarned) {
|
|
1159
1220
|
existing.__dupWarned = true;
|
|
1160
1221
|
devWarn(
|
|
1161
|
-
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity
|
|
1222
|
+
`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.`
|
|
1162
1223
|
);
|
|
1163
1224
|
}
|
|
1164
1225
|
return existing;
|
|
@@ -1257,8 +1318,101 @@ function bindDynamic(el, nameGetter, valueGetter) {
|
|
|
1257
1318
|
};
|
|
1258
1319
|
}
|
|
1259
1320
|
|
|
1321
|
+
// src/core/rendering/focusPreservation.ts
|
|
1322
|
+
var IDENTITY_ATTRS = ["data-focus-key", "id", "name"];
|
|
1323
|
+
var SELECTABLE_TYPES = /* @__PURE__ */ new Set(["text", "search", "url", "tel", "password", ""]);
|
|
1324
|
+
function selectionOf(el) {
|
|
1325
|
+
const tag = el.tagName;
|
|
1326
|
+
const selectable = tag === "TEXTAREA" || tag === "INPUT" && SELECTABLE_TYPES.has(el.type.toLowerCase());
|
|
1327
|
+
if (!selectable) return { start: null, end: null, direction: null };
|
|
1328
|
+
const field = el;
|
|
1329
|
+
return { start: field.selectionStart, end: field.selectionEnd, direction: field.selectionDirection };
|
|
1330
|
+
}
|
|
1331
|
+
function captureFocusWithin(nodes) {
|
|
1332
|
+
if (nodes.length === 0 || typeof document === "undefined") return null;
|
|
1333
|
+
const active = document.activeElement;
|
|
1334
|
+
if (!active || active === document.body) return null;
|
|
1335
|
+
let inside = false;
|
|
1336
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
1337
|
+
const n = nodes[i2];
|
|
1338
|
+
if (n === active || n.nodeType === 1 && n.contains(active)) {
|
|
1339
|
+
inside = true;
|
|
1340
|
+
break;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
if (!inside) return null;
|
|
1344
|
+
let attr = null;
|
|
1345
|
+
let value = null;
|
|
1346
|
+
for (let i2 = 0; i2 < IDENTITY_ATTRS.length; i2++) {
|
|
1347
|
+
const candidate = active.getAttribute(IDENTITY_ATTRS[i2]);
|
|
1348
|
+
if (candidate) {
|
|
1349
|
+
attr = IDENTITY_ATTRS[i2];
|
|
1350
|
+
value = candidate;
|
|
1351
|
+
break;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
return { el: active, attr, value, tag: active.tagName, ...selectionOf(active) };
|
|
1355
|
+
}
|
|
1356
|
+
function quote(value) {
|
|
1357
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
1358
|
+
}
|
|
1359
|
+
function findUniqueByIdentity(nodes, selector) {
|
|
1360
|
+
let el = null;
|
|
1361
|
+
let count = 0;
|
|
1362
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
1363
|
+
const n = nodes[i2];
|
|
1364
|
+
if (n.nodeType !== 1) continue;
|
|
1365
|
+
const root = n;
|
|
1366
|
+
if (root.matches(selector)) {
|
|
1367
|
+
count++;
|
|
1368
|
+
el ?? (el = root);
|
|
1369
|
+
}
|
|
1370
|
+
const inner = root.querySelectorAll(selector);
|
|
1371
|
+
for (let j = 0; j < inner.length; j++) {
|
|
1372
|
+
count++;
|
|
1373
|
+
el ?? (el = inner[j]);
|
|
1374
|
+
}
|
|
1375
|
+
if (count > 1) return { el: null, count };
|
|
1376
|
+
}
|
|
1377
|
+
return count === 1 ? { el, count } : { el: null, count };
|
|
1378
|
+
}
|
|
1379
|
+
function refocus(el, snapshot) {
|
|
1380
|
+
el.focus();
|
|
1381
|
+
if (snapshot.start !== null && typeof el.setSelectionRange === "function") {
|
|
1382
|
+
const field = el;
|
|
1383
|
+
const max = field.value.length;
|
|
1384
|
+
const start = Math.min(snapshot.start, max);
|
|
1385
|
+
const end = Math.min(snapshot.end ?? start, max);
|
|
1386
|
+
field.setSelectionRange(start, end, snapshot.direction ?? "none");
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
function restoreFocusWithin(snapshot, nodes, where) {
|
|
1390
|
+
if (!snapshot) return;
|
|
1391
|
+
if (typeof document === "undefined") return;
|
|
1392
|
+
const active = document.activeElement;
|
|
1393
|
+
if (active === snapshot.el) return;
|
|
1394
|
+
if (active && active !== document.body && active !== document.documentElement) return;
|
|
1395
|
+
if (snapshot.el.isConnected) {
|
|
1396
|
+
refocus(snapshot.el, snapshot);
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
let ambiguous = false;
|
|
1400
|
+
if (snapshot.attr && snapshot.value) {
|
|
1401
|
+
const { el: replacement, count } = findUniqueByIdentity(nodes, `[${snapshot.attr}=${quote(snapshot.value)}]`);
|
|
1402
|
+
if (replacement && replacement.tagName === snapshot.tag) {
|
|
1403
|
+
refocus(replacement, snapshot);
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
ambiguous = count > 1;
|
|
1407
|
+
}
|
|
1408
|
+
devWarnLazy(() => {
|
|
1409
|
+
const id = snapshot.attr ? ` (${snapshot.attr}="${snapshot.value}")` : "";
|
|
1410
|
+
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";
|
|
1411
|
+
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.`;
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1260
1415
|
// src/reactivity/bindChildNode.ts
|
|
1261
|
-
var _isDev5 = isDev();
|
|
1262
1416
|
function bindChildNode(placeholder, getter) {
|
|
1263
1417
|
let lastNodes = [];
|
|
1264
1418
|
function commit() {
|
|
@@ -1269,6 +1423,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
1269
1423
|
reportError(err, { phase: "binding", name: "bindChildNode", node: placeholder });
|
|
1270
1424
|
return;
|
|
1271
1425
|
}
|
|
1426
|
+
const focused = captureFocusWithin(lastNodes);
|
|
1272
1427
|
if (result == null || typeof result === "boolean") {
|
|
1273
1428
|
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
1274
1429
|
const node = lastNodes[i2];
|
|
@@ -1276,6 +1431,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
1276
1431
|
if (node.parentNode) node.parentNode.removeChild(node);
|
|
1277
1432
|
}
|
|
1278
1433
|
lastNodes.length = 0;
|
|
1434
|
+
restoreFocusWithin(focused, lastNodes, "bindChildNode");
|
|
1279
1435
|
return;
|
|
1280
1436
|
}
|
|
1281
1437
|
const parent = placeholder.parentNode;
|
|
@@ -1292,8 +1448,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
1292
1448
|
if (item == null || typeof item === "boolean") continue;
|
|
1293
1449
|
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
1294
1450
|
if (seen.has(node)) {
|
|
1295
|
-
if (
|
|
1296
|
-
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
1451
|
+
if (DEV) devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
1297
1452
|
continue;
|
|
1298
1453
|
}
|
|
1299
1454
|
seen.add(node);
|
|
@@ -1326,13 +1481,13 @@ function bindChildNode(placeholder, getter) {
|
|
|
1326
1481
|
prev = node;
|
|
1327
1482
|
}
|
|
1328
1483
|
lastNodes = newNodes;
|
|
1484
|
+
restoreFocusWithin(focused, newNodes, "bindChildNode");
|
|
1329
1485
|
}
|
|
1330
1486
|
return reactiveBinding2(commit, placeholder);
|
|
1331
1487
|
}
|
|
1332
1488
|
|
|
1333
1489
|
// src/core/rendering/tagFactory.ts
|
|
1334
1490
|
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
1335
|
-
var _isDev6 = isDev();
|
|
1336
1491
|
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
1337
1492
|
function isBlockedTag(tag) {
|
|
1338
1493
|
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
@@ -1350,18 +1505,9 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
|
1350
1505
|
"self",
|
|
1351
1506
|
"frames"
|
|
1352
1507
|
]);
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
const tokens = t.split(/\s+/);
|
|
1357
|
-
let sawClassish = false;
|
|
1358
|
-
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
1359
|
-
const tok = tokens[i2];
|
|
1360
|
-
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return false;
|
|
1361
|
-
if (/[-:/0-9]/.test(tok)) sawClassish = true;
|
|
1362
|
-
}
|
|
1363
|
-
return sawClassish;
|
|
1364
|
-
}
|
|
1508
|
+
var warnedLoneStrings = /* @__PURE__ */ new Set();
|
|
1509
|
+
var MAX_WARNED_LONE_STRINGS = 100;
|
|
1510
|
+
var loneStringCapAnnounced = false;
|
|
1365
1511
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
1366
1512
|
function toKebab(prop) {
|
|
1367
1513
|
let cached = kebabCache.get(prop);
|
|
@@ -1373,13 +1519,13 @@ function toKebab(prop) {
|
|
|
1373
1519
|
function applyStyle(el, style2) {
|
|
1374
1520
|
if (typeof style2 === "function") {
|
|
1375
1521
|
const teardown = reactiveBinding2(() => {
|
|
1376
|
-
el.setAttribute("style", sanitizeStyleAttribute(String(style2())));
|
|
1522
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(style2()), { element: el }));
|
|
1377
1523
|
}, el);
|
|
1378
1524
|
registerDisposer(el, teardown);
|
|
1379
1525
|
return;
|
|
1380
1526
|
}
|
|
1381
1527
|
if (typeof style2 === "string") {
|
|
1382
|
-
el.setAttribute("style", sanitizeStyleAttribute(style2));
|
|
1528
|
+
el.setAttribute("style", sanitizeStyleAttribute(style2, { element: el }));
|
|
1383
1529
|
return;
|
|
1384
1530
|
}
|
|
1385
1531
|
const htmlEl = el;
|
|
@@ -1389,11 +1535,11 @@ function applyStyle(el, style2) {
|
|
|
1389
1535
|
if (typeof val === "function") {
|
|
1390
1536
|
const getter = val;
|
|
1391
1537
|
const teardown = reactiveBinding2(() => {
|
|
1392
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
|
|
1538
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter()), { property: name, element: el }));
|
|
1393
1539
|
}, el);
|
|
1394
1540
|
registerDisposer(el, teardown);
|
|
1395
1541
|
} else {
|
|
1396
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
|
|
1542
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
|
|
1397
1543
|
}
|
|
1398
1544
|
}
|
|
1399
1545
|
}
|
|
@@ -1500,11 +1646,26 @@ var tagFactory = (tag, ns) => {
|
|
|
1500
1646
|
appendChildren(el, second);
|
|
1501
1647
|
return el;
|
|
1502
1648
|
}
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1649
|
+
devWarnLazy(() => {
|
|
1650
|
+
const tokens = first.trim().split(/\s+/);
|
|
1651
|
+
if (tokens.length < 2) return "";
|
|
1652
|
+
let utilityTokens = 0;
|
|
1653
|
+
for (let i2 = 0; i2 < tokens.length; i2++) {
|
|
1654
|
+
const tok = tokens[i2];
|
|
1655
|
+
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return "";
|
|
1656
|
+
if (/[-:/0-9]/.test(tok)) utilityTokens++;
|
|
1657
|
+
}
|
|
1658
|
+
if (utilityTokens < 2) return "";
|
|
1659
|
+
const key = `${tag}|${first}`;
|
|
1660
|
+
if (warnedLoneStrings.has(key)) return "";
|
|
1661
|
+
if (warnedLoneStrings.size >= MAX_WARNED_LONE_STRINGS) {
|
|
1662
|
+
if (loneStringCapAnnounced) return "";
|
|
1663
|
+
loneStringCapAnnounced = true;
|
|
1664
|
+
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.`;
|
|
1665
|
+
}
|
|
1666
|
+
warnedLoneStrings.add(key);
|
|
1667
|
+
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.`;
|
|
1668
|
+
});
|
|
1508
1669
|
el.textContent = first;
|
|
1509
1670
|
return el;
|
|
1510
1671
|
}
|
|
@@ -1521,7 +1682,7 @@ var tagFactory = (tag, ns) => {
|
|
|
1521
1682
|
if (pClass != null) applyClass(el, pClass);
|
|
1522
1683
|
const pId = props.id;
|
|
1523
1684
|
if (pId != null) {
|
|
1524
|
-
if (
|
|
1685
|
+
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
1525
1686
|
devWarn(
|
|
1526
1687
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
1527
1688
|
);
|
|
@@ -1536,7 +1697,7 @@ var tagFactory = (tag, ns) => {
|
|
|
1536
1697
|
const handler = pOn[ev];
|
|
1537
1698
|
if (typeof handler === "function") {
|
|
1538
1699
|
el.addEventListener(ev, handler);
|
|
1539
|
-
} else if (
|
|
1700
|
+
} else if (DEV) {
|
|
1540
1701
|
devWarn(
|
|
1541
1702
|
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
1542
1703
|
);
|
|
@@ -2335,7 +2496,6 @@ var isBatching = API2.isBatching;
|
|
|
2335
2496
|
|
|
2336
2497
|
// src/core/signals/signal.ts
|
|
2337
2498
|
var _g2 = globalThis;
|
|
2338
|
-
var _isDev7 = isDev();
|
|
2339
2499
|
function signal(initial, options) {
|
|
2340
2500
|
const state2 = {
|
|
2341
2501
|
value: initial,
|
|
@@ -2348,7 +2508,7 @@ function signal(initial, options) {
|
|
|
2348
2508
|
_d: false,
|
|
2349
2509
|
_validate: void 0
|
|
2350
2510
|
};
|
|
2351
|
-
const debugName =
|
|
2511
|
+
const debugName = DEV ? options?.name : void 0;
|
|
2352
2512
|
const equalsFn = options?.equals;
|
|
2353
2513
|
if (debugName) state2.__name = debugName;
|
|
2354
2514
|
function get() {
|
|
@@ -2365,7 +2525,7 @@ function signal(initial, options) {
|
|
|
2365
2525
|
if (equalsFn(prev, newValue)) return;
|
|
2366
2526
|
state2.value = newValue;
|
|
2367
2527
|
state2.__v++;
|
|
2368
|
-
if (
|
|
2528
|
+
if (DEV) {
|
|
2369
2529
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2370
2530
|
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
2371
2531
|
}
|
|
@@ -2373,7 +2533,7 @@ function signal(initial, options) {
|
|
|
2373
2533
|
notifySubscribers2(state2);
|
|
2374
2534
|
}
|
|
2375
2535
|
};
|
|
2376
|
-
} else if (
|
|
2536
|
+
} else if (DEV) {
|
|
2377
2537
|
set = (next) => {
|
|
2378
2538
|
const prev = state2.value;
|
|
2379
2539
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
@@ -2398,7 +2558,7 @@ function signal(initial, options) {
|
|
|
2398
2558
|
}
|
|
2399
2559
|
};
|
|
2400
2560
|
}
|
|
2401
|
-
if (
|
|
2561
|
+
if (DEV) {
|
|
2402
2562
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2403
2563
|
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
2404
2564
|
}
|
|
@@ -3390,11 +3550,10 @@ function setGlobalErrorHandler(handler) {
|
|
|
3390
3550
|
}
|
|
3391
3551
|
|
|
3392
3552
|
// src/core/rendering/context.ts
|
|
3393
|
-
var _isDev8 = isDev();
|
|
3394
3553
|
function context(defaultValue) {
|
|
3395
3554
|
const [getValue, setValue] = signal(defaultValue);
|
|
3396
3555
|
const warnIfSSR = (method) => {
|
|
3397
|
-
if (!
|
|
3556
|
+
if (!DEV || !isSSR()) return;
|
|
3398
3557
|
devWarn(
|
|
3399
3558
|
`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.`
|
|
3400
3559
|
);
|
|
@@ -3422,7 +3581,7 @@ function context(defaultValue) {
|
|
|
3422
3581
|
setValue(value);
|
|
3423
3582
|
try {
|
|
3424
3583
|
const result = fn();
|
|
3425
|
-
if (
|
|
3584
|
+
if (DEV && result !== null && typeof result?.then === "function") {
|
|
3426
3585
|
devWarn(
|
|
3427
3586
|
"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."
|
|
3428
3587
|
);
|
|
@@ -3449,34 +3608,53 @@ function __resetIdCounter() {
|
|
|
3449
3608
|
|
|
3450
3609
|
// src/core/rendering/directives.ts
|
|
3451
3610
|
function show(condition, element) {
|
|
3611
|
+
const resolved = typeof element === "function" ? element() : element;
|
|
3452
3612
|
const update = () => {
|
|
3453
|
-
|
|
3613
|
+
resolved.style.display = condition() ? "" : "none";
|
|
3454
3614
|
};
|
|
3455
|
-
registerDisposer(
|
|
3456
|
-
return
|
|
3615
|
+
registerDisposer(resolved, track2(update));
|
|
3616
|
+
return resolved;
|
|
3617
|
+
}
|
|
3618
|
+
function attachBranch(parent, anchor, branch, attachedOnce, where) {
|
|
3619
|
+
const result = typeof branch === "function" ? branch() : branch;
|
|
3620
|
+
if (result == null || typeof result === "boolean") return { node: null, owned: false };
|
|
3621
|
+
const node = result instanceof Node ? result : document.createTextNode(String(result));
|
|
3622
|
+
const handedIn = node === branch;
|
|
3623
|
+
const seenBefore = attachedOnce.has(node);
|
|
3624
|
+
const owned = !handedIn && !seenBefore;
|
|
3625
|
+
attachedOnce.add(node);
|
|
3626
|
+
if (seenBefore) {
|
|
3627
|
+
devWarnLazy(
|
|
3628
|
+
() => `${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.`
|
|
3629
|
+
);
|
|
3630
|
+
}
|
|
3631
|
+
parent.insertBefore(node, anchor.nextSibling);
|
|
3632
|
+
return { node, owned };
|
|
3457
3633
|
}
|
|
3458
3634
|
function when(condition, thenBranch, elseBranch) {
|
|
3459
3635
|
const anchor = document.createComment("when");
|
|
3460
3636
|
let currentNode = null;
|
|
3461
3637
|
let lastCondition;
|
|
3462
3638
|
let initialized = false;
|
|
3639
|
+
const attachedOnce = /* @__PURE__ */ new WeakSet();
|
|
3640
|
+
let currentNodeOwned = false;
|
|
3463
3641
|
const update = () => {
|
|
3464
3642
|
const show2 = condition();
|
|
3465
3643
|
const parent = anchor.parentNode;
|
|
3466
3644
|
if (!parent) return;
|
|
3467
3645
|
if (initialized && show2 === lastCondition) return;
|
|
3468
3646
|
lastCondition = show2;
|
|
3647
|
+
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
3469
3648
|
if (currentNode?.parentNode) {
|
|
3470
|
-
dispose(currentNode);
|
|
3649
|
+
if (currentNodeOwned) dispose(currentNode);
|
|
3471
3650
|
currentNode.parentNode.removeChild(currentNode);
|
|
3472
3651
|
currentNode = null;
|
|
3473
3652
|
}
|
|
3474
|
-
const
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
}
|
|
3653
|
+
const branch = show2 ? thenBranch : elseBranch !== void 0 ? elseBranch : null;
|
|
3654
|
+
const attached = attachBranch(parent, anchor, branch, attachedOnce, "when");
|
|
3655
|
+
currentNode = attached.node;
|
|
3656
|
+
currentNodeOwned = attached.owned;
|
|
3657
|
+
restoreFocusWithin(focused, currentNode ? [currentNode] : [], "when");
|
|
3480
3658
|
initialized = true;
|
|
3481
3659
|
};
|
|
3482
3660
|
registerDisposer(anchor, track2(update));
|
|
@@ -3492,26 +3670,25 @@ function match(value, cases, fallback) {
|
|
|
3492
3670
|
let currentNode = null;
|
|
3493
3671
|
let lastKey;
|
|
3494
3672
|
let initialized = false;
|
|
3673
|
+
const attachedOnce = /* @__PURE__ */ new WeakSet();
|
|
3674
|
+
let currentNodeOwned = false;
|
|
3495
3675
|
const update = () => {
|
|
3496
3676
|
const key = String(value());
|
|
3497
3677
|
const parent = anchor.parentNode;
|
|
3498
3678
|
if (!parent) return;
|
|
3499
3679
|
if (initialized && key === lastKey) return;
|
|
3500
3680
|
lastKey = key;
|
|
3681
|
+
const focused = currentNode ? captureFocusWithin([currentNode]) : null;
|
|
3501
3682
|
if (currentNode?.parentNode) {
|
|
3502
|
-
dispose(currentNode);
|
|
3683
|
+
if (currentNodeOwned) dispose(currentNode);
|
|
3503
3684
|
currentNode.parentNode.removeChild(currentNode);
|
|
3504
3685
|
currentNode = null;
|
|
3505
3686
|
}
|
|
3506
|
-
const
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
parent.insertBefore(node, anchor.nextSibling);
|
|
3512
|
-
currentNode = node;
|
|
3513
|
-
}
|
|
3514
|
-
}
|
|
3687
|
+
const branch = Object.hasOwn(cases, key) ? cases[key] : fallback;
|
|
3688
|
+
const attached = attachBranch(parent, anchor, branch ?? null, attachedOnce, "match");
|
|
3689
|
+
currentNode = attached.node;
|
|
3690
|
+
currentNodeOwned = attached.owned;
|
|
3691
|
+
restoreFocusWithin(focused, currentNode ? [currentNode] : [], "match");
|
|
3515
3692
|
initialized = true;
|
|
3516
3693
|
};
|
|
3517
3694
|
registerDisposer(anchor, track2(update));
|
|
@@ -3556,7 +3733,6 @@ function DynamicComponent(is) {
|
|
|
3556
3733
|
}
|
|
3557
3734
|
|
|
3558
3735
|
// src/core/rendering/each.ts
|
|
3559
|
-
var _isDev9 = isDev();
|
|
3560
3736
|
function resolveNodeChild(child) {
|
|
3561
3737
|
if (typeof child === "function") {
|
|
3562
3738
|
return resolveNodeChild(child());
|
|
@@ -3647,7 +3823,7 @@ function each(getArray, render, options) {
|
|
|
3647
3823
|
workMap.clear();
|
|
3648
3824
|
keyIndexMap.clear();
|
|
3649
3825
|
for (let i2 = 0; i2 < newLen; i2++) {
|
|
3650
|
-
if (
|
|
3826
|
+
if (DEV && keyIndexMap.has(newKeys[i2])) {
|
|
3651
3827
|
devWarn(
|
|
3652
3828
|
`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.`
|
|
3653
3829
|
);
|
|
@@ -3831,7 +4007,6 @@ function resolveChild(child) {
|
|
|
3831
4007
|
}
|
|
3832
4008
|
|
|
3833
4009
|
// src/core/rendering/htm.ts
|
|
3834
|
-
var _isDev10 = isDev();
|
|
3835
4010
|
var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
3836
4011
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
3837
4012
|
"area",
|
|
@@ -3918,13 +4093,13 @@ function parseTemplate(strings) {
|
|
|
3918
4093
|
skipWs();
|
|
3919
4094
|
const exprIdx = tryExprIdx();
|
|
3920
4095
|
if (exprIdx >= 0) return { kind: "expr", idx: exprIdx };
|
|
3921
|
-
const
|
|
3922
|
-
if (
|
|
4096
|
+
const quote2 = template2[pos];
|
|
4097
|
+
if (quote2 === '"' || quote2 === "'") {
|
|
3923
4098
|
pos++;
|
|
3924
4099
|
const statics = [];
|
|
3925
4100
|
const exprs = [];
|
|
3926
4101
|
let current = "";
|
|
3927
|
-
while (pos < len && template2[pos] !==
|
|
4102
|
+
while (pos < len && template2[pos] !== quote2) {
|
|
3928
4103
|
const innerIdx = tryExprIdx();
|
|
3929
4104
|
if (innerIdx >= 0) {
|
|
3930
4105
|
statics.push(current);
|
|
@@ -4111,7 +4286,7 @@ function executeElement(tmpl, values) {
|
|
|
4111
4286
|
const fn = values[attr.idx];
|
|
4112
4287
|
if (typeof fn === "function") {
|
|
4113
4288
|
el.addEventListener(attr.name, fn);
|
|
4114
|
-
} else if (
|
|
4289
|
+
} else if (DEV) {
|
|
4115
4290
|
devWarn(
|
|
4116
4291
|
`html: on:${attr.name} handler is not a function (got ${typeof fn}). Event listener was not attached.`
|
|
4117
4292
|
);
|
|
@@ -5386,7 +5561,6 @@ function schedule(strategy, el, activate, options) {
|
|
|
5386
5561
|
}
|
|
5387
5562
|
|
|
5388
5563
|
// src/platform/ssr.ts
|
|
5389
|
-
var _isDev11 = isDev();
|
|
5390
5564
|
function trustHTML(html3) {
|
|
5391
5565
|
return html3;
|
|
5392
5566
|
}
|