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/ecosystem.cjs
CHANGED
|
@@ -32,23 +32,23 @@ __export(ecosystem_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(ecosystem_exports);
|
|
33
33
|
|
|
34
34
|
// src/core/dev.ts
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// this branch is unreachable here.
|
|
40
|
-
/* v8 ignore next 2 */
|
|
41
|
-
typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
var _isDev = isDev();
|
|
35
|
+
var DEV = typeof __SIBU_DEV__ !== "undefined" ? !!__SIBU_DEV__ : typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
|
|
36
|
+
// safe default: off in browser, on in test/dev Node
|
|
37
|
+
typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
|
|
38
|
+
);
|
|
45
39
|
function devAssert(condition, message) {
|
|
46
|
-
if (
|
|
40
|
+
if ((typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) && !condition) {
|
|
47
41
|
throw new Error(`[SibuJS] ${message}`);
|
|
48
42
|
}
|
|
49
43
|
}
|
|
44
|
+
function devWarnLazy(build) {
|
|
45
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
46
|
+
const message = build();
|
|
47
|
+
if (message) console.warn(`[SibuJS] ${message}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
50
|
function devWarn(message) {
|
|
51
|
-
if (
|
|
51
|
+
if (typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : DEV) {
|
|
52
52
|
console.warn(`[SibuJS] ${message}`);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -597,17 +597,16 @@ function forEachSubscriber(signal2, visit) {
|
|
|
597
597
|
}
|
|
598
598
|
|
|
599
599
|
// src/reactivity/track.ts
|
|
600
|
-
var
|
|
601
|
-
var _runtimeVersion = true ? "4.1.0" : "dev";
|
|
600
|
+
var _runtimeVersion = true ? "4.2.0" : "dev";
|
|
602
601
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
603
602
|
function resolveReactiveApi() {
|
|
604
603
|
const g = globalThis;
|
|
605
604
|
const existing = g[REGISTRY_KEY];
|
|
606
605
|
if (existing) {
|
|
607
|
-
if (
|
|
606
|
+
if (DEV && !existing.__dupWarned) {
|
|
608
607
|
existing.__dupWarned = true;
|
|
609
608
|
devWarn(
|
|
610
|
-
`Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity
|
|
609
|
+
`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.`
|
|
611
610
|
);
|
|
612
611
|
}
|
|
613
612
|
return existing;
|
|
@@ -869,7 +868,6 @@ var isBatching = API2.isBatching;
|
|
|
869
868
|
|
|
870
869
|
// src/core/signals/signal.ts
|
|
871
870
|
var _g2 = globalThis;
|
|
872
|
-
var _isDev3 = isDev();
|
|
873
871
|
function signal(initial, options) {
|
|
874
872
|
const state2 = {
|
|
875
873
|
value: initial,
|
|
@@ -882,7 +880,7 @@ function signal(initial, options) {
|
|
|
882
880
|
_d: false,
|
|
883
881
|
_validate: void 0
|
|
884
882
|
};
|
|
885
|
-
const debugName =
|
|
883
|
+
const debugName = DEV ? options?.name : void 0;
|
|
886
884
|
const equalsFn = options?.equals;
|
|
887
885
|
if (debugName) state2.__name = debugName;
|
|
888
886
|
function get() {
|
|
@@ -899,7 +897,7 @@ function signal(initial, options) {
|
|
|
899
897
|
if (equalsFn(prev, newValue)) return;
|
|
900
898
|
state2.value = newValue;
|
|
901
899
|
state2.__v++;
|
|
902
|
-
if (
|
|
900
|
+
if (DEV) {
|
|
903
901
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
904
902
|
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
905
903
|
}
|
|
@@ -907,7 +905,7 @@ function signal(initial, options) {
|
|
|
907
905
|
notifySubscribers2(state2);
|
|
908
906
|
}
|
|
909
907
|
};
|
|
910
|
-
} else if (
|
|
908
|
+
} else if (DEV) {
|
|
911
909
|
set = (next) => {
|
|
912
910
|
const prev = state2.value;
|
|
913
911
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
@@ -932,7 +930,7 @@ function signal(initial, options) {
|
|
|
932
930
|
}
|
|
933
931
|
};
|
|
934
932
|
}
|
|
935
|
-
if (
|
|
933
|
+
if (DEV) {
|
|
936
934
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
937
935
|
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
938
936
|
}
|
|
@@ -1293,20 +1291,75 @@ function decodeCssEscapes(value) {
|
|
|
1293
1291
|
}
|
|
1294
1292
|
return out;
|
|
1295
1293
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1294
|
+
var BLOCKED_CSS_NEEDLES = [
|
|
1295
|
+
"url(",
|
|
1296
|
+
"expression(",
|
|
1297
|
+
"javascript:",
|
|
1298
|
+
"vbscript:",
|
|
1299
|
+
"-moz-binding",
|
|
1300
|
+
"behavior:",
|
|
1301
|
+
"@import",
|
|
1302
|
+
"image-set(",
|
|
1303
|
+
"filter:progid"
|
|
1304
|
+
];
|
|
1305
|
+
function describeElement(el) {
|
|
1306
|
+
if (!el) return "an element";
|
|
1307
|
+
let out = el.tagName.toLowerCase();
|
|
1308
|
+
const id = el.getAttribute("id");
|
|
1309
|
+
if (id) out += `#${id}`;
|
|
1310
|
+
const cls = el.getAttribute("class");
|
|
1311
|
+
if (cls) out += `.${cls.trim().split(/\s+/).slice(0, 3).join(".")}`;
|
|
1312
|
+
return `<${out}>`;
|
|
1313
|
+
}
|
|
1314
|
+
var warnedDeclarations = /* @__PURE__ */ new Set();
|
|
1315
|
+
var MAX_WARNED_DECLARATIONS = 100;
|
|
1316
|
+
var declarationCapAnnounced = false;
|
|
1317
|
+
function warnDroppedDeclaration(value, reason, ctx) {
|
|
1318
|
+
devWarnLazy(() => {
|
|
1319
|
+
const reasons = [
|
|
1320
|
+
"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",
|
|
1321
|
+
"expression() executes arbitrary script in legacy engines",
|
|
1322
|
+
"the javascript: scheme executes script",
|
|
1323
|
+
"the vbscript: scheme executes script",
|
|
1324
|
+
"-moz-binding loads and runs remote XBL",
|
|
1325
|
+
"behavior: loads and runs a remote HTC script",
|
|
1326
|
+
"@import pulls in a remote stylesheet",
|
|
1327
|
+
"image-set() fetches remote images, the same exfiltration channel as url()",
|
|
1328
|
+
"filter:progid activates legacy scriptable filters"
|
|
1329
|
+
];
|
|
1330
|
+
const declaration = ctx?.property ? `${ctx.property}: ${value}` : value;
|
|
1331
|
+
const where = describeElement(ctx?.element);
|
|
1332
|
+
const key = `${where}|${declaration}`;
|
|
1333
|
+
if (warnedDeclarations.has(key)) return "";
|
|
1334
|
+
if (warnedDeclarations.size >= MAX_WARNED_DECLARATIONS) {
|
|
1335
|
+
if (declarationCapAnnounced) return "";
|
|
1336
|
+
declarationCapAnnounced = true;
|
|
1337
|
+
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.`;
|
|
1338
|
+
}
|
|
1339
|
+
warnedDeclarations.add(key);
|
|
1340
|
+
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.`;
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
function blockedCssReason(value) {
|
|
1344
|
+
if (!CSS_DANGER_GATE.test(value)) return -1;
|
|
1298
1345
|
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
1299
1346
|
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
1300
|
-
|
|
1301
|
-
return
|
|
1347
|
+
for (let i = 0; i < BLOCKED_CSS_NEEDLES.length; i++) {
|
|
1348
|
+
if (lower.includes(BLOCKED_CSS_NEEDLES[i])) return i;
|
|
1302
1349
|
}
|
|
1303
|
-
return
|
|
1350
|
+
return -1;
|
|
1304
1351
|
}
|
|
1305
|
-
function
|
|
1352
|
+
function sanitizeCSSValue(value, context) {
|
|
1353
|
+
const reason = blockedCssReason(value);
|
|
1354
|
+
if (reason === -1) return value;
|
|
1355
|
+
warnDroppedDeclaration(value, reason, context);
|
|
1356
|
+
return "";
|
|
1357
|
+
}
|
|
1358
|
+
function sanitizeStyleAttribute(cssText, context) {
|
|
1306
1359
|
const input = String(cssText);
|
|
1307
1360
|
if (input.trim() === "") return "";
|
|
1308
1361
|
if (typeof document === "undefined") {
|
|
1309
|
-
return sanitizeCSSValue(input) === "" ? "" : input;
|
|
1362
|
+
return sanitizeCSSValue(input, context) === "" ? "" : input;
|
|
1310
1363
|
}
|
|
1311
1364
|
const probe = document.createElement("div");
|
|
1312
1365
|
try {
|
|
@@ -1318,8 +1371,12 @@ function sanitizeStyleAttribute(cssText) {
|
|
|
1318
1371
|
for (let i = 0; i < probe.style.length; i++) {
|
|
1319
1372
|
const property = probe.style[i];
|
|
1320
1373
|
const value = probe.style.getPropertyValue(property);
|
|
1321
|
-
|
|
1322
|
-
if (
|
|
1374
|
+
let reason = blockedCssReason(value);
|
|
1375
|
+
if (reason === -1) reason = blockedCssReason(`${property}:${value}`);
|
|
1376
|
+
if (reason !== -1) {
|
|
1377
|
+
warnDroppedDeclaration(value, reason, { property, element: context?.element });
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1323
1380
|
const priority = probe.style.getPropertyPriority(property);
|
|
1324
1381
|
declarations.push(`${property}: ${value}${priority ? ` !${priority}` : ""}`);
|
|
1325
1382
|
}
|
|
@@ -1347,16 +1404,15 @@ var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
|
1347
1404
|
function isHtmlContentAttribute(name) {
|
|
1348
1405
|
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
1349
1406
|
}
|
|
1350
|
-
function sanitizeAttributeString(attr, value) {
|
|
1407
|
+
function sanitizeAttributeString(attr, value, context) {
|
|
1351
1408
|
const lower = attr.toLowerCase();
|
|
1352
1409
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
1353
1410
|
if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
|
|
1354
|
-
if (lower === "style") return sanitizeStyleAttribute(value);
|
|
1411
|
+
if (lower === "style") return sanitizeStyleAttribute(value, context);
|
|
1355
1412
|
return value;
|
|
1356
1413
|
}
|
|
1357
1414
|
|
|
1358
1415
|
// src/utils/setSafeAttribute.ts
|
|
1359
|
-
var _isDev4 = isDev();
|
|
1360
1416
|
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
1361
1417
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
1362
1418
|
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
@@ -1379,7 +1435,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1379
1435
|
const ns = namespaceFor(el, name);
|
|
1380
1436
|
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
1381
1437
|
if (isEventHandlerAttr(name)) {
|
|
1382
|
-
if (
|
|
1438
|
+
if (DEV) {
|
|
1383
1439
|
devWarn(
|
|
1384
1440
|
`${options.label ?? "setSafeAttribute"}: refusing to set event-handler attribute "${name}". Its value would be evaluated as JavaScript. Use on:{ ${name.slice(2)}: fn } instead.`
|
|
1385
1441
|
);
|
|
@@ -1394,7 +1450,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1394
1450
|
return true;
|
|
1395
1451
|
}
|
|
1396
1452
|
if (isHtmlContentAttribute(name)) {
|
|
1397
|
-
if (
|
|
1453
|
+
if (DEV) {
|
|
1398
1454
|
devWarn(
|
|
1399
1455
|
`${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.`
|
|
1400
1456
|
);
|
|
@@ -1423,7 +1479,7 @@ function setSafeAttribute(el, name, value, options = {}) {
|
|
|
1423
1479
|
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
1424
1480
|
return true;
|
|
1425
1481
|
}
|
|
1426
|
-
const safe = sanitizeAttributeString(name, str);
|
|
1482
|
+
const safe = sanitizeAttributeString(name, str, { element: el });
|
|
1427
1483
|
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
1428
1484
|
if (current === safe) return true;
|
|
1429
1485
|
if (ns) el.setAttributeNS(ns, name, safe);
|
|
@@ -1461,7 +1517,6 @@ function reportDrainRunaway(label, executed, remaining) {
|
|
|
1461
1517
|
{ executed, remaining }
|
|
1462
1518
|
);
|
|
1463
1519
|
}
|
|
1464
|
-
var _isDev5 = isDev();
|
|
1465
1520
|
var activeBindingCount = 0;
|
|
1466
1521
|
function registerDisposer(node, teardown) {
|
|
1467
1522
|
let disposers = elementDisposers.get(node);
|
|
@@ -1470,7 +1525,7 @@ function registerDisposer(node, teardown) {
|
|
|
1470
1525
|
elementDisposers.set(node, disposers);
|
|
1471
1526
|
}
|
|
1472
1527
|
disposers.push(teardown);
|
|
1473
|
-
if (
|
|
1528
|
+
if (DEV) activeBindingCount++;
|
|
1474
1529
|
}
|
|
1475
1530
|
function dispose(node) {
|
|
1476
1531
|
const stack = [node];
|
|
@@ -1493,13 +1548,13 @@ function dispose(node) {
|
|
|
1493
1548
|
if (!pending || pending.length === 0) break;
|
|
1494
1549
|
const snapshot = pending.slice();
|
|
1495
1550
|
elementDisposers.delete(current);
|
|
1496
|
-
if (
|
|
1551
|
+
if (DEV) activeBindingCount -= snapshot.length;
|
|
1497
1552
|
for (let i2 = 0; i2 < snapshot.length; i2++) {
|
|
1498
1553
|
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
1499
1554
|
const rest = snapshot.slice(i2);
|
|
1500
1555
|
const added = elementDisposers.get(current);
|
|
1501
1556
|
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
1502
|
-
if (
|
|
1557
|
+
if (DEV) activeBindingCount += rest.length;
|
|
1503
1558
|
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
1504
1559
|
runaway = true;
|
|
1505
1560
|
break;
|
|
@@ -1516,8 +1571,101 @@ function dispose(node) {
|
|
|
1516
1571
|
}
|
|
1517
1572
|
}
|
|
1518
1573
|
|
|
1574
|
+
// src/core/rendering/focusPreservation.ts
|
|
1575
|
+
var IDENTITY_ATTRS = ["data-focus-key", "id", "name"];
|
|
1576
|
+
var SELECTABLE_TYPES = /* @__PURE__ */ new Set(["text", "search", "url", "tel", "password", ""]);
|
|
1577
|
+
function selectionOf(el) {
|
|
1578
|
+
const tag = el.tagName;
|
|
1579
|
+
const selectable = tag === "TEXTAREA" || tag === "INPUT" && SELECTABLE_TYPES.has(el.type.toLowerCase());
|
|
1580
|
+
if (!selectable) return { start: null, end: null, direction: null };
|
|
1581
|
+
const field = el;
|
|
1582
|
+
return { start: field.selectionStart, end: field.selectionEnd, direction: field.selectionDirection };
|
|
1583
|
+
}
|
|
1584
|
+
function captureFocusWithin(nodes) {
|
|
1585
|
+
if (nodes.length === 0 || typeof document === "undefined") return null;
|
|
1586
|
+
const active = document.activeElement;
|
|
1587
|
+
if (!active || active === document.body) return null;
|
|
1588
|
+
let inside = false;
|
|
1589
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1590
|
+
const n = nodes[i];
|
|
1591
|
+
if (n === active || n.nodeType === 1 && n.contains(active)) {
|
|
1592
|
+
inside = true;
|
|
1593
|
+
break;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
if (!inside) return null;
|
|
1597
|
+
let attr = null;
|
|
1598
|
+
let value = null;
|
|
1599
|
+
for (let i = 0; i < IDENTITY_ATTRS.length; i++) {
|
|
1600
|
+
const candidate = active.getAttribute(IDENTITY_ATTRS[i]);
|
|
1601
|
+
if (candidate) {
|
|
1602
|
+
attr = IDENTITY_ATTRS[i];
|
|
1603
|
+
value = candidate;
|
|
1604
|
+
break;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
return { el: active, attr, value, tag: active.tagName, ...selectionOf(active) };
|
|
1608
|
+
}
|
|
1609
|
+
function quote(value) {
|
|
1610
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
1611
|
+
}
|
|
1612
|
+
function findUniqueByIdentity(nodes, selector) {
|
|
1613
|
+
let el = null;
|
|
1614
|
+
let count = 0;
|
|
1615
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
1616
|
+
const n = nodes[i];
|
|
1617
|
+
if (n.nodeType !== 1) continue;
|
|
1618
|
+
const root = n;
|
|
1619
|
+
if (root.matches(selector)) {
|
|
1620
|
+
count++;
|
|
1621
|
+
el ?? (el = root);
|
|
1622
|
+
}
|
|
1623
|
+
const inner = root.querySelectorAll(selector);
|
|
1624
|
+
for (let j = 0; j < inner.length; j++) {
|
|
1625
|
+
count++;
|
|
1626
|
+
el ?? (el = inner[j]);
|
|
1627
|
+
}
|
|
1628
|
+
if (count > 1) return { el: null, count };
|
|
1629
|
+
}
|
|
1630
|
+
return count === 1 ? { el, count } : { el: null, count };
|
|
1631
|
+
}
|
|
1632
|
+
function refocus(el, snapshot) {
|
|
1633
|
+
el.focus();
|
|
1634
|
+
if (snapshot.start !== null && typeof el.setSelectionRange === "function") {
|
|
1635
|
+
const field = el;
|
|
1636
|
+
const max = field.value.length;
|
|
1637
|
+
const start = Math.min(snapshot.start, max);
|
|
1638
|
+
const end = Math.min(snapshot.end ?? start, max);
|
|
1639
|
+
field.setSelectionRange(start, end, snapshot.direction ?? "none");
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
function restoreFocusWithin(snapshot, nodes, where) {
|
|
1643
|
+
if (!snapshot) return;
|
|
1644
|
+
if (typeof document === "undefined") return;
|
|
1645
|
+
const active = document.activeElement;
|
|
1646
|
+
if (active === snapshot.el) return;
|
|
1647
|
+
if (active && active !== document.body && active !== document.documentElement) return;
|
|
1648
|
+
if (snapshot.el.isConnected) {
|
|
1649
|
+
refocus(snapshot.el, snapshot);
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
let ambiguous = false;
|
|
1653
|
+
if (snapshot.attr && snapshot.value) {
|
|
1654
|
+
const { el: replacement, count } = findUniqueByIdentity(nodes, `[${snapshot.attr}=${quote(snapshot.value)}]`);
|
|
1655
|
+
if (replacement && replacement.tagName === snapshot.tag) {
|
|
1656
|
+
refocus(replacement, snapshot);
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
ambiguous = count > 1;
|
|
1660
|
+
}
|
|
1661
|
+
devWarnLazy(() => {
|
|
1662
|
+
const id = snapshot.attr ? ` (${snapshot.attr}="${snapshot.value}")` : "";
|
|
1663
|
+
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";
|
|
1664
|
+
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.`;
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1519
1668
|
// src/reactivity/bindChildNode.ts
|
|
1520
|
-
var _isDev6 = isDev();
|
|
1521
1669
|
function bindChildNode(placeholder, getter) {
|
|
1522
1670
|
let lastNodes = [];
|
|
1523
1671
|
function commit() {
|
|
@@ -1528,6 +1676,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
1528
1676
|
reportError(err, { phase: "binding", name: "bindChildNode", node: placeholder });
|
|
1529
1677
|
return;
|
|
1530
1678
|
}
|
|
1679
|
+
const focused = captureFocusWithin(lastNodes);
|
|
1531
1680
|
if (result == null || typeof result === "boolean") {
|
|
1532
1681
|
for (let i = 0; i < lastNodes.length; i++) {
|
|
1533
1682
|
const node = lastNodes[i];
|
|
@@ -1535,6 +1684,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
1535
1684
|
if (node.parentNode) node.parentNode.removeChild(node);
|
|
1536
1685
|
}
|
|
1537
1686
|
lastNodes.length = 0;
|
|
1687
|
+
restoreFocusWithin(focused, lastNodes, "bindChildNode");
|
|
1538
1688
|
return;
|
|
1539
1689
|
}
|
|
1540
1690
|
const parent = placeholder.parentNode;
|
|
@@ -1551,8 +1701,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
1551
1701
|
if (item == null || typeof item === "boolean") continue;
|
|
1552
1702
|
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
1553
1703
|
if (seen.has(node)) {
|
|
1554
|
-
if (
|
|
1555
|
-
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
1704
|
+
if (DEV) devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
1556
1705
|
continue;
|
|
1557
1706
|
}
|
|
1558
1707
|
seen.add(node);
|
|
@@ -1585,12 +1734,12 @@ function bindChildNode(placeholder, getter) {
|
|
|
1585
1734
|
prev = node;
|
|
1586
1735
|
}
|
|
1587
1736
|
lastNodes = newNodes;
|
|
1737
|
+
restoreFocusWithin(focused, newNodes, "bindChildNode");
|
|
1588
1738
|
}
|
|
1589
1739
|
return reactiveBinding2(commit, placeholder);
|
|
1590
1740
|
}
|
|
1591
1741
|
|
|
1592
1742
|
// src/core/rendering/tagFactory.ts
|
|
1593
|
-
var _isDev7 = isDev();
|
|
1594
1743
|
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
1595
1744
|
function isBlockedTag(tag) {
|
|
1596
1745
|
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
@@ -1608,18 +1757,9 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
|
1608
1757
|
"self",
|
|
1609
1758
|
"frames"
|
|
1610
1759
|
]);
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
const tokens = t.split(/\s+/);
|
|
1615
|
-
let sawClassish = false;
|
|
1616
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
1617
|
-
const tok = tokens[i];
|
|
1618
|
-
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return false;
|
|
1619
|
-
if (/[-:/0-9]/.test(tok)) sawClassish = true;
|
|
1620
|
-
}
|
|
1621
|
-
return sawClassish;
|
|
1622
|
-
}
|
|
1760
|
+
var warnedLoneStrings = /* @__PURE__ */ new Set();
|
|
1761
|
+
var MAX_WARNED_LONE_STRINGS = 100;
|
|
1762
|
+
var loneStringCapAnnounced = false;
|
|
1623
1763
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
1624
1764
|
function toKebab(prop) {
|
|
1625
1765
|
let cached = kebabCache.get(prop);
|
|
@@ -1631,13 +1771,13 @@ function toKebab(prop) {
|
|
|
1631
1771
|
function applyStyle(el, style) {
|
|
1632
1772
|
if (typeof style === "function") {
|
|
1633
1773
|
const teardown = reactiveBinding2(() => {
|
|
1634
|
-
el.setAttribute("style", sanitizeStyleAttribute(String(style())));
|
|
1774
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(style()), { element: el }));
|
|
1635
1775
|
}, el);
|
|
1636
1776
|
registerDisposer(el, teardown);
|
|
1637
1777
|
return;
|
|
1638
1778
|
}
|
|
1639
1779
|
if (typeof style === "string") {
|
|
1640
|
-
el.setAttribute("style", sanitizeStyleAttribute(style));
|
|
1780
|
+
el.setAttribute("style", sanitizeStyleAttribute(style, { element: el }));
|
|
1641
1781
|
return;
|
|
1642
1782
|
}
|
|
1643
1783
|
const htmlEl = el;
|
|
@@ -1647,11 +1787,11 @@ function applyStyle(el, style) {
|
|
|
1647
1787
|
if (typeof val === "function") {
|
|
1648
1788
|
const getter = val;
|
|
1649
1789
|
const teardown = reactiveBinding2(() => {
|
|
1650
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
|
|
1790
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter()), { property: name, element: el }));
|
|
1651
1791
|
}, el);
|
|
1652
1792
|
registerDisposer(el, teardown);
|
|
1653
1793
|
} else {
|
|
1654
|
-
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val)));
|
|
1794
|
+
htmlEl.style.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
|
|
1655
1795
|
}
|
|
1656
1796
|
}
|
|
1657
1797
|
}
|
|
@@ -1758,11 +1898,26 @@ var tagFactory = (tag, ns) => {
|
|
|
1758
1898
|
appendChildren(el, second);
|
|
1759
1899
|
return el;
|
|
1760
1900
|
}
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1901
|
+
devWarnLazy(() => {
|
|
1902
|
+
const tokens = first.trim().split(/\s+/);
|
|
1903
|
+
if (tokens.length < 2) return "";
|
|
1904
|
+
let utilityTokens = 0;
|
|
1905
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1906
|
+
const tok = tokens[i];
|
|
1907
|
+
if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return "";
|
|
1908
|
+
if (/[-:/0-9]/.test(tok)) utilityTokens++;
|
|
1909
|
+
}
|
|
1910
|
+
if (utilityTokens < 2) return "";
|
|
1911
|
+
const key = `${tag}|${first}`;
|
|
1912
|
+
if (warnedLoneStrings.has(key)) return "";
|
|
1913
|
+
if (warnedLoneStrings.size >= MAX_WARNED_LONE_STRINGS) {
|
|
1914
|
+
if (loneStringCapAnnounced) return "";
|
|
1915
|
+
loneStringCapAnnounced = true;
|
|
1916
|
+
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.`;
|
|
1917
|
+
}
|
|
1918
|
+
warnedLoneStrings.add(key);
|
|
1919
|
+
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.`;
|
|
1920
|
+
});
|
|
1766
1921
|
el.textContent = first;
|
|
1767
1922
|
return el;
|
|
1768
1923
|
}
|
|
@@ -1779,7 +1934,7 @@ var tagFactory = (tag, ns) => {
|
|
|
1779
1934
|
if (pClass != null) applyClass(el, pClass);
|
|
1780
1935
|
const pId = props.id;
|
|
1781
1936
|
if (pId != null) {
|
|
1782
|
-
if (
|
|
1937
|
+
if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
1783
1938
|
devWarn(
|
|
1784
1939
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
1785
1940
|
);
|
|
@@ -1794,7 +1949,7 @@ var tagFactory = (tag, ns) => {
|
|
|
1794
1949
|
const handler = pOn[ev];
|
|
1795
1950
|
if (typeof handler === "function") {
|
|
1796
1951
|
el.addEventListener(ev, handler);
|
|
1797
|
-
} else if (
|
|
1952
|
+
} else if (DEV) {
|
|
1798
1953
|
devWarn(
|
|
1799
1954
|
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
1800
1955
|
);
|
package/dist/ecosystem.js
CHANGED
|
@@ -7,19 +7,19 @@ import {
|
|
|
7
7
|
mobXAdapter,
|
|
8
8
|
reduxAdapter,
|
|
9
9
|
zustandAdapter
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GDUNQCCW.js";
|
|
11
11
|
import "./chunk-WWV3SJ3L.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-6ZGI3RBE.js";
|
|
13
|
+
import "./chunk-HJEPKZ2O.js";
|
|
14
|
+
import "./chunk-2LOYNGBY.js";
|
|
15
|
+
import "./chunk-IXKSNWV5.js";
|
|
16
16
|
import "./chunk-7ZHH77QA.js";
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-7VEC3UD2.js";
|
|
18
|
+
import "./chunk-5DXA2J44.js";
|
|
19
|
+
import "./chunk-QKRPLZ2V.js";
|
|
20
|
+
import "./chunk-HECVW343.js";
|
|
21
|
+
import "./chunk-7ALC7KGE.js";
|
|
22
|
+
import "./chunk-2WLZ6757.js";
|
|
23
23
|
export {
|
|
24
24
|
antdAdapter,
|
|
25
25
|
chakraAdapter,
|