@zeus-js/runtime-dom 0.1.1-beta.0 → 0.1.1-beta.10

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.
@@ -1,18 +1,29 @@
1
1
  /**
2
- * runtime-dom v0.1.1-beta.0
2
+ * runtime-dom v0.1.1-beta.10
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
6
6
  var ZeusRuntimeDOM = (function(exports) {
7
7
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
8
8
  //#region packages/core/runtime-dom/src/template.ts
9
- function template(html, _isImportNode = false, _isSVG = false, _isMathML = false) {
10
- const t = document.createElement("template");
11
- t.innerHTML = html;
9
+ function template(html, _isImportNode = false, isSVG = false, _isMathML = false) {
10
+ const content = isSVG ? createSvgContent(html) : createHtmlContent(html);
12
11
  return function clone() {
13
- return t.content.cloneNode(true);
12
+ return content.cloneNode(true);
14
13
  };
15
14
  }
15
+ function createHtmlContent(html) {
16
+ const template = document.createElement("template");
17
+ template.innerHTML = html;
18
+ return template.content;
19
+ }
20
+ function createSvgContent(html) {
21
+ const wrapper = document.createElementNS("http://www.w3.org/2000/svg", "svg");
22
+ wrapper.innerHTML = html;
23
+ const content = document.createDocumentFragment();
24
+ while (wrapper.firstChild) content.appendChild(wrapper.firstChild);
25
+ return content;
26
+ }
16
27
  //#endregion
17
28
  //#region packages/core/shared/src/makeMap.ts
18
29
  /**
@@ -269,7 +280,8 @@ var ZeusRuntimeDOM = (function(exports) {
269
280
  trigger() {
270
281
  if (this.flags & 64) pausedQueueEffects.add(this);
271
282
  else if (this.scheduler) this.scheduler();
272
- else this.runIfDirty();
283
+ else if (this.flags & 128) this.runIfDirty();
284
+ else this.run();
273
285
  }
274
286
  /**
275
287
  * @internal
@@ -495,6 +507,31 @@ var ZeusRuntimeDOM = (function(exports) {
495
507
  }
496
508
  }
497
509
  }
510
+ /**
511
+ * Batches reactive updates synchronously within the given function.
512
+ * All updates triggered inside `fn` are deferred until the function completes,
513
+ * then flushed together in a single batch.
514
+ */
515
+ function batch(fn) {
516
+ startBatch();
517
+ try {
518
+ return fn();
519
+ } finally {
520
+ endBatch();
521
+ }
522
+ }
523
+ /**
524
+ * Executes the given function without tracking reactive dependencies.
525
+ * Any reactive reads inside `fn` will not trigger effect re-runs.
526
+ */
527
+ function untrack(fn) {
528
+ pauseTracking();
529
+ try {
530
+ return fn();
531
+ } finally {
532
+ resetTracking();
533
+ }
534
+ }
498
535
  //#endregion
499
536
  //#region packages/core/signal/src/dep.ts
500
537
  /**
@@ -539,6 +576,7 @@ var ZeusRuntimeDOM = (function(exports) {
539
576
  }
540
577
  track(debugInfo) {
541
578
  if (!activeSub || !shouldTrack || activeSub === this.computed) return;
579
+ if (this.computed) activeSub.flags |= 128;
542
580
  let link = this.activeLink;
543
581
  if (link === void 0 || link.sub !== activeSub) {
544
582
  link = this.activeLink = new Link(activeSub, this);
@@ -872,60 +910,6 @@ var ZeusRuntimeDOM = (function(exports) {
872
910
  return res;
873
911
  }
874
912
  //#endregion
875
- //#region packages/core/signal/src/ref.ts
876
- let _ReactiveFlags$IS_REF, _ReactiveFlags$IS_SHA;
877
- /*@__NO_SIDE_EFFECTS__*/
878
- function isRef(r) {
879
- return r ? r["__v_isRef"] === true : false;
880
- }
881
- /*@__NO_SIDE_EFFECTS__*/
882
- function ref(value) {
883
- return createRef(value, false);
884
- }
885
- function createRef(rawValue, shallow) {
886
- if (/* @__PURE__ */ isRef(rawValue)) return rawValue;
887
- return new RefImpl(rawValue, shallow);
888
- }
889
- _ReactiveFlags$IS_REF = "__v_isRef";
890
- _ReactiveFlags$IS_SHA = "__v_isShallow";
891
- /**
892
- * @internal
893
- */
894
- var RefImpl = class {
895
- constructor(value, isShallow) {
896
- this.dep = new Dep();
897
- this[_ReactiveFlags$IS_REF] = true;
898
- this[_ReactiveFlags$IS_SHA] = false;
899
- this._rawValue = isShallow ? value : /* @__PURE__ */ toRaw(value);
900
- this._value = isShallow ? value : toReactive(value);
901
- this["__v_isShallow"] = isShallow;
902
- }
903
- get value() {
904
- this.dep.track({
905
- target: this,
906
- type: "get",
907
- key: "value"
908
- });
909
- return this._value;
910
- }
911
- set value(newValue) {
912
- const oldValue = this._rawValue;
913
- const useDirectValue = this["__v_isShallow"] || /* @__PURE__ */ isShallow(newValue) || /* @__PURE__ */ isReadonly(newValue);
914
- newValue = useDirectValue ? newValue : /* @__PURE__ */ toRaw(newValue);
915
- if (hasChanged(newValue, oldValue)) {
916
- this._rawValue = newValue;
917
- this._value = useDirectValue ? newValue : toReactive(newValue);
918
- this.dep.trigger({
919
- target: this,
920
- type: "set",
921
- key: "value",
922
- newValue,
923
- oldValue
924
- });
925
- }
926
- }
927
- };
928
- //#endregion
929
913
  //#region packages/core/signal/src/baseHandlers.ts
930
914
  const isNonTrackableKeys = /*@__PURE__*/ makeMap(`__proto__,__v_isRef,__isVue`);
931
915
  const builtInSymbols = new Set(/*@__PURE__*/ Object.getOwnPropertyNames(Symbol).filter((key) => key !== "arguments" && key !== "caller").map((key) => Symbol[key]).filter(isSymbol));
@@ -1358,11 +1342,84 @@ var ZeusRuntimeDOM = (function(exports) {
1358
1342
  */
1359
1343
  const toReadonly = (value) => isObject(value) ? /* @__PURE__ */ readonly(value) : value;
1360
1344
  //#endregion
1345
+ //#region packages/core/signal/src/ref.ts
1346
+ let _ReactiveFlags$IS_REF, _ReactiveFlags$IS_SHA;
1347
+ /*@__NO_SIDE_EFFECTS__*/
1348
+ function isRef(r) {
1349
+ return r ? r["__v_isRef"] === true : false;
1350
+ }
1351
+ /*@__NO_SIDE_EFFECTS__*/
1352
+ function ref(value) {
1353
+ return createRef(value, false);
1354
+ }
1355
+ /*@__NO_SIDE_EFFECTS__*/
1356
+ function shallowRef(value) {
1357
+ return createRef(value, true);
1358
+ }
1359
+ function createRef(rawValue, shallow) {
1360
+ if (/* @__PURE__ */ isRef(rawValue)) return rawValue;
1361
+ return new RefImpl(rawValue, shallow);
1362
+ }
1363
+ _ReactiveFlags$IS_REF = "__v_isRef";
1364
+ _ReactiveFlags$IS_SHA = "__v_isShallow";
1365
+ /**
1366
+ * @internal
1367
+ */
1368
+ var RefImpl = class {
1369
+ constructor(value, isShallow) {
1370
+ this.dep = new Dep();
1371
+ this[_ReactiveFlags$IS_REF] = true;
1372
+ this[_ReactiveFlags$IS_SHA] = false;
1373
+ this._rawValue = isShallow ? value : /* @__PURE__ */ toRaw(value);
1374
+ this._value = isShallow ? value : toReactive(value);
1375
+ this["__v_isShallow"] = isShallow;
1376
+ }
1377
+ get value() {
1378
+ this.dep.track({
1379
+ target: this,
1380
+ type: "get",
1381
+ key: "value"
1382
+ });
1383
+ return this._value;
1384
+ }
1385
+ set value(newValue) {
1386
+ const oldValue = this._rawValue;
1387
+ const useDirectValue = this["__v_isShallow"] || /* @__PURE__ */ isShallow(newValue) || /* @__PURE__ */ isReadonly(newValue);
1388
+ newValue = useDirectValue ? newValue : /* @__PURE__ */ toRaw(newValue);
1389
+ if (hasChanged(newValue, oldValue)) {
1390
+ this._rawValue = newValue;
1391
+ this._value = useDirectValue ? newValue : toReactive(newValue);
1392
+ this.dep.trigger({
1393
+ target: this,
1394
+ type: "set",
1395
+ key: "value",
1396
+ newValue,
1397
+ oldValue
1398
+ });
1399
+ }
1400
+ }
1401
+ };
1402
+ //#endregion
1403
+ //#region packages/core/signal/src/primitives.ts
1404
+ function createSignal(initialValue) {
1405
+ const source = /* @__PURE__ */ shallowRef(initialValue);
1406
+ const read = () => source.value;
1407
+ const write = (value) => {
1408
+ const next = typeof value === "function" ? value(source.value) : value;
1409
+ source.value = next;
1410
+ return next;
1411
+ };
1412
+ return [read, write];
1413
+ }
1414
+ //#endregion
1361
1415
  //#region packages/core/signal/src/state.ts
1362
1416
  function state(value) {
1363
1417
  if (arguments.length === 0) return /* @__PURE__ */ ref();
1364
1418
  return isProxyable(value) ? /* @__PURE__ */ reactive(value) : /* @__PURE__ */ ref(value);
1365
1419
  }
1420
+ function shallowState(value) {
1421
+ return arguments.length === 0 ? /* @__PURE__ */ shallowRef() : /* @__PURE__ */ shallowRef(value);
1422
+ }
1366
1423
  function isProxyable(value) {
1367
1424
  if (value === null || typeof value !== "object") return false;
1368
1425
  if (Array.isArray(value)) return true;
@@ -1374,6 +1431,32 @@ var ZeusRuntimeDOM = (function(exports) {
1374
1431
  return proto === Object.prototype || proto === null;
1375
1432
  }
1376
1433
  //#endregion
1434
+ //#region packages/core/runtime-dom/src/domMove.ts
1435
+ const activeMoveRoots = /* @__PURE__ */ new Set();
1436
+ function moveNodeBefore(parent, node, marker) {
1437
+ activeMoveRoots.add(node);
1438
+ try {
1439
+ const moveBefore = parent.moveBefore;
1440
+ if (typeof moveBefore === "function") moveBefore.call(parent, node, marker);
1441
+ else parent.insertBefore(node, marker);
1442
+ } finally {
1443
+ activeMoveRoots.delete(node);
1444
+ }
1445
+ }
1446
+ function isWithinRuntimeDomMove(node) {
1447
+ let current = node;
1448
+ while (current) {
1449
+ if (activeMoveRoots.has(current)) return true;
1450
+ if (current.parentNode) {
1451
+ current = current.parentNode;
1452
+ continue;
1453
+ }
1454
+ const root = current.getRootNode();
1455
+ current = "host" in root ? root.host : null;
1456
+ }
1457
+ return false;
1458
+ }
1459
+ //#endregion
1377
1460
  //#region packages/core/runtime-dom/src/domOwnership.ts
1378
1461
  const activeLightDomHosts = /* @__PURE__ */ new WeakMap();
1379
1462
  const runtimeOwnedNodes = /* @__PURE__ */ new WeakSet();
@@ -1408,6 +1491,14 @@ var ZeusRuntimeDOM = (function(exports) {
1408
1491
  for (const item of value) nodes.push(...insertTracked(parent, item, marker));
1409
1492
  return nodes;
1410
1493
  }
1494
+ if (value instanceof Node && value.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
1495
+ const nodes = Array.from(value.childNodes);
1496
+ for (const node of nodes) {
1497
+ trackRuntimeDomInsertion(parent, node);
1498
+ parent.insertBefore(node, marker);
1499
+ }
1500
+ return nodes;
1501
+ }
1411
1502
  const node = value instanceof Node ? value : document.createTextNode(String(value));
1412
1503
  trackRuntimeDomInsertion(parent, node);
1413
1504
  parent.insertBefore(node, marker);
@@ -1422,7 +1513,7 @@ var ZeusRuntimeDOM = (function(exports) {
1422
1513
  function moveRangeBefore(nodes, parent, marker = null) {
1423
1514
  for (const node of nodes) {
1424
1515
  trackRuntimeDomInsertion(parent, node);
1425
- parent.insertBefore(node, marker);
1516
+ moveNodeBefore(parent, node, marker);
1426
1517
  }
1427
1518
  }
1428
1519
  //#endregion
@@ -1467,10 +1558,11 @@ var ZeusRuntimeDOM = (function(exports) {
1467
1558
  replace(render) {
1468
1559
  this.dispose();
1469
1560
  const scope = effectScope(true);
1561
+ const parent = this.resolveParent(this.marker);
1470
1562
  let nodes = [];
1471
1563
  try {
1472
1564
  scope.run(() => {
1473
- nodes = runWithOwner(this.context.owner, () => withHostContext(this.context.host, () => insertTracked(this.parent, render(), this.marker)));
1565
+ nodes = runWithOwner(this.context.owner, () => withHostContext(this.context.host, () => insertTracked(parent, render(), this.marker)));
1474
1566
  });
1475
1567
  } catch (error) {
1476
1568
  scope.stop();
@@ -1488,11 +1580,15 @@ var ZeusRuntimeDOM = (function(exports) {
1488
1580
  this.nodes = [];
1489
1581
  }
1490
1582
  moveBefore(marker) {
1491
- moveRangeBefore(this.nodes, this.parent, marker);
1583
+ moveRangeBefore(this.nodes, this.resolveParent(marker), marker);
1492
1584
  }
1493
1585
  current() {
1494
1586
  return this.nodes;
1495
1587
  }
1588
+ resolveParent(marker) {
1589
+ var _ref, _marker$parentNode, _this$marker;
1590
+ return (_ref = (_marker$parentNode = marker === null || marker === void 0 ? void 0 : marker.parentNode) !== null && _marker$parentNode !== void 0 ? _marker$parentNode : (_this$marker = this.marker) === null || _this$marker === void 0 ? void 0 : _this$marker.parentNode) !== null && _ref !== void 0 ? _ref : this.parent;
1591
+ }
1496
1592
  };
1497
1593
  //#endregion
1498
1594
  //#region packages/core/runtime-dom/src/insert.ts
@@ -1702,14 +1798,23 @@ var ZeusRuntimeDOM = (function(exports) {
1702
1798
  }
1703
1799
  //#endregion
1704
1800
  //#region packages/core/runtime-dom/src/bindings.ts
1705
- function bindText(node, value) {
1706
- effect(() => {
1707
- node.data = stringifyText(value());
1801
+ function bindText(node, value, once = false) {
1802
+ applyBinding(value, once, (next) => {
1803
+ node.data = stringifyText(next);
1804
+ });
1805
+ }
1806
+ function bindTextContent(el, value, once = false) {
1807
+ applyBinding(value, once, (next) => {
1808
+ el.textContent = stringifyText(next);
1708
1809
  });
1709
1810
  }
1710
- function bindTextContent(el, value) {
1811
+ function applyBinding(value, once, apply) {
1812
+ if (once) {
1813
+ untrack(() => apply(value()));
1814
+ return;
1815
+ }
1711
1816
  effect(() => {
1712
- el.textContent = stringifyText(value());
1817
+ apply(value());
1713
1818
  });
1714
1819
  }
1715
1820
  function stringifyText(value) {
@@ -1762,19 +1867,19 @@ var ZeusRuntimeDOM = (function(exports) {
1762
1867
  function normalizeAttrName(name) {
1763
1868
  return name === "className" ? "class" : name;
1764
1869
  }
1765
- function bindAttr(el, name, value) {
1766
- effect(() => {
1767
- setAttr(el, name, value());
1870
+ function bindAttr(el, name, value, once = false) {
1871
+ applyBinding(value, once, (next) => {
1872
+ setAttr(el, name, next);
1768
1873
  });
1769
1874
  }
1770
- function bindProp(el, name, value) {
1771
- effect(() => {
1772
- el[name] = value();
1875
+ function bindProp(el, name, value, once = false) {
1876
+ applyBinding(value, once, (next) => {
1877
+ el[name] = next;
1773
1878
  });
1774
1879
  }
1775
- function bindClass(el, value) {
1776
- effect(() => {
1777
- const next = normalizeClass(value());
1880
+ function bindClass(el, value, once = false) {
1881
+ applyBinding(value, once, (value) => {
1882
+ const next = normalizeClass(value);
1778
1883
  if (next) el.setAttribute("class", next);
1779
1884
  else el.removeAttribute("class");
1780
1885
  });
@@ -1786,10 +1891,9 @@ var ZeusRuntimeDOM = (function(exports) {
1786
1891
  if (typeof value === "object") return Object.keys(value).filter((key) => value[key]).join(" ");
1787
1892
  return "";
1788
1893
  }
1789
- function bindStyle(el, value) {
1894
+ function bindStyle(el, value, once = false) {
1790
1895
  let prev;
1791
- effect(() => {
1792
- const next = value();
1896
+ applyBinding(value, once, (next) => {
1793
1897
  if (next == null) {
1794
1898
  el.removeAttribute("style");
1795
1899
  prev = void 0;
@@ -1800,42 +1904,41 @@ var ZeusRuntimeDOM = (function(exports) {
1800
1904
  prev = void 0;
1801
1905
  return;
1802
1906
  }
1803
- patchStyle(el, prev, next);
1804
- prev = next;
1907
+ prev = patchStyle(el, prev, next);
1805
1908
  });
1806
1909
  }
1807
1910
  function patchStyle(el, prev, next) {
1808
1911
  const style = el.style;
1809
- if (prev) {
1810
- for (const key in prev) if (!(key in next)) style.setProperty(toKebabCase$2(key), "");
1912
+ const values = prev ? prev[0] : Object.create(null);
1913
+ const state = style.cssText + Object.keys(next);
1914
+ const styleChanged = prev && state != prev[1];
1915
+ for (const key in values) if (!(key in next)) {
1916
+ style.setProperty(key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`), "");
1917
+ delete values[key];
1811
1918
  }
1812
1919
  for (const key in next) {
1813
1920
  const value = next[key];
1814
- const name = toKebabCase$2(key);
1815
- if (value == null) style.setProperty(name, "");
1816
- else style.setProperty(name, normalizeStyleValue(key, value));
1921
+ const expected = value == null ? "" : normalizeStyleValue(key, value);
1922
+ if (values[key] === expected && !styleChanged) continue;
1923
+ style.setProperty(key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`), expected);
1924
+ values[key] = expected;
1817
1925
  }
1926
+ return [values, style.cssText + Object.keys(next)];
1818
1927
  }
1819
1928
  function normalizeStyleValue(key, value) {
1820
- if (typeof value === "number" && value !== 0 && !isUnitlessNumber(key)) return `${value}px`;
1929
+ if (typeof value === "number" && value !== 0 && unitlessNumbers[key] !== true) return `${value}px`;
1821
1930
  return String(value);
1822
1931
  }
1823
- const unitlessNumbers = /* @__PURE__ */ new Set([
1824
- "opacity",
1825
- "zIndex",
1826
- "fontWeight",
1827
- "lineHeight",
1828
- "flex",
1829
- "flexGrow",
1830
- "flexShrink",
1831
- "order"
1832
- ]);
1833
- function isUnitlessNumber(key) {
1834
- return unitlessNumbers.has(key);
1835
- }
1836
- function toKebabCase$2(value) {
1837
- return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
1838
- }
1932
+ const unitlessNumbers = {
1933
+ opacity: true,
1934
+ zIndex: true,
1935
+ fontWeight: true,
1936
+ lineHeight: true,
1937
+ flex: true,
1938
+ flexGrow: true,
1939
+ flexShrink: true,
1940
+ order: true
1941
+ };
1839
1942
  //#endregion
1840
1943
  //#region packages/core/runtime-dom/src/events.ts
1841
1944
  const delegatedEvents = /* @__PURE__ */ new Set();
@@ -1945,6 +2048,30 @@ var ZeusRuntimeDOM = (function(exports) {
1945
2048
  function disposeListRecord(record) {
1946
2049
  record.subtree.dispose();
1947
2050
  }
2051
+ function isImmediatelyBefore(record, anchor) {
2052
+ const nodes = record.subtree.current();
2053
+ const last = nodes[nodes.length - 1];
2054
+ return last === void 0 || last.nextSibling === anchor;
2055
+ }
2056
+ function containsNode(record, node) {
2057
+ let current = node;
2058
+ while (current) {
2059
+ if (record.subtree.current().some((root) => root === current || root.contains(current))) return true;
2060
+ const treeRoot = current.getRootNode();
2061
+ current = "host" in treeRoot ? treeRoot.host : null;
2062
+ }
2063
+ return false;
2064
+ }
2065
+ function getDeepestActiveElement(parent) {
2066
+ var _parent$ownerDocument, _parent$ownerDocument2, _active$shadowRoot;
2067
+ const treeRoot = parent.getRootNode();
2068
+ let active = "activeElement" in treeRoot ? treeRoot.activeElement : (_parent$ownerDocument = (_parent$ownerDocument2 = parent.ownerDocument) === null || _parent$ownerDocument2 === void 0 ? void 0 : _parent$ownerDocument2.activeElement) !== null && _parent$ownerDocument !== void 0 ? _parent$ownerDocument : null;
2069
+ while (active === null || active === void 0 || (_active$shadowRoot = active.shadowRoot) === null || _active$shadowRoot === void 0 ? void 0 : _active$shadowRoot.activeElement) active = active.shadowRoot.activeElement;
2070
+ return active;
2071
+ }
2072
+ function duplicateKeyError(key, index) {
2073
+ return /* @__PURE__ */ new Error(`[Zeus runtime] <For> received duplicate key ${String(key)} at index ${index}.`);
2074
+ }
1948
2075
  function mountFor$1(parent, marker, each, key, render) {
1949
2076
  if (!key) {
1950
2077
  mountIndexFor(parent, marker, each, render);
@@ -1954,63 +2081,248 @@ var ZeusRuntimeDOM = (function(exports) {
1954
2081
  }
1955
2082
  function mountIndexFor(parent, marker, each, render) {
1956
2083
  const subtree = new ScopedSubtree(parent, marker, captureScopedSubtreeContext());
1957
- const runner = effect(() => {
1958
- var _each;
1959
- const list = (_each = each()) !== null && _each !== void 0 ? _each : [];
1960
- subtree.replace(() => list.map((item, index) => render(item, index)));
1961
- });
1962
- onScopeDispose(() => {
2084
+ let latestItems = [];
2085
+ let reconcileRequested = false;
2086
+ let reconciling = false;
2087
+ let disposed = false;
2088
+ let runner;
2089
+ const dispose = () => {
2090
+ if (disposed) return;
2091
+ disposed = true;
2092
+ if (runner) stop(runner);
2093
+ subtree.dispose();
2094
+ };
2095
+ onScopeDispose(dispose, true);
2096
+ const drainReconciliations = () => {
2097
+ if (disposed || reconciling) return;
2098
+ reconciling = true;
2099
+ try {
2100
+ while (reconcileRequested && !disposed) {
2101
+ reconcileRequested = false;
2102
+ untrack(() => {
2103
+ subtree.replace(() => latestItems.map((item, index) => render(() => item, () => index)));
2104
+ });
2105
+ }
2106
+ } finally {
2107
+ reconciling = false;
2108
+ if (disposed) subtree.dispose();
2109
+ }
2110
+ };
2111
+ const scheduleReconciliation = () => {
2112
+ if (disposed || !runner) return;
2113
+ runner();
2114
+ if (disposed) return;
2115
+ reconcileRequested = true;
2116
+ drainReconciliations();
2117
+ };
2118
+ try {
2119
+ runner = effect(() => {
2120
+ var _each;
2121
+ const nextItems = (_each = each()) !== null && _each !== void 0 ? _each : [];
2122
+ for (let i = 0; i < nextItems.length; i++) nextItems[i];
2123
+ latestItems = nextItems;
2124
+ }, { scheduler: scheduleReconciliation });
2125
+ } catch (error) {
2126
+ dispose();
2127
+ throw error;
2128
+ }
2129
+ if (disposed) {
1963
2130
  stop(runner);
1964
2131
  subtree.dispose();
1965
- }, true);
2132
+ return;
2133
+ }
2134
+ reconcileRequested = true;
2135
+ try {
2136
+ drainReconciliations();
2137
+ } catch (error) {
2138
+ dispose();
2139
+ throw error;
2140
+ }
1966
2141
  }
1967
2142
  function mountKeyedFor(parent, marker, each, key, render) {
1968
2143
  let records = [];
1969
2144
  const subtreeContext = captureScopedSubtreeContext();
1970
- const runner = effect(() => {
1971
- var _each2;
1972
- const nextItems = (_each2 = each()) !== null && _each2 !== void 0 ? _each2 : [];
2145
+ let latestItems = [];
2146
+ const latestKeys = [];
2147
+ let latestItemsUseFixedSlots = false;
2148
+ let reconcileRequested = false;
2149
+ let reconciling = false;
2150
+ let disposed = false;
2151
+ let runner;
2152
+ const dispose = () => {
2153
+ if (disposed) return;
2154
+ disposed = true;
2155
+ if (runner) stop(runner);
2156
+ const currentRecords = records;
2157
+ records = [];
2158
+ for (const record of currentRecords) disposeListRecord(record);
2159
+ };
2160
+ onScopeDispose(dispose, true);
2161
+ const reconcileEntries = (nextEntries) => {
2162
+ if (disposed) return;
1973
2163
  const oldMap = /* @__PURE__ */ new Map();
1974
2164
  for (const record of records) oldMap.set(record.key, record);
1975
2165
  const nextRecords = [];
1976
- for (let i = 0; i < nextItems.length; i++) {
1977
- const item = nextItems[i];
1978
- const itemKey = key(item, i);
1979
- const oldRecord = oldMap.get(itemKey);
1980
- if (oldRecord) {
1981
- oldMap.delete(itemKey);
1982
- oldRecord.item = item;
1983
- oldRecord.index = i;
1984
- nextRecords.push(oldRecord);
1985
- } else {
1986
- const subtree = new ScopedSubtree(parent, marker, subtreeContext);
1987
- subtree.replace(() => render(item, i));
1988
- nextRecords.push({
1989
- key: itemKey,
1990
- item,
1991
- index: i,
1992
- subtree
1993
- });
2166
+ const createdRecords = [];
2167
+ try {
2168
+ batch(() => {
2169
+ for (let i = 0; i < nextEntries.length; i++) {
2170
+ const { item, key: itemKey } = nextEntries[i];
2171
+ const oldRecord = oldMap.get(itemKey);
2172
+ if (oldRecord) {
2173
+ oldMap.delete(itemKey);
2174
+ if (!Object.is(oldRecord.item, item)) {
2175
+ oldRecord.item = item;
2176
+ oldRecord.setItem(() => item);
2177
+ }
2178
+ oldRecord.setIndex(i);
2179
+ nextRecords.push(oldRecord);
2180
+ } else {
2181
+ const [readItem, setItem] = createSignal(item);
2182
+ const [readIndex, setIndex] = createSignal(i);
2183
+ const subtree = new ScopedSubtree(parent, marker, subtreeContext);
2184
+ const record = {
2185
+ item,
2186
+ key: itemKey,
2187
+ setItem,
2188
+ setIndex,
2189
+ subtree
2190
+ };
2191
+ createdRecords.push(record);
2192
+ subtree.replace(() => render(readItem, readIndex));
2193
+ nextRecords.push(record);
2194
+ }
2195
+ if (disposed) break;
2196
+ }
2197
+ });
2198
+ } catch (error) {
2199
+ for (const record of createdRecords) disposeListRecord(record);
2200
+ throw error;
2201
+ }
2202
+ if (disposed) {
2203
+ for (const record of createdRecords) disposeListRecord(record);
2204
+ return;
2205
+ }
2206
+ const activeElement = getDeepestActiveElement(parent);
2207
+ const shouldRestoreFocus = Boolean(activeElement && nextRecords.some((record) => containsNode(record, activeElement)));
2208
+ let committed = false;
2209
+ try {
2210
+ for (const record of oldMap.values()) disposeListRecord(record);
2211
+ if (disposed) {
2212
+ for (const record of createdRecords) disposeListRecord(record);
2213
+ return;
2214
+ }
2215
+ records = nextRecords;
2216
+ committed = true;
2217
+ let moved = false;
2218
+ let anchor = marker;
2219
+ for (let i = nextRecords.length - 1; i >= 0; i--) {
2220
+ var _record$subtree$curre;
2221
+ const record = nextRecords[i];
2222
+ if (!isImmediatelyBefore(record, anchor)) {
2223
+ record.subtree.moveBefore(anchor);
2224
+ moved = true;
2225
+ }
2226
+ anchor = (_record$subtree$curre = record.subtree.current()[0]) !== null && _record$subtree$curre !== void 0 ? _record$subtree$curre : anchor;
1994
2227
  }
2228
+ if (disposed) return;
2229
+ if (moved && shouldRestoreFocus) {
2230
+ var _focus;
2231
+ (_focus = activeElement.focus) === null || _focus === void 0 || _focus.call(activeElement, { preventScroll: true });
2232
+ }
2233
+ if (!disposed) emitDevtoolsEvent({
2234
+ type: "mount-for",
2235
+ length: nextRecords.length
2236
+ });
2237
+ } catch (error) {
2238
+ if (!committed) for (const record of createdRecords) disposeListRecord(record);
2239
+ throw error;
2240
+ }
2241
+ };
2242
+ const reconcileLatestItems = () => {
2243
+ if (disposed) return;
2244
+ if (latestItemsUseFixedSlots) {
2245
+ const items = latestItems;
2246
+ batch(() => {
2247
+ for (let i = 0; i < items.length; i++) {
2248
+ const item = items[i];
2249
+ const record = records[i];
2250
+ if (!Object.is(record.item, item)) {
2251
+ record.item = item;
2252
+ record.setItem(() => item);
2253
+ }
2254
+ }
2255
+ });
2256
+ if (!disposed) emitDevtoolsEvent({
2257
+ type: "mount-for",
2258
+ length: records.length
2259
+ });
2260
+ return;
1995
2261
  }
1996
- for (const record of oldMap.values()) disposeListRecord(record);
1997
- for (let i = nextRecords.length - 1; i >= 0; i--) {
1998
- var _nextRecords$subtree$;
1999
- const record = nextRecords[i];
2000
- const anchor = i === nextRecords.length - 1 ? marker : (_nextRecords$subtree$ = nextRecords[i + 1].subtree.current()[0]) !== null && _nextRecords$subtree$ !== void 0 ? _nextRecords$subtree$ : marker;
2001
- record.subtree.moveBefore(anchor);
2262
+ const items = latestItems;
2263
+ const nextEntries = [];
2264
+ const nextKeys = /* @__PURE__ */ new Set();
2265
+ for (let i = 0; i < items.length; i++) {
2266
+ const item = items[i];
2267
+ const itemKey = latestKeys[i];
2268
+ if (nextKeys.has(itemKey)) throw duplicateKeyError(itemKey, i);
2269
+ nextKeys.add(itemKey);
2270
+ nextEntries.push({
2271
+ item,
2272
+ key: itemKey
2273
+ });
2002
2274
  }
2003
- emitDevtoolsEvent({
2004
- type: "mount-for",
2005
- length: nextRecords.length
2006
- });
2007
- records = nextRecords;
2008
- });
2009
- onScopeDispose(() => {
2275
+ reconcileEntries(nextEntries);
2276
+ };
2277
+ const drainReconciliations = () => {
2278
+ if (reconciling) return;
2279
+ reconciling = true;
2280
+ try {
2281
+ while (reconcileRequested) {
2282
+ reconcileRequested = false;
2283
+ untrack(reconcileLatestItems);
2284
+ }
2285
+ } finally {
2286
+ reconciling = false;
2287
+ }
2288
+ };
2289
+ const scheduleReconciliation = () => {
2290
+ if (disposed || !runner) return;
2291
+ runner();
2292
+ if (disposed) return;
2293
+ reconcileRequested = true;
2294
+ drainReconciliations();
2295
+ };
2296
+ try {
2297
+ runner = effect(() => {
2298
+ var _each2;
2299
+ const nextItems = (_each2 = each()) !== null && _each2 !== void 0 ? _each2 : [];
2300
+ let useFixedSlots = nextItems.length === records.length;
2301
+ for (let i = 0; i < nextItems.length; i++) {
2302
+ const item = nextItems[i];
2303
+ const itemKey = key(item, i);
2304
+ latestKeys[i] = itemKey;
2305
+ if (useFixedSlots && !Object.is(itemKey, records[i].key)) useFixedSlots = false;
2306
+ }
2307
+ latestKeys.length = nextItems.length;
2308
+ latestItems = nextItems;
2309
+ latestItemsUseFixedSlots = useFixedSlots;
2310
+ }, { scheduler: scheduleReconciliation });
2311
+ } catch (error) {
2312
+ dispose();
2313
+ throw error;
2314
+ }
2315
+ if (disposed) {
2010
2316
  stop(runner);
2011
- for (const record of records) disposeListRecord(record);
2012
- records = [];
2013
- }, true);
2317
+ return;
2318
+ }
2319
+ reconcileRequested = true;
2320
+ try {
2321
+ drainReconciliations();
2322
+ } catch (error) {
2323
+ dispose();
2324
+ throw error;
2325
+ }
2014
2326
  }
2015
2327
  //#endregion
2016
2328
  //#region packages/core/runtime-dom/src/controlFlow.ts
@@ -2235,7 +2547,14 @@ var ZeusRuntimeDOM = (function(exports) {
2235
2547
  function replaceOutletNodes(outlet, nextNodes) {
2236
2548
  const parent = outlet.end.parentNode;
2237
2549
  if (!parent || parent !== outlet.start.parentNode) return;
2550
+ const currentNodes = [];
2238
2551
  let current = outlet.start.nextSibling;
2552
+ while (current && current !== outlet.end) {
2553
+ currentNodes.push(current);
2554
+ current = current.nextSibling;
2555
+ }
2556
+ if (currentNodes.length === nextNodes.length && currentNodes.every((node, index) => node === nextNodes[index])) return;
2557
+ current = outlet.start.nextSibling;
2239
2558
  while (current && current !== outlet.end) {
2240
2559
  const next = current.nextSibling;
2241
2560
  parent.removeChild(current);
@@ -2289,6 +2608,7 @@ var ZeusRuntimeDOM = (function(exports) {
2289
2608
  values: input,
2290
2609
  attr: options.attr,
2291
2610
  reflect: options.reflect,
2611
+ reactivity: options.reactivity,
2292
2612
  default: options.default,
2293
2613
  serialize: options.serialize,
2294
2614
  deserialize: options.deserialize
@@ -2298,6 +2618,7 @@ var ZeusRuntimeDOM = (function(exports) {
2298
2618
  type,
2299
2619
  attr: options.attr,
2300
2620
  reflect: type === Boolean ? (_options$reflect = options.reflect) !== null && _options$reflect !== void 0 ? _options$reflect : true : options.reflect,
2621
+ reactivity: options.reactivity,
2301
2622
  default: type === Boolean ? (_options$default = options.default) !== null && _options$default !== void 0 ? _options$default : false : options.default,
2302
2623
  serialize: options.serialize,
2303
2624
  deserialize: options.deserialize
@@ -2320,7 +2641,7 @@ var ZeusRuntimeDOM = (function(exports) {
2320
2641
  const slots = /* @__PURE__ */ new Map();
2321
2642
  const props = {};
2322
2643
  for (const def of defs) {
2323
- const slot = state();
2644
+ const slot = def.reactivity === "shallow" ? shallowState() : state();
2324
2645
  slots.set(def.name, slot);
2325
2646
  Object.defineProperty(props, def.name, {
2326
2647
  configurable: false,
@@ -2389,6 +2710,7 @@ var ZeusRuntimeDOM = (function(exports) {
2389
2710
  this.mountLifecycle.connect();
2390
2711
  }
2391
2712
  disconnectedCallback() {
2713
+ if (isWithinRuntimeDomMove(this)) return;
2392
2714
  this.mountLifecycle.disconnect();
2393
2715
  }
2394
2716
  mountElement() {
@@ -2579,7 +2901,8 @@ var ZeusRuntimeDOM = (function(exports) {
2579
2901
  name: propKey,
2580
2902
  attrName: isAttributeBackedConstructor(type) ? toKebabCase(propKey) : false,
2581
2903
  type: normalizePropType(type),
2582
- reflect: false
2904
+ reflect: false,
2905
+ reactivity: "deep"
2583
2906
  };
2584
2907
  }
2585
2908
  const type = input === null || input === void 0 ? void 0 : input.type;
@@ -2589,6 +2912,7 @@ var ZeusRuntimeDOM = (function(exports) {
2589
2912
  attrName: (input === null || input === void 0 ? void 0 : input.attr) === void 0 ? defaultAttr : input.attr,
2590
2913
  type: normalizePropType(type),
2591
2914
  reflect: Boolean(input === null || input === void 0 ? void 0 : input.reflect),
2915
+ reactivity: (input === null || input === void 0 ? void 0 : input.reactivity) === "shallow" ? "shallow" : "deep",
2592
2916
  default: input === null || input === void 0 ? void 0 : input.default,
2593
2917
  serialize: input === null || input === void 0 ? void 0 : input.serialize,
2594
2918
  deserialize: input === null || input === void 0 ? void 0 : input.deserialize