@jxsuite/runtime 3.0.0 → 4.0.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/dist/runtime.js +1400 -541
- package/dist/runtime.js.map +11 -10
- package/package.json +5 -4
- package/src/css.ts +883 -0
- package/src/expression.ts +34 -2
- package/src/runtime.ts +1633 -420
- package/src/statements.ts +42 -5
- package/src/types.ts +73 -1
package/dist/runtime.js
CHANGED
|
@@ -177,6 +177,13 @@ class EffectScope {
|
|
|
177
177
|
function effectScope(detached) {
|
|
178
178
|
return new EffectScope(detached);
|
|
179
179
|
}
|
|
180
|
+
function onScopeDispose(fn, failSilently = false) {
|
|
181
|
+
if (activeEffectScope) {
|
|
182
|
+
activeEffectScope.cleanups.push(fn);
|
|
183
|
+
} else if (!failSilently) {
|
|
184
|
+
warn(`onScopeDispose() is called when there is no active effect scope to be associated with.`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
180
187
|
var activeSub;
|
|
181
188
|
var pausedQueueEffects = /* @__PURE__ */ new WeakSet;
|
|
182
189
|
|
|
@@ -1012,6 +1019,7 @@ class ReadonlyReactiveHandler extends BaseReactiveHandler {
|
|
|
1012
1019
|
}
|
|
1013
1020
|
var mutableHandlers = /* @__PURE__ */ new MutableReactiveHandler;
|
|
1014
1021
|
var readonlyHandlers = /* @__PURE__ */ new ReadonlyReactiveHandler;
|
|
1022
|
+
var shallowReactiveHandlers = /* @__PURE__ */ new MutableReactiveHandler(true);
|
|
1015
1023
|
var toShallow = (value) => value;
|
|
1016
1024
|
var getProto = (v) => Reflect.getPrototypeOf(v);
|
|
1017
1025
|
function createIterableMethod(method, isReadonly2, isShallow2) {
|
|
@@ -1189,6 +1197,9 @@ function createInstrumentationGetter(isReadonly2, shallow) {
|
|
|
1189
1197
|
var mutableCollectionHandlers = {
|
|
1190
1198
|
get: /* @__PURE__ */ createInstrumentationGetter(false, false)
|
|
1191
1199
|
};
|
|
1200
|
+
var shallowCollectionHandlers = {
|
|
1201
|
+
get: /* @__PURE__ */ createInstrumentationGetter(false, true)
|
|
1202
|
+
};
|
|
1192
1203
|
var readonlyCollectionHandlers = {
|
|
1193
1204
|
get: /* @__PURE__ */ createInstrumentationGetter(true, false)
|
|
1194
1205
|
};
|
|
@@ -1223,6 +1234,9 @@ function reactive(target) {
|
|
|
1223
1234
|
}
|
|
1224
1235
|
return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
|
|
1225
1236
|
}
|
|
1237
|
+
function shallowReactive(target) {
|
|
1238
|
+
return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap);
|
|
1239
|
+
}
|
|
1226
1240
|
function readonly(target) {
|
|
1227
1241
|
return createReactiveObject(target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap);
|
|
1228
1242
|
}
|
|
@@ -1384,6 +1398,386 @@ function computed(getterOrOptions, debugOptions, isSSR = false) {
|
|
|
1384
1398
|
return cRef;
|
|
1385
1399
|
}
|
|
1386
1400
|
|
|
1401
|
+
// ../schema/src/guards.ts
|
|
1402
|
+
function isJsonObject(value) {
|
|
1403
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1404
|
+
}
|
|
1405
|
+
function isRef2(value) {
|
|
1406
|
+
return isJsonObject(value) && typeof value.$ref === "string";
|
|
1407
|
+
}
|
|
1408
|
+
function isFunctionDef(value) {
|
|
1409
|
+
return isJsonObject(value) && value.$prototype === "Function";
|
|
1410
|
+
}
|
|
1411
|
+
function isExpressionDef(value) {
|
|
1412
|
+
return isJsonObject(value) && isJsonObject(value.$expression);
|
|
1413
|
+
}
|
|
1414
|
+
function isNamedFormulaDef(value) {
|
|
1415
|
+
return isExpressionDef(value) && Array.isArray(value.parameters) && value.parameters.length > 0;
|
|
1416
|
+
}
|
|
1417
|
+
function hasStructuredBody(value) {
|
|
1418
|
+
return isFunctionDef(value) && Array.isArray(value.body);
|
|
1419
|
+
}
|
|
1420
|
+
function isPrototypeDef(value) {
|
|
1421
|
+
return isJsonObject(value) && typeof value.$prototype === "string" && value.$prototype !== "Function";
|
|
1422
|
+
}
|
|
1423
|
+
function isServerFnDef(value) {
|
|
1424
|
+
return isJsonObject(value) && value.timing === "server" && typeof value.$src === "string" && typeof value.$export === "string" && !value.$prototype;
|
|
1425
|
+
}
|
|
1426
|
+
var SCHEMA_KEYWORDS = new Set([
|
|
1427
|
+
"type",
|
|
1428
|
+
"enum",
|
|
1429
|
+
"minimum",
|
|
1430
|
+
"maximum",
|
|
1431
|
+
"minLength",
|
|
1432
|
+
"maxLength",
|
|
1433
|
+
"pattern",
|
|
1434
|
+
"format",
|
|
1435
|
+
"items",
|
|
1436
|
+
"properties",
|
|
1437
|
+
"required",
|
|
1438
|
+
"description",
|
|
1439
|
+
"title",
|
|
1440
|
+
"$comment"
|
|
1441
|
+
]);
|
|
1442
|
+
function isMappedArray(value) {
|
|
1443
|
+
return isJsonObject(value) && value.$prototype === "Array";
|
|
1444
|
+
}
|
|
1445
|
+
function isTemplateString(value) {
|
|
1446
|
+
return typeof value === "string" && value.includes("${");
|
|
1447
|
+
}
|
|
1448
|
+
function bodyReturnsValue(body) {
|
|
1449
|
+
return /\breturn\b[^\S\n]*(?![;}\s]|$)/.test(body);
|
|
1450
|
+
}
|
|
1451
|
+
function paramNames(parameters) {
|
|
1452
|
+
if (!parameters) {
|
|
1453
|
+
return [];
|
|
1454
|
+
}
|
|
1455
|
+
return parameters.map((p) => typeof p === "string" ? p : p.name);
|
|
1456
|
+
}
|
|
1457
|
+
function isTagExpression(tagName) {
|
|
1458
|
+
if (!isJsonObject(tagName) || !isJsonObject(tagName.$expression)) {
|
|
1459
|
+
return false;
|
|
1460
|
+
}
|
|
1461
|
+
const expression = tagName.$expression;
|
|
1462
|
+
if (expression.operator === "?:") {
|
|
1463
|
+
return typeof expression.value === "string" && typeof expression.initial === "string";
|
|
1464
|
+
}
|
|
1465
|
+
if (expression.operator === "switch") {
|
|
1466
|
+
return isJsonObject(expression.cases) && Object.values(expression.cases).every((tag) => typeof tag === "string") && typeof expression.default === "string";
|
|
1467
|
+
}
|
|
1468
|
+
return false;
|
|
1469
|
+
}
|
|
1470
|
+
function isPrivateStateKey(key) {
|
|
1471
|
+
return key.startsWith("#");
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
// src/css.ts
|
|
1475
|
+
function camelToKebab(s) {
|
|
1476
|
+
return s.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
1477
|
+
}
|
|
1478
|
+
var MEDIA_TYPES = new Set(["all", "print", "screen", "speech"]);
|
|
1479
|
+
function resolveAtQuery(atKey, mediaQueries) {
|
|
1480
|
+
if (atKey.startsWith("@--")) {
|
|
1481
|
+
return mediaQueries[atKey.slice(1)] ?? atKey.slice(1);
|
|
1482
|
+
}
|
|
1483
|
+
if (atKey.startsWith("@(")) {
|
|
1484
|
+
const inner = atKey.slice(2, -1).trim();
|
|
1485
|
+
return MEDIA_TYPES.has(inner.toLowerCase()) ? inner : atKey.slice(1);
|
|
1486
|
+
}
|
|
1487
|
+
return null;
|
|
1488
|
+
}
|
|
1489
|
+
function isDeclarationAtRule(atKey) {
|
|
1490
|
+
return atKey.startsWith("@position-try") || atKey.startsWith("@property") || atKey.startsWith("@font-face") || atKey.startsWith("@counter-style");
|
|
1491
|
+
}
|
|
1492
|
+
function isKeyframesAtRule(atKey) {
|
|
1493
|
+
return atKey.startsWith("@keyframes");
|
|
1494
|
+
}
|
|
1495
|
+
function resolveNestedSelector(scope, key) {
|
|
1496
|
+
const resolved = [];
|
|
1497
|
+
for (const scopePart of splitSelectorList(scope)) {
|
|
1498
|
+
for (const keyPart of splitSelectorList(key)) {
|
|
1499
|
+
resolved.push(resolveOneNestedSelector(scopePart, keyPart));
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
return resolved.join(", ");
|
|
1503
|
+
}
|
|
1504
|
+
function resolveOneNestedSelector(scope, key) {
|
|
1505
|
+
if (key.startsWith("&")) {
|
|
1506
|
+
return key.replaceAll("&", scope);
|
|
1507
|
+
}
|
|
1508
|
+
if (key.startsWith("[") || key.startsWith(":") || key.startsWith(".")) {
|
|
1509
|
+
return `${scope}${key}`;
|
|
1510
|
+
}
|
|
1511
|
+
return `${scope} ${key}`;
|
|
1512
|
+
}
|
|
1513
|
+
function splitSelectorList(selector) {
|
|
1514
|
+
const members = [];
|
|
1515
|
+
let depth = 0;
|
|
1516
|
+
let quote = null;
|
|
1517
|
+
let start = 0;
|
|
1518
|
+
for (let i = 0;i < selector.length; i += 1) {
|
|
1519
|
+
const ch = selector[i];
|
|
1520
|
+
if (quote) {
|
|
1521
|
+
if (ch === "\\") {
|
|
1522
|
+
i += 1;
|
|
1523
|
+
} else if (ch === quote) {
|
|
1524
|
+
quote = null;
|
|
1525
|
+
}
|
|
1526
|
+
continue;
|
|
1527
|
+
}
|
|
1528
|
+
if (ch === '"' || ch === "'") {
|
|
1529
|
+
quote = ch;
|
|
1530
|
+
} else if (ch === "(" || ch === "[") {
|
|
1531
|
+
depth += 1;
|
|
1532
|
+
} else if (ch === ")" || ch === "]") {
|
|
1533
|
+
depth = Math.max(0, depth - 1);
|
|
1534
|
+
} else if (ch === "," && depth === 0) {
|
|
1535
|
+
members.push(selector.slice(start, i));
|
|
1536
|
+
start = i + 1;
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
members.push(selector.slice(start));
|
|
1540
|
+
const trimmed = members.map((member) => member.trim()).filter((member) => member !== "");
|
|
1541
|
+
return trimmed.length > 0 ? trimmed : [selector];
|
|
1542
|
+
}
|
|
1543
|
+
function transposeCanvasPopoverSelector(selector) {
|
|
1544
|
+
return transposeCanvasOverlaySelector(selector);
|
|
1545
|
+
}
|
|
1546
|
+
var COMPOUND_BREAK = /[\s>+~,()]/;
|
|
1547
|
+
var LEADING_TYPE = /^[A-Za-z_\u{00A0}-\u{FFFF}][\w\u{00A0}-\u{FFFF}-]*/u;
|
|
1548
|
+
function transposeOpenAttribute(selector, options) {
|
|
1549
|
+
let out = "";
|
|
1550
|
+
let from = 0;
|
|
1551
|
+
for (;; ) {
|
|
1552
|
+
const at = selector.indexOf("[open]", from);
|
|
1553
|
+
if (at === -1) {
|
|
1554
|
+
return out + selector.slice(from);
|
|
1555
|
+
}
|
|
1556
|
+
let start = at;
|
|
1557
|
+
while (start > 0 && !COMPOUND_BREAK.test(selector[start - 1])) {
|
|
1558
|
+
start -= 1;
|
|
1559
|
+
}
|
|
1560
|
+
const type = LEADING_TYPE.exec(selector.slice(start, at))?.[0]?.toLowerCase();
|
|
1561
|
+
const dialog = type === undefined ? options.dialog === true : type === "dialog";
|
|
1562
|
+
out += selector.slice(from, at) + (dialog ? "[data-jx-dialog-open]" : "[open]");
|
|
1563
|
+
from = at + "[open]".length;
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
function transposeCanvasOverlaySelector(selector, options = {}) {
|
|
1567
|
+
if (selector.includes("::backdrop")) {
|
|
1568
|
+
return null;
|
|
1569
|
+
}
|
|
1570
|
+
const transposed = selector.replaceAll(":popover-open", "[data-jx-popover-open]").replaceAll(":modal", "[data-jx-dialog-open]").replaceAll("[inert]", "[data-jx-inert]");
|
|
1571
|
+
return transposeOpenAttribute(transposed, options);
|
|
1572
|
+
}
|
|
1573
|
+
var COLOR_SCHEME_ATTR = "data-color-scheme";
|
|
1574
|
+
var COLOR_SCHEME_STORAGE_KEY = "jx-color-scheme";
|
|
1575
|
+
function pureSchemeOf(query) {
|
|
1576
|
+
const m = /^\(\s*prefers-color-scheme\s*:\s*(light|dark)\s*\)$/.exec(query.trim());
|
|
1577
|
+
return m?.[1] ?? null;
|
|
1578
|
+
}
|
|
1579
|
+
function schemeSelectors(selector, scheme) {
|
|
1580
|
+
if (selector === ":root" || selector === "html") {
|
|
1581
|
+
return {
|
|
1582
|
+
auto: `${selector}:where(:not([${COLOR_SCHEME_ATTR}]))`,
|
|
1583
|
+
forced: `${selector}:where([${COLOR_SCHEME_ATTR}="${scheme}"])`
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
return {
|
|
1587
|
+
auto: `:where(:root:not([${COLOR_SCHEME_ATTR}])) ${selector}`,
|
|
1588
|
+
forced: `:where(:root[${COLOR_SCHEME_ATTR}="${scheme}"]) ${selector}`
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1591
|
+
function isNestedSelectorKey(key) {
|
|
1592
|
+
return key.startsWith(":") || key.startsWith(".") || key.startsWith("&") || key.startsWith("[");
|
|
1593
|
+
}
|
|
1594
|
+
function cssPropertyName(property) {
|
|
1595
|
+
return property.startsWith("--") ? property : camelToKebab(property);
|
|
1596
|
+
}
|
|
1597
|
+
function hashCss(text) {
|
|
1598
|
+
let h = 2166136261;
|
|
1599
|
+
for (let i = 0;i < text.length; i += 1) {
|
|
1600
|
+
h ^= text.charCodeAt(i);
|
|
1601
|
+
h = Math.imul(h, 16777619);
|
|
1602
|
+
}
|
|
1603
|
+
return (h >>> 0).toString(36);
|
|
1604
|
+
}
|
|
1605
|
+
function cssRuleText(conditions, selector, declarations) {
|
|
1606
|
+
const body = declarations.map(([property, value]) => `${property}: ${value}`).join("; ");
|
|
1607
|
+
let text = selector === null ? body : `${selector} { ${body} }`;
|
|
1608
|
+
for (let i = conditions.length - 1;i >= 0; i -= 1) {
|
|
1609
|
+
text = `${conditions[i]} { ${text} }`;
|
|
1610
|
+
}
|
|
1611
|
+
return text;
|
|
1612
|
+
}
|
|
1613
|
+
function cssKeyframesText(conditions, name, blocks) {
|
|
1614
|
+
const body = blocks.map(({ selector, declarations }) => `${selector} { ${declarations.map(([property, value]) => `${property}: ${value}`).join("; ")} }`).join(" ");
|
|
1615
|
+
let text = `@keyframes ${name} { ${body} }`;
|
|
1616
|
+
for (let i = conditions.length - 1;i >= 0; i -= 1) {
|
|
1617
|
+
text = `${conditions[i]} { ${text} }`;
|
|
1618
|
+
}
|
|
1619
|
+
return text;
|
|
1620
|
+
}
|
|
1621
|
+
function withoutKeyframes(block) {
|
|
1622
|
+
const keyframeKeys = Object.keys(block).filter((key) => isKeyframesAtRule(key));
|
|
1623
|
+
if (keyframeKeys.length === 0) {
|
|
1624
|
+
return block;
|
|
1625
|
+
}
|
|
1626
|
+
const rest = { ...block };
|
|
1627
|
+
for (const key of keyframeKeys) {
|
|
1628
|
+
delete rest[key];
|
|
1629
|
+
}
|
|
1630
|
+
return rest;
|
|
1631
|
+
}
|
|
1632
|
+
function compoundsOntoScope(key) {
|
|
1633
|
+
const rest = key.startsWith("&") ? key.slice(1) : key;
|
|
1634
|
+
return rest === "" || rest.startsWith(":") || rest.startsWith(".") || rest.startsWith("[");
|
|
1635
|
+
}
|
|
1636
|
+
function buildStyleRules(style, options = {}) {
|
|
1637
|
+
const {
|
|
1638
|
+
scope = null,
|
|
1639
|
+
mediaQueries = {},
|
|
1640
|
+
transposeValue = (value) => value,
|
|
1641
|
+
transposeSelector = (selector) => selector,
|
|
1642
|
+
resolveValue
|
|
1643
|
+
} = options;
|
|
1644
|
+
const rules = [];
|
|
1645
|
+
const isBlock = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && !isRef2(value);
|
|
1646
|
+
const blocksOf = (key, value) => {
|
|
1647
|
+
if (isBlock(value)) {
|
|
1648
|
+
return [value];
|
|
1649
|
+
}
|
|
1650
|
+
if (!isDeclarationAtRule(key) || !Array.isArray(value) || value.length === 0) {
|
|
1651
|
+
return [];
|
|
1652
|
+
}
|
|
1653
|
+
return value.every((entry) => isBlock(entry)) ? value : [];
|
|
1654
|
+
};
|
|
1655
|
+
const declarationValue = (property, value, reactive, target) => {
|
|
1656
|
+
if (value === undefined || value === null) {
|
|
1657
|
+
return null;
|
|
1658
|
+
}
|
|
1659
|
+
if (isRef2(value)) {
|
|
1660
|
+
return reactive ? resolveValue?.(property, value, target) ?? null : null;
|
|
1661
|
+
}
|
|
1662
|
+
if (typeof value === "object") {
|
|
1663
|
+
return null;
|
|
1664
|
+
}
|
|
1665
|
+
const raw = String(value);
|
|
1666
|
+
if (isTemplateString(raw)) {
|
|
1667
|
+
return reactive ? resolveValue?.(property, raw, target) ?? null : null;
|
|
1668
|
+
}
|
|
1669
|
+
return transposeValue(raw);
|
|
1670
|
+
};
|
|
1671
|
+
const declarationsOf = (node, skipSelectorKeys, reactive = true, target = "self") => {
|
|
1672
|
+
const declarations = [];
|
|
1673
|
+
for (const [key, value] of Object.entries(node)) {
|
|
1674
|
+
if (blocksOf(key, value).length > 0) {
|
|
1675
|
+
continue;
|
|
1676
|
+
}
|
|
1677
|
+
if (skipSelectorKeys && (key.startsWith("@") || isNestedSelectorKey(key))) {
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
if (key.startsWith("$")) {
|
|
1681
|
+
continue;
|
|
1682
|
+
}
|
|
1683
|
+
const resolved = declarationValue(key, value, reactive, target);
|
|
1684
|
+
if (resolved !== null) {
|
|
1685
|
+
declarations.push([cssPropertyName(key), resolved]);
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
return declarations;
|
|
1689
|
+
};
|
|
1690
|
+
const emit = (conditions, selector, declarations, target, description) => {
|
|
1691
|
+
if (declarations.length === 0) {
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
let resolved = selector;
|
|
1695
|
+
if (resolved !== null) {
|
|
1696
|
+
const transposed = transposeSelector(resolved);
|
|
1697
|
+
if (transposed === null) {
|
|
1698
|
+
return;
|
|
1699
|
+
}
|
|
1700
|
+
resolved = transposed;
|
|
1701
|
+
}
|
|
1702
|
+
const text = cssRuleText(conditions, resolved, declarations);
|
|
1703
|
+
rules.push({
|
|
1704
|
+
text,
|
|
1705
|
+
conditions: [...conditions],
|
|
1706
|
+
selector: resolved,
|
|
1707
|
+
declarations,
|
|
1708
|
+
target,
|
|
1709
|
+
key: hashCss(text),
|
|
1710
|
+
...typeof description === "string" && description !== "" ? { description } : {}
|
|
1711
|
+
});
|
|
1712
|
+
};
|
|
1713
|
+
const emitKeyframes = (atKey, block, conditions) => {
|
|
1714
|
+
const name = atKey.slice("@keyframes".length).trim();
|
|
1715
|
+
if (name === "") {
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
const blocks = [];
|
|
1719
|
+
for (const [key, value] of Object.entries(block)) {
|
|
1720
|
+
if (!isBlock(value)) {
|
|
1721
|
+
continue;
|
|
1722
|
+
}
|
|
1723
|
+
const declarations = declarationsOf(value, true, false, "unscoped");
|
|
1724
|
+
if (declarations.length > 0) {
|
|
1725
|
+
blocks.push({ declarations, selector: key.trim() });
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
if (blocks.length === 0) {
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
const text = cssKeyframesText(conditions, name, blocks);
|
|
1732
|
+
rules.push({
|
|
1733
|
+
blocks,
|
|
1734
|
+
conditions: [...conditions],
|
|
1735
|
+
declarations: [],
|
|
1736
|
+
key: hashCss(text),
|
|
1737
|
+
selector: null,
|
|
1738
|
+
target: "unscoped",
|
|
1739
|
+
text
|
|
1740
|
+
});
|
|
1741
|
+
};
|
|
1742
|
+
const walkAt = (atKey, block, selector, conditions, target) => {
|
|
1743
|
+
if (atKey === "@--") {
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
if (isDeclarationAtRule(atKey)) {
|
|
1747
|
+
emit([...conditions, atKey], null, declarationsOf(block, false, true, "unscoped"), "unscoped", block["$description"]);
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
if (isKeyframesAtRule(atKey)) {
|
|
1751
|
+
emitKeyframes(atKey, block, conditions);
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1754
|
+
const query = resolveAtQuery(atKey, mediaQueries);
|
|
1755
|
+
const atRule = query === null ? atKey : `@media ${query}`;
|
|
1756
|
+
const scheme = query === null ? null : pureSchemeOf(query);
|
|
1757
|
+
if (scheme !== null && selector !== null) {
|
|
1758
|
+
const { auto, forced } = schemeSelectors(selector, scheme);
|
|
1759
|
+
walk(block, auto, [...conditions, atRule], target);
|
|
1760
|
+
walk(withoutKeyframes(block), forced, conditions, target);
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
walk(block, selector, [...conditions, atRule], target);
|
|
1764
|
+
};
|
|
1765
|
+
function walk(node, selector, conditions, target) {
|
|
1766
|
+
emit(conditions, selector, declarationsOf(node, true, true, target), target, node["$description"]);
|
|
1767
|
+
for (const [key, value] of Object.entries(node)) {
|
|
1768
|
+
for (const block of blocksOf(key, value)) {
|
|
1769
|
+
if (key.startsWith("@")) {
|
|
1770
|
+
walkAt(key, block, selector, conditions, target);
|
|
1771
|
+
} else if (selector !== null) {
|
|
1772
|
+
walk(block, resolveNestedSelector(selector, key), conditions, compoundsOntoScope(key) ? target : "descendant");
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
walk(style, scope, [], "self");
|
|
1778
|
+
return rules;
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1387
1781
|
// ../schema/src/intl.ts
|
|
1388
1782
|
var DEFAULT_FORMAT_LOCALE = "en-US";
|
|
1389
1783
|
var DEFAULT_TIME_ZONE = "UTC";
|
|
@@ -1614,8 +2008,8 @@ function withPageLocale(path, args, state) {
|
|
|
1614
2008
|
filled[index] = locale;
|
|
1615
2009
|
return filled;
|
|
1616
2010
|
}
|
|
1617
|
-
function isBlessedGlobal(
|
|
1618
|
-
return
|
|
2011
|
+
function isBlessedGlobal(ref) {
|
|
2012
|
+
return ref.startsWith("window#/") && BLESSED_GLOBALS.has(ref.slice("window#/".length));
|
|
1619
2013
|
}
|
|
1620
2014
|
function isMutating(op) {
|
|
1621
2015
|
return MUTATING_OPS.has(op);
|
|
@@ -1654,24 +2048,43 @@ function resolveOperand(operand, state, event, iterCtx, trace) {
|
|
|
1654
2048
|
trace?.report(trace.path ?? [], operand);
|
|
1655
2049
|
return operand;
|
|
1656
2050
|
}
|
|
1657
|
-
function
|
|
1658
|
-
|
|
2051
|
+
function calleeOwner(ref, state, event, iterCtx) {
|
|
2052
|
+
const parentRef = (prefix) => {
|
|
2053
|
+
const rest = ref.slice(prefix.length);
|
|
2054
|
+
if (!rest.includes("/")) {
|
|
2055
|
+
return state;
|
|
2056
|
+
}
|
|
2057
|
+
return resolveExprRef(ref.slice(0, ref.lastIndexOf("/")), state, event, iterCtx);
|
|
2058
|
+
};
|
|
2059
|
+
if (ref.startsWith("#/state/")) {
|
|
2060
|
+
return parentRef("#/state/");
|
|
2061
|
+
}
|
|
2062
|
+
if (ref.startsWith("parent#/")) {
|
|
2063
|
+
return parentRef("parent#/");
|
|
2064
|
+
}
|
|
2065
|
+
if (ref.startsWith("$map/") || ref.startsWith("$args/")) {
|
|
2066
|
+
return ref.split("/").length > 2 ? resolveExprRef(ref.slice(0, ref.lastIndexOf("/")), state, event, iterCtx) : undefined;
|
|
2067
|
+
}
|
|
2068
|
+
return;
|
|
2069
|
+
}
|
|
2070
|
+
function resolveExprRef(ref, state, event, iterCtx) {
|
|
2071
|
+
if (ref === "$reduce/acc") {
|
|
1659
2072
|
return iterCtx?.acc;
|
|
1660
2073
|
}
|
|
1661
|
-
if (
|
|
2074
|
+
if (ref.startsWith("$reduce/")) {
|
|
1662
2075
|
return iterCtx?.acc;
|
|
1663
2076
|
}
|
|
1664
|
-
if (
|
|
1665
|
-
const parts =
|
|
2077
|
+
if (ref.startsWith("$args/")) {
|
|
2078
|
+
const parts = ref.slice("$args/".length).split("/");
|
|
1666
2079
|
const base = iterCtx?.args?.[parts[0]];
|
|
1667
2080
|
return parts.length > 1 ? getPath(base, parts.slice(1).join("/")) : base;
|
|
1668
2081
|
}
|
|
1669
|
-
if (
|
|
1670
|
-
const path =
|
|
2082
|
+
if (ref.startsWith("event#/")) {
|
|
2083
|
+
const path = ref.slice("event#/".length);
|
|
1671
2084
|
return getPath(event, path);
|
|
1672
2085
|
}
|
|
1673
|
-
if (
|
|
1674
|
-
const parts =
|
|
2086
|
+
if (ref.startsWith("$map/")) {
|
|
2087
|
+
const parts = ref.split("/");
|
|
1675
2088
|
const [, key] = parts;
|
|
1676
2089
|
let base;
|
|
1677
2090
|
const map = scopeMap(state);
|
|
@@ -1684,23 +2097,23 @@ function resolveExprRef(ref2, state, event, iterCtx) {
|
|
|
1684
2097
|
}
|
|
1685
2098
|
return parts.length > 2 ? getPath(base, parts.slice(2).join("/")) : base;
|
|
1686
2099
|
}
|
|
1687
|
-
if (
|
|
1688
|
-
return readPath(state,
|
|
2100
|
+
if (ref.startsWith("#/state/")) {
|
|
2101
|
+
return readPath(state, ref.slice("#/state/".length));
|
|
1689
2102
|
}
|
|
1690
|
-
if (
|
|
1691
|
-
return readPath(state,
|
|
2103
|
+
if (ref.startsWith("parent#/")) {
|
|
2104
|
+
return readPath(state, ref.slice("parent#/".length));
|
|
1692
2105
|
}
|
|
1693
|
-
if (
|
|
1694
|
-
return getPath(globalThis.window,
|
|
2106
|
+
if (ref.startsWith("window#/")) {
|
|
2107
|
+
return getPath(globalThis.window, ref.slice("window#/".length));
|
|
1695
2108
|
}
|
|
1696
|
-
if (
|
|
1697
|
-
return getPath(globalThis.document,
|
|
2109
|
+
if (ref.startsWith("document#/")) {
|
|
2110
|
+
return getPath(globalThis.document, ref.slice("document#/".length));
|
|
1698
2111
|
}
|
|
1699
|
-
return readPath(state,
|
|
2112
|
+
return readPath(state, ref) ?? null;
|
|
1700
2113
|
}
|
|
1701
|
-
function resolveWritableRef(
|
|
1702
|
-
if (
|
|
1703
|
-
const parts =
|
|
2114
|
+
function resolveWritableRef(ref, state, _event, iterCtx) {
|
|
2115
|
+
if (ref.startsWith("$map/")) {
|
|
2116
|
+
const parts = ref.split("/");
|
|
1704
2117
|
const [, key] = parts;
|
|
1705
2118
|
let base;
|
|
1706
2119
|
const map = scopeMap(state);
|
|
@@ -1722,8 +2135,8 @@ function resolveWritableRef(ref2, state, _event, iterCtx) {
|
|
|
1722
2135
|
obj: scopeMap(state) ?? state
|
|
1723
2136
|
};
|
|
1724
2137
|
}
|
|
1725
|
-
if (
|
|
1726
|
-
const sub =
|
|
2138
|
+
if (ref.startsWith("#/state/")) {
|
|
2139
|
+
const sub = ref.slice("#/state/".length);
|
|
1727
2140
|
const slash = sub.indexOf("/");
|
|
1728
2141
|
if (slash === -1) {
|
|
1729
2142
|
return { key: sub, obj: state };
|
|
@@ -1736,7 +2149,7 @@ function resolveWritableRef(ref2, state, _event, iterCtx) {
|
|
|
1736
2149
|
}
|
|
1737
2150
|
return { key: lastKey, obj };
|
|
1738
2151
|
}
|
|
1739
|
-
return { key:
|
|
2152
|
+
return { key: ref, obj: state };
|
|
1740
2153
|
}
|
|
1741
2154
|
function evaluateExpression(node, state, event, iterCtx, trace) {
|
|
1742
2155
|
const result = evaluateNode(node, state, event, iterCtx, trace);
|
|
@@ -1783,19 +2196,19 @@ function evaluateNode(node, state, event, iterCtx, trace) {
|
|
|
1783
2196
|
}
|
|
1784
2197
|
const callee = resolveExprRef(calleeRef, state, event, iterCtx);
|
|
1785
2198
|
if (typeof callee === "function") {
|
|
1786
|
-
return callee(
|
|
2199
|
+
return callee.apply(calleeOwner(calleeRef, state, event, iterCtx), argValues);
|
|
1787
2200
|
}
|
|
1788
2201
|
if (callee && typeof callee === "object" && "$expression" in callee) {
|
|
1789
|
-
const
|
|
2202
|
+
const def = callee;
|
|
1790
2203
|
const args = {};
|
|
1791
|
-
for (const [i, p] of (
|
|
2204
|
+
for (const [i, p] of (def.parameters ?? []).entries()) {
|
|
1792
2205
|
const name = typeof p === "string" ? p : p?.name ?? "";
|
|
1793
2206
|
if (!name) {
|
|
1794
2207
|
continue;
|
|
1795
2208
|
}
|
|
1796
2209
|
args[name] = argValues[i] === undefined && typeof p === "object" && p !== null && "default" in p ? p.default : argValues[i];
|
|
1797
2210
|
}
|
|
1798
|
-
return evaluateExpression(
|
|
2211
|
+
return evaluateExpression(def.$expression, state, event, { args, callDepth });
|
|
1799
2212
|
}
|
|
1800
2213
|
throw new TypeError(`$expression: call target "${calleeRef}" is not callable`);
|
|
1801
2214
|
}
|
|
@@ -1969,69 +2382,6 @@ function evaluateOperand(operand, state, event, iterCtx) {
|
|
|
1969
2382
|
return resolveOperand(operand, state, event, iterCtx);
|
|
1970
2383
|
}
|
|
1971
2384
|
|
|
1972
|
-
// ../schema/src/guards.ts
|
|
1973
|
-
function isJsonObject(value) {
|
|
1974
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1975
|
-
}
|
|
1976
|
-
function isRef2(value) {
|
|
1977
|
-
return isJsonObject(value) && typeof value.$ref === "string";
|
|
1978
|
-
}
|
|
1979
|
-
function isFunctionDef(value) {
|
|
1980
|
-
return isJsonObject(value) && value.$prototype === "Function";
|
|
1981
|
-
}
|
|
1982
|
-
function isExpressionDef(value) {
|
|
1983
|
-
return isJsonObject(value) && isJsonObject(value.$expression);
|
|
1984
|
-
}
|
|
1985
|
-
function isNamedFormulaDef(value) {
|
|
1986
|
-
return isExpressionDef(value) && Array.isArray(value.parameters) && value.parameters.length > 0;
|
|
1987
|
-
}
|
|
1988
|
-
function hasStructuredBody(value) {
|
|
1989
|
-
return isFunctionDef(value) && Array.isArray(value.body);
|
|
1990
|
-
}
|
|
1991
|
-
function isPrototypeDef(value) {
|
|
1992
|
-
return isJsonObject(value) && typeof value.$prototype === "string" && value.$prototype !== "Function";
|
|
1993
|
-
}
|
|
1994
|
-
function isServerFnDef(value) {
|
|
1995
|
-
return isJsonObject(value) && value.timing === "server" && typeof value.$src === "string" && typeof value.$export === "string" && !value.$prototype;
|
|
1996
|
-
}
|
|
1997
|
-
var SCHEMA_KEYWORDS = new Set([
|
|
1998
|
-
"type",
|
|
1999
|
-
"enum",
|
|
2000
|
-
"minimum",
|
|
2001
|
-
"maximum",
|
|
2002
|
-
"minLength",
|
|
2003
|
-
"maxLength",
|
|
2004
|
-
"pattern",
|
|
2005
|
-
"format",
|
|
2006
|
-
"items",
|
|
2007
|
-
"properties",
|
|
2008
|
-
"required",
|
|
2009
|
-
"description",
|
|
2010
|
-
"title",
|
|
2011
|
-
"$comment"
|
|
2012
|
-
]);
|
|
2013
|
-
function isMappedArray(value) {
|
|
2014
|
-
return isJsonObject(value) && value.$prototype === "Array";
|
|
2015
|
-
}
|
|
2016
|
-
function isTemplateString(value) {
|
|
2017
|
-
return typeof value === "string" && value.includes("${");
|
|
2018
|
-
}
|
|
2019
|
-
function bodyReturnsValue(body) {
|
|
2020
|
-
return /\breturn\b[^\S\n]*(?![;}\s]|$)/.test(body);
|
|
2021
|
-
}
|
|
2022
|
-
function paramNames(parameters) {
|
|
2023
|
-
if (!parameters) {
|
|
2024
|
-
return [];
|
|
2025
|
-
}
|
|
2026
|
-
return parameters.map((p) => typeof p === "string" ? p : p.name);
|
|
2027
|
-
}
|
|
2028
|
-
function isTagExpression(tagName) {
|
|
2029
|
-
return isJsonObject(tagName) && isJsonObject(tagName.$expression);
|
|
2030
|
-
}
|
|
2031
|
-
function isPrivateStateKey(key) {
|
|
2032
|
-
return key.startsWith("#");
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
2385
|
// ../schema/src/asset-paths.ts
|
|
2036
2386
|
var URL_TERMINATOR = String.raw`"'\s<>()\\`;
|
|
2037
2387
|
function parseSrcset(value) {
|
|
@@ -2084,6 +2434,12 @@ function statementKind(statement) {
|
|
|
2084
2434
|
if ("$switch" in statement) {
|
|
2085
2435
|
return "switch";
|
|
2086
2436
|
}
|
|
2437
|
+
if ("stopPropagation" in statement) {
|
|
2438
|
+
return "stopPropagation";
|
|
2439
|
+
}
|
|
2440
|
+
if ("preventDefault" in statement) {
|
|
2441
|
+
return "preventDefault";
|
|
2442
|
+
}
|
|
2087
2443
|
return "dispatch";
|
|
2088
2444
|
}
|
|
2089
2445
|
async function runStatements(statements, state, event, opts = {}) {
|
|
@@ -2117,7 +2473,8 @@ async function runStatements(statements, state, event, opts = {}) {
|
|
|
2117
2473
|
}
|
|
2118
2474
|
case "dispatch": {
|
|
2119
2475
|
const dispatch = statement;
|
|
2120
|
-
const
|
|
2476
|
+
const fallback = typeof opts.target === "function" ? opts.target() : opts.target;
|
|
2477
|
+
const target = event?.currentTarget ?? fallback;
|
|
2121
2478
|
if (!target) {
|
|
2122
2479
|
break;
|
|
2123
2480
|
}
|
|
@@ -2134,6 +2491,14 @@ async function runStatements(statements, state, event, opts = {}) {
|
|
|
2134
2491
|
target.dispatchEvent(new CustomEvent(dispatch.dispatchEvent, init));
|
|
2135
2492
|
break;
|
|
2136
2493
|
}
|
|
2494
|
+
case "stopPropagation": {
|
|
2495
|
+
event?.stopPropagation();
|
|
2496
|
+
break;
|
|
2497
|
+
}
|
|
2498
|
+
case "preventDefault": {
|
|
2499
|
+
event?.preventDefault();
|
|
2500
|
+
break;
|
|
2501
|
+
}
|
|
2137
2502
|
default: {
|
|
2138
2503
|
break;
|
|
2139
2504
|
}
|
|
@@ -2196,28 +2561,99 @@ function checkSchemaVersion($schema) {
|
|
|
2196
2561
|
async function Jx(source, target = document.body, options) {
|
|
2197
2562
|
const base = options?.base ? new URL(options.base, location.href).href : typeof source === "string" ? new URL(source, location.href).href : location.href;
|
|
2198
2563
|
const doc = await resolve(source);
|
|
2564
|
+
if (doc.$media) {
|
|
2565
|
+
_rootMedia = doc.$media;
|
|
2566
|
+
}
|
|
2567
|
+
const mounted = await mount(doc, target, {
|
|
2568
|
+
base,
|
|
2569
|
+
...options?.onNodeCreated ? { onNodeCreated: options.onNodeCreated } : {},
|
|
2570
|
+
...options?.signal ? { signal: options.signal } : {}
|
|
2571
|
+
});
|
|
2572
|
+
return mounted.scope;
|
|
2573
|
+
}
|
|
2574
|
+
var HOST_SCOPE_RESERVED = /^[$#]/;
|
|
2575
|
+
function assertHostScope(scope) {
|
|
2576
|
+
for (const key of Object.keys(scope)) {
|
|
2577
|
+
if (HOST_SCOPE_RESERVED.test(key)) {
|
|
2578
|
+
throw new TypeError(`Jx mount: host scope key "${key}" is reserved — names beginning with "$" or "#" are ` + `runtime vocabulary`);
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
async function mount(doc, target, options = {}) {
|
|
2583
|
+
const hostScope = options.scope ?? {};
|
|
2584
|
+
assertHostScope(hostScope);
|
|
2585
|
+
const base = options.base ? new URL(options.base, location.href).href : location.href;
|
|
2586
|
+
const ctx = {
|
|
2587
|
+
base,
|
|
2588
|
+
media: options.media ?? doc.$media ?? null,
|
|
2589
|
+
root: null,
|
|
2590
|
+
...options.resolver ? { resolver: options.resolver } : {},
|
|
2591
|
+
...options.skipServerFunctions === undefined ? {} : { skipServerFunctions: options.skipServerFunctions },
|
|
2592
|
+
...options.skipAutoRequests === undefined ? {} : { skipAutoRequests: options.skipAutoRequests }
|
|
2593
|
+
};
|
|
2199
2594
|
checkSchemaVersion(doc.$schema);
|
|
2200
2595
|
if (doc.$elements) {
|
|
2201
|
-
await registerElements(doc.$elements, base);
|
|
2596
|
+
await registerElements(doc.$elements, base, ctx);
|
|
2202
2597
|
}
|
|
2203
2598
|
if (doc.$head) {
|
|
2204
2599
|
injectHead(doc.$head, base);
|
|
2205
2600
|
}
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2601
|
+
const scope = await buildScope(doc, hostScope, base, ctx);
|
|
2602
|
+
const elements = new Set;
|
|
2603
|
+
const renderOptions = {
|
|
2604
|
+
_ctx: ctx,
|
|
2605
|
+
onNodeCreated: (el, path, def, state) => {
|
|
2606
|
+
if (el instanceof Element && el.tagName.includes("-")) {
|
|
2607
|
+
elements.add(el.tagName.toLowerCase());
|
|
2608
|
+
}
|
|
2609
|
+
options.onNodeCreated?.(el, path, def, state);
|
|
2610
|
+
},
|
|
2611
|
+
...options.onNodeMoved ? { onNodeMoved: options.onNodeMoved } : {}
|
|
2612
|
+
};
|
|
2613
|
+
const { result: root, stop } = runScoped(() => renderNode(doc, scope, renderOptions));
|
|
2614
|
+
ctx.root = root;
|
|
2615
|
+
let mounted = false;
|
|
2616
|
+
let disposed = false;
|
|
2617
|
+
const dispose = () => {
|
|
2618
|
+
if (disposed) {
|
|
2619
|
+
return;
|
|
2620
|
+
}
|
|
2621
|
+
disposed = true;
|
|
2622
|
+
options.signal?.removeEventListener("abort", dispose);
|
|
2623
|
+
stop();
|
|
2624
|
+
if (mounted && typeof scope.onUnmount === "function") {
|
|
2625
|
+
scope.onUnmount(scope);
|
|
2626
|
+
}
|
|
2627
|
+
root.remove();
|
|
2628
|
+
};
|
|
2629
|
+
if (options.signal?.aborted) {
|
|
2630
|
+
dispose();
|
|
2631
|
+
} else {
|
|
2632
|
+
options.signal?.addEventListener("abort", dispose, { once: true });
|
|
2633
|
+
target.append(root);
|
|
2634
|
+
mounted = true;
|
|
2635
|
+
if (typeof scope.onMount === "function") {
|
|
2636
|
+
scope.onMount(scope);
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
return { scope, root, elements, dispose };
|
|
2215
2640
|
}
|
|
2216
2641
|
var _resolveCache = new Map;
|
|
2217
|
-
|
|
2642
|
+
function preloadDocument(url, doc) {
|
|
2643
|
+
const settled = Promise.resolve(doc);
|
|
2644
|
+
_resolveCache.set(url, settled);
|
|
2645
|
+
try {
|
|
2646
|
+
_resolveCache.set(new URL(url, location.href).href, settled);
|
|
2647
|
+
} catch {}
|
|
2648
|
+
}
|
|
2649
|
+
async function resolve(source, ctx) {
|
|
2218
2650
|
if (typeof source !== "string") {
|
|
2219
2651
|
return source;
|
|
2220
2652
|
}
|
|
2653
|
+
const served = ctx?.resolver?.(source);
|
|
2654
|
+
if (served) {
|
|
2655
|
+
return served;
|
|
2656
|
+
}
|
|
2221
2657
|
if (_resolveCache.has(source)) {
|
|
2222
2658
|
return _resolveCache.get(source);
|
|
2223
2659
|
}
|
|
@@ -2303,10 +2739,36 @@ var _canvasDelinkAnchors = false;
|
|
|
2303
2739
|
function setCanvasDelinkAnchors(on) {
|
|
2304
2740
|
_canvasDelinkAnchors = on;
|
|
2305
2741
|
}
|
|
2742
|
+
var _canvasDelinkPopovers = false;
|
|
2743
|
+
function setCanvasDelinkPopovers(on) {
|
|
2744
|
+
_canvasDelinkPopovers = on;
|
|
2745
|
+
}
|
|
2746
|
+
var _canvasDelinkCommands = false;
|
|
2747
|
+
function setCanvasDelinkCommands(on) {
|
|
2748
|
+
_canvasDelinkCommands = on;
|
|
2749
|
+
}
|
|
2750
|
+
var _canvasInsideStampedHost = false;
|
|
2751
|
+
function canvasStamped(el) {
|
|
2752
|
+
return _canvasInsideStampedHost || el.dataset.jxPath !== undefined;
|
|
2753
|
+
}
|
|
2306
2754
|
function canvasAttrName(el, key) {
|
|
2307
2755
|
if (_canvasDelinkAnchors && key === "href" && (el.tagName === "A" || el.tagName === "AREA")) {
|
|
2308
2756
|
return "data-jx-href";
|
|
2309
2757
|
}
|
|
2758
|
+
if (_canvasDelinkPopovers && key === "popover" && canvasStamped(el)) {
|
|
2759
|
+
return "data-jx-popover";
|
|
2760
|
+
}
|
|
2761
|
+
if (_canvasDelinkCommands && canvasStamped(el)) {
|
|
2762
|
+
if (key === "commandfor") {
|
|
2763
|
+
return "data-jx-commandfor";
|
|
2764
|
+
}
|
|
2765
|
+
if (key === "inert") {
|
|
2766
|
+
return "data-jx-inert";
|
|
2767
|
+
}
|
|
2768
|
+
if (key === "open" && el.tagName === "DIALOG") {
|
|
2769
|
+
return "data-jx-open";
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2310
2772
|
return key;
|
|
2311
2773
|
}
|
|
2312
2774
|
var _canvasAssetResolver = null;
|
|
@@ -2386,71 +2848,84 @@ function boundPropKey(key, val, state) {
|
|
|
2386
2848
|
}
|
|
2387
2849
|
return sub;
|
|
2388
2850
|
}
|
|
2389
|
-
async function buildScope(doc, parentScope = {}, base = location.href) {
|
|
2851
|
+
async function buildScope(doc, parentScope = {}, base = location.href, ctx) {
|
|
2852
|
+
const dispatchRoot = () => ctx?.root ?? null;
|
|
2390
2853
|
const raw = {};
|
|
2391
|
-
for (const [key, val] of Object.entries(parentScope)) {
|
|
2392
|
-
raw[key] = val;
|
|
2393
|
-
}
|
|
2394
2854
|
const defs = doc.state ?? {};
|
|
2855
|
+
const linked = isReactive(parentScope);
|
|
2856
|
+
for (const key of Object.keys(parentScope)) {
|
|
2857
|
+
if (linked && !(key in defs)) {
|
|
2858
|
+
Object.defineProperty(raw, key, {
|
|
2859
|
+
configurable: true,
|
|
2860
|
+
enumerable: true,
|
|
2861
|
+
get: () => parentScope[key],
|
|
2862
|
+
set: (value) => {
|
|
2863
|
+
parentScope[key] = value;
|
|
2864
|
+
}
|
|
2865
|
+
});
|
|
2866
|
+
} else {
|
|
2867
|
+
raw[key] = parentScope[key];
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2395
2870
|
const imports = doc.imports ?? {};
|
|
2396
|
-
for (const [,
|
|
2397
|
-
if (isPrototypeDef(
|
|
2398
|
-
const mapped = imports[
|
|
2871
|
+
for (const [, def] of Object.entries(defs)) {
|
|
2872
|
+
if (isPrototypeDef(def) && !def.$src) {
|
|
2873
|
+
const mapped = imports[def.$prototype];
|
|
2399
2874
|
if (mapped) {
|
|
2400
2875
|
if (!mapped.endsWith(".class.json")) {
|
|
2401
|
-
console.warn(`Jx: import "${
|
|
2876
|
+
console.warn(`Jx: import "${def.$prototype}" must map to a .class.json path, got "${mapped}"`);
|
|
2402
2877
|
continue;
|
|
2403
2878
|
}
|
|
2404
|
-
|
|
2879
|
+
def.$src = mapped;
|
|
2405
2880
|
}
|
|
2406
2881
|
}
|
|
2407
2882
|
}
|
|
2408
|
-
for (const [key,
|
|
2409
|
-
if (typeof
|
|
2410
|
-
if (!
|
|
2411
|
-
raw[key] =
|
|
2883
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
2884
|
+
if (typeof def === "string") {
|
|
2885
|
+
if (!def.includes("${")) {
|
|
2886
|
+
raw[key] = def;
|
|
2412
2887
|
}
|
|
2413
2888
|
continue;
|
|
2414
2889
|
}
|
|
2415
|
-
if (typeof
|
|
2416
|
-
raw[key] =
|
|
2890
|
+
if (typeof def === "number" || typeof def === "boolean" || def === null) {
|
|
2891
|
+
raw[key] = def;
|
|
2417
2892
|
continue;
|
|
2418
2893
|
}
|
|
2419
|
-
if (Array.isArray(
|
|
2420
|
-
raw[key] =
|
|
2894
|
+
if (Array.isArray(def)) {
|
|
2895
|
+
raw[key] = def;
|
|
2421
2896
|
continue;
|
|
2422
2897
|
}
|
|
2423
|
-
if (typeof
|
|
2424
|
-
if (
|
|
2898
|
+
if (typeof def === "object") {
|
|
2899
|
+
if (def.$prototype) {
|
|
2425
2900
|
continue;
|
|
2426
2901
|
}
|
|
2427
|
-
if (isExpressionDef(
|
|
2902
|
+
if (isExpressionDef(def)) {
|
|
2428
2903
|
continue;
|
|
2429
2904
|
}
|
|
2430
|
-
if (isServerFnDef(
|
|
2905
|
+
if (isServerFnDef(def)) {
|
|
2431
2906
|
continue;
|
|
2432
2907
|
}
|
|
2433
|
-
if ("default" in
|
|
2434
|
-
raw[key] =
|
|
2908
|
+
if ("default" in def) {
|
|
2909
|
+
raw[key] = def.default;
|
|
2435
2910
|
continue;
|
|
2436
2911
|
}
|
|
2437
|
-
if (hasSchemaKeywords(
|
|
2912
|
+
if (hasSchemaKeywords(def)) {
|
|
2438
2913
|
continue;
|
|
2439
2914
|
}
|
|
2440
|
-
raw[key] =
|
|
2915
|
+
raw[key] = def;
|
|
2441
2916
|
}
|
|
2442
2917
|
}
|
|
2443
2918
|
const state = reactive(raw);
|
|
2444
|
-
for (const [key,
|
|
2445
|
-
if (typeof
|
|
2446
|
-
state[key] = computed(() => evaluateTemplate(
|
|
2919
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
2920
|
+
if (typeof def === "string" && def.includes("${")) {
|
|
2921
|
+
state[key] = computed(() => evaluateTemplate(def, state));
|
|
2447
2922
|
}
|
|
2448
2923
|
}
|
|
2449
|
-
for (const [key,
|
|
2450
|
-
if (isExpressionDef(
|
|
2451
|
-
const node =
|
|
2452
|
-
if (isNamedFormulaDef(
|
|
2453
|
-
const params =
|
|
2924
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
2925
|
+
if (isExpressionDef(def)) {
|
|
2926
|
+
const node = def.$expression;
|
|
2927
|
+
if (isNamedFormulaDef(def)) {
|
|
2928
|
+
const params = def.parameters;
|
|
2454
2929
|
state[key] = (...argValues) => {
|
|
2455
2930
|
const args = {};
|
|
2456
2931
|
for (const [i, p] of params.entries()) {
|
|
@@ -2470,11 +2945,11 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
|
|
|
2470
2945
|
}
|
|
2471
2946
|
}
|
|
2472
2947
|
}
|
|
2473
|
-
for (const [key,
|
|
2474
|
-
if (hasStructuredBody(
|
|
2475
|
-
const { body } =
|
|
2476
|
-
if (Array.isArray(
|
|
2477
|
-
const params =
|
|
2948
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
2949
|
+
if (hasStructuredBody(def)) {
|
|
2950
|
+
const { body } = def;
|
|
2951
|
+
if (Array.isArray(def.parameters) && def.parameters.length > 0) {
|
|
2952
|
+
const params = def.parameters;
|
|
2478
2953
|
state[key] = (...argValues) => {
|
|
2479
2954
|
const args = {};
|
|
2480
2955
|
for (const [i, p] of params.entries()) {
|
|
@@ -2484,34 +2959,35 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
|
|
|
2484
2959
|
}
|
|
2485
2960
|
args[name] = argValues[i] === undefined && typeof p === "object" && p !== null && "default" in p ? p.default : argValues[i];
|
|
2486
2961
|
}
|
|
2487
|
-
return runStatements(body, state, null, { args });
|
|
2962
|
+
return runStatements(body, state, null, { args, target: dispatchRoot });
|
|
2488
2963
|
};
|
|
2489
2964
|
} else {
|
|
2490
2965
|
const handler = (s, event) => {
|
|
2491
|
-
runStatements(body, s, event ?? null);
|
|
2966
|
+
runStatements(body, s, event ?? null, { target: dispatchRoot });
|
|
2492
2967
|
};
|
|
2493
2968
|
state[key] = handler;
|
|
2494
2969
|
}
|
|
2495
|
-
} else if (isFunctionDef(
|
|
2496
|
-
state[key] = await resolveFunction(
|
|
2970
|
+
} else if (isFunctionDef(def)) {
|
|
2971
|
+
state[key] = await resolveFunction(def, state, key, base);
|
|
2497
2972
|
}
|
|
2498
2973
|
}
|
|
2499
|
-
for (const [key,
|
|
2500
|
-
if (isPrototypeDef(
|
|
2501
|
-
state[key] = await resolvePrototype(
|
|
2974
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
2975
|
+
if (isPrototypeDef(def)) {
|
|
2976
|
+
state[key] = await resolvePrototype(def, state, key, base, ctx);
|
|
2502
2977
|
}
|
|
2503
2978
|
}
|
|
2504
|
-
if (!_serverFnConfig.skip) {
|
|
2505
|
-
for (const [key,
|
|
2506
|
-
if (isServerFnDef(
|
|
2507
|
-
state[key] = await resolveServerFunction(
|
|
2979
|
+
if (!(ctx?.skipServerFunctions ?? _serverFnConfig.skip)) {
|
|
2980
|
+
for (const [key, def] of Object.entries(defs)) {
|
|
2981
|
+
if (isServerFnDef(def)) {
|
|
2982
|
+
state[key] = await resolveServerFunction(def, state, key, base);
|
|
2508
2983
|
}
|
|
2509
2984
|
}
|
|
2510
2985
|
}
|
|
2986
|
+
const rootMedia = ctx?.media ?? _rootMedia;
|
|
2511
2987
|
if (doc.$media) {
|
|
2512
2988
|
state["$media"] = doc.$media;
|
|
2513
|
-
} else if (!state["$media"] && Object.keys(
|
|
2514
|
-
state["$media"] =
|
|
2989
|
+
} else if (!state["$media"] && Object.keys(rootMedia).length > 0) {
|
|
2990
|
+
state["$media"] = rootMedia;
|
|
2515
2991
|
}
|
|
2516
2992
|
return state;
|
|
2517
2993
|
}
|
|
@@ -2555,36 +3031,72 @@ function evaluateAttrTemplate(str, state) {
|
|
|
2555
3031
|
return fn(state, $map, $map?.item, $map?.index);
|
|
2556
3032
|
}
|
|
2557
3033
|
var _moduleCache = new Map;
|
|
2558
|
-
|
|
2559
|
-
|
|
3034
|
+
var _moduleLoaders = new Map;
|
|
3035
|
+
function preloadModule(specifier, mod) {
|
|
3036
|
+
if (typeof mod === "function") {
|
|
3037
|
+
_moduleCache.delete(specifier);
|
|
3038
|
+
_moduleLoaders.set(specifier, mod);
|
|
3039
|
+
return;
|
|
3040
|
+
}
|
|
3041
|
+
_moduleLoaders.delete(specifier);
|
|
3042
|
+
_moduleCache.set(specifier, mod);
|
|
3043
|
+
}
|
|
3044
|
+
function seededModule(src) {
|
|
3045
|
+
const cached = _moduleCache.get(src);
|
|
3046
|
+
if (cached) {
|
|
3047
|
+
return cached;
|
|
3048
|
+
}
|
|
3049
|
+
const pending = _moduleLoaders.get(src);
|
|
3050
|
+
if (!pending) {
|
|
3051
|
+
return;
|
|
3052
|
+
}
|
|
3053
|
+
if (typeof pending !== "function") {
|
|
3054
|
+
return pending;
|
|
3055
|
+
}
|
|
3056
|
+
const load = Promise.resolve(pending()).then((mod) => {
|
|
3057
|
+
_moduleCache.set(src, mod);
|
|
3058
|
+
_moduleLoaders.delete(src);
|
|
3059
|
+
return mod;
|
|
3060
|
+
}, (error) => {
|
|
3061
|
+
_moduleLoaders.set(src, pending);
|
|
3062
|
+
throw error;
|
|
3063
|
+
});
|
|
3064
|
+
_moduleLoaders.set(src, load);
|
|
3065
|
+
return load;
|
|
3066
|
+
}
|
|
3067
|
+
async function resolveFunction(def, state, key, base) {
|
|
3068
|
+
if (def.body && def.$src) {
|
|
2560
3069
|
throw new Error(`Jx: '${key}' declares both body and $src — these are mutually exclusive`);
|
|
2561
3070
|
}
|
|
2562
|
-
if (!
|
|
2563
|
-
const params = resolveParamNames(
|
|
3071
|
+
if (!def.body && !def.$src) {
|
|
3072
|
+
const params = resolveParamNames(def);
|
|
2564
3073
|
const noop = new Function(...params, "");
|
|
2565
3074
|
Object.defineProperty(noop, "name", {
|
|
2566
3075
|
configurable: true,
|
|
2567
|
-
value:
|
|
3076
|
+
value: def.name ?? key
|
|
2568
3077
|
});
|
|
2569
3078
|
return noop;
|
|
2570
3079
|
}
|
|
2571
3080
|
let fn;
|
|
2572
|
-
if (typeof
|
|
2573
|
-
const params = resolveParamNames(
|
|
2574
|
-
fn = new Function(...params,
|
|
3081
|
+
if (typeof def.body === "string") {
|
|
3082
|
+
const params = resolveParamNames(def);
|
|
3083
|
+
fn = new Function(...params, def.body);
|
|
2575
3084
|
Object.defineProperty(fn, "name", {
|
|
2576
3085
|
configurable: true,
|
|
2577
|
-
value:
|
|
3086
|
+
value: def.name ?? key
|
|
2578
3087
|
});
|
|
2579
3088
|
} else {
|
|
2580
|
-
const src =
|
|
3089
|
+
const src = def.$src;
|
|
2581
3090
|
if (!src) {
|
|
2582
3091
|
throw new Error(`Jx: '${key}' has neither body nor $src`);
|
|
2583
3092
|
}
|
|
2584
|
-
const exportName =
|
|
3093
|
+
const exportName = def.$export ?? key;
|
|
2585
3094
|
let mod;
|
|
2586
|
-
|
|
2587
|
-
|
|
3095
|
+
const seeded = seededModule(src);
|
|
3096
|
+
if (seeded instanceof Promise) {
|
|
3097
|
+
mod = await seeded;
|
|
3098
|
+
} else if (seeded) {
|
|
3099
|
+
mod = seeded;
|
|
2588
3100
|
} else {
|
|
2589
3101
|
if (base) {
|
|
2590
3102
|
const resolvedSrc = new URL(src, base).href;
|
|
@@ -2604,11 +3116,11 @@ async function resolveFunction(def2, state, key, base) {
|
|
|
2604
3116
|
}
|
|
2605
3117
|
fn = candidate;
|
|
2606
3118
|
}
|
|
2607
|
-
const hasParams = (
|
|
3119
|
+
const hasParams = (def.parameters ?? def.arguments ?? []).length > 0;
|
|
2608
3120
|
let isComputed = false;
|
|
2609
3121
|
if (!hasParams) {
|
|
2610
|
-
if (typeof
|
|
2611
|
-
isComputed = bodyReturnsValue(
|
|
3122
|
+
if (typeof def.body === "string") {
|
|
3123
|
+
isComputed = bodyReturnsValue(def.body);
|
|
2612
3124
|
} else if (fn) {
|
|
2613
3125
|
isComputed = fn.length <= 1 && bodyReturnsValue(fn.toString());
|
|
2614
3126
|
}
|
|
@@ -2618,8 +3130,8 @@ async function resolveFunction(def2, state, key, base) {
|
|
|
2618
3130
|
}
|
|
2619
3131
|
return fn;
|
|
2620
3132
|
}
|
|
2621
|
-
function resolveParamNames(
|
|
2622
|
-
const names =
|
|
3133
|
+
function resolveParamNames(def) {
|
|
3134
|
+
const names = def.parameters ? paramNames(def.parameters) : def.arguments ?? [];
|
|
2623
3135
|
return names.length > 0 && names[0] === "state" ? names : ["state", ...names];
|
|
2624
3136
|
}
|
|
2625
3137
|
var RESERVED_KEYS = new Set([
|
|
@@ -2668,19 +3180,19 @@ function elementNamespace(tagName, inherited) {
|
|
|
2668
3180
|
}
|
|
2669
3181
|
return inherited ?? null;
|
|
2670
3182
|
}
|
|
2671
|
-
function renderNode(
|
|
3183
|
+
function renderNode(def, state, options) {
|
|
2672
3184
|
const path = options?._path ?? [];
|
|
2673
|
-
if (typeof
|
|
2674
|
-
const textNode = document.createTextNode(String(
|
|
2675
|
-
if (typeof
|
|
3185
|
+
if (typeof def === "string" || typeof def === "number" || typeof def === "boolean") {
|
|
3186
|
+
const textNode = document.createTextNode(String(def));
|
|
3187
|
+
if (typeof def === "string" && isTemplateString(def)) {
|
|
2676
3188
|
effect(() => {
|
|
2677
|
-
textNode.textContent = evaluateTemplate(
|
|
3189
|
+
textNode.textContent = evaluateTemplate(def, state);
|
|
2678
3190
|
});
|
|
2679
3191
|
}
|
|
2680
3192
|
return textNode;
|
|
2681
3193
|
}
|
|
2682
3194
|
let localState = state;
|
|
2683
|
-
for (const [key, val] of Object.entries(
|
|
3195
|
+
for (const [key, val] of Object.entries(def)) {
|
|
2684
3196
|
if (key.startsWith("$") && !RESERVED_KEYS.has(key)) {
|
|
2685
3197
|
if (localState === state) {
|
|
2686
3198
|
localState = Object.create(state);
|
|
@@ -2688,38 +3200,41 @@ function renderNode(def2, state, options) {
|
|
|
2688
3200
|
localState[key] = isRefObj(val) ? resolveRef(val.$ref, state) : val;
|
|
2689
3201
|
}
|
|
2690
3202
|
}
|
|
2691
|
-
if ("$ref" in
|
|
2692
|
-
const refTarget = String(
|
|
3203
|
+
if ("$ref" in def && !def.tagName) {
|
|
3204
|
+
const refTarget = String(def.$ref ?? "");
|
|
2693
3205
|
if (!warnedRefChildren.has(refTarget)) {
|
|
2694
3206
|
warnedRefChildren.add(refTarget);
|
|
2695
3207
|
console.warn(`Jx: a $ref child ("${refTarget}") is not a supported component instance; register the ` + `component in $elements and use its custom-element tag instead (spec §13).`);
|
|
2696
3208
|
}
|
|
2697
3209
|
}
|
|
2698
|
-
const tagName = resolveTagName(
|
|
3210
|
+
const tagName = resolveTagName(def.tagName, localState);
|
|
2699
3211
|
const isCustomEl = tagName.includes("-") && customElements.get(tagName);
|
|
2700
|
-
if (
|
|
2701
|
-
return renderCustomElementWithProps(
|
|
3212
|
+
if (def.$props && isCustomEl) {
|
|
3213
|
+
return renderCustomElementWithProps(def, localState, options, path);
|
|
2702
3214
|
}
|
|
2703
|
-
if (
|
|
3215
|
+
if (def.$props) {
|
|
2704
3216
|
if (tagName.includes("-")) {
|
|
2705
|
-
return renderCustomElementWithProps(
|
|
3217
|
+
return renderCustomElementWithProps(def, localState, options, path);
|
|
2706
3218
|
}
|
|
2707
|
-
const { $props: _$props, ...rest } =
|
|
2708
|
-
return renderNode(rest, mergeProps(
|
|
3219
|
+
const { $props: _$props, ...rest } = def;
|
|
3220
|
+
return renderNode(rest, mergeProps(def, localState), options);
|
|
2709
3221
|
}
|
|
2710
|
-
if (
|
|
2711
|
-
return renderSwitch(
|
|
3222
|
+
if (def.$switch) {
|
|
3223
|
+
return renderSwitch(def, localState, options);
|
|
2712
3224
|
}
|
|
2713
3225
|
const ns = elementNamespace(tagName, options?._ns);
|
|
2714
3226
|
const childNs = tagName === "foreignObject" ? null : ns;
|
|
2715
3227
|
const el = ns ? document.createElementNS(ns, tagName) : document.createElement(tagName);
|
|
2716
3228
|
if (options?.onNodeCreated) {
|
|
2717
|
-
options.onNodeCreated(el, path,
|
|
3229
|
+
options.onNodeCreated(el, path, def, localState);
|
|
2718
3230
|
}
|
|
2719
|
-
applyProperties(el,
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
3231
|
+
applyProperties(el, def, localState);
|
|
3232
|
+
if (def.style && tagName.includes("-")) {
|
|
3233
|
+
callSiteStyles.set(el, def.style);
|
|
3234
|
+
}
|
|
3235
|
+
applyStyle(el, def.style ?? {}, localState["$media"] ?? {}, localState);
|
|
3236
|
+
applyAttributes(el, def.attributes ?? {}, localState);
|
|
3237
|
+
const kids = def.children;
|
|
2723
3238
|
if (isMappedArray(kids)) {
|
|
2724
3239
|
const arrOpts = options || childNs ? { ...options, _ns: childNs, _path: [...path, "children"] } : undefined;
|
|
2725
3240
|
renderMappedArrayInto(el, kids, localState, arrOpts);
|
|
@@ -2736,49 +3251,58 @@ function renderNode(def2, state, options) {
|
|
|
2736
3251
|
}
|
|
2737
3252
|
return el;
|
|
2738
3253
|
}
|
|
2739
|
-
function applyProperties(el,
|
|
2740
|
-
for (const [key, val] of Object.entries(
|
|
3254
|
+
function applyProperties(el, def, state) {
|
|
3255
|
+
for (const [key, val] of Object.entries(def)) {
|
|
2741
3256
|
if (RESERVED_KEYS.has(key)) {
|
|
2742
3257
|
continue;
|
|
2743
3258
|
}
|
|
2744
3259
|
if (key.startsWith("$")) {
|
|
2745
3260
|
continue;
|
|
2746
3261
|
}
|
|
2747
|
-
if (key.startsWith("on")) {
|
|
2748
|
-
|
|
2749
|
-
const handler = resolveRef(val.$ref, state);
|
|
2750
|
-
if (typeof handler === "function") {
|
|
2751
|
-
const scope = state;
|
|
2752
|
-
const handlerFn = handler;
|
|
2753
|
-
el.addEventListener(key.slice(2), (e) => handlerFn(scope, e));
|
|
2754
|
-
}
|
|
2755
|
-
continue;
|
|
2756
|
-
}
|
|
2757
|
-
if (hasStructuredBody(val)) {
|
|
2758
|
-
const { body } = val;
|
|
2759
|
-
const scope = state;
|
|
2760
|
-
el.addEventListener(key.slice(2), (e) => {
|
|
2761
|
-
runStatements(body, scope, e);
|
|
2762
|
-
});
|
|
2763
|
-
continue;
|
|
2764
|
-
}
|
|
2765
|
-
if (isFunctionDef(val) && typeof val.body === "string") {
|
|
2766
|
-
const params = resolveParamNames(val);
|
|
2767
|
-
const fn = new Function(...params, val.body);
|
|
2768
|
-
const scope = state;
|
|
2769
|
-
el.addEventListener(key.slice(2), (e) => fn(scope, e));
|
|
2770
|
-
continue;
|
|
2771
|
-
}
|
|
2772
|
-
if (isExpressionDef(val)) {
|
|
2773
|
-
const node = val.$expression;
|
|
2774
|
-
const scope = state;
|
|
2775
|
-
el.addEventListener(key.slice(2), (e) => evaluateExpression(node, scope, e));
|
|
2776
|
-
continue;
|
|
2777
|
-
}
|
|
3262
|
+
if (key.startsWith("on") && bindHandler(el, key, val, state)) {
|
|
3263
|
+
continue;
|
|
2778
3264
|
}
|
|
2779
3265
|
bindProperty(el, key, val, state);
|
|
2780
3266
|
}
|
|
2781
3267
|
}
|
|
3268
|
+
function bindHandler(el, key, val, state) {
|
|
3269
|
+
const type = key.slice(2);
|
|
3270
|
+
const scope = state;
|
|
3271
|
+
if (isRefObj(val)) {
|
|
3272
|
+
const handler = resolveRef(val.$ref, state);
|
|
3273
|
+
if (typeof handler === "function") {
|
|
3274
|
+
const handlerFn = handler;
|
|
3275
|
+
el.addEventListener(type, (e) => handlerFn(scope, e));
|
|
3276
|
+
}
|
|
3277
|
+
return true;
|
|
3278
|
+
}
|
|
3279
|
+
if (hasStructuredBody(val)) {
|
|
3280
|
+
const { body } = val;
|
|
3281
|
+
el.addEventListener(type, (e) => {
|
|
3282
|
+
runStatements(body, scope, e);
|
|
3283
|
+
});
|
|
3284
|
+
return true;
|
|
3285
|
+
}
|
|
3286
|
+
if (isFunctionDef(val) && typeof val.body === "string") {
|
|
3287
|
+
const params = resolveParamNames(val);
|
|
3288
|
+
const fn = new Function(...params, val.body);
|
|
3289
|
+
el.addEventListener(type, (e) => fn(scope, e));
|
|
3290
|
+
return true;
|
|
3291
|
+
}
|
|
3292
|
+
if (isExpressionDef(val)) {
|
|
3293
|
+
const node = val.$expression;
|
|
3294
|
+
el.addEventListener(type, (e) => evaluateExpression(node, scope, e));
|
|
3295
|
+
return true;
|
|
3296
|
+
}
|
|
3297
|
+
return false;
|
|
3298
|
+
}
|
|
3299
|
+
function bindDefinitionHandlers(host, def, state) {
|
|
3300
|
+
for (const [key, val] of Object.entries(def)) {
|
|
3301
|
+
if (key.startsWith("on") && !RESERVED_KEYS.has(key)) {
|
|
3302
|
+
bindHandler(host, key, val, state);
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
2782
3306
|
function bindProperty(el, key, val, state) {
|
|
2783
3307
|
const target = el;
|
|
2784
3308
|
const boundProp = boundPropKey(key, val, state);
|
|
@@ -2792,6 +3316,9 @@ function bindProperty(el, key, val, state) {
|
|
|
2792
3316
|
node.setAttribute("class", resolved == null ? "" : String(resolved));
|
|
2793
3317
|
return;
|
|
2794
3318
|
}
|
|
3319
|
+
if (target[key] === resolved) {
|
|
3320
|
+
return;
|
|
3321
|
+
}
|
|
2795
3322
|
target[key] = resolved;
|
|
2796
3323
|
};
|
|
2797
3324
|
if (isRefObj(val)) {
|
|
@@ -2813,144 +3340,300 @@ function bindProperty(el, key, val, state) {
|
|
|
2813
3340
|
}
|
|
2814
3341
|
write(asAsset(val));
|
|
2815
3342
|
}
|
|
2816
|
-
function
|
|
2817
|
-
const
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
3343
|
+
function cssomSink(sheet, detach) {
|
|
3344
|
+
const entries = [];
|
|
3345
|
+
return {
|
|
3346
|
+
detach,
|
|
3347
|
+
insert(texts) {
|
|
3348
|
+
const rules = [];
|
|
3349
|
+
for (const text of texts) {
|
|
3350
|
+
const index = sheet.cssRules.length;
|
|
3351
|
+
try {
|
|
3352
|
+
sheet.insertRule(text, index);
|
|
3353
|
+
} catch {
|
|
3354
|
+
continue;
|
|
3355
|
+
}
|
|
3356
|
+
const rule = sheet.cssRules[index];
|
|
3357
|
+
if (rule) {
|
|
3358
|
+
rules.push(rule);
|
|
2826
3359
|
}
|
|
2827
3360
|
}
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
3361
|
+
const inserted = { rules, texts };
|
|
3362
|
+
entries.push(inserted);
|
|
3363
|
+
return inserted;
|
|
3364
|
+
},
|
|
3365
|
+
remove(inserted) {
|
|
3366
|
+
const at = entries.indexOf(inserted);
|
|
3367
|
+
if (at !== -1) {
|
|
3368
|
+
entries.splice(at, 1);
|
|
2836
3369
|
}
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
3370
|
+
if (inserted.rules.length === 0) {
|
|
3371
|
+
return;
|
|
3372
|
+
}
|
|
3373
|
+
const list = [...sheet.cssRules];
|
|
3374
|
+
const indices = inserted.rules.map((rule) => list.indexOf(rule)).filter((index) => index >= 0).toSorted((a, b) => b - a);
|
|
3375
|
+
for (const index of indices) {
|
|
3376
|
+
sheet.deleteRule(index);
|
|
3377
|
+
}
|
|
3378
|
+
inserted.rules.length = 0;
|
|
3379
|
+
},
|
|
3380
|
+
replaceAll(texts) {
|
|
3381
|
+
entries.length = 0;
|
|
3382
|
+
entries.push({ rules: [], texts });
|
|
3383
|
+
sheet.replaceSync(texts.join(`
|
|
3384
|
+
`));
|
|
3385
|
+
},
|
|
3386
|
+
text() {
|
|
3387
|
+
return entries.flatMap((entry) => entry.texts.join(`
|
|
3388
|
+
`)).join(`
|
|
3389
|
+
`);
|
|
2844
3390
|
}
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
3391
|
+
};
|
|
3392
|
+
}
|
|
3393
|
+
function textSink(tag) {
|
|
3394
|
+
const entries = [];
|
|
3395
|
+
const write = () => {
|
|
3396
|
+
tag.textContent = entries.map((entry) => entry.texts.join(`
|
|
3397
|
+
`)).join(`
|
|
3398
|
+
`);
|
|
3399
|
+
};
|
|
3400
|
+
return {
|
|
3401
|
+
detach() {
|
|
3402
|
+
tag.remove();
|
|
3403
|
+
},
|
|
3404
|
+
insert(texts) {
|
|
3405
|
+
const inserted = { rules: [], texts };
|
|
3406
|
+
entries.push(inserted);
|
|
3407
|
+
write();
|
|
3408
|
+
return inserted;
|
|
3409
|
+
},
|
|
3410
|
+
remove(inserted) {
|
|
3411
|
+
const index = entries.indexOf(inserted);
|
|
3412
|
+
if (index !== -1) {
|
|
3413
|
+
entries.splice(index, 1);
|
|
3414
|
+
write();
|
|
2853
3415
|
}
|
|
2854
|
-
}
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
});
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
3416
|
+
},
|
|
3417
|
+
replaceAll(texts) {
|
|
3418
|
+
entries.length = 0;
|
|
3419
|
+
entries.push({ rules: [], texts });
|
|
3420
|
+
write();
|
|
3421
|
+
},
|
|
3422
|
+
text() {
|
|
3423
|
+
return tag.textContent ?? "";
|
|
2862
3424
|
}
|
|
3425
|
+
};
|
|
3426
|
+
}
|
|
3427
|
+
function openSink(doc) {
|
|
3428
|
+
const view = doc.defaultView;
|
|
3429
|
+
const SheetConstructor = view?.CSSStyleSheet;
|
|
3430
|
+
if (typeof SheetConstructor === "function" && Array.isArray(doc.adoptedStyleSheets)) {
|
|
3431
|
+
try {
|
|
3432
|
+
const sheet = new SheetConstructor;
|
|
3433
|
+
doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, sheet];
|
|
3434
|
+
return cssomSink(sheet, () => {
|
|
3435
|
+
doc.adoptedStyleSheets = doc.adoptedStyleSheets.filter((s) => s !== sheet);
|
|
3436
|
+
});
|
|
3437
|
+
} catch {}
|
|
3438
|
+
}
|
|
3439
|
+
const tag = doc.createElement("style");
|
|
3440
|
+
tag.dataset.jxSheet = "";
|
|
3441
|
+
(doc.head ?? doc.documentElement).append(tag);
|
|
3442
|
+
return tag.sheet ? cssomSink(tag.sheet, () => tag.remove()) : textSink(tag);
|
|
3443
|
+
}
|
|
3444
|
+
var sheetStates = new WeakMap;
|
|
3445
|
+
function sheetStateFor(doc) {
|
|
3446
|
+
const existing = sheetStates.get(doc);
|
|
3447
|
+
if (existing) {
|
|
3448
|
+
return existing;
|
|
3449
|
+
}
|
|
3450
|
+
const created = {
|
|
3451
|
+
hoisted: new Map,
|
|
3452
|
+
interned: new Map,
|
|
3453
|
+
scratch: null,
|
|
3454
|
+
scratchOwners: new Map,
|
|
3455
|
+
serial: 0,
|
|
3456
|
+
shared: openSink(doc)
|
|
3457
|
+
};
|
|
3458
|
+
sheetStates.set(doc, created);
|
|
3459
|
+
return created;
|
|
3460
|
+
}
|
|
3461
|
+
var elementStyles = new WeakMap;
|
|
3462
|
+
var SCOPE_TOKEN = "\x01jx-scope\x01";
|
|
3463
|
+
function rewriteScratch(state) {
|
|
3464
|
+
if (!state.scratch) {
|
|
3465
|
+
return;
|
|
2863
3466
|
}
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
3467
|
+
state.scratch.replaceAll([...state.scratchOwners.values()].flat());
|
|
3468
|
+
}
|
|
3469
|
+
function releaseInterned(state, table, key) {
|
|
3470
|
+
const entry = table.get(key);
|
|
3471
|
+
if (!entry) {
|
|
2868
3472
|
return;
|
|
2869
3473
|
}
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
if (baseCSS) {
|
|
2875
|
-
css += `[data-jx="${uid}"] { ${baseCSS} }
|
|
2876
|
-
`;
|
|
2877
|
-
}
|
|
2878
|
-
function emitNested(scope, rules) {
|
|
2879
|
-
const props = toCSSText(rules);
|
|
2880
|
-
if (props) {
|
|
2881
|
-
css += `${scope} { ${props} }
|
|
2882
|
-
`;
|
|
2883
|
-
}
|
|
2884
|
-
for (const [sel, sub] of Object.entries(rules)) {
|
|
2885
|
-
if (sub === null || typeof sub !== "object" || Array.isArray(sub)) {
|
|
2886
|
-
continue;
|
|
2887
|
-
}
|
|
2888
|
-
if (sel.startsWith("@")) {
|
|
2889
|
-
continue;
|
|
2890
|
-
}
|
|
2891
|
-
const resolved = sel.startsWith("&") ? sel.replace("&", scope) : sel.startsWith("[") ? `${scope}${sel}` : sel.startsWith(":") || sel.startsWith(".") ? `${scope}${sel}` : `${scope} ${sel}`;
|
|
2892
|
-
emitNested(resolved, sub);
|
|
2893
|
-
}
|
|
3474
|
+
entry.refs -= 1;
|
|
3475
|
+
if (entry.refs <= 0) {
|
|
3476
|
+
table.delete(key);
|
|
3477
|
+
state.shared.remove(entry.inserted);
|
|
2894
3478
|
}
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
3479
|
+
}
|
|
3480
|
+
function retainInterned(state, table, key, texts) {
|
|
3481
|
+
const existing = table.get(key);
|
|
3482
|
+
if (existing) {
|
|
3483
|
+
existing.refs += 1;
|
|
3484
|
+
return;
|
|
2898
3485
|
}
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
continue;
|
|
2906
|
-
}
|
|
2907
|
-
const resolved = sel.startsWith("&") ? sel.replace("&", parentSel) : sel.startsWith("[") ? `${parentSel}${sel}` : sel.startsWith(":") || sel.startsWith(".") ? `${parentSel}${sel}` : `${parentSel} ${sel}`;
|
|
2908
|
-
const props = toCSSText(sub);
|
|
2909
|
-
if (props) {
|
|
2910
|
-
css += `${atRule} { ${resolved} { ${props} } }
|
|
2911
|
-
`;
|
|
2912
|
-
}
|
|
2913
|
-
emitMediaNested(atRule, resolved, sub);
|
|
2914
|
-
}
|
|
3486
|
+
table.set(key, { inserted: state.shared.insert(texts), refs: 1 });
|
|
3487
|
+
}
|
|
3488
|
+
function releaseElementStyles(el, only) {
|
|
3489
|
+
const entry = elementStyles.get(el);
|
|
3490
|
+
if (!entry || only !== undefined && entry !== only) {
|
|
3491
|
+
return;
|
|
2915
3492
|
}
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
emitNested(forced, rules);
|
|
2930
|
-
} else {
|
|
2931
|
-
css += `${atRule} { ${scope} { ${toCSSText(rules)} } }
|
|
2932
|
-
`;
|
|
2933
|
-
emitMediaNested(atRule, scope, rules);
|
|
3493
|
+
elementStyles.delete(el);
|
|
3494
|
+
entry.stop?.();
|
|
3495
|
+
for (const name of entry.vars) {
|
|
3496
|
+
el.style.removeProperty(name);
|
|
3497
|
+
}
|
|
3498
|
+
delete el.dataset.jx;
|
|
3499
|
+
if (sheetStates.get(entry.doc) !== entry.state) {
|
|
3500
|
+
return;
|
|
3501
|
+
}
|
|
3502
|
+
const { state } = entry;
|
|
3503
|
+
if (entry.interned === null) {
|
|
3504
|
+
if (state.scratchOwners.delete(el)) {
|
|
3505
|
+
rewriteScratch(state);
|
|
2934
3506
|
}
|
|
3507
|
+
} else {
|
|
3508
|
+
releaseInterned(state, state.interned, entry.interned);
|
|
3509
|
+
}
|
|
3510
|
+
for (const key of entry.hoisted) {
|
|
3511
|
+
releaseInterned(state, state.hoisted, key);
|
|
3512
|
+
}
|
|
3513
|
+
}
|
|
3514
|
+
function resetDocumentStyles(doc = document) {
|
|
3515
|
+
const state = sheetStates.get(doc);
|
|
3516
|
+
if (!state) {
|
|
3517
|
+
return;
|
|
3518
|
+
}
|
|
3519
|
+
sheetStates.delete(doc);
|
|
3520
|
+
for (const el of state.scratchOwners.keys()) {
|
|
3521
|
+
elementStyles.delete(el);
|
|
3522
|
+
delete el.dataset.jx;
|
|
3523
|
+
}
|
|
3524
|
+
state.scratchOwners.clear();
|
|
3525
|
+
state.interned.clear();
|
|
3526
|
+
state.hoisted.clear();
|
|
3527
|
+
state.shared.detach();
|
|
3528
|
+
state.scratch?.detach();
|
|
3529
|
+
}
|
|
3530
|
+
function documentStyleText(doc = document) {
|
|
3531
|
+
const state = sheetStates.get(doc);
|
|
3532
|
+
if (!state) {
|
|
3533
|
+
return "";
|
|
2935
3534
|
}
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
3535
|
+
return [state.shared.text(), state.scratch?.text() ?? ""].filter(Boolean).join(`
|
|
3536
|
+
`);
|
|
3537
|
+
}
|
|
3538
|
+
function declaresDisplay(style) {
|
|
3539
|
+
return Boolean(style) && typeof style === "object" && "display" in style;
|
|
3540
|
+
}
|
|
3541
|
+
var callSiteStyles = new WeakMap;
|
|
3542
|
+
function mergeStyle(base, over) {
|
|
3543
|
+
if (!over) {
|
|
3544
|
+
return base;
|
|
3545
|
+
}
|
|
3546
|
+
const out = { ...base };
|
|
3547
|
+
for (const [key, value] of Object.entries(over)) {
|
|
3548
|
+
const prior = out[key];
|
|
3549
|
+
out[key] = prior !== null && typeof prior === "object" && value !== null && typeof value === "object" && !Array.isArray(value) ? mergeStyle(prior, value) : value;
|
|
3550
|
+
}
|
|
3551
|
+
return out;
|
|
3552
|
+
}
|
|
3553
|
+
function applyStyle(el, styleDef, mediaQueries = {}, state = {}) {
|
|
3554
|
+
applyStyleInto(el, styleDef, mediaQueries, state, false);
|
|
2941
3555
|
}
|
|
2942
|
-
var elementStyleTags = new WeakMap;
|
|
2943
3556
|
function reapplyStyle(el, styleDef, mediaQueries = {}, state = {}) {
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
3557
|
+
applyStyleInto(el, styleDef ?? {}, mediaQueries, state, true);
|
|
3558
|
+
}
|
|
3559
|
+
function applyStyleInto(el, styleDef, mediaQueries, state, live) {
|
|
3560
|
+
releaseElementStyles(el);
|
|
3561
|
+
const doc = el.ownerDocument ?? document;
|
|
3562
|
+
const sheetState = sheetStateFor(doc);
|
|
3563
|
+
const transposeSelector = (_canvasDelinkPopovers || _canvasDelinkCommands) && canvasStamped(el) ? (selector) => transposeCanvasOverlaySelector(selector, {
|
|
3564
|
+
dialog: el.tagName === "DIALOG"
|
|
3565
|
+
}) : (selector) => selector;
|
|
3566
|
+
let serial = -1;
|
|
3567
|
+
let indirect = 0;
|
|
3568
|
+
const sources = [];
|
|
3569
|
+
const rules = buildStyleRules(styleDef, {
|
|
3570
|
+
mediaQueries,
|
|
3571
|
+
resolveValue: (property, value, target) => {
|
|
3572
|
+
if (target === "self" && property.startsWith("--")) {
|
|
3573
|
+
sources.push({ name: property, value });
|
|
3574
|
+
return null;
|
|
3575
|
+
}
|
|
3576
|
+
if (serial < 0) {
|
|
3577
|
+
({ serial } = sheetState);
|
|
3578
|
+
sheetState.serial += 1;
|
|
3579
|
+
}
|
|
3580
|
+
const name = `--jx-r${serial}-${indirect}`;
|
|
3581
|
+
indirect += 1;
|
|
3582
|
+
sources.push({ name, value });
|
|
3583
|
+
return `var(${name})`;
|
|
3584
|
+
},
|
|
3585
|
+
scope: SCOPE_TOKEN,
|
|
3586
|
+
transposeSelector,
|
|
3587
|
+
transposeValue: canvasStyleValue
|
|
3588
|
+
});
|
|
3589
|
+
if (rules.length === 0 && sources.length === 0) {
|
|
3590
|
+
return;
|
|
2948
3591
|
}
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
3592
|
+
const scoped = rules.filter((rule) => rule.target !== "unscoped");
|
|
3593
|
+
const unscoped = rules.filter((rule) => rule.target === "unscoped");
|
|
3594
|
+
for (const rule of unscoped) {
|
|
3595
|
+
retainInterned(sheetState, sheetState.hoisted, rule.text, [rule.text]);
|
|
3596
|
+
}
|
|
3597
|
+
const uid = `jx-${hashCss(scoped.map((rule) => rule.key).join("|"))}`;
|
|
3598
|
+
const texts = scoped.map((rule) => rule.text.replaceAll(SCOPE_TOKEN, `[data-jx="${uid}"]`));
|
|
3599
|
+
if (texts.length > 0) {
|
|
3600
|
+
el.dataset.jx = uid;
|
|
3601
|
+
if (live) {
|
|
3602
|
+
sheetState.scratch ??= openSink(doc);
|
|
3603
|
+
sheetState.scratchOwners.set(el, texts);
|
|
3604
|
+
rewriteScratch(sheetState);
|
|
3605
|
+
} else {
|
|
3606
|
+
retainInterned(sheetState, sheetState.interned, uid, texts);
|
|
3607
|
+
}
|
|
3608
|
+
}
|
|
3609
|
+
const entry = {
|
|
3610
|
+
doc,
|
|
3611
|
+
hoisted: unscoped.map((rule) => rule.text),
|
|
3612
|
+
interned: texts.length > 0 && !live ? uid : null,
|
|
3613
|
+
state: sheetState,
|
|
3614
|
+
stop: null,
|
|
3615
|
+
uid,
|
|
3616
|
+
vars: sources.map((source) => source.name)
|
|
3617
|
+
};
|
|
3618
|
+
if (sources.length > 0) {
|
|
3619
|
+
const scope = effectScope();
|
|
3620
|
+
scope.run(() => {
|
|
3621
|
+
for (const { name, value } of sources) {
|
|
3622
|
+
effect(() => {
|
|
3623
|
+
const resolved = isRefObj(value) ? resolveRef(value.$ref, state) : evaluateTemplate(value, state);
|
|
3624
|
+
el.style.setProperty(name, canvasStyleValue(String(resolved ?? "")));
|
|
3625
|
+
});
|
|
3626
|
+
}
|
|
3627
|
+
});
|
|
3628
|
+
entry.stop = () => scope.stop();
|
|
3629
|
+
}
|
|
3630
|
+
elementStyles.set(el, entry);
|
|
3631
|
+
onScopeDispose(() => releaseElementStyles(el, entry), true);
|
|
2952
3632
|
}
|
|
2953
3633
|
var ENUMERATED_ATTRS = new Set(["contenteditable", "draggable", "spellcheck"]);
|
|
3634
|
+
function enumeratedAttrNames() {
|
|
3635
|
+
return [...ENUMERATED_ATTRS].toSorted();
|
|
3636
|
+
}
|
|
2954
3637
|
function booleanAttrValue(name, value) {
|
|
2955
3638
|
const lower = name.toLowerCase();
|
|
2956
3639
|
if (lower.startsWith("aria-") || ENUMERATED_ATTRS.has(lower)) {
|
|
@@ -2962,6 +3645,10 @@ function applyAttributes(el, attrs, state) {
|
|
|
2962
3645
|
for (const [k, v] of Object.entries(attrs)) {
|
|
2963
3646
|
const attr = canvasAttrName(el, k);
|
|
2964
3647
|
const write = (resolved) => {
|
|
3648
|
+
if (resolved === null || resolved === undefined) {
|
|
3649
|
+
el.removeAttribute(attr);
|
|
3650
|
+
return;
|
|
3651
|
+
}
|
|
2965
3652
|
if (typeof resolved === "boolean") {
|
|
2966
3653
|
const text = booleanAttrValue(attr, resolved);
|
|
2967
3654
|
if (text === null) {
|
|
@@ -2971,7 +3658,7 @@ function applyAttributes(el, attrs, state) {
|
|
|
2971
3658
|
}
|
|
2972
3659
|
return;
|
|
2973
3660
|
}
|
|
2974
|
-
el.setAttribute(attr, canvasAssetValue(el.tagName, k, String(resolved
|
|
3661
|
+
el.setAttribute(attr, canvasAssetValue(el.tagName, k, String(resolved)));
|
|
2975
3662
|
};
|
|
2976
3663
|
if (isRefObj(v)) {
|
|
2977
3664
|
effect(() => write(resolveRef(v.$ref, state)));
|
|
@@ -2986,8 +3673,69 @@ function renderMappedArrayInto(parentEl, arrayDef, state, options) {
|
|
|
2986
3673
|
const path = options?._path ?? [];
|
|
2987
3674
|
const anchor = document.createComment("jx-array");
|
|
2988
3675
|
parentEl.append(anchor);
|
|
2989
|
-
const { items: itemsSrc, map: mapDef, filter: filterRef, sort: sortRef } = arrayDef;
|
|
2990
|
-
|
|
3676
|
+
const { items: itemsSrc, map: mapDef, filter: filterRef, sort: sortRef, key: keyRef } = arrayDef;
|
|
3677
|
+
const keyPointer = isRefObj(keyRef) ? keyRef.$ref : null;
|
|
3678
|
+
let warned = false;
|
|
3679
|
+
const warnOnce = (message) => {
|
|
3680
|
+
if (!warned) {
|
|
3681
|
+
warned = true;
|
|
3682
|
+
console.warn(`Jx $map: ${message}`);
|
|
3683
|
+
}
|
|
3684
|
+
};
|
|
3685
|
+
let rows = [];
|
|
3686
|
+
const teardown = (row) => {
|
|
3687
|
+
row.scope.stop();
|
|
3688
|
+
row.node.remove();
|
|
3689
|
+
};
|
|
3690
|
+
const createRow = (key, item, index) => {
|
|
3691
|
+
const map = shallowReactive({ index, item });
|
|
3692
|
+
const child = Object.create(state);
|
|
3693
|
+
child.$map = map;
|
|
3694
|
+
Object.defineProperty(child, "$map/item", { enumerable: true, get: () => map.item });
|
|
3695
|
+
Object.defineProperty(child, "$map/index", { enumerable: true, get: () => map.index });
|
|
3696
|
+
const scope = effectScope(true);
|
|
3697
|
+
const childOpts = options ? { ...options, _path: [...path, "map", index] } : undefined;
|
|
3698
|
+
const node = scope.run(() => renderNode(mapDef, child, childOpts));
|
|
3699
|
+
return { key, map, node, scope };
|
|
3700
|
+
};
|
|
3701
|
+
const reconcile = (list, keys) => {
|
|
3702
|
+
const previous = new Map;
|
|
3703
|
+
for (const row of rows) {
|
|
3704
|
+
previous.set(row.key, row);
|
|
3705
|
+
}
|
|
3706
|
+
const next = [];
|
|
3707
|
+
for (let index = 0;index < list.length; index++) {
|
|
3708
|
+
const key = keys[index];
|
|
3709
|
+
const item = list[index];
|
|
3710
|
+
const existing = previous.get(key);
|
|
3711
|
+
if (existing) {
|
|
3712
|
+
previous.delete(key);
|
|
3713
|
+
if (existing.map.item !== item) {
|
|
3714
|
+
existing.map.item = item;
|
|
3715
|
+
}
|
|
3716
|
+
if (existing.map.index !== index) {
|
|
3717
|
+
existing.map.index = index;
|
|
3718
|
+
options?.onNodeMoved?.(existing.node, [...path, "map", index]);
|
|
3719
|
+
}
|
|
3720
|
+
next.push(existing);
|
|
3721
|
+
} else {
|
|
3722
|
+
next.push(createRow(key, item, index));
|
|
3723
|
+
}
|
|
3724
|
+
}
|
|
3725
|
+
for (const row of previous.values()) {
|
|
3726
|
+
teardown(row);
|
|
3727
|
+
}
|
|
3728
|
+
let cursor = rows.find((row) => !previous.has(row.key))?.node ?? anchor;
|
|
3729
|
+
for (const row of next) {
|
|
3730
|
+
if (row.node === cursor) {
|
|
3731
|
+
cursor = cursor.nextSibling ?? anchor;
|
|
3732
|
+
continue;
|
|
3733
|
+
}
|
|
3734
|
+
cursor.before(row.node);
|
|
3735
|
+
}
|
|
3736
|
+
rows = next;
|
|
3737
|
+
};
|
|
3738
|
+
const update = () => {
|
|
2991
3739
|
let items = isRefObj(itemsSrc) ? resolveRef(itemsSrc.$ref, state) : itemsSrc;
|
|
2992
3740
|
if (Array.isArray(items) && isRefObj(filterRef)) {
|
|
2993
3741
|
const fn = resolveRef(filterRef.$ref, state);
|
|
@@ -3001,30 +3749,65 @@ function renderMappedArrayInto(parentEl, arrayDef, state, options) {
|
|
|
3001
3749
|
items = [...items].toSorted(fn);
|
|
3002
3750
|
}
|
|
3003
3751
|
}
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
child["$map/item"] = item;
|
|
3014
|
-
child["$map/index"] = index;
|
|
3015
|
-
const childOpts = options ? { ...options, _path: [...path, "map", index] } : undefined;
|
|
3016
|
-
const node = renderNode(mapDef, child, childOpts);
|
|
3017
|
-
anchor.before(node);
|
|
3018
|
-
nodes.push(node);
|
|
3752
|
+
const list = Array.isArray(items) && mapDef ? items : [];
|
|
3753
|
+
const keys = list.map((item, index) => mappedRowKey(keyPointer, item, index, warnOnce));
|
|
3754
|
+
const seen = new Set;
|
|
3755
|
+
for (let i = 0;i < keys.length; i++) {
|
|
3756
|
+
if (seen.has(keys[i])) {
|
|
3757
|
+
warnOnce(`duplicate key ${String(keys[i])} — every occurrence after the first is rebuilt on each change`);
|
|
3758
|
+
keys[i] = { duplicate: i };
|
|
3759
|
+
} else {
|
|
3760
|
+
seen.add(keys[i]);
|
|
3019
3761
|
}
|
|
3020
|
-
}
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3762
|
+
}
|
|
3763
|
+
pauseTracking();
|
|
3764
|
+
try {
|
|
3765
|
+
reconcile(list, keys);
|
|
3766
|
+
} finally {
|
|
3767
|
+
resetTracking();
|
|
3768
|
+
}
|
|
3769
|
+
};
|
|
3770
|
+
let queued = false;
|
|
3771
|
+
let stopped = false;
|
|
3772
|
+
const runner = effect(update, {
|
|
3773
|
+
scheduler: () => {
|
|
3774
|
+
if (queued) {
|
|
3775
|
+
return;
|
|
3025
3776
|
}
|
|
3026
|
-
|
|
3777
|
+
queued = true;
|
|
3778
|
+
queueMicrotask(() => {
|
|
3779
|
+
queued = false;
|
|
3780
|
+
if (!stopped) {
|
|
3781
|
+
runner();
|
|
3782
|
+
}
|
|
3783
|
+
});
|
|
3784
|
+
}
|
|
3027
3785
|
});
|
|
3786
|
+
onScopeDispose(() => {
|
|
3787
|
+
stopped = true;
|
|
3788
|
+
for (const row of rows) {
|
|
3789
|
+
teardown(row);
|
|
3790
|
+
}
|
|
3791
|
+
rows = [];
|
|
3792
|
+
}, true);
|
|
3793
|
+
}
|
|
3794
|
+
function mappedRowKey(pointer, item, index, warnOnce) {
|
|
3795
|
+
if (pointer === null) {
|
|
3796
|
+
return index;
|
|
3797
|
+
}
|
|
3798
|
+
if (pointer === "$map/item") {
|
|
3799
|
+
return item;
|
|
3800
|
+
}
|
|
3801
|
+
if (pointer.startsWith("$map/item/")) {
|
|
3802
|
+
const key = readPath(item, pointer.slice("$map/item/".length));
|
|
3803
|
+
if (key === undefined || key === null) {
|
|
3804
|
+
warnOnce(`key "${pointer}" is empty for some items — those rows fall back to their index`);
|
|
3805
|
+
return index;
|
|
3806
|
+
}
|
|
3807
|
+
return key;
|
|
3808
|
+
}
|
|
3809
|
+
warnOnce(`key "${pointer}" is not a $map/item pointer — rows fall back to their index`);
|
|
3810
|
+
return index;
|
|
3028
3811
|
}
|
|
3029
3812
|
function resolveTagName(tagName, scope) {
|
|
3030
3813
|
if (typeof tagName === "string") {
|
|
@@ -3040,65 +3823,86 @@ function resolveTagName(tagName, scope) {
|
|
|
3040
3823
|
const key = evaluateOperand(expression.target, scope, null);
|
|
3041
3824
|
return expression.cases[String(key)] ?? expression.default;
|
|
3042
3825
|
}
|
|
3043
|
-
function renderSwitch(
|
|
3826
|
+
function renderSwitch(def, state, options) {
|
|
3044
3827
|
const path = options?._path ?? [];
|
|
3045
|
-
const container = document.createElement(resolveTagName(
|
|
3828
|
+
const container = document.createElement(resolveTagName(def.tagName, state));
|
|
3046
3829
|
if (options?.onNodeCreated) {
|
|
3047
|
-
options.onNodeCreated(container, path,
|
|
3830
|
+
options.onNodeCreated(container, path, def, state);
|
|
3048
3831
|
}
|
|
3049
|
-
applyProperties(container,
|
|
3050
|
-
applyStyle(container,
|
|
3051
|
-
applyAttributes(container,
|
|
3832
|
+
applyProperties(container, def, state);
|
|
3833
|
+
applyStyle(container, def.style ?? {}, state["$media"] ?? {}, state);
|
|
3834
|
+
applyAttributes(container, def.attributes ?? {}, state);
|
|
3052
3835
|
let generation = 0;
|
|
3836
|
+
let live = null;
|
|
3837
|
+
let renderedKey = null;
|
|
3838
|
+
const retire = () => {
|
|
3839
|
+
live?.stop();
|
|
3840
|
+
live = null;
|
|
3841
|
+
};
|
|
3053
3842
|
effect(() => {
|
|
3054
|
-
|
|
3055
|
-
|
|
3843
|
+
if (!isRefObj(def.$switch)) {
|
|
3844
|
+
retire();
|
|
3845
|
+
container.replaceChildren();
|
|
3846
|
+
generation += 1;
|
|
3056
3847
|
return;
|
|
3057
3848
|
}
|
|
3058
|
-
const key = resolveRef(
|
|
3059
|
-
|
|
3849
|
+
const key = String(resolveRef(def.$switch.$ref, state));
|
|
3850
|
+
if (key === renderedKey) {
|
|
3851
|
+
return;
|
|
3852
|
+
}
|
|
3853
|
+
renderedKey = key;
|
|
3854
|
+
retire();
|
|
3855
|
+
container.replaceChildren();
|
|
3856
|
+
generation += 1;
|
|
3857
|
+
const caseDef = def.cases?.[key];
|
|
3060
3858
|
if (!caseDef) {
|
|
3061
3859
|
return;
|
|
3062
3860
|
}
|
|
3861
|
+
const gen = generation;
|
|
3862
|
+
const scope = effectScope(true);
|
|
3863
|
+
live = scope;
|
|
3864
|
+
const childOpts = options ? { ...options, _path: [...path, "cases", key] } : undefined;
|
|
3063
3865
|
if (isRefObj(caseDef)) {
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
const { href } = new URL(caseDef.$ref, location.href);
|
|
3067
|
-
resolve(href).then(async (doc) => {
|
|
3866
|
+
const { href } = new URL(caseDef.$ref, options?._ctx?.base ?? location.href);
|
|
3867
|
+
resolve(href, options?._ctx).then(async (doc) => {
|
|
3068
3868
|
if (gen !== generation) {
|
|
3069
3869
|
return;
|
|
3070
3870
|
}
|
|
3071
|
-
const childScope = await buildScope(doc, {}, href);
|
|
3871
|
+
const childScope = await buildScope(doc, {}, href, options?._ctx);
|
|
3072
3872
|
if (gen !== generation) {
|
|
3073
3873
|
return;
|
|
3074
3874
|
}
|
|
3075
3875
|
container.replaceChildren();
|
|
3076
|
-
|
|
3077
|
-
container.append(renderNode(doc, childScope, childOpts2));
|
|
3876
|
+
scope.run(() => container.append(renderNode(doc, childScope, childOpts)));
|
|
3078
3877
|
}).catch((error) => console.error("Jx $switch: failed to load external case", caseDef.$ref, error));
|
|
3079
3878
|
return;
|
|
3080
3879
|
}
|
|
3081
|
-
|
|
3082
|
-
|
|
3880
|
+
pauseTracking();
|
|
3881
|
+
try {
|
|
3882
|
+
scope.run(() => container.append(renderNode(caseDef, state, childOpts)));
|
|
3883
|
+
} finally {
|
|
3884
|
+
resetTracking();
|
|
3885
|
+
}
|
|
3083
3886
|
});
|
|
3887
|
+
onScopeDispose(retire, true);
|
|
3084
3888
|
return container;
|
|
3085
3889
|
}
|
|
3086
|
-
async function resolvePrototype(
|
|
3087
|
-
if (
|
|
3088
|
-
return resolveExternalPrototype(
|
|
3890
|
+
async function resolvePrototype(def, state, key, base, ctx) {
|
|
3891
|
+
if (def.$src) {
|
|
3892
|
+
return resolveExternalPrototype(def, state, key, base);
|
|
3089
3893
|
}
|
|
3090
|
-
switch (
|
|
3894
|
+
switch (def.$prototype) {
|
|
3091
3895
|
case "Request": {
|
|
3092
3896
|
const s = ref(null);
|
|
3093
|
-
const debounceMs =
|
|
3897
|
+
const debounceMs = def.debounce ?? 0;
|
|
3094
3898
|
let debounceTimer = null;
|
|
3095
|
-
if (!
|
|
3899
|
+
if (!def.manual && !(ctx?.skipAutoRequests ?? _autoRequestConfig.skip)) {
|
|
3096
3900
|
effect(() => {
|
|
3097
3901
|
let url;
|
|
3098
|
-
if (isTemplateString(
|
|
3099
|
-
url = evaluateTemplate(
|
|
3902
|
+
if (isTemplateString(def.url)) {
|
|
3903
|
+
url = evaluateTemplate(def.url, state);
|
|
3100
3904
|
} else {
|
|
3101
|
-
({ url } =
|
|
3905
|
+
({ url } = def);
|
|
3102
3906
|
}
|
|
3103
3907
|
if (!url || url === "undefined" || url.includes("undefined")) {
|
|
3104
3908
|
return;
|
|
@@ -3111,11 +3915,11 @@ async function resolvePrototype(def2, state, key, base) {
|
|
|
3111
3915
|
}
|
|
3112
3916
|
});
|
|
3113
3917
|
const doFetch = () => fetch(url, {
|
|
3114
|
-
method:
|
|
3918
|
+
method: def.method ?? "GET",
|
|
3115
3919
|
signal: controller.signal,
|
|
3116
|
-
...
|
|
3117
|
-
...
|
|
3118
|
-
body: typeof
|
|
3920
|
+
...def.headers && { headers: def.headers },
|
|
3921
|
+
...def.body && {
|
|
3922
|
+
body: typeof def.body === "object" ? JSON.stringify(def.body) : def.body
|
|
3119
3923
|
}
|
|
3120
3924
|
}).then((r) => r.ok ? r.json() : Promise.reject(r.statusText)).then((d) => {
|
|
3121
3925
|
s.value = d;
|
|
@@ -3136,7 +3940,7 @@ async function resolvePrototype(def2, state, key, base) {
|
|
|
3136
3940
|
case "URLSearchParams": {
|
|
3137
3941
|
return computed(() => {
|
|
3138
3942
|
const p = {};
|
|
3139
|
-
for (const [k, v] of Object.entries(
|
|
3943
|
+
for (const [k, v] of Object.entries(def)) {
|
|
3140
3944
|
if (k !== "$prototype") {
|
|
3141
3945
|
p[k] = isRefObj(v) ? resolveRef(v.$ref, state) : isTemplateString(v) ? evaluateTemplate(v, state) : v;
|
|
3142
3946
|
}
|
|
@@ -3146,14 +3950,14 @@ async function resolvePrototype(def2, state, key, base) {
|
|
|
3146
3950
|
}
|
|
3147
3951
|
case "LocalStorage":
|
|
3148
3952
|
case "SessionStorage": {
|
|
3149
|
-
const store =
|
|
3150
|
-
const k =
|
|
3953
|
+
const store = def.$prototype === "LocalStorage" ? localStorage : sessionStorage;
|
|
3954
|
+
const k = def.key ?? key;
|
|
3151
3955
|
let init;
|
|
3152
3956
|
try {
|
|
3153
3957
|
const s = store.getItem(k);
|
|
3154
|
-
init = s !== null ? JSON.parse(s) :
|
|
3958
|
+
init = s !== null ? JSON.parse(s) : def.default ?? null;
|
|
3155
3959
|
} catch {
|
|
3156
|
-
init =
|
|
3960
|
+
init = def.default ?? null;
|
|
3157
3961
|
}
|
|
3158
3962
|
const storageState = ref(init);
|
|
3159
3963
|
effect(() => {
|
|
@@ -3171,7 +3975,7 @@ async function resolvePrototype(def2, state, key, base) {
|
|
|
3171
3975
|
return storageState;
|
|
3172
3976
|
}
|
|
3173
3977
|
case "Cookie": {
|
|
3174
|
-
const name =
|
|
3978
|
+
const name = def.name ?? key;
|
|
3175
3979
|
const read = () => {
|
|
3176
3980
|
const raw = readCookie(document.cookie, name);
|
|
3177
3981
|
if (raw === null) {
|
|
@@ -3183,9 +3987,9 @@ async function resolvePrototype(def2, state, key, base) {
|
|
|
3183
3987
|
return raw;
|
|
3184
3988
|
}
|
|
3185
3989
|
};
|
|
3186
|
-
const cookieState = ref(read() ??
|
|
3990
|
+
const cookieState = ref(read() ?? def.default ?? null);
|
|
3187
3991
|
effect(() => {
|
|
3188
|
-
document.cookie = serializeCookie(name, cookieState.value,
|
|
3992
|
+
document.cookie = serializeCookie(name, cookieState.value, def);
|
|
3189
3993
|
});
|
|
3190
3994
|
return cookieState;
|
|
3191
3995
|
}
|
|
@@ -3198,7 +4002,7 @@ async function resolvePrototype(def2, state, key, base) {
|
|
|
3198
4002
|
keyPath = "id",
|
|
3199
4003
|
autoIncrement = true,
|
|
3200
4004
|
indexes = []
|
|
3201
|
-
} =
|
|
4005
|
+
} = def;
|
|
3202
4006
|
if (!database || !store) {
|
|
3203
4007
|
throw new Error(`Jx: IndexedDB entry '${key}' requires database and store`);
|
|
3204
4008
|
}
|
|
@@ -3228,28 +4032,28 @@ async function resolvePrototype(def2, state, key, base) {
|
|
|
3228
4032
|
return idbState;
|
|
3229
4033
|
}
|
|
3230
4034
|
case "Set": {
|
|
3231
|
-
return new Set(Array.isArray(
|
|
4035
|
+
return new Set(Array.isArray(def.default) ? def.default : []);
|
|
3232
4036
|
}
|
|
3233
4037
|
case "Map": {
|
|
3234
|
-
return new Map(Object.entries(isJsonObject(
|
|
4038
|
+
return new Map(Object.entries(isJsonObject(def.default) ? def.default : {}));
|
|
3235
4039
|
}
|
|
3236
4040
|
case "FormData": {
|
|
3237
4041
|
const fd = new FormData;
|
|
3238
|
-
for (const [k, v] of Object.entries(
|
|
4042
|
+
for (const [k, v] of Object.entries(def.fields ?? {})) {
|
|
3239
4043
|
fd.append(k, v);
|
|
3240
4044
|
}
|
|
3241
4045
|
return fd;
|
|
3242
4046
|
}
|
|
3243
4047
|
case "Blob": {
|
|
3244
|
-
return new Blob(
|
|
3245
|
-
type: typeof
|
|
4048
|
+
return new Blob(def.parts ?? [], {
|
|
4049
|
+
type: typeof def.type === "string" ? def.type : "text/plain"
|
|
3246
4050
|
});
|
|
3247
4051
|
}
|
|
3248
4052
|
case "ReadableStream": {
|
|
3249
4053
|
return null;
|
|
3250
4054
|
}
|
|
3251
4055
|
default: {
|
|
3252
|
-
console.warn(`Jx: unknown $prototype "${
|
|
4056
|
+
console.warn(`Jx: unknown $prototype "${def.$prototype}" for "${key}". Did you mean to add '$src'?`);
|
|
3253
4057
|
return ref(null);
|
|
3254
4058
|
}
|
|
3255
4059
|
}
|
|
@@ -3266,17 +4070,20 @@ var EXTERNAL_RESERVED = new Set([
|
|
|
3266
4070
|
"arguments",
|
|
3267
4071
|
"name"
|
|
3268
4072
|
]);
|
|
3269
|
-
async function resolveExternalPrototype(
|
|
3270
|
-
const src =
|
|
4073
|
+
async function resolveExternalPrototype(def, state, key, base) {
|
|
4074
|
+
const src = def.$src;
|
|
3271
4075
|
if (!src || !src.endsWith(".class.json")) {
|
|
3272
|
-
throw new Error(`Jx: $prototype "${
|
|
4076
|
+
throw new Error(`Jx: $prototype "${def.$prototype}" requires a .class.json $src, got "${src}". Wrap the class in a .class.json schema with $implementation.`);
|
|
3273
4077
|
}
|
|
3274
|
-
return resolveClassJson(
|
|
4078
|
+
return resolveClassJson(def, state, key, base);
|
|
3275
4079
|
}
|
|
3276
|
-
async function importAndInstantiate(
|
|
4080
|
+
async function importAndInstantiate(def, src, exportName, base) {
|
|
3277
4081
|
let mod;
|
|
3278
|
-
|
|
3279
|
-
|
|
4082
|
+
const seeded = seededModule(src);
|
|
4083
|
+
if (seeded instanceof Promise) {
|
|
4084
|
+
mod = await seeded;
|
|
4085
|
+
} else if (seeded) {
|
|
4086
|
+
mod = seeded;
|
|
3280
4087
|
} else {
|
|
3281
4088
|
try {
|
|
3282
4089
|
mod = await import(src);
|
|
@@ -3298,7 +4105,7 @@ async function importAndInstantiate(def2, src, exportName, base) {
|
|
|
3298
4105
|
throw new TypeError(`Jx: "${exportName}" from "${src}" is not a class`);
|
|
3299
4106
|
}
|
|
3300
4107
|
const config = {};
|
|
3301
|
-
for (const [k, v] of Object.entries(
|
|
4108
|
+
for (const [k, v] of Object.entries(def)) {
|
|
3302
4109
|
if (!EXTERNAL_RESERVED.has(k)) {
|
|
3303
4110
|
config[k] = v;
|
|
3304
4111
|
}
|
|
@@ -3321,15 +4128,15 @@ async function importAndInstantiate(def2, src, exportName, base) {
|
|
|
3321
4128
|
}
|
|
3322
4129
|
return s;
|
|
3323
4130
|
}
|
|
3324
|
-
async function resolveClassJson(
|
|
3325
|
-
const src =
|
|
4131
|
+
async function resolveClassJson(def, state, key, base) {
|
|
4132
|
+
const src = def.$src;
|
|
3326
4133
|
if (!src) {
|
|
3327
4134
|
throw new Error(`Jx: class entry '${key}' has no $src`);
|
|
3328
4135
|
}
|
|
3329
4136
|
let classDef;
|
|
3330
4137
|
const isBareSpecifier = !src.startsWith(".") && !src.startsWith("/") && !src.startsWith("http") && !src.startsWith("file:");
|
|
3331
4138
|
if (isBareSpecifier) {
|
|
3332
|
-
return resolveViaDevProxy(
|
|
4139
|
+
return resolveViaDevProxy(def, state, key, base);
|
|
3333
4140
|
}
|
|
3334
4141
|
try {
|
|
3335
4142
|
const url = base ? new URL(src, base).href : src;
|
|
@@ -3339,25 +4146,25 @@ async function resolveClassJson(def2, state, key, base) {
|
|
|
3339
4146
|
}
|
|
3340
4147
|
classDef = await res.json();
|
|
3341
4148
|
} catch {
|
|
3342
|
-
return resolveViaDevProxy(
|
|
4149
|
+
return resolveViaDevProxy(def, state, key, base);
|
|
3343
4150
|
}
|
|
3344
4151
|
if (classDef.$implementation) {
|
|
3345
4152
|
const schemaStr = JSON.stringify(classDef);
|
|
3346
4153
|
if (schemaStr.includes('"#/$context/')) {
|
|
3347
|
-
return resolveViaDevProxy(
|
|
4154
|
+
return resolveViaDevProxy(def, state, key, base);
|
|
3348
4155
|
}
|
|
3349
4156
|
const schemaUrl = base ? new URL(src, base).href : new URL(src, location.href).href;
|
|
3350
4157
|
const implSrc = new URL(classDef.$implementation, schemaUrl).href;
|
|
3351
|
-
const exportName =
|
|
4158
|
+
const exportName = def.$export ?? classDef.title ?? def.$prototype;
|
|
3352
4159
|
try {
|
|
3353
|
-
return await importAndInstantiate(
|
|
4160
|
+
return await importAndInstantiate(def, implSrc, exportName, base);
|
|
3354
4161
|
} catch {
|
|
3355
|
-
return resolveViaDevProxy(
|
|
4162
|
+
return resolveViaDevProxy(def, state, key, base);
|
|
3356
4163
|
}
|
|
3357
4164
|
}
|
|
3358
4165
|
const DynClass = classFromSchema(classDef);
|
|
3359
4166
|
const config = {};
|
|
3360
|
-
for (const [k, v] of Object.entries(
|
|
4167
|
+
for (const [k, v] of Object.entries(def)) {
|
|
3361
4168
|
if (!EXTERNAL_RESERVED.has(k)) {
|
|
3362
4169
|
config[k] = v;
|
|
3363
4170
|
}
|
|
@@ -3444,9 +4251,9 @@ function classFromSchema(classDef) {
|
|
|
3444
4251
|
const dynCtor = DynClass;
|
|
3445
4252
|
return dynCtor;
|
|
3446
4253
|
}
|
|
3447
|
-
async function resolveViaDevProxy(
|
|
4254
|
+
async function resolveViaDevProxy(def, state, key, base) {
|
|
3448
4255
|
const config = {};
|
|
3449
|
-
for (const [k, v] of Object.entries(
|
|
4256
|
+
for (const [k, v] of Object.entries(def)) {
|
|
3450
4257
|
if (!EXTERNAL_RESERVED.has(k)) {
|
|
3451
4258
|
config[k] = v;
|
|
3452
4259
|
}
|
|
@@ -3455,9 +4262,9 @@ async function resolveViaDevProxy(def2, state, key, base) {
|
|
|
3455
4262
|
const doResolve = (resolvedConfig) => fetch(resolveProxyPath("/__jx_resolve__"), {
|
|
3456
4263
|
body: JSON.stringify({
|
|
3457
4264
|
$base: base,
|
|
3458
|
-
$export:
|
|
3459
|
-
$prototype:
|
|
3460
|
-
$src:
|
|
4265
|
+
$export: def.$export,
|
|
4266
|
+
$prototype: def.$prototype,
|
|
4267
|
+
$src: def.$src,
|
|
3461
4268
|
...resolvedConfig
|
|
3462
4269
|
}),
|
|
3463
4270
|
headers: { "Content-Type": "application/json" },
|
|
@@ -3486,12 +4293,15 @@ async function resolveViaDevProxy(def2, state, key, base) {
|
|
|
3486
4293
|
}
|
|
3487
4294
|
return s;
|
|
3488
4295
|
}
|
|
3489
|
-
async function resolveServerFunction(
|
|
3490
|
-
const src =
|
|
3491
|
-
const exportName =
|
|
4296
|
+
async function resolveServerFunction(def, state, key, base) {
|
|
4297
|
+
const src = def.$src;
|
|
4298
|
+
const exportName = def.$export;
|
|
3492
4299
|
let mod;
|
|
3493
|
-
|
|
3494
|
-
|
|
4300
|
+
const seeded = seededModule(src);
|
|
4301
|
+
if (seeded instanceof Promise) {
|
|
4302
|
+
mod = await seeded;
|
|
4303
|
+
} else if (seeded) {
|
|
4304
|
+
mod = seeded;
|
|
3495
4305
|
} else {
|
|
3496
4306
|
try {
|
|
3497
4307
|
mod = await import(src);
|
|
@@ -3501,10 +4311,10 @@ async function resolveServerFunction(def2, state, key, base) {
|
|
|
3501
4311
|
const resolvedSrc = new URL(src, base).href;
|
|
3502
4312
|
mod = await import(resolvedSrc);
|
|
3503
4313
|
} catch {
|
|
3504
|
-
return resolveServerFunctionViaProxy(
|
|
4314
|
+
return resolveServerFunctionViaProxy(def, state, key, base);
|
|
3505
4315
|
}
|
|
3506
4316
|
} else {
|
|
3507
|
-
return resolveServerFunctionViaProxy(
|
|
4317
|
+
return resolveServerFunctionViaProxy(def, state, key, base);
|
|
3508
4318
|
}
|
|
3509
4319
|
}
|
|
3510
4320
|
_moduleCache.set(src, mod);
|
|
@@ -3517,7 +4327,7 @@ async function resolveServerFunction(def2, state, key, base) {
|
|
|
3517
4327
|
throw new TypeError(`Jx: "${exportName}" from "${src}" is not a function`);
|
|
3518
4328
|
}
|
|
3519
4329
|
const fn = candidate;
|
|
3520
|
-
const rawArgs =
|
|
4330
|
+
const rawArgs = def.arguments ?? {};
|
|
3521
4331
|
const hasReactiveArg = Object.values(rawArgs).some((v) => isRefObj(v));
|
|
3522
4332
|
const resolveArgs = () => {
|
|
3523
4333
|
const args = {};
|
|
@@ -3540,8 +4350,8 @@ async function resolveServerFunction(def2, state, key, base) {
|
|
|
3540
4350
|
}
|
|
3541
4351
|
return s;
|
|
3542
4352
|
}
|
|
3543
|
-
async function resolveServerFunctionViaProxy(
|
|
3544
|
-
const rawArgs =
|
|
4353
|
+
async function resolveServerFunctionViaProxy(def, state, key, base) {
|
|
4354
|
+
const rawArgs = def.arguments ?? {};
|
|
3545
4355
|
const hasReactiveArg = Object.values(rawArgs).some((v) => isRefObj(v));
|
|
3546
4356
|
const resolveArgs = () => {
|
|
3547
4357
|
const args = {};
|
|
@@ -3553,8 +4363,8 @@ async function resolveServerFunctionViaProxy(def2, state, key, base) {
|
|
|
3553
4363
|
const doResolve = (args) => fetch(resolveProxyPath("/__jx_server__"), {
|
|
3554
4364
|
body: JSON.stringify({
|
|
3555
4365
|
$base: base,
|
|
3556
|
-
$export:
|
|
3557
|
-
$src:
|
|
4366
|
+
$export: def.$export,
|
|
4367
|
+
$src: def.$src,
|
|
3558
4368
|
arguments: args
|
|
3559
4369
|
}),
|
|
3560
4370
|
headers: { "Content-Type": "application/json" },
|
|
@@ -3585,8 +4395,8 @@ function resolveRef(refPath, state) {
|
|
|
3585
4395
|
if (typeof refPath !== "string") {
|
|
3586
4396
|
return refPath;
|
|
3587
4397
|
}
|
|
3588
|
-
if (refPath.startsWith("$map/")) {
|
|
3589
|
-
const parts = refPath.split("/");
|
|
4398
|
+
if (refPath.startsWith("$map/") || refPath.startsWith("#/$map/")) {
|
|
4399
|
+
const parts = (refPath.startsWith("#/") ? refPath.slice(2) : refPath).split("/");
|
|
3590
4400
|
const [, key] = parts;
|
|
3591
4401
|
const map = state.$map;
|
|
3592
4402
|
const base = map?.[key] ?? state[`$map/${key}`];
|
|
@@ -3612,12 +4422,41 @@ function isSignal(v) {
|
|
|
3612
4422
|
function isRefObj(v) {
|
|
3613
4423
|
return isRef2(v);
|
|
3614
4424
|
}
|
|
3615
|
-
function isNestedSelector(k) {
|
|
3616
|
-
return k.startsWith(":") || k.startsWith(".") || k.startsWith("&") || k.startsWith("[");
|
|
3617
|
-
}
|
|
3618
4425
|
function getPath2(obj, path) {
|
|
3619
4426
|
return readPath(obj, path);
|
|
3620
4427
|
}
|
|
4428
|
+
function absorbAttribute(state, name, value, defaults) {
|
|
4429
|
+
const camelKey = name.replaceAll(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
4430
|
+
const current = state[camelKey];
|
|
4431
|
+
if (typeof current === "boolean") {
|
|
4432
|
+
state[camelKey] = value !== null && value !== "false";
|
|
4433
|
+
return;
|
|
4434
|
+
}
|
|
4435
|
+
if (value === null) {
|
|
4436
|
+
const declared = defaults?.get(camelKey);
|
|
4437
|
+
state[camelKey] = declared === undefined ? typeof current === "number" ? 0 : "" : declared;
|
|
4438
|
+
return;
|
|
4439
|
+
}
|
|
4440
|
+
state[camelKey] = typeof current === "number" ? Number(value) : value;
|
|
4441
|
+
}
|
|
4442
|
+
function declaredDefaults(def) {
|
|
4443
|
+
const out = new Map;
|
|
4444
|
+
for (const [key, entry] of Object.entries(def.state ?? {})) {
|
|
4445
|
+
if (entry !== null && typeof entry === "object") {
|
|
4446
|
+
const obj = entry;
|
|
4447
|
+
if ("default" in obj) {
|
|
4448
|
+
out.set(key, obj["default"]);
|
|
4449
|
+
continue;
|
|
4450
|
+
}
|
|
4451
|
+
if (COMPUTED_STATE_KEYS.some((marker) => (marker in obj))) {
|
|
4452
|
+
continue;
|
|
4453
|
+
}
|
|
4454
|
+
}
|
|
4455
|
+
out.set(key, entry);
|
|
4456
|
+
}
|
|
4457
|
+
return out;
|
|
4458
|
+
}
|
|
4459
|
+
var COMPUTED_STATE_KEYS = ["$expression", "$prototype", "$ref", "$src"];
|
|
3621
4460
|
var _privatePropWarned = new Set;
|
|
3622
4461
|
function instanceSupplies(el, key) {
|
|
3623
4462
|
if (Object.hasOwn(el, key)) {
|
|
@@ -3643,9 +4482,9 @@ function refusePrivateProp(key, where) {
|
|
|
3643
4482
|
function _resetPrivatePropWarnings() {
|
|
3644
4483
|
_privatePropWarned.clear();
|
|
3645
4484
|
}
|
|
3646
|
-
function mergeProps(
|
|
4485
|
+
function mergeProps(def, parentState) {
|
|
3647
4486
|
const child = Object.create(parentState);
|
|
3648
|
-
for (const [k, v] of Object.entries(
|
|
4487
|
+
for (const [k, v] of Object.entries(def.$props ?? {})) {
|
|
3649
4488
|
if (refusePrivateProp(k, "$props")) {
|
|
3650
4489
|
continue;
|
|
3651
4490
|
}
|
|
@@ -3653,47 +4492,38 @@ function mergeProps(def2, parentState) {
|
|
|
3653
4492
|
}
|
|
3654
4493
|
return child;
|
|
3655
4494
|
}
|
|
3656
|
-
function camelToKebab(s) {
|
|
3657
|
-
return s.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
|
|
3658
|
-
}
|
|
3659
4495
|
function toCSSText(rules) {
|
|
3660
|
-
return Object.entries(rules).filter(([k, v]) => !
|
|
4496
|
+
return Object.entries(rules).filter(([k, v]) => !isNestedSelectorKey(k) && (v === null || typeof v !== "object")).map(([p, v]) => `${cssPropertyName(p)}: ${canvasStyleValue(String(v))}`).join("; ");
|
|
3661
4497
|
}
|
|
3662
|
-
var
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
4498
|
+
var _rootMedia = {};
|
|
4499
|
+
var _elementDefs = new Map;
|
|
4500
|
+
function elementDefinition(tagName) {
|
|
4501
|
+
return _elementDefs.get(tagName);
|
|
4502
|
+
}
|
|
4503
|
+
async function redefineElement(doc, baseUrl) {
|
|
4504
|
+
const base = baseUrl ?? location.href;
|
|
4505
|
+
const { tagName } = doc;
|
|
4506
|
+
if (!tagName || !tagName.includes("-")) {
|
|
4507
|
+
throw new Error(`Jx redefineElement: tagName "${tagName}" must contain a hyphen`);
|
|
3666
4508
|
}
|
|
3667
|
-
if (
|
|
3668
|
-
|
|
3669
|
-
return
|
|
4509
|
+
if (!customElements.get(tagName)) {
|
|
4510
|
+
await defineElement(doc, base);
|
|
4511
|
+
return;
|
|
3670
4512
|
}
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
var COLOR_SCHEME_ATTR = "data-color-scheme";
|
|
3674
|
-
var COLOR_SCHEME_STORAGE_KEY = "jx-color-scheme";
|
|
3675
|
-
function pureSchemeOf(query) {
|
|
3676
|
-
const m = /^\(\s*prefers-color-scheme\s*:\s*(light|dark)\s*\)$/.exec(query.trim());
|
|
3677
|
-
return m?.[1] ?? null;
|
|
3678
|
-
}
|
|
3679
|
-
function schemeSelectors(selector, scheme) {
|
|
3680
|
-
if (selector === ":root" || selector === "html") {
|
|
3681
|
-
return {
|
|
3682
|
-
auto: `${selector}:where(:not([${COLOR_SCHEME_ATTR}]))`,
|
|
3683
|
-
forced: `${selector}:where([${COLOR_SCHEME_ATTR}="${scheme}"])`
|
|
3684
|
-
};
|
|
4513
|
+
if (doc.$elements) {
|
|
4514
|
+
await registerElements(doc.$elements, base);
|
|
3685
4515
|
}
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
4516
|
+
const before = _elementDefs.get(tagName)?.doc.observedAttributes ?? [];
|
|
4517
|
+
const after = doc.observedAttributes ?? [];
|
|
4518
|
+
if (JSON.stringify(before) !== JSON.stringify(after)) {
|
|
4519
|
+
console.warn(`Jx redefineElement: <${tagName}> keeps observedAttributes [${before.join(", ")}] as first defined; [${after.join(", ")}] takes effect only in a fresh realm`);
|
|
4520
|
+
}
|
|
4521
|
+
_elementDefs.set(tagName, { base, doc });
|
|
3690
4522
|
}
|
|
3691
|
-
var _rootMedia = {};
|
|
3692
|
-
var _elementDefs = new Map;
|
|
3693
4523
|
function setRootMedia(map) {
|
|
3694
4524
|
_rootMedia = map ?? {};
|
|
3695
4525
|
}
|
|
3696
|
-
async function registerElements(elements, base) {
|
|
4526
|
+
async function registerElements(elements, base, ctx) {
|
|
3697
4527
|
for (const entry of elements) {
|
|
3698
4528
|
if (typeof entry === "string") {
|
|
3699
4529
|
try {
|
|
@@ -3708,7 +4538,7 @@ async function registerElements(elements, base) {
|
|
|
3708
4538
|
continue;
|
|
3709
4539
|
}
|
|
3710
4540
|
const { href } = new URL(entry.$ref, base);
|
|
3711
|
-
const doc = await resolve(href);
|
|
4541
|
+
const doc = await resolve(href, ctx);
|
|
3712
4542
|
if (!doc.tagName || !doc.tagName.includes("-")) {
|
|
3713
4543
|
continue;
|
|
3714
4544
|
}
|
|
@@ -3716,7 +4546,7 @@ async function registerElements(elements, base) {
|
|
|
3716
4546
|
continue;
|
|
3717
4547
|
}
|
|
3718
4548
|
if (doc.$elements) {
|
|
3719
|
-
await registerElements(doc.$elements, href);
|
|
4549
|
+
await registerElements(doc.$elements, href, ctx);
|
|
3720
4550
|
}
|
|
3721
4551
|
await defineElement(doc, href);
|
|
3722
4552
|
}
|
|
@@ -3778,8 +4608,9 @@ async function defineElement(source, baseUrl) {
|
|
|
3778
4608
|
await registerElements(source_.$elements, base);
|
|
3779
4609
|
}
|
|
3780
4610
|
_elementDefs.set(tagName, { base, doc: source_ });
|
|
3781
|
-
const
|
|
3782
|
-
const
|
|
4611
|
+
const initialDef = source_;
|
|
4612
|
+
const initialBase = base;
|
|
4613
|
+
const observedAttrs = initialDef.observedAttributes ?? [];
|
|
3783
4614
|
const ElementClass = class extends HTMLElement {
|
|
3784
4615
|
_jxInitialized = false;
|
|
3785
4616
|
_state = null;
|
|
@@ -3794,7 +4625,15 @@ async function defineElement(source, baseUrl) {
|
|
|
3794
4625
|
return;
|
|
3795
4626
|
}
|
|
3796
4627
|
this._jxInitialized = true;
|
|
3797
|
-
const
|
|
4628
|
+
const live = _elementDefs.get(tagName) ?? { base: initialBase, doc: initialDef };
|
|
4629
|
+
const def = live.doc;
|
|
4630
|
+
const defBase = live.base;
|
|
4631
|
+
const state = await buildScope(def, {}, defBase, { base: defBase, media: null, root: this });
|
|
4632
|
+
for (const attr of observedAttrs) {
|
|
4633
|
+
if (this.hasAttribute(attr)) {
|
|
4634
|
+
absorbAttribute(state, attr, this.getAttribute(attr));
|
|
4635
|
+
}
|
|
4636
|
+
}
|
|
3798
4637
|
const propsAttr = this.dataset.jxProps;
|
|
3799
4638
|
if (propsAttr) {
|
|
3800
4639
|
try {
|
|
@@ -3803,7 +4642,7 @@ async function defineElement(source, baseUrl) {
|
|
|
3803
4642
|
if (refusePrivateProp(key, "data-jx-props")) {
|
|
3804
4643
|
continue;
|
|
3805
4644
|
}
|
|
3806
|
-
if (key in (
|
|
4645
|
+
if (key in (def.state ?? {})) {
|
|
3807
4646
|
state[key] = val;
|
|
3808
4647
|
}
|
|
3809
4648
|
}
|
|
@@ -3817,12 +4656,12 @@ async function defineElement(source, baseUrl) {
|
|
|
3817
4656
|
this.removeAttribute(name);
|
|
3818
4657
|
continue;
|
|
3819
4658
|
}
|
|
3820
|
-
if (key in (
|
|
4659
|
+
if (key in (def.state ?? {})) {
|
|
3821
4660
|
state[key] = this.getAttribute(name);
|
|
3822
4661
|
this.removeAttribute(name);
|
|
3823
4662
|
}
|
|
3824
4663
|
}
|
|
3825
|
-
for (const key of Object.keys(
|
|
4664
|
+
for (const key of Object.keys(def.state ?? {})) {
|
|
3826
4665
|
if (isPrivateStateKey(key)) {
|
|
3827
4666
|
continue;
|
|
3828
4667
|
}
|
|
@@ -3830,7 +4669,7 @@ async function defineElement(source, baseUrl) {
|
|
|
3830
4669
|
state[key] = this[key];
|
|
3831
4670
|
}
|
|
3832
4671
|
}
|
|
3833
|
-
for (const key of Object.keys(
|
|
4672
|
+
for (const key of Object.keys(def.state ?? {})) {
|
|
3834
4673
|
if (isPrivateStateKey(key)) {
|
|
3835
4674
|
continue;
|
|
3836
4675
|
}
|
|
@@ -3847,22 +4686,28 @@ async function defineElement(source, baseUrl) {
|
|
|
3847
4686
|
this._state = state;
|
|
3848
4687
|
const slottedChildren = [...this.childNodes];
|
|
3849
4688
|
this.replaceChildren();
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
}
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
if (!Array.isArray(
|
|
3856
|
-
bindProperty(this, "textContent",
|
|
3857
|
-
}
|
|
3858
|
-
const children = Array.isArray(
|
|
3859
|
-
|
|
3860
|
-
|
|
4689
|
+
const defStyle = declaresDisplay(def.style) ? def.style : { display: "block", ...def.style };
|
|
4690
|
+
const hostStyle = mergeStyle(defStyle, callSiteStyles.get(this));
|
|
4691
|
+
applyStyle(this, hostStyle, state["$media"] ?? {}, state);
|
|
4692
|
+
applyAttributes(this, def.attributes ?? {}, state);
|
|
4693
|
+
bindDefinitionHandlers(this, def, state);
|
|
4694
|
+
if (!Array.isArray(def.children) && def.textContent !== undefined) {
|
|
4695
|
+
bindProperty(this, "textContent", def.textContent, state);
|
|
4696
|
+
}
|
|
4697
|
+
const children = Array.isArray(def.children) ? def.children : [];
|
|
4698
|
+
const wasInside = _canvasInsideStampedHost;
|
|
4699
|
+
_canvasInsideStampedHost ||= this.dataset.jxPath !== undefined;
|
|
4700
|
+
try {
|
|
4701
|
+
for (const childDef of children) {
|
|
4702
|
+
this.append(renderNode(childDef, state));
|
|
4703
|
+
}
|
|
4704
|
+
} finally {
|
|
4705
|
+
_canvasInsideStampedHost = wasInside;
|
|
3861
4706
|
}
|
|
3862
4707
|
distributeSlots(this, slottedChildren);
|
|
3863
4708
|
const { onMount } = state;
|
|
3864
4709
|
if (typeof onMount === "function") {
|
|
3865
|
-
queueMicrotask(() => onMount(state));
|
|
4710
|
+
queueMicrotask(() => onMount(state, this));
|
|
3866
4711
|
}
|
|
3867
4712
|
}
|
|
3868
4713
|
disconnectedCallback() {
|
|
@@ -3879,25 +4724,17 @@ async function defineElement(source, baseUrl) {
|
|
|
3879
4724
|
if (!this._state || oldVal === newVal) {
|
|
3880
4725
|
return;
|
|
3881
4726
|
}
|
|
3882
|
-
|
|
3883
|
-
const current = this._state[camelKey];
|
|
3884
|
-
if (typeof current === "number") {
|
|
3885
|
-
this._state[camelKey] = Number(newVal);
|
|
3886
|
-
} else if (typeof current === "boolean") {
|
|
3887
|
-
this._state[camelKey] = newVal !== null && newVal !== "false";
|
|
3888
|
-
} else {
|
|
3889
|
-
this._state[camelKey] = newVal;
|
|
3890
|
-
}
|
|
4727
|
+
absorbAttribute(this._state, name, newVal, declaredDefaults(_elementDefs.get(tagName)?.doc ?? initialDef));
|
|
3891
4728
|
}
|
|
3892
4729
|
};
|
|
3893
4730
|
customElements.define(tagName, ElementClass);
|
|
3894
4731
|
}
|
|
3895
|
-
function renderCustomElementWithProps(
|
|
3896
|
-
const el = document.createElement(resolveTagName(
|
|
4732
|
+
function renderCustomElementWithProps(def, state, options, path) {
|
|
4733
|
+
const el = document.createElement(resolveTagName(def.tagName, state));
|
|
3897
4734
|
if (options?.onNodeCreated) {
|
|
3898
|
-
options.onNodeCreated(el, path ?? [],
|
|
4735
|
+
options.onNodeCreated(el, path ?? [], def, state);
|
|
3899
4736
|
}
|
|
3900
|
-
for (const [key, val] of Object.entries(
|
|
4737
|
+
for (const [key, val] of Object.entries(def.$props ?? {})) {
|
|
3901
4738
|
if (refusePrivateProp(key, "$props")) {
|
|
3902
4739
|
continue;
|
|
3903
4740
|
}
|
|
@@ -3918,19 +4755,25 @@ function renderCustomElementWithProps(def2, state, options, path) {
|
|
|
3918
4755
|
write(val);
|
|
3919
4756
|
}
|
|
3920
4757
|
}
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
4758
|
+
if (def.style) {
|
|
4759
|
+
callSiteStyles.set(el, def.style);
|
|
4760
|
+
}
|
|
4761
|
+
applyStyle(el, def.style ?? {}, state["$media"] ?? {}, state);
|
|
4762
|
+
applyAttributes(el, def.attributes ?? {}, state);
|
|
4763
|
+
applyProperties(el, def, state);
|
|
4764
|
+
const children = Array.isArray(def.children) ? def.children : [];
|
|
3924
4765
|
for (let i = 0;i < children.length; i++) {
|
|
4766
|
+
const child = children[i];
|
|
3925
4767
|
const childOpts = options && path ? { ...options, _path: [...path, "children", i] } : undefined;
|
|
3926
|
-
|
|
4768
|
+
if (isMappedArray(child)) {
|
|
4769
|
+
renderMappedArrayInto(el, child, state, childOpts);
|
|
4770
|
+
} else {
|
|
4771
|
+
el.append(renderNode(child, state, childOpts));
|
|
4772
|
+
}
|
|
3927
4773
|
}
|
|
3928
4774
|
return el;
|
|
3929
4775
|
}
|
|
3930
4776
|
function distributeSlots(host, slottedChildren) {
|
|
3931
|
-
if (slottedChildren.length === 0) {
|
|
3932
|
-
return;
|
|
3933
|
-
}
|
|
3934
4777
|
const slots = host.querySelectorAll("slot");
|
|
3935
4778
|
if (slots.length === 0) {
|
|
3936
4779
|
return;
|
|
@@ -3951,12 +4794,7 @@ function distributeSlots(host, slottedChildren) {
|
|
|
3951
4794
|
for (const slot of slots) {
|
|
3952
4795
|
const name = slot.getAttribute("name");
|
|
3953
4796
|
const matches = name ? named.get(name) ?? [] : unnamed;
|
|
3954
|
-
|
|
3955
|
-
slot.replaceChildren();
|
|
3956
|
-
for (const child of matches) {
|
|
3957
|
-
slot.append(child);
|
|
3958
|
-
}
|
|
3959
|
-
}
|
|
4797
|
+
slot.replaceWith(...matches.length > 0 ? matches : [...slot.childNodes]);
|
|
3960
4798
|
}
|
|
3961
4799
|
}
|
|
3962
4800
|
export {
|
|
@@ -3969,19 +4807,35 @@ export {
|
|
|
3969
4807
|
applyStyle,
|
|
3970
4808
|
booleanAttrValue,
|
|
3971
4809
|
buildScope,
|
|
4810
|
+
buildStyleRules,
|
|
3972
4811
|
camelToKebab,
|
|
3973
4812
|
canvasStyleValue,
|
|
4813
|
+
cssPropertyName,
|
|
4814
|
+
cssRuleText,
|
|
3974
4815
|
defineElement,
|
|
3975
|
-
|
|
4816
|
+
documentStyleText,
|
|
4817
|
+
elementDefinition,
|
|
4818
|
+
enumeratedAttrNames,
|
|
3976
4819
|
hasSchemaKeywords,
|
|
4820
|
+
hashCss,
|
|
4821
|
+
isDeclarationAtRule,
|
|
4822
|
+
isKeyframesAtRule,
|
|
4823
|
+
isNestedSelectorKey,
|
|
3977
4824
|
isSignal,
|
|
3978
4825
|
isSingleExpression,
|
|
4826
|
+
mount,
|
|
3979
4827
|
observeScope,
|
|
4828
|
+
preloadDocument,
|
|
4829
|
+
preloadModule,
|
|
3980
4830
|
pureSchemeOf,
|
|
3981
4831
|
reapplyStyle,
|
|
4832
|
+
redefineElement,
|
|
4833
|
+
releaseElementStyles,
|
|
3982
4834
|
renderNode,
|
|
4835
|
+
resetDocumentStyles,
|
|
3983
4836
|
resolve,
|
|
3984
4837
|
resolveAtQuery,
|
|
4838
|
+
resolveNestedSelector,
|
|
3985
4839
|
resolvePrototype,
|
|
3986
4840
|
resolveRef,
|
|
3987
4841
|
resolveTagName,
|
|
@@ -3989,6 +4843,8 @@ export {
|
|
|
3989
4843
|
schemeSelectors,
|
|
3990
4844
|
setCanvasAssetResolver,
|
|
3991
4845
|
setCanvasDelinkAnchors,
|
|
4846
|
+
setCanvasDelinkCommands,
|
|
4847
|
+
setCanvasDelinkPopovers,
|
|
3992
4848
|
setCanvasViewportTranspose,
|
|
3993
4849
|
setResolveToken,
|
|
3994
4850
|
setRootMedia,
|
|
@@ -3996,9 +4852,12 @@ export {
|
|
|
3996
4852
|
setSkipContentResolution,
|
|
3997
4853
|
setSkipServerFunctions,
|
|
3998
4854
|
setStampPropBindings,
|
|
4855
|
+
splitSelectorList,
|
|
3999
4856
|
toCSSText,
|
|
4857
|
+
transposeCanvasOverlaySelector,
|
|
4858
|
+
transposeCanvasPopoverSelector,
|
|
4000
4859
|
transposeCanvasUnits
|
|
4001
4860
|
};
|
|
4002
4861
|
|
|
4003
|
-
//# debugId=
|
|
4862
|
+
//# debugId=A89AF23A7F8742C664756E2164756E21
|
|
4004
4863
|
//# sourceMappingURL=runtime.js.map
|