@jxsuite/runtime 0.28.2 → 0.28.3

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 CHANGED
@@ -1,4 +1,4 @@
1
- // ../../node_modules/.bun/@vue+shared@3.5.35/node_modules/@vue/shared/dist/shared.esm-bundler.js
1
+ // ../../node_modules/.bun/@vue+shared@3.5.38/node_modules/@vue/shared/dist/shared.esm-bundler.js
2
2
  function makeMap(str) {
3
3
  const map = /* @__PURE__ */ Object.create(null);
4
4
  for (const key of str.split(","))
@@ -46,7 +46,7 @@ var hasChanged = (value, oldValue) => !Object.is(value, oldValue);
46
46
  var specialBooleanAttrs = `itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly`;
47
47
  var isBooleanAttr = /* @__PURE__ */ makeMap(specialBooleanAttrs + `,async,autofocus,autoplay,controls,default,defer,disabled,hidden,inert,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected`);
48
48
 
49
- // ../../node_modules/.bun/@vue+reactivity@3.5.35/node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js
49
+ // ../../node_modules/.bun/@vue+reactivity@3.5.38/node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js
50
50
  function warn(msg, ...args) {
51
51
  console.warn(`[Vue warn] ${msg}`, ...args);
52
52
  }
@@ -1259,6 +1259,10 @@ function computed(getterOrOptions, debugOptions, isSSR = false) {
1259
1259
  }
1260
1260
 
1261
1261
  // src/expression.ts
1262
+ function scopeMap(state) {
1263
+ const map = state.$map;
1264
+ return map && typeof map === "object" ? map : undefined;
1265
+ }
1262
1266
  var MUTATING_OPS = new Set([
1263
1267
  "=",
1264
1268
  "+=",
@@ -1300,8 +1304,9 @@ function isMutating(op) {
1300
1304
  return MUTATING_OPS.has(op);
1301
1305
  }
1302
1306
  function resolveOperand(operand, state, event, iterCtx) {
1303
- if (operand === null || operand === undefined)
1307
+ if (operand === null || operand === undefined) {
1304
1308
  return operand;
1309
+ }
1305
1310
  if (typeof operand === "object" && !Array.isArray(operand) && "operator" in operand) {
1306
1311
  return evaluateExpression(operand, state, event, iterCtx);
1307
1312
  }
@@ -1326,66 +1331,76 @@ function resolveExprRef(ref2, state, event, iterCtx) {
1326
1331
  }
1327
1332
  if (ref2.startsWith("$map/")) {
1328
1333
  const parts = ref2.split("/");
1329
- const key = parts[1];
1334
+ const [, key] = parts;
1330
1335
  let base;
1331
- if (key === "item")
1332
- base = iterCtx?.item ?? state.$map?.item ?? state["$map/item"];
1333
- else if (key === "index")
1334
- base = iterCtx?.index ?? state.$map?.index ?? state["$map/index"];
1335
- else
1336
- base = state.$map?.[key] ?? state["$map/" + key];
1336
+ const map = scopeMap(state);
1337
+ if (key === "item") {
1338
+ base = iterCtx?.item ?? map?.item ?? state["$map/item"];
1339
+ } else if (key === "index") {
1340
+ base = iterCtx?.index ?? map?.index ?? state["$map/index"];
1341
+ } else {
1342
+ base = map?.[key] ?? state[`$map/${key}`];
1343
+ }
1337
1344
  return parts.length > 2 ? getPath(base, parts.slice(2).join("/")) : base;
1338
1345
  }
1339
1346
  if (ref2.startsWith("#/state/")) {
1340
1347
  const sub = ref2.slice("#/state/".length);
1341
1348
  const slash = sub.indexOf("/");
1342
- if (slash < 0)
1349
+ if (slash === -1) {
1343
1350
  return state[sub];
1351
+ }
1344
1352
  return getPath(state[sub.slice(0, slash)], sub.slice(slash + 1));
1345
1353
  }
1346
- if (ref2.startsWith("parent#/"))
1354
+ if (ref2.startsWith("parent#/")) {
1347
1355
  return state[ref2.slice("parent#/".length)];
1348
- if (ref2.startsWith("window#/"))
1356
+ }
1357
+ if (ref2.startsWith("window#/")) {
1349
1358
  return getPath(globalThis.window, ref2.slice("window#/".length));
1350
- if (ref2.startsWith("document#/"))
1359
+ }
1360
+ if (ref2.startsWith("document#/")) {
1351
1361
  return getPath(globalThis.document, ref2.slice("document#/".length));
1362
+ }
1352
1363
  return state[ref2] ?? null;
1353
1364
  }
1354
1365
  function resolveWritableRef(ref2, state, event, iterCtx) {
1355
1366
  if (ref2.startsWith("$map/")) {
1356
1367
  const parts = ref2.split("/");
1357
- const key = parts[1];
1368
+ const [, key] = parts;
1358
1369
  let base;
1359
- if (key === "item")
1360
- base = iterCtx?.item ?? state.$map?.item ?? state["$map/item"];
1361
- else if (key === "index")
1362
- base = iterCtx?.index ?? state.$map?.index ?? state["$map/index"];
1363
- else
1364
- base = state.$map?.[key] ?? state["$map/" + key];
1370
+ const map = scopeMap(state);
1371
+ if (key === "item") {
1372
+ base = iterCtx?.item ?? map?.item ?? state["$map/item"];
1373
+ } else if (key === "index") {
1374
+ base = iterCtx?.index ?? map?.index ?? state["$map/index"];
1375
+ } else {
1376
+ base = map?.[key] ?? state[`$map/${key}`];
1377
+ }
1365
1378
  if (parts.length > 2) {
1366
1379
  const pathParts = parts.slice(2);
1367
1380
  const lastKey = pathParts.pop();
1368
1381
  const obj = pathParts.length > 0 ? getPath(base, pathParts.join("/")) : base;
1369
- return { obj, key: lastKey };
1382
+ return { key: lastKey, obj };
1370
1383
  }
1371
1384
  return {
1372
- obj: state.$map ?? state,
1373
- key: key === "item" ? "$map/item" : "$map/index"
1385
+ key: key === "item" ? "$map/item" : "$map/index",
1386
+ obj: scopeMap(state) ?? state
1374
1387
  };
1375
1388
  }
1376
1389
  if (ref2.startsWith("#/state/")) {
1377
1390
  const sub = ref2.slice("#/state/".length);
1378
1391
  const slash = sub.indexOf("/");
1379
- if (slash < 0)
1380
- return { obj: state, key: sub };
1392
+ if (slash === -1) {
1393
+ return { key: sub, obj: state };
1394
+ }
1381
1395
  const parts = sub.split("/");
1382
1396
  const lastKey = parts.pop();
1383
1397
  let obj = state;
1384
- for (const p of parts)
1398
+ for (const p of parts) {
1385
1399
  obj = obj[p];
1386
- return { obj, key: lastKey };
1400
+ }
1401
+ return { key: lastKey, obj };
1387
1402
  }
1388
- return { obj: state, key: ref2 };
1403
+ return { key: ref2, obj: state };
1389
1404
  }
1390
1405
  function evaluateExpression(node, state, event, iterCtx) {
1391
1406
  const { operator, target, value, initial } = node;
@@ -1394,117 +1409,200 @@ function evaluateExpression(node, state, event, iterCtx) {
1394
1409
  }
1395
1410
  if (UNARY_OPS.has(operator) && !("value" in node)) {
1396
1411
  const operand = resolveOperand(target, state, event, iterCtx);
1397
- if (operator === "!")
1412
+ if (operator === "!") {
1398
1413
  return !operand;
1399
- if (operator === "-")
1414
+ }
1415
+ if (operator === "-") {
1400
1416
  return -operand;
1417
+ }
1401
1418
  }
1402
1419
  if (BINARY_OPS.has(operator)) {
1403
1420
  const left = resolveOperand(target, state, event, iterCtx);
1404
1421
  const right = resolveOperand(value, state, event, iterCtx);
1405
1422
  switch (operator) {
1406
- case "+":
1423
+ case "+": {
1407
1424
  return left + right;
1408
- case "-":
1425
+ }
1426
+ case "-": {
1409
1427
  return left - right;
1410
- case "*":
1428
+ }
1429
+ case "*": {
1411
1430
  return left * right;
1412
- case "/":
1431
+ }
1432
+ case "/": {
1413
1433
  return left / right;
1414
- case "%":
1434
+ }
1435
+ case "%": {
1415
1436
  return left % right;
1416
- case "===":
1437
+ }
1438
+ case "===": {
1417
1439
  return left === right;
1418
- case "!==":
1440
+ }
1441
+ case "!==": {
1419
1442
  return left !== right;
1420
- case "<":
1443
+ }
1444
+ case "<": {
1421
1445
  return left < right;
1422
- case "<=":
1446
+ }
1447
+ case "<=": {
1423
1448
  return left <= right;
1424
- case ">":
1449
+ }
1450
+ case ">": {
1425
1451
  return left > right;
1426
- case ">=":
1452
+ }
1453
+ case ">=": {
1427
1454
  return left >= right;
1428
- case "&&":
1455
+ }
1456
+ case "&&": {
1429
1457
  return left && right;
1430
- case "||":
1458
+ }
1459
+ case "||": {
1431
1460
  return left || right;
1461
+ }
1462
+ default: {
1463
+ break;
1464
+ }
1432
1465
  }
1433
1466
  }
1434
1467
  if (ASSIGNMENT_OPS.has(operator)) {
1435
1468
  const rhs = resolveOperand(value, state, event, iterCtx);
1436
1469
  const { obj, key } = resolveWritableRef(target.$ref, state, event, iterCtx);
1437
1470
  switch (operator) {
1438
- case "=":
1471
+ case "=": {
1439
1472
  obj[key] = rhs;
1440
1473
  break;
1441
- case "+=":
1442
- obj[key] += rhs;
1474
+ }
1475
+ case "+=": {
1476
+ const current = obj[key];
1477
+ obj[key] = current + rhs;
1443
1478
  break;
1444
- case "-=":
1445
- obj[key] -= rhs;
1479
+ }
1480
+ case "-=": {
1481
+ const current = obj[key];
1482
+ obj[key] = current - rhs;
1446
1483
  break;
1447
- case "*=":
1448
- obj[key] *= rhs;
1484
+ }
1485
+ case "*=": {
1486
+ const current = obj[key];
1487
+ obj[key] = current * rhs;
1449
1488
  break;
1450
- case "/=":
1451
- obj[key] /= rhs;
1489
+ }
1490
+ case "/=": {
1491
+ const current = obj[key];
1492
+ obj[key] = current / rhs;
1452
1493
  break;
1494
+ }
1495
+ default: {
1496
+ break;
1497
+ }
1453
1498
  }
1454
1499
  return;
1455
1500
  }
1456
1501
  if (ARRAY_METHOD_OPS.has(operator)) {
1457
1502
  const arr = resolveOperand(target, state, event, iterCtx);
1458
1503
  switch (operator) {
1459
- case "push":
1504
+ case "push": {
1460
1505
  return arr.push(resolveOperand(value, state, event, iterCtx));
1461
- case "unshift":
1506
+ }
1507
+ case "unshift": {
1462
1508
  return arr.unshift(resolveOperand(value, state, event, iterCtx));
1463
- case "pop":
1509
+ }
1510
+ case "pop": {
1464
1511
  return arr.pop();
1465
- case "shift":
1512
+ }
1513
+ case "shift": {
1466
1514
  return arr.shift();
1515
+ }
1467
1516
  case "splice": {
1468
1517
  const args = resolveOperand(value, state, event, iterCtx);
1469
1518
  return arr.splice(...args);
1470
1519
  }
1520
+ default: {
1521
+ break;
1522
+ }
1471
1523
  }
1472
1524
  }
1473
1525
  if (AGGREGATE_OPS.has(operator)) {
1474
1526
  const arr = resolveOperand(target, state, event, iterCtx);
1475
1527
  if (operator === "reduce") {
1476
- const seed = resolveOperand(initial, state, event, iterCtx);
1477
- return arr.reduce((acc, item, index) => {
1478
- return evaluateExpression(value, state, event, {
1528
+ let acc = resolveOperand(initial, state, event, iterCtx);
1529
+ for (const [index, item] of arr.entries()) {
1530
+ acc = evaluateExpression(value, state, event, {
1479
1531
  acc,
1480
- item,
1481
- index
1532
+ index,
1533
+ item
1482
1534
  });
1483
- }, seed);
1535
+ }
1536
+ return acc;
1484
1537
  }
1485
1538
  if (operator === "map") {
1486
- return arr.map((item, index) => {
1487
- return evaluateExpression(value, state, event, {
1488
- ...iterCtx,
1489
- item,
1490
- index
1491
- });
1492
- });
1539
+ return arr.map((item, index) => evaluateExpression(value, state, event, {
1540
+ ...iterCtx,
1541
+ index,
1542
+ item
1543
+ }));
1493
1544
  }
1494
1545
  if (operator === "filter") {
1495
- return arr.filter((item, index) => {
1496
- return evaluateExpression(value, state, event, {
1497
- ...iterCtx,
1498
- item,
1499
- index
1500
- });
1501
- });
1546
+ return arr.filter((item, index) => evaluateExpression(value, state, event, {
1547
+ ...iterCtx,
1548
+ index,
1549
+ item
1550
+ }));
1502
1551
  }
1503
1552
  }
1504
1553
  return;
1505
1554
  }
1506
1555
  function getPath(obj, path) {
1507
- return path.split(/[./]/).reduce((o, k) => o?.[k], obj);
1556
+ let current = obj;
1557
+ for (const k of path.split(/[./]/)) {
1558
+ current = current?.[k];
1559
+ }
1560
+ return current;
1561
+ }
1562
+
1563
+ // ../schema/src/guards.ts
1564
+ function isJsonObject(value) {
1565
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1566
+ }
1567
+ function isRef2(value) {
1568
+ return isJsonObject(value) && typeof value.$ref === "string";
1569
+ }
1570
+ function isFunctionDef(value) {
1571
+ return isJsonObject(value) && value.$prototype === "Function";
1572
+ }
1573
+ function isExpressionDef(value) {
1574
+ return isJsonObject(value) && isJsonObject(value.$expression);
1575
+ }
1576
+ function isPrototypeDef(value) {
1577
+ return isJsonObject(value) && typeof value.$prototype === "string" && value.$prototype !== "Function";
1578
+ }
1579
+ function isServerFnDef(value) {
1580
+ return isJsonObject(value) && value.timing === "server" && typeof value.$src === "string" && typeof value.$export === "string" && !value.$prototype;
1581
+ }
1582
+ var SCHEMA_KEYWORDS = new Set([
1583
+ "type",
1584
+ "enum",
1585
+ "minimum",
1586
+ "maximum",
1587
+ "minLength",
1588
+ "maxLength",
1589
+ "pattern",
1590
+ "format",
1591
+ "items",
1592
+ "properties",
1593
+ "required",
1594
+ "description",
1595
+ "title",
1596
+ "$comment"
1597
+ ]);
1598
+ function isMappedArray(value) {
1599
+ return isJsonObject(value) && value.$prototype === "Array";
1600
+ }
1601
+ function paramNames(parameters) {
1602
+ if (!parameters) {
1603
+ return [];
1604
+ }
1605
+ return parameters.map((p) => typeof p === "string" ? p : p.name);
1508
1606
  }
1509
1607
 
1510
1608
  // src/runtime.ts
@@ -1521,26 +1619,30 @@ async function Jx(source, target = document.body, options) {
1521
1619
  _rootMedia = doc.$media;
1522
1620
  }
1523
1621
  const state = await buildScope(doc, {}, base);
1524
- target.appendChild(renderNode(doc, state, options));
1525
- if (typeof state.onMount === "function")
1622
+ target.append(renderNode(doc, state, options));
1623
+ if (typeof state.onMount === "function") {
1526
1624
  state.onMount(state);
1625
+ }
1527
1626
  return state;
1528
1627
  }
1529
1628
  var _resolveCache = new Map;
1530
1629
  async function resolve(source) {
1531
- if (typeof source !== "string")
1630
+ if (typeof source !== "string") {
1532
1631
  return source;
1533
- if (_resolveCache.has(source))
1632
+ }
1633
+ if (_resolveCache.has(source)) {
1534
1634
  return _resolveCache.get(source);
1635
+ }
1535
1636
  const p = fetch(source).then((res) => {
1536
- if (!res.ok)
1637
+ if (!res.ok) {
1537
1638
  throw new Error(`Jx: failed to fetch ${source} (${res.status})`);
1639
+ }
1538
1640
  return res.json();
1539
1641
  });
1540
1642
  _resolveCache.set(source, p);
1541
1643
  return p;
1542
1644
  }
1543
- var SCHEMA_KEYWORDS = new Set([
1645
+ var SCHEMA_KEYWORDS2 = new Set([
1544
1646
  "type",
1545
1647
  "properties",
1546
1648
  "items",
@@ -1566,10 +1668,10 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
1566
1668
  const defs = doc.state ?? {};
1567
1669
  const imports = doc.imports ?? {};
1568
1670
  for (const [, def2] of Object.entries(defs)) {
1569
- if (def2 && typeof def2 === "object" && !Array.isArray(def2) && def2.$prototype && def2.$prototype !== "Function" && !def2.$src) {
1671
+ if (isPrototypeDef(def2) && !def2.$src) {
1570
1672
  const mapped = imports[def2.$prototype];
1571
1673
  if (mapped) {
1572
- if (typeof mapped !== "string" || !mapped.endsWith(".class.json")) {
1674
+ if (!mapped.endsWith(".class.json")) {
1573
1675
  console.warn(`Jx: import "${def2.$prototype}" must map to a .class.json path, got "${mapped}"`);
1574
1676
  continue;
1575
1677
  }
@@ -1579,8 +1681,9 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
1579
1681
  }
1580
1682
  for (const [key, def2] of Object.entries(defs)) {
1581
1683
  if (typeof def2 === "string") {
1582
- if (!def2.includes("${"))
1684
+ if (!def2.includes("${")) {
1583
1685
  raw[key] = def2;
1686
+ }
1584
1687
  continue;
1585
1688
  }
1586
1689
  if (typeof def2 === "number" || typeof def2 === "boolean" || def2 === null) {
@@ -1592,19 +1695,22 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
1592
1695
  continue;
1593
1696
  }
1594
1697
  if (typeof def2 === "object") {
1595
- const d = def2;
1596
- if (d.$prototype)
1698
+ if (def2.$prototype) {
1597
1699
  continue;
1598
- if ("$expression" in d)
1700
+ }
1701
+ if (isExpressionDef(def2)) {
1599
1702
  continue;
1600
- if (d.timing === "server" && d.$src && d.$export)
1703
+ }
1704
+ if (isServerFnDef(def2)) {
1601
1705
  continue;
1602
- if ("default" in d) {
1603
- raw[key] = d.default;
1706
+ }
1707
+ if ("default" in def2) {
1708
+ raw[key] = def2.default;
1604
1709
  continue;
1605
1710
  }
1606
- if (hasSchemaKeywords(d))
1711
+ if (hasSchemaKeywords(def2)) {
1607
1712
  continue;
1713
+ }
1608
1714
  raw[key] = def2;
1609
1715
  }
1610
1716
  }
@@ -1615,28 +1721,29 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
1615
1721
  }
1616
1722
  }
1617
1723
  for (const [key, def2] of Object.entries(defs)) {
1618
- if (def2 && typeof def2 === "object" && !Array.isArray(def2) && "$expression" in def2) {
1724
+ if (isExpressionDef(def2)) {
1619
1725
  const node = def2.$expression;
1620
1726
  if (isMutating(node.operator)) {
1621
- state[key] = (s, event) => evaluateExpression(node, s, event);
1727
+ const handler = (s, event) => evaluateExpression(node, s, event);
1728
+ state[key] = handler;
1622
1729
  } else {
1623
1730
  state[key] = computed(() => evaluateExpression(node, state, null));
1624
1731
  }
1625
1732
  }
1626
1733
  }
1627
1734
  for (const [key, def2] of Object.entries(defs)) {
1628
- if (typeof def2 === "object" && def2?.$prototype === "Function") {
1735
+ if (isFunctionDef(def2)) {
1629
1736
  state[key] = await resolveFunction(def2, state, key, base);
1630
1737
  }
1631
1738
  }
1632
1739
  for (const [key, def2] of Object.entries(defs)) {
1633
- if (typeof def2 === "object" && def2?.$prototype && def2.$prototype !== "Function") {
1740
+ if (isPrototypeDef(def2)) {
1634
1741
  state[key] = await resolvePrototype(def2, state, key, base);
1635
1742
  }
1636
1743
  }
1637
1744
  if (!_serverFnConfig.skip) {
1638
1745
  for (const [key, def2] of Object.entries(defs)) {
1639
- if (def2 != null && typeof def2 === "object" && def2.timing === "server" && def2.$src && def2.$export && !def2.$prototype) {
1746
+ if (isServerFnDef(def2)) {
1640
1747
  state[key] = await resolveServerFunction(def2, state, key, base);
1641
1748
  }
1642
1749
  }
@@ -1650,8 +1757,9 @@ async function buildScope(doc, parentScope = {}, base = location.href) {
1650
1757
  }
1651
1758
  function hasSchemaKeywords(obj) {
1652
1759
  for (const k of Object.keys(obj)) {
1653
- if (SCHEMA_KEYWORDS.has(k))
1760
+ if (SCHEMA_KEYWORDS2.has(k)) {
1654
1761
  return true;
1762
+ }
1655
1763
  }
1656
1764
  return false;
1657
1765
  }
@@ -1669,8 +1777,8 @@ async function resolveFunction(def2, state, key, base) {
1669
1777
  const params = resolveParamNames(def2);
1670
1778
  const noop = new Function(...params, "");
1671
1779
  Object.defineProperty(noop, "name", {
1672
- value: def2.name ?? key,
1673
- configurable: true
1780
+ configurable: true,
1781
+ value: def2.name ?? key
1674
1782
  });
1675
1783
  return noop;
1676
1784
  }
@@ -1679,11 +1787,14 @@ async function resolveFunction(def2, state, key, base) {
1679
1787
  const params = resolveParamNames(def2);
1680
1788
  fn = new Function(...params, def2.body);
1681
1789
  Object.defineProperty(fn, "name", {
1682
- value: def2.name ?? key,
1683
- configurable: true
1790
+ configurable: true,
1791
+ value: def2.name ?? key
1684
1792
  });
1685
1793
  } else {
1686
1794
  const src = def2.$src;
1795
+ if (!src) {
1796
+ throw new Error(`Jx: '${key}' has neither body nor $src`);
1797
+ }
1687
1798
  const exportName = def2.$export ?? key;
1688
1799
  let mod;
1689
1800
  if (_moduleCache.has(src)) {
@@ -1703,7 +1814,7 @@ async function resolveFunction(def2, state, key, base) {
1703
1814
  }
1704
1815
  fn = mod[exportName] ?? mod.default?.[exportName];
1705
1816
  if (typeof fn !== "function") {
1706
- throw new Error(`Jx: export "${exportName}" not found or not a function in "${src}"`);
1817
+ throw new TypeError(`Jx: export "${exportName}" not found or not a function in "${src}"`);
1707
1818
  }
1708
1819
  }
1709
1820
  const hasParams = (def2.parameters ?? def2.arguments ?? []).length > 0;
@@ -1721,13 +1832,7 @@ async function resolveFunction(def2, state, key, base) {
1721
1832
  return fn;
1722
1833
  }
1723
1834
  function resolveParamNames(def2) {
1724
- const raw = def2.parameters ?? def2.arguments ?? [];
1725
- let names;
1726
- if (Array.isArray(raw) && raw.length > 0 && typeof raw[0] === "object") {
1727
- names = raw.map((p) => p.name ?? p.identifier ?? "arg");
1728
- } else {
1729
- names = raw;
1730
- }
1835
+ const names = def2.parameters ? paramNames(def2.parameters) : def2.arguments ?? [];
1731
1836
  return names.length > 0 && names[0] === "state" ? names : ["state", ...names];
1732
1837
  }
1733
1838
  var RESERVED_KEYS = new Set([
@@ -1778,8 +1883,9 @@ function renderNode(def2, state, options) {
1778
1883
  let localState = state;
1779
1884
  for (const [key, val] of Object.entries(def2)) {
1780
1885
  if (key.startsWith("$") && !RESERVED_KEYS.has(key)) {
1781
- if (localState === state)
1886
+ if (localState === state) {
1782
1887
  localState = Object.create(state);
1888
+ }
1783
1889
  localState[key] = isRefObj(val) ? resolveRef(val.$ref, state) : val;
1784
1890
  }
1785
1891
  }
@@ -1792,20 +1898,23 @@ function renderNode(def2, state, options) {
1792
1898
  const { $props: _$props, ...rest } = def2;
1793
1899
  return renderNode(rest, mergeProps(def2, localState), options);
1794
1900
  }
1795
- if (def2.$switch)
1901
+ if (def2.$switch) {
1796
1902
  return renderSwitch(def2, localState, options);
1797
- if (def2.children?.$prototype === "Array")
1798
- return renderMappedArray(def2, localState, options);
1903
+ }
1904
+ if (isMappedArray(def2.children)) {
1905
+ return renderMappedArray(def2, def2.children, localState, options);
1906
+ }
1799
1907
  const el = document.createElement(tagName);
1800
- if (options?.onNodeCreated)
1908
+ if (options?.onNodeCreated) {
1801
1909
  options.onNodeCreated(el, path, def2);
1910
+ }
1802
1911
  applyProperties(el, def2, localState);
1803
1912
  applyStyle(el, def2.style ?? {}, localState["$media"] ?? {}, localState);
1804
1913
  applyAttributes(el, def2.attributes ?? {}, localState);
1805
1914
  const children = Array.isArray(def2.children) ? def2.children : [];
1806
1915
  for (let i = 0;i < children.length; i++) {
1807
1916
  const childOpts = options ? { ...options, _path: [...path, "children", i] } : undefined;
1808
- el.appendChild(renderNode(children[i], localState, childOpts));
1917
+ el.append(renderNode(children[i], localState, childOpts));
1809
1918
  }
1810
1919
  return el;
1811
1920
  }
@@ -1814,10 +1923,12 @@ function isTemplateString(val) {
1814
1923
  }
1815
1924
  function applyProperties(el, def2, state) {
1816
1925
  for (const [key, val] of Object.entries(def2)) {
1817
- if (RESERVED_KEYS.has(key))
1926
+ if (RESERVED_KEYS.has(key)) {
1818
1927
  continue;
1819
- if (key.startsWith("$"))
1928
+ }
1929
+ if (key.startsWith("$")) {
1820
1930
  continue;
1931
+ }
1821
1932
  if (key.startsWith("on")) {
1822
1933
  if (isRefObj(val)) {
1823
1934
  const handler = resolveRef(val.$ref, state);
@@ -1827,14 +1938,14 @@ function applyProperties(el, def2, state) {
1827
1938
  }
1828
1939
  continue;
1829
1940
  }
1830
- if (val && typeof val === "object" && val.$prototype === "Function" && val.body) {
1941
+ if (isFunctionDef(val) && val.body) {
1831
1942
  const params = resolveParamNames(val);
1832
1943
  const fn = new Function(...params, val.body);
1833
1944
  const scope = state;
1834
1945
  el.addEventListener(key.slice(2), (e) => fn(scope, e));
1835
1946
  continue;
1836
1947
  }
1837
- if (val && typeof val === "object" && "$expression" in val) {
1948
+ if (isExpressionDef(val)) {
1838
1949
  const node = val.$expression;
1839
1950
  const scope = state;
1840
1951
  el.addEventListener(key.slice(2), (e) => evaluateExpression(node, scope, e));
@@ -1880,50 +1991,66 @@ function applyStyle(el, styleDef, mediaQueries = {}, state = {}) {
1880
1991
  }
1881
1992
  }
1882
1993
  for (const [prop, val] of Object.entries(styleDef)) {
1883
- if (prop.startsWith("@"))
1884
- media[prop] = val;
1885
- else if (isNestedSelector(prop))
1886
- nested[prop] = val;
1887
- else if (val !== null && typeof val === "object" && !Array.isArray(val))
1888
- nested[prop] = val;
1889
- else if (prop.startsWith("--")) {
1890
- if (isTemplateString(val))
1994
+ if (val !== null && typeof val === "object" && !Array.isArray(val)) {
1995
+ if (prop.startsWith("@")) {
1996
+ media[prop] = val;
1997
+ } else {
1998
+ nested[prop] = val;
1999
+ }
2000
+ continue;
2001
+ }
2002
+ if (prop.startsWith("@") || isNestedSelector(prop)) {
2003
+ continue;
2004
+ }
2005
+ if (val === undefined) {
2006
+ continue;
2007
+ }
2008
+ const scalar = String(val);
2009
+ if (prop.startsWith("--")) {
2010
+ if (isTemplateString(val)) {
1891
2011
  effect(() => {
1892
2012
  el.style.setProperty(prop, evaluateTemplate(val, state));
1893
2013
  });
1894
- else
1895
- el.style.setProperty(prop, val);
1896
- } else if (isTemplateString(val))
2014
+ } else {
2015
+ el.style.setProperty(prop, scalar);
2016
+ }
2017
+ } else if (isTemplateString(val)) {
1897
2018
  effect(() => {
1898
2019
  el.style[prop] = evaluateTemplate(val, state);
1899
2020
  });
1900
- else if (mediaOverriddenProps.has(prop))
1901
- baseDecls[prop] = val;
1902
- else
1903
- el.style[prop] = val;
2021
+ } else if (mediaOverriddenProps.has(prop)) {
2022
+ baseDecls[prop] = scalar;
2023
+ } else {
2024
+ el.style[prop] = scalar;
2025
+ }
1904
2026
  }
1905
2027
  const hasNested = Object.keys(nested).length > 0;
1906
2028
  const hasMedia = Object.keys(media).length > 0;
1907
2029
  const hasBaseDecls = Object.keys(baseDecls).length > 0;
1908
- if (!hasNested && !hasMedia && !hasBaseDecls)
2030
+ if (!hasNested && !hasMedia && !hasBaseDecls) {
1909
2031
  return;
2032
+ }
1910
2033
  const uid = `jx-${Math.random().toString(36).slice(2, 7)}`;
1911
2034
  el.dataset.jx = uid;
1912
2035
  let css = "";
1913
2036
  const baseCSS = toCSSText(baseDecls);
1914
- if (baseCSS)
2037
+ if (baseCSS) {
1915
2038
  css += `[data-jx="${uid}"] { ${baseCSS} }
1916
2039
  `;
2040
+ }
1917
2041
  function emitNested(scope, rules) {
1918
2042
  const props = toCSSText(rules);
1919
- if (props)
2043
+ if (props) {
1920
2044
  css += `${scope} { ${props} }
1921
2045
  `;
2046
+ }
1922
2047
  for (const [sel, sub] of Object.entries(rules)) {
1923
- if (sub === null || typeof sub !== "object" || Array.isArray(sub))
2048
+ if (sub === null || typeof sub !== "object" || Array.isArray(sub)) {
1924
2049
  continue;
1925
- if (sel.startsWith("@"))
2050
+ }
2051
+ if (sel.startsWith("@")) {
1926
2052
  continue;
2053
+ }
1927
2054
  const resolved = sel.startsWith("&") ? sel.replace("&", scope) : sel.startsWith("[") ? `${scope}${sel}` : sel.startsWith(":") || sel.startsWith(".") ? `${scope}${sel}` : `${scope} ${sel}`;
1928
2055
  emitNested(resolved, sub);
1929
2056
  }
@@ -1932,32 +2059,36 @@ function applyStyle(el, styleDef, mediaQueries = {}, state = {}) {
1932
2059
  const resolved = sel.startsWith("&") ? sel.replace("&", `[data-jx="${uid}"]`) : sel.startsWith("[") ? `[data-jx="${uid}"]${sel}` : sel.startsWith(":") || sel.startsWith(".") ? `[data-jx="${uid}"]${sel}` : `[data-jx="${uid}"] ${sel}`;
1933
2060
  emitNested(resolved, rules);
1934
2061
  }
1935
- for (const [key, rules] of Object.entries(media)) {
1936
- let emitMediaNested = function(parentSel, obj) {
1937
- for (const [sel, sub] of Object.entries(obj)) {
1938
- if (sub === null || typeof sub !== "object" || Array.isArray(sub))
1939
- continue;
1940
- if (sel.startsWith("@"))
1941
- continue;
1942
- const resolved = sel.startsWith("&") ? sel.replace("&", parentSel) : sel.startsWith("[") ? `${parentSel}${sel}` : sel.startsWith(":") || sel.startsWith(".") ? `${parentSel}${sel}` : `${parentSel} ${sel}`;
1943
- const props = toCSSText(sub);
1944
- if (props)
1945
- css += `${atRule} { ${resolved} { ${props} } }
2062
+ function emitMediaNested(atRule, parentSel, obj) {
2063
+ for (const [sel, sub] of Object.entries(obj)) {
2064
+ if (sub === null || typeof sub !== "object" || Array.isArray(sub)) {
2065
+ continue;
2066
+ }
2067
+ if (sel.startsWith("@")) {
2068
+ continue;
2069
+ }
2070
+ const resolved = sel.startsWith("&") ? sel.replace("&", parentSel) : sel.startsWith("[") ? `${parentSel}${sel}` : sel.startsWith(":") || sel.startsWith(".") ? `${parentSel}${sel}` : `${parentSel} ${sel}`;
2071
+ const props = toCSSText(sub);
2072
+ if (props) {
2073
+ css += `${atRule} { ${resolved} { ${props} } }
1946
2074
  `;
1947
- emitMediaNested(resolved, sub);
1948
2075
  }
1949
- };
1950
- if (key === "@--")
2076
+ emitMediaNested(atRule, resolved, sub);
2077
+ }
2078
+ }
2079
+ for (const [key, rules] of Object.entries(media)) {
2080
+ if (key === "@--") {
1951
2081
  continue;
2082
+ }
1952
2083
  const atRule = key.startsWith("@--") ? `@media ${mediaQueries[key.slice(1)] ?? key.slice(1)}` : key.startsWith("@(") ? `@media ${key.slice(1)}` : key;
1953
2084
  const scope = `[data-jx="${uid}"]`;
1954
2085
  css += `${atRule} { ${scope} { ${toCSSText(rules)} } }
1955
2086
  `;
1956
- emitMediaNested(scope, rules);
2087
+ emitMediaNested(atRule, scope, rules);
1957
2088
  }
1958
2089
  const tag = document.createElement("style");
1959
2090
  tag.textContent = css;
1960
- document.head.appendChild(tag);
2091
+ document.head.append(tag);
1961
2092
  }
1962
2093
  function applyAttributes(el, attrs, state) {
1963
2094
  for (const [k, v] of Object.entries(attrs)) {
@@ -1970,78 +2101,87 @@ function applyAttributes(el, attrs, state) {
1970
2101
  }
1971
2102
  }
1972
2103
  }
1973
- function renderMappedArray(def2, state, options) {
2104
+ function renderMappedArray(def2, arrayDef, state, options) {
1974
2105
  const path = options?._path ?? [];
1975
2106
  const container = document.createElement(def2.tagName ?? "div");
1976
- if (options?.onNodeCreated)
2107
+ if (options?.onNodeCreated) {
1977
2108
  options.onNodeCreated(container, path, def2);
2109
+ }
1978
2110
  applyProperties(container, def2, state);
1979
2111
  applyStyle(container, def2.style ?? {}, state["$media"] ?? {}, state);
1980
2112
  applyAttributes(container, def2.attributes ?? {}, state);
1981
- const { items: itemsSrc, map: mapDef, filter: filterRef, sort: sortRef } = def2.children;
2113
+ const { items: itemsSrc, map: mapDef, filter: filterRef, sort: sortRef } = arrayDef;
1982
2114
  effect(() => {
1983
2115
  container.innerHTML = "";
1984
2116
  let items;
1985
- if (isRefObj(itemsSrc)) {
1986
- items = resolveRef(itemsSrc.$ref, state);
1987
- } else {
1988
- items = itemsSrc;
1989
- }
1990
- if (!Array.isArray(items))
2117
+ items = isRefObj(itemsSrc) ? resolveRef(itemsSrc.$ref, state) : itemsSrc;
2118
+ if (!Array.isArray(items)) {
1991
2119
  return;
1992
- if (filterRef) {
2120
+ }
2121
+ if (isRefObj(filterRef)) {
1993
2122
  const fn = resolveRef(filterRef.$ref, state);
1994
- if (typeof fn === "function")
2123
+ if (typeof fn === "function") {
1995
2124
  items = items.filter(fn);
2125
+ }
1996
2126
  }
1997
- if (sortRef) {
2127
+ if (isRefObj(sortRef)) {
1998
2128
  const fn = resolveRef(sortRef.$ref, state);
1999
- if (typeof fn === "function")
2000
- items = [...items].sort(fn);
2129
+ if (typeof fn === "function") {
2130
+ items = [...items].toSorted(fn);
2131
+ }
2001
2132
  }
2002
- items.forEach((item, index) => {
2133
+ for (const [index, item] of items.entries()) {
2003
2134
  const child = Object.create(state);
2004
- child.$map = { item, index };
2135
+ child.$map = { index, item };
2005
2136
  child["$map/item"] = item;
2006
2137
  child["$map/index"] = index;
2007
2138
  const childOpts = options ? { ...options, _path: [...path, "children", "map", index] } : undefined;
2008
- container.appendChild(renderNode(mapDef, child, childOpts));
2009
- });
2139
+ if (mapDef) {
2140
+ container.append(renderNode(mapDef, child, childOpts));
2141
+ }
2142
+ }
2010
2143
  });
2011
2144
  return container;
2012
2145
  }
2013
2146
  function renderSwitch(def2, state, options) {
2014
2147
  const path = options?._path ?? [];
2015
2148
  const container = document.createElement(def2.tagName ?? "div");
2016
- if (options?.onNodeCreated)
2149
+ if (options?.onNodeCreated) {
2017
2150
  options.onNodeCreated(container, path, def2);
2151
+ }
2018
2152
  applyProperties(container, def2, state);
2019
2153
  applyStyle(container, def2.style ?? {}, state["$media"] ?? {}, state);
2020
2154
  applyAttributes(container, def2.attributes ?? {}, state);
2021
2155
  let generation = 0;
2022
2156
  effect(() => {
2023
2157
  container.innerHTML = "";
2158
+ if (!isRefObj(def2.$switch)) {
2159
+ return;
2160
+ }
2024
2161
  const key = resolveRef(def2.$switch.$ref, state);
2025
2162
  const caseDef = def2.cases?.[key];
2026
- if (!caseDef)
2163
+ if (!caseDef) {
2027
2164
  return;
2165
+ }
2028
2166
  if (isRefObj(caseDef)) {
2029
- const gen = ++generation;
2030
- const href = new URL(caseDef.$ref, location.href).href;
2167
+ const gen = generation += 1;
2168
+ const { href } = new URL(caseDef.$ref, location.href);
2031
2169
  resolve(href).then(async (doc) => {
2032
- if (gen !== generation)
2170
+ if (gen !== generation) {
2033
2171
  return;
2172
+ }
2034
2173
  const childScope = await buildScope(doc, {}, href);
2035
- if (gen !== generation)
2174
+ if (gen !== generation) {
2036
2175
  return;
2176
+ }
2037
2177
  container.innerHTML = "";
2038
2178
  const childOpts2 = options ? { ...options, _path: [...path, "cases", key] } : undefined;
2039
- container.appendChild(renderNode(doc, childScope, childOpts2));
2040
- }).catch((e) => console.error("Jx $switch: failed to load external case", caseDef.$ref, e));
2179
+ container.append(renderNode(doc, childScope, childOpts2));
2180
+ }).catch((error) => console.error("Jx $switch: failed to load external case", caseDef.$ref, error));
2041
2181
  return;
2042
2182
  }
2043
2183
  const childOpts = options ? { ...options, _path: [...path, "cases", key] } : undefined;
2044
- container.appendChild(renderNode(caseDef, state, childOpts));
2184
+ container.append(renderNode(caseDef, state, childOpts));
2045
2185
  });
2046
2186
  return container;
2047
2187
  }
@@ -2060,28 +2200,31 @@ async function resolvePrototype(def2, state, key, base) {
2060
2200
  if (isTemplateString(def2.url)) {
2061
2201
  url = evaluateTemplate(def2.url, state);
2062
2202
  } else {
2063
- url = def2.url;
2203
+ ({ url } = def2);
2064
2204
  }
2065
- if (!url || url === "undefined" || url.includes("undefined"))
2205
+ if (!url || url === "undefined" || url.includes("undefined")) {
2066
2206
  return;
2207
+ }
2067
2208
  const controller = new AbortController;
2068
2209
  onEffectCleanup(() => {
2069
2210
  controller.abort();
2070
- if (debounceTimer !== null)
2211
+ if (debounceTimer !== null) {
2071
2212
  clearTimeout(debounceTimer);
2213
+ }
2072
2214
  });
2073
2215
  const doFetch = () => fetch(url, {
2074
- signal: controller.signal,
2075
2216
  method: def2.method ?? "GET",
2217
+ signal: controller.signal,
2076
2218
  ...def2.headers && { headers: def2.headers },
2077
2219
  ...def2.body && {
2078
2220
  body: typeof def2.body === "object" ? JSON.stringify(def2.body) : def2.body
2079
2221
  }
2080
2222
  }).then((r) => r.ok ? r.json() : Promise.reject(r.statusText)).then((d) => {
2081
2223
  s.value = d;
2082
- }).catch((e) => {
2083
- if (e.name !== "AbortError")
2084
- s.value = { error: String(e) };
2224
+ }).catch((error) => {
2225
+ if (!(error instanceof Error && error.name === "AbortError")) {
2226
+ s.value = { error: String(error) };
2227
+ }
2085
2228
  });
2086
2229
  if (debounceMs > 0) {
2087
2230
  debounceTimer = setTimeout(doFetch, debounceMs);
@@ -2092,7 +2235,7 @@ async function resolvePrototype(def2, state, key, base) {
2092
2235
  }
2093
2236
  return s;
2094
2237
  }
2095
- case "URLSearchParams":
2238
+ case "URLSearchParams": {
2096
2239
  return computed(() => {
2097
2240
  const p = {};
2098
2241
  for (const [k, v] of Object.entries(def2)) {
@@ -2102,6 +2245,7 @@ async function resolvePrototype(def2, state, key, base) {
2102
2245
  }
2103
2246
  return new URLSearchParams(p).toString();
2104
2247
  });
2248
+ }
2105
2249
  case "LocalStorage":
2106
2250
  case "SessionStorage": {
2107
2251
  const store = def2.$prototype === "LocalStorage" ? localStorage : sessionStorage;
@@ -2131,9 +2275,10 @@ async function resolvePrototype(def2, state, key, base) {
2131
2275
  case "Cookie": {
2132
2276
  const name = def2.name ?? key;
2133
2277
  const read = () => {
2134
- const m = document.cookie.match(new RegExp("(?:^|; )" + name + "=([^;]*)"));
2135
- if (!m)
2278
+ const m = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
2279
+ if (!m) {
2136
2280
  return null;
2281
+ }
2137
2282
  try {
2138
2283
  return JSON.parse(decodeURIComponent(m[1]));
2139
2284
  } catch {
@@ -2144,16 +2289,21 @@ async function resolvePrototype(def2, state, key, base) {
2144
2289
  effect(() => {
2145
2290
  const v = cookieState.value;
2146
2291
  let s = `${name}=${encodeURIComponent(JSON.stringify(v))}`;
2147
- if (def2.maxAge !== undefined)
2292
+ if (def2.maxAge !== undefined) {
2148
2293
  s += `; Max-Age=${def2.maxAge}`;
2149
- if (def2.path)
2294
+ }
2295
+ if (def2.path) {
2150
2296
  s += `; Path=${def2.path}`;
2151
- if (def2.domain)
2297
+ }
2298
+ if (def2.domain) {
2152
2299
  s += `; Domain=${def2.domain}`;
2153
- if (def2.secure)
2300
+ }
2301
+ if (def2.secure) {
2154
2302
  s += `; Secure`;
2155
- if (def2.sameSite)
2303
+ }
2304
+ if (def2.sameSite) {
2156
2305
  s += `; SameSite=${def2.sameSite}`;
2306
+ }
2157
2307
  document.cookie = s;
2158
2308
  });
2159
2309
  return cookieState;
@@ -2168,47 +2318,59 @@ async function resolvePrototype(def2, state, key, base) {
2168
2318
  autoIncrement = true,
2169
2319
  indexes = []
2170
2320
  } = def2;
2321
+ if (!database || !store) {
2322
+ throw new Error(`Jx: IndexedDB entry '${key}' requires database and store`);
2323
+ }
2171
2324
  const req = indexedDB.open(database, version);
2172
- req.onupgradeneeded = (e) => {
2325
+ req.addEventListener("upgradeneeded", (e) => {
2173
2326
  const db = e.target.result;
2174
2327
  if (!db.objectStoreNames.contains(store)) {
2175
- const os = db.createObjectStore(store, { keyPath, autoIncrement });
2176
- for (const i of indexes)
2328
+ const os = db.createObjectStore(store, { autoIncrement, keyPath });
2329
+ for (const i of indexes) {
2177
2330
  os.createIndex(i.name, i.keyPath, { unique: i.unique ?? false });
2331
+ }
2178
2332
  }
2179
- };
2180
- req.onsuccess = (e) => {
2333
+ });
2334
+ req.addEventListener("success", (e) => {
2181
2335
  const db = e.target.result;
2182
2336
  idbState.value = {
2183
2337
  database,
2184
- store,
2185
- version,
2338
+ getStore: (mode = "readwrite") => Promise.resolve(db.transaction(store, mode).objectStore(store)),
2186
2339
  isReady: true,
2187
- getStore: (mode = "readwrite") => Promise.resolve(db.transaction(store, mode).objectStore(store))
2340
+ store,
2341
+ version
2188
2342
  };
2189
- };
2190
- req.onerror = () => {
2343
+ });
2344
+ req.addEventListener("error", () => {
2191
2345
  idbState.value = { error: req.error?.message };
2192
- };
2346
+ });
2193
2347
  return idbState;
2194
2348
  }
2195
- case "Set":
2196
- return new Set(def2.default ?? []);
2197
- case "Map":
2198
- return new Map(Object.entries(def2.default ?? {}));
2349
+ case "Set": {
2350
+ return new Set(Array.isArray(def2.default) ? def2.default : []);
2351
+ }
2352
+ case "Map": {
2353
+ return new Map(Object.entries(isJsonObject(def2.default) ? def2.default : {}));
2354
+ }
2199
2355
  case "FormData": {
2200
2356
  const fd = new FormData;
2201
- for (const [k, v] of Object.entries(def2.fields ?? {}))
2357
+ for (const [k, v] of Object.entries(def2.fields ?? {})) {
2202
2358
  fd.append(k, v);
2359
+ }
2203
2360
  return fd;
2204
2361
  }
2205
- case "Blob":
2206
- return new Blob(def2.parts ?? [], { type: def2.type ?? "text/plain" });
2207
- case "ReadableStream":
2362
+ case "Blob": {
2363
+ return new Blob(def2.parts ?? [], {
2364
+ type: typeof def2.type === "string" ? def2.type : "text/plain"
2365
+ });
2366
+ }
2367
+ case "ReadableStream": {
2208
2368
  return null;
2209
- default:
2369
+ }
2370
+ default: {
2210
2371
  console.warn(`Jx: unknown $prototype "${def2.$prototype}" for "${key}". Did you mean to add '$src'?`);
2211
2372
  return ref(null);
2373
+ }
2212
2374
  }
2213
2375
  }
2214
2376
  var EXTERNAL_RESERVED = new Set([
@@ -2225,7 +2387,7 @@ var EXTERNAL_RESERVED = new Set([
2225
2387
  ]);
2226
2388
  async function resolveExternalPrototype(def2, state, key, base) {
2227
2389
  const src = def2.$src;
2228
- if (!src.endsWith(".class.json")) {
2390
+ if (!src || !src.endsWith(".class.json")) {
2229
2391
  throw new Error(`Jx: $prototype "${def2.$prototype}" requires a .class.json $src, got "${src}". Wrap the class in a .class.json schema with $implementation.`);
2230
2392
  }
2231
2393
  return resolveClassJson(def2, state, key, base);
@@ -2252,19 +2414,20 @@ async function importAndInstantiate(def2, src, exportName, base) {
2252
2414
  throw new Error(`Jx: export "${exportName}" not found in "${src}"`);
2253
2415
  }
2254
2416
  if (typeof ExportedClass !== "function") {
2255
- throw new Error(`Jx: "${exportName}" from "${src}" is not a class`);
2417
+ throw new TypeError(`Jx: "${exportName}" from "${src}" is not a class`);
2256
2418
  }
2257
2419
  const config = {};
2258
2420
  for (const [k, v] of Object.entries(def2)) {
2259
- if (!EXTERNAL_RESERVED.has(k))
2421
+ if (!EXTERNAL_RESERVED.has(k)) {
2260
2422
  config[k] = v;
2423
+ }
2261
2424
  }
2262
2425
  const instance = new ExportedClass(config);
2263
2426
  let value;
2264
2427
  if (typeof instance.resolve === "function") {
2265
2428
  value = await instance.resolve();
2266
2429
  } else if ("value" in instance) {
2267
- value = instance.value;
2430
+ ({ value } = instance);
2268
2431
  } else {
2269
2432
  value = instance;
2270
2433
  }
@@ -2278,6 +2441,9 @@ async function importAndInstantiate(def2, src, exportName, base) {
2278
2441
  }
2279
2442
  async function resolveClassJson(def2, state, key, base) {
2280
2443
  const src = def2.$src;
2444
+ if (!src) {
2445
+ throw new Error(`Jx: class entry '${key}' has no $src`);
2446
+ }
2281
2447
  let classDef;
2282
2448
  const isBareSpecifier = !src.startsWith(".") && !src.startsWith("/") && !src.startsWith("http") && !src.startsWith("file:");
2283
2449
  if (isBareSpecifier) {
@@ -2286,8 +2452,9 @@ async function resolveClassJson(def2, state, key, base) {
2286
2452
  try {
2287
2453
  const url = base ? new URL(src, base).href : src;
2288
2454
  const res = await fetch(url);
2289
- if (!res.ok)
2455
+ if (!res.ok) {
2290
2456
  throw new Error(`HTTP ${res.status}`);
2457
+ }
2291
2458
  classDef = await res.json();
2292
2459
  } catch {
2293
2460
  return resolveViaDevProxy(def2, state, key, base);
@@ -2309,15 +2476,16 @@ async function resolveClassJson(def2, state, key, base) {
2309
2476
  const DynClass = classFromSchema(classDef);
2310
2477
  const config = {};
2311
2478
  for (const [k, v] of Object.entries(def2)) {
2312
- if (!EXTERNAL_RESERVED.has(k))
2479
+ if (!EXTERNAL_RESERVED.has(k)) {
2313
2480
  config[k] = v;
2481
+ }
2314
2482
  }
2315
2483
  const instance = new DynClass(config);
2316
2484
  let value;
2317
2485
  if (typeof instance.resolve === "function") {
2318
2486
  value = await instance.resolve();
2319
2487
  } else if ("value" in instance) {
2320
- value = instance.value;
2488
+ ({ value } = instance);
2321
2489
  } else {
2322
2490
  value = instance;
2323
2491
  }
@@ -2331,23 +2499,24 @@ async function resolveClassJson(def2, state, key, base) {
2331
2499
  }
2332
2500
  function classFromSchema(classDef) {
2333
2501
  const fields = classDef.$defs?.fields ?? {};
2334
- const ctor = classDef.$defs?.constructor;
2502
+ const rawCtor = classDef.$defs?.constructor;
2503
+ const ctor = typeof rawCtor === "object" ? rawCtor : undefined;
2335
2504
  const methods = classDef.$defs?.methods ?? {};
2336
2505
 
2337
2506
  class DynClass {
2338
2507
  constructor(config = {}) {
2339
- for (const [key, field] of Object.entries(fields)) {
2340
- const typedField = field;
2508
+ for (const [key, typedField] of Object.entries(fields)) {
2341
2509
  const id = typedField.identifier ?? key;
2342
2510
  const propName = typedField.access === "private" ? `_${id}` : id;
2343
- if (config[id] !== undefined)
2511
+ if (config[id] !== undefined) {
2344
2512
  this[propName] = config[id];
2345
- else if (typedField.initializer !== undefined)
2513
+ } else if (typedField.initializer !== undefined) {
2346
2514
  this[propName] = typedField.initializer;
2347
- else if (typedField.default !== undefined)
2515
+ } else if (typedField.default !== undefined) {
2348
2516
  this[propName] = structuredClone(typedField.default);
2349
- else
2517
+ } else {
2350
2518
  this[propName] = null;
2519
+ }
2351
2520
  }
2352
2521
  if (ctor?.body) {
2353
2522
  const bodyStr = Array.isArray(ctor.body) ? ctor.body.join(`
@@ -2356,23 +2525,25 @@ function classFromSchema(classDef) {
2356
2525
  }
2357
2526
  }
2358
2527
  }
2359
- for (const [key, method] of Object.entries(methods)) {
2360
- const typedMethod = method;
2528
+ for (const [key, typedMethod] of Object.entries(methods)) {
2361
2529
  const name = typedMethod.identifier ?? key;
2362
2530
  const params = (typedMethod.parameters ?? []).map((p) => {
2363
- if (p.$ref)
2531
+ if (p.$ref) {
2364
2532
  return p.$ref.split("/").pop();
2365
- return p.identifier ?? p.name ?? "arg";
2533
+ }
2534
+ const n = p.identifier ?? p.name;
2535
+ return typeof n === "string" ? n : "arg";
2366
2536
  });
2367
2537
  const bodyStr = Array.isArray(typedMethod.body) ? typedMethod.body.join(`
2368
2538
  `) : typedMethod.body ?? "";
2369
2539
  if (typedMethod.role === "accessor") {
2370
2540
  const descriptor = {};
2371
- if (typedMethod.getter)
2372
- descriptor.get = new Function(typedMethod.getter.body);
2541
+ if (typedMethod.getter) {
2542
+ descriptor.get = new Function(typedMethod.getter.body ?? "");
2543
+ }
2373
2544
  if (typedMethod.setter) {
2374
2545
  const sp = (typedMethod.setter.parameters ?? []).map((p) => p.$ref?.split("/").pop() ?? "v");
2375
- descriptor.set = new Function(...sp, typedMethod.setter.body);
2546
+ descriptor.set = new Function(...sp, typedMethod.setter.body ?? "");
2376
2547
  }
2377
2548
  Object.defineProperty(DynClass.prototype, name, {
2378
2549
  ...descriptor,
@@ -2385,8 +2556,8 @@ function classFromSchema(classDef) {
2385
2556
  }
2386
2557
  }
2387
2558
  Object.defineProperty(DynClass, "name", {
2388
- value: classDef.title,
2389
- configurable: true
2559
+ configurable: true,
2560
+ value: classDef.title
2390
2561
  });
2391
2562
  const dynCtor = DynClass;
2392
2563
  return dynCtor;
@@ -2394,23 +2565,25 @@ function classFromSchema(classDef) {
2394
2565
  async function resolveViaDevProxy(def2, state, key, base) {
2395
2566
  const config = {};
2396
2567
  for (const [k, v] of Object.entries(def2)) {
2397
- if (!EXTERNAL_RESERVED.has(k))
2568
+ if (!EXTERNAL_RESERVED.has(k)) {
2398
2569
  config[k] = v;
2570
+ }
2399
2571
  }
2400
2572
  const hasTemplates = Object.values(config).some((v) => isTemplateString(v));
2401
2573
  const doResolve = (resolvedConfig) => fetch("/__jx_resolve__", {
2402
- method: "POST",
2403
- headers: { "Content-Type": "application/json" },
2404
2574
  body: JSON.stringify({
2405
- $src: def2.$src,
2406
- $prototype: def2.$prototype,
2407
- $export: def2.$export,
2408
2575
  $base: base,
2576
+ $export: def2.$export,
2577
+ $prototype: def2.$prototype,
2578
+ $src: def2.$src,
2409
2579
  ...resolvedConfig
2410
- })
2580
+ }),
2581
+ headers: { "Content-Type": "application/json" },
2582
+ method: "POST"
2411
2583
  }).then((r) => {
2412
- if (!r.ok)
2584
+ if (!r.ok) {
2413
2585
  throw new Error(`Jx dev proxy ${r.status} for "${key}"`);
2586
+ }
2414
2587
  return r.json();
2415
2588
  });
2416
2589
  const s = ref(null);
@@ -2422,12 +2595,12 @@ async function resolveViaDevProxy(def2, state, key, base) {
2422
2595
  }
2423
2596
  doResolve(resolvedConfig).then((value) => {
2424
2597
  s.value = value;
2425
- }).catch((e) => console.error("Jx dev proxy:", e));
2598
+ }).catch((error) => console.error("Jx dev proxy:", error));
2426
2599
  });
2427
2600
  } else {
2428
2601
  doResolve(config).then((value) => {
2429
2602
  s.value = value;
2430
- }).catch((e) => console.error("Jx dev proxy:", e));
2603
+ }).catch((error) => console.error("Jx dev proxy:", error));
2431
2604
  }
2432
2605
  return s;
2433
2606
  }
@@ -2455,10 +2628,12 @@ async function resolveServerFunction(def2, state, key, base) {
2455
2628
  _moduleCache.set(src, mod);
2456
2629
  }
2457
2630
  const fn = mod[exportName] ?? mod.default?.[exportName];
2458
- if (!fn)
2631
+ if (!fn) {
2459
2632
  throw new Error(`Jx: export "${exportName}" not found in "${src}" for "${key}"`);
2460
- if (typeof fn !== "function")
2461
- throw new Error(`Jx: "${exportName}" from "${src}" is not a function`);
2633
+ }
2634
+ if (typeof fn !== "function") {
2635
+ throw new TypeError(`Jx: "${exportName}" from "${src}" is not a function`);
2636
+ }
2462
2637
  const rawArgs = def2.arguments ?? {};
2463
2638
  const hasReactiveArg = Object.values(rawArgs).some((v) => isRefObj(v));
2464
2639
  const resolveArgs = () => {
@@ -2493,17 +2668,18 @@ async function resolveServerFunctionViaProxy(def2, state, key, base) {
2493
2668
  return args;
2494
2669
  };
2495
2670
  const doResolve = (args) => fetch("/__jx_server__", {
2496
- method: "POST",
2497
- headers: { "Content-Type": "application/json" },
2498
2671
  body: JSON.stringify({
2499
- $src: def2.$src,
2500
- $export: def2.$export,
2501
2672
  $base: base,
2673
+ $export: def2.$export,
2674
+ $src: def2.$src,
2502
2675
  arguments: args
2503
- })
2676
+ }),
2677
+ headers: { "Content-Type": "application/json" },
2678
+ method: "POST"
2504
2679
  }).then((r) => {
2505
- if (!r.ok)
2680
+ if (!r.ok) {
2506
2681
  throw new Error(`Jx server proxy ${r.status} for "${key}"`);
2682
+ }
2507
2683
  return r.json();
2508
2684
  });
2509
2685
  const s = ref(null);
@@ -2513,50 +2689,60 @@ async function resolveServerFunctionViaProxy(def2, state, key, base) {
2513
2689
  onEffectCleanup(() => {});
2514
2690
  doResolve(args).then((result) => {
2515
2691
  s.value = result;
2516
- }).catch((e) => console.error("Jx server proxy:", e));
2692
+ }).catch((error) => console.error("Jx server proxy:", error));
2517
2693
  });
2518
2694
  } else {
2519
2695
  doResolve(resolveArgs()).then((result) => {
2520
2696
  s.value = result;
2521
- }).catch((e) => console.error("Jx server proxy:", e));
2697
+ }).catch((error) => console.error("Jx server proxy:", error));
2522
2698
  }
2523
2699
  return s;
2524
2700
  }
2525
- function resolveRef(ref2, state) {
2526
- if (typeof ref2 !== "string")
2527
- return ref2;
2528
- if (ref2.startsWith("$map/")) {
2529
- const parts = ref2.split("/");
2530
- const key = parts[1];
2531
- const base = state.$map?.[key] ?? state["$map/" + key];
2701
+ function resolveRef(refPath, state) {
2702
+ if (typeof refPath !== "string") {
2703
+ return refPath;
2704
+ }
2705
+ if (refPath.startsWith("$map/")) {
2706
+ const parts = refPath.split("/");
2707
+ const [, key] = parts;
2708
+ const map = state.$map;
2709
+ const base = map?.[key] ?? state[`$map/${key}`];
2532
2710
  return parts.length > 2 ? getPath2(base, parts.slice(2).join("/")) : base;
2533
2711
  }
2534
- if (ref2.startsWith("#/state/")) {
2535
- const sub = ref2.slice("#/state/".length);
2712
+ if (refPath.startsWith("#/state/")) {
2713
+ const sub = refPath.slice("#/state/".length);
2536
2714
  const slash = sub.indexOf("/");
2537
- if (slash < 0)
2715
+ if (slash === -1) {
2538
2716
  return state[sub];
2717
+ }
2539
2718
  return getPath2(state[sub.slice(0, slash)], sub.slice(slash + 1));
2540
2719
  }
2541
- if (ref2.startsWith("parent#/"))
2542
- return state[ref2.slice("parent#/".length)];
2543
- if (ref2.startsWith("window#/"))
2544
- return getPath2(globalThis.window, ref2.slice("window#/".length));
2545
- if (ref2.startsWith("document#/"))
2546
- return getPath2(globalThis.document, ref2.slice("document#/".length));
2547
- return state[ref2] ?? null;
2720
+ if (refPath.startsWith("parent#/")) {
2721
+ return state[refPath.slice("parent#/".length)];
2722
+ }
2723
+ if (refPath.startsWith("window#/")) {
2724
+ return getPath2(globalThis.window, refPath.slice("window#/".length));
2725
+ }
2726
+ if (refPath.startsWith("document#/")) {
2727
+ return getPath2(globalThis.document, refPath.slice("document#/".length));
2728
+ }
2729
+ return state[refPath] ?? null;
2548
2730
  }
2549
2731
  function isSignal(v) {
2550
2732
  return isRef(v);
2551
2733
  }
2552
2734
  function isRefObj(v) {
2553
- return v !== null && typeof v === "object" && typeof v.$ref === "string";
2735
+ return isRef2(v);
2554
2736
  }
2555
2737
  function isNestedSelector(k) {
2556
2738
  return k.startsWith(":") || k.startsWith(".") || k.startsWith("&") || k.startsWith("[");
2557
2739
  }
2558
2740
  function getPath2(obj, path) {
2559
- return path.split(/[./]/).reduce((o, k) => o?.[k], obj);
2741
+ let current = obj;
2742
+ for (const k of path.split(/[./]/)) {
2743
+ current = current?.[k];
2744
+ }
2745
+ return current;
2560
2746
  }
2561
2747
  function mergeProps(def2, parentState) {
2562
2748
  const child = Object.create(parentState);
@@ -2566,7 +2752,7 @@ function mergeProps(def2, parentState) {
2566
2752
  return child;
2567
2753
  }
2568
2754
  function camelToKebab(s) {
2569
- return s.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
2755
+ return s.replaceAll(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
2570
2756
  }
2571
2757
  function toCSSText(rules) {
2572
2758
  return Object.entries(rules).filter(([k, v]) => !isNestedSelector(k) && (v === null || typeof v !== "object")).map(([p, v]) => `${camelToKebab(p)}: ${v}`).join("; ");
@@ -2579,19 +2765,22 @@ async function registerElements(elements, base) {
2579
2765
  try {
2580
2766
  const specifier = entry.startsWith("/") || entry.startsWith(".") ? entry : `/node_modules/${entry}`;
2581
2767
  await import(specifier);
2582
- } catch (e) {
2583
- console.warn(`Jx: failed to import package "${entry}"`, e);
2768
+ } catch (error) {
2769
+ console.warn(`Jx: failed to import package "${entry}"`, error);
2584
2770
  }
2585
2771
  continue;
2586
2772
  }
2587
- if (!isRefObj(entry))
2773
+ if (!isRefObj(entry)) {
2588
2774
  continue;
2589
- const href = new URL(entry.$ref, base).href;
2775
+ }
2776
+ const { href } = new URL(entry.$ref, base);
2590
2777
  const doc = await resolve(href);
2591
- if (!doc.tagName || !doc.tagName.includes("-"))
2778
+ if (!doc.tagName || !doc.tagName.includes("-")) {
2592
2779
  continue;
2593
- if (customElements.get(doc.tagName))
2780
+ }
2781
+ if (customElements.get(doc.tagName)) {
2594
2782
  continue;
2783
+ }
2595
2784
  if (doc.$elements) {
2596
2785
  await registerElements(doc.$elements, href);
2597
2786
  }
@@ -2600,48 +2789,56 @@ async function registerElements(elements, base) {
2600
2789
  }
2601
2790
  function injectHead(entries, _base) {
2602
2791
  for (const entry of entries) {
2603
- if (!entry || !entry.tagName)
2792
+ if (!entry || !entry.tagName) {
2604
2793
  continue;
2794
+ }
2605
2795
  const tag = entry.tagName.toLowerCase();
2606
2796
  const attrs = { ...entry.attributes };
2607
2797
  for (const key of ["href", "src"]) {
2608
- if (attrs[key] && !attrs[key].startsWith("/") && !attrs[key].startsWith(".") && !attrs[key].startsWith("http")) {
2609
- attrs[key] = `/node_modules/${attrs[key]}`;
2798
+ const v = attrs[key];
2799
+ if (typeof v === "string" && v && !v.startsWith("/") && !v.startsWith(".") && !v.startsWith("http")) {
2800
+ attrs[key] = `/node_modules/${v}`;
2610
2801
  }
2611
2802
  }
2612
2803
  const selector = `${tag}${attrs.href ? `[href="${attrs.href}"]` : ""}${attrs.src ? `[src="${attrs.src}"]` : ""}`;
2613
- if (selector !== tag && document.head.querySelector(selector))
2804
+ if (selector !== tag && document.head.querySelector(selector)) {
2614
2805
  continue;
2806
+ }
2615
2807
  const el = document.createElement(tag);
2616
2808
  for (const [k, v] of Object.entries(attrs)) {
2617
- el.setAttribute(k, v);
2809
+ el.setAttribute(k, String(v));
2618
2810
  }
2619
- if (entry.textContent)
2811
+ if (entry.textContent) {
2620
2812
  el.textContent = entry.textContent;
2621
- document.head.appendChild(el);
2813
+ }
2814
+ document.head.append(el);
2622
2815
  }
2623
2816
  }
2624
2817
  var _definedSources = new Set;
2625
- async function defineElement(source, base) {
2818
+ async function defineElement(source, baseUrl) {
2819
+ let base = baseUrl;
2820
+ let doc = source;
2626
2821
  if (typeof source === "string") {
2627
2822
  base = new URL(source, base ?? location.href).href;
2628
- if (_definedSources.has(base))
2823
+ if (_definedSources.has(base)) {
2629
2824
  return;
2825
+ }
2630
2826
  _definedSources.add(base);
2631
- source = await resolve(source);
2827
+ doc = await resolve(source);
2632
2828
  }
2633
- base = base ?? location.href;
2634
- const source_ = source;
2635
- const tagName = source_.tagName;
2829
+ base ??= location.href;
2830
+ const source_ = doc;
2831
+ const { tagName } = source_;
2636
2832
  if (!tagName || !tagName.includes("-")) {
2637
2833
  throw new Error(`Jx defineElement: tagName "${tagName}" must contain a hyphen`);
2638
2834
  }
2639
- if (customElements.get(tagName))
2835
+ if (customElements.get(tagName)) {
2640
2836
  return;
2837
+ }
2641
2838
  if (source_.$elements) {
2642
2839
  await registerElements(source_.$elements, base);
2643
2840
  }
2644
- _elementDefs.set(tagName, { doc: source_, base });
2841
+ _elementDefs.set(tagName, { base, doc: source_ });
2645
2842
  const def2 = source_;
2646
2843
  const observedAttrs = def2.observedAttributes ?? [];
2647
2844
  const ElementClass = class extends HTMLElement {
@@ -2651,20 +2848,22 @@ async function defineElement(source, base) {
2651
2848
  return observedAttrs;
2652
2849
  }
2653
2850
  async connectedCallback() {
2654
- if (this._jxInitialized)
2851
+ if (this._jxInitialized) {
2655
2852
  return;
2853
+ }
2656
2854
  this._jxInitialized = true;
2657
2855
  const state = await buildScope(def2, {}, base);
2658
- const propsAttr = this.getAttribute("data-jx-props");
2856
+ const propsAttr = this.dataset.jxProps;
2659
2857
  if (propsAttr) {
2660
2858
  try {
2661
2859
  const props = JSON.parse(propsAttr);
2662
2860
  for (const [key, val] of Object.entries(props)) {
2663
- if (key in (def2.state ?? {}))
2861
+ if (key in (def2.state ?? {})) {
2664
2862
  state[key] = val;
2863
+ }
2665
2864
  }
2666
2865
  } catch {}
2667
- this.removeAttribute("data-jx-props");
2866
+ delete this.dataset.jxProps;
2668
2867
  }
2669
2868
  for (const key of Object.keys(def2.state ?? {})) {
2670
2869
  if (key in this && this[key] !== undefined) {
@@ -2674,28 +2873,30 @@ async function defineElement(source, base) {
2674
2873
  for (const key of Object.keys(def2.state ?? {})) {
2675
2874
  if (!(key in HTMLElement.prototype)) {
2676
2875
  Object.defineProperty(this, key, {
2876
+ configurable: true,
2677
2877
  get: () => state[key],
2678
2878
  set: (v) => {
2679
2879
  state[key] = v;
2680
- },
2681
- configurable: true
2880
+ }
2682
2881
  });
2683
2882
  }
2684
2883
  }
2685
2884
  this._state = state;
2686
- const slottedChildren = Array.from(this.childNodes);
2885
+ const slottedChildren = [...this.childNodes];
2687
2886
  this.innerHTML = "";
2688
- if (!this.style.display)
2887
+ if (!this.style.display) {
2689
2888
  this.style.display = "block";
2889
+ }
2690
2890
  applyStyle(this, def2.style ?? {}, state["$media"] ?? {}, state);
2691
2891
  applyAttributes(this, def2.attributes ?? {}, state);
2692
2892
  const children = Array.isArray(def2.children) ? def2.children : [];
2693
2893
  for (const childDef of children) {
2694
- this.appendChild(renderNode(childDef, state));
2894
+ this.append(renderNode(childDef, state));
2695
2895
  }
2696
2896
  distributeSlots(this, slottedChildren);
2697
- if (typeof state.onMount === "function") {
2698
- queueMicrotask(() => state.onMount(state));
2897
+ const { onMount } = state;
2898
+ if (typeof onMount === "function") {
2899
+ queueMicrotask(() => onMount(state));
2699
2900
  }
2700
2901
  }
2701
2902
  disconnectedCallback() {
@@ -2709,24 +2910,27 @@ async function defineElement(source, base) {
2709
2910
  }
2710
2911
  }
2711
2912
  attributeChangedCallback(name, oldVal, newVal) {
2712
- if (!this._state || oldVal === newVal)
2913
+ if (!this._state || oldVal === newVal) {
2713
2914
  return;
2714
- const camelKey = name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
2915
+ }
2916
+ const camelKey = name.replaceAll(/-([a-z])/g, (_, c) => c.toUpperCase());
2715
2917
  const current = this._state[camelKey];
2716
- if (typeof current === "number")
2918
+ if (typeof current === "number") {
2717
2919
  this._state[camelKey] = Number(newVal);
2718
- else if (typeof current === "boolean")
2920
+ } else if (typeof current === "boolean") {
2719
2921
  this._state[camelKey] = newVal !== null && newVal !== "false";
2720
- else
2922
+ } else {
2721
2923
  this._state[camelKey] = newVal;
2924
+ }
2722
2925
  }
2723
2926
  };
2724
2927
  customElements.define(tagName, ElementClass);
2725
2928
  }
2726
2929
  function renderCustomElementWithProps(def2, state, options, path) {
2727
- const el = document.createElement(def2.tagName);
2728
- if (options?.onNodeCreated)
2930
+ const el = document.createElement(def2.tagName ?? "div");
2931
+ if (options?.onNodeCreated) {
2729
2932
  options.onNodeCreated(el, path ?? [], def2);
2933
+ }
2730
2934
  for (const [key, val] of Object.entries(def2.$props ?? {})) {
2731
2935
  if (isRefObj(val)) {
2732
2936
  const refVal = val;
@@ -2748,23 +2952,26 @@ function renderCustomElementWithProps(def2, state, options, path) {
2748
2952
  const children = Array.isArray(def2.children) ? def2.children : [];
2749
2953
  for (let i = 0;i < children.length; i++) {
2750
2954
  const childOpts = options && path ? { ...options, _path: [...path, "children", i] } : undefined;
2751
- el.appendChild(renderNode(children[i], state, childOpts));
2955
+ el.append(renderNode(children[i], state, childOpts));
2752
2956
  }
2753
2957
  return el;
2754
2958
  }
2755
2959
  function distributeSlots(host, slottedChildren) {
2756
- if (slottedChildren.length === 0)
2960
+ if (slottedChildren.length === 0) {
2757
2961
  return;
2962
+ }
2758
2963
  const slots = host.querySelectorAll("slot");
2759
- if (slots.length === 0)
2964
+ if (slots.length === 0) {
2760
2965
  return;
2966
+ }
2761
2967
  const named = new Map;
2762
2968
  const unnamed = [];
2763
2969
  for (const child of slottedChildren) {
2764
2970
  if (child.nodeType === Node.ELEMENT_NODE && child.getAttribute("slot")) {
2765
2971
  const name = child.getAttribute("slot");
2766
- if (!named.has(name))
2972
+ if (!named.has(name)) {
2767
2973
  named.set(name, []);
2974
+ }
2768
2975
  named.get(name).push(child);
2769
2976
  } else {
2770
2977
  unnamed.push(child);
@@ -2776,7 +2983,7 @@ function distributeSlots(host, slottedChildren) {
2776
2983
  if (matches.length > 0) {
2777
2984
  slot.innerHTML = "";
2778
2985
  for (const child of matches) {
2779
- slot.appendChild(child);
2986
+ slot.append(child);
2780
2987
  }
2781
2988
  }
2782
2989
  }
@@ -2799,5 +3006,5 @@ export {
2799
3006
  Jx
2800
3007
  };
2801
3008
 
2802
- //# debugId=D6000E7448ED71C464756E2164756E21
3009
+ //# debugId=32F6E02650EECC3864756E2164756E21
2803
3010
  //# sourceMappingURL=runtime.js.map