@zeus-js/runtime-dom 0.1.0-beta.7 → 0.1.0-beta.9

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,5 +1,5 @@
1
1
  /**
2
- * runtime-dom v0.1.0-beta.7
2
+ * runtime-dom v0.1.0-beta.9
3
3
  * (c) 2026 baicie
4
4
  * Released under the MIT License.
5
5
  **/
@@ -213,8 +213,9 @@ var ZeusRuntimeDOM = (function(exports) {
213
213
  this.depsTail = void 0;
214
214
  this.flags = 5;
215
215
  this.next = void 0;
216
- this.cleanup = void 0;
216
+ this.cleanups = void 0;
217
217
  this.scheduler = void 0;
218
+ this.scope = activeEffectScope;
218
219
  if (activeEffectScope) if (activeEffectScope.active) activeEffectScope.effects.push(this);
219
220
  else this.flags &= -2;
220
221
  }
@@ -475,13 +476,20 @@ var ZeusRuntimeDOM = (function(exports) {
475
476
  shouldTrack = last === void 0 ? true : last;
476
477
  }
477
478
  function cleanupEffect(e) {
478
- const { cleanup } = e;
479
- e.cleanup = void 0;
480
- if (cleanup) {
479
+ const cleanups = e.cleanups;
480
+ e.cleanups = void 0;
481
+ if (cleanups) {
481
482
  const prevSub = activeSub;
482
483
  activeSub = void 0;
483
484
  try {
484
- cleanup();
485
+ let error;
486
+ for (const cleanup of cleanups) try {
487
+ cleanup();
488
+ } catch (cleanupError) {
489
+ var _error;
490
+ (_error = error) !== null && _error !== void 0 || (error = cleanupError);
491
+ }
492
+ if (error) throw error;
485
493
  } finally {
486
494
  activeSub = prevSub;
487
495
  }
@@ -1366,6 +1374,58 @@ var ZeusRuntimeDOM = (function(exports) {
1366
1374
  return proto === Object.prototype || proto === null;
1367
1375
  }
1368
1376
  //#endregion
1377
+ //#region packages/core/runtime-dom/src/domOwnership.ts
1378
+ const activeLightDomHosts = /* @__PURE__ */ new WeakMap();
1379
+ const runtimeOwnedNodes = /* @__PURE__ */ new WeakSet();
1380
+ function registerLightDomHost(host, lightChildren) {
1381
+ const ownership = { lightChildren };
1382
+ activeLightDomHosts.set(host, ownership);
1383
+ return () => {
1384
+ if (activeLightDomHosts.get(host) === ownership) activeLightDomHosts.delete(host);
1385
+ };
1386
+ }
1387
+ function trackRuntimeDomInsertion(parent, node) {
1388
+ const ownership = activeLightDomHosts.get(parent);
1389
+ if (!ownership) return;
1390
+ if (node.nodeType === 11) {
1391
+ for (const child of node.childNodes) trackRuntimeNode(ownership, child);
1392
+ return;
1393
+ }
1394
+ trackRuntimeNode(ownership, node);
1395
+ }
1396
+ function isRuntimeOwnedNode(node) {
1397
+ return runtimeOwnedNodes.has(node);
1398
+ }
1399
+ function trackRuntimeNode(ownership, node) {
1400
+ if (!ownership.lightChildren.includes(node)) runtimeOwnedNodes.add(node);
1401
+ }
1402
+ //#endregion
1403
+ //#region packages/core/runtime-dom/src/range.ts
1404
+ function insertTracked(parent, value, marker = null) {
1405
+ if (value === void 0 || value == null || value === false || value === true) return [];
1406
+ if (Array.isArray(value)) {
1407
+ const nodes = [];
1408
+ for (const item of value) nodes.push(...insertTracked(parent, item, marker));
1409
+ return nodes;
1410
+ }
1411
+ const node = value instanceof Node ? value : document.createTextNode(String(value));
1412
+ trackRuntimeDomInsertion(parent, node);
1413
+ parent.insertBefore(node, marker);
1414
+ return [node];
1415
+ }
1416
+ function removeNodes$1(nodes) {
1417
+ for (const node of nodes) {
1418
+ var _node$parentNode2;
1419
+ (_node$parentNode2 = node.parentNode) === null || _node$parentNode2 === void 0 || _node$parentNode2.removeChild(node);
1420
+ }
1421
+ }
1422
+ function moveRangeBefore(nodes, parent, marker = null) {
1423
+ for (const node of nodes) {
1424
+ trackRuntimeDomInsertion(parent, node);
1425
+ parent.insertBefore(node, marker);
1426
+ }
1427
+ }
1428
+ //#endregion
1369
1429
  //#region packages/core/runtime-dom/src/hostContext.ts
1370
1430
  let currentHostContext;
1371
1431
  function getCurrentHostContext() {
@@ -1390,48 +1450,50 @@ var ZeusRuntimeDOM = (function(exports) {
1390
1450
  });
1391
1451
  }
1392
1452
  //#endregion
1393
- //#region packages/core/runtime-dom/src/range.ts
1394
- var DynamicRange = class {
1395
- constructor(parent, marker) {
1453
+ //#region packages/core/runtime-dom/src/scopedSubtree.ts
1454
+ function captureScopedSubtreeContext() {
1455
+ return {
1456
+ owner: getCurrentOwner(),
1457
+ host: captureCurrentHostContext()
1458
+ };
1459
+ }
1460
+ var ScopedSubtree = class {
1461
+ constructor(parent, marker, context) {
1396
1462
  this.parent = parent;
1397
1463
  this.marker = marker;
1464
+ this.context = context;
1398
1465
  this.nodes = [];
1399
1466
  }
1400
- replace(value) {
1401
- this.clear();
1402
- this.nodes = insertTracked(this.parent, value, this.marker);
1403
- }
1404
- clear() {
1405
- for (const node of this.nodes) {
1406
- var _node$parentNode;
1407
- (_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 || _node$parentNode.removeChild(node);
1467
+ replace(render) {
1468
+ this.dispose();
1469
+ const scope = effectScope(true);
1470
+ let nodes = [];
1471
+ try {
1472
+ scope.run(() => {
1473
+ nodes = runWithOwner(this.context.owner, () => withHostContext(this.context.host, () => insertTracked(this.parent, render(), this.marker)));
1474
+ });
1475
+ } catch (error) {
1476
+ scope.stop();
1477
+ removeNodes$1(nodes);
1478
+ throw error;
1408
1479
  }
1480
+ this.scope = scope;
1481
+ this.nodes = nodes;
1482
+ }
1483
+ dispose() {
1484
+ var _this$scope;
1485
+ (_this$scope = this.scope) === null || _this$scope === void 0 || _this$scope.stop();
1486
+ this.scope = void 0;
1487
+ removeNodes$1(this.nodes);
1409
1488
  this.nodes = [];
1410
1489
  }
1490
+ moveBefore(marker) {
1491
+ moveRangeBefore(this.nodes, this.parent, marker);
1492
+ }
1411
1493
  current() {
1412
1494
  return this.nodes;
1413
1495
  }
1414
1496
  };
1415
- function insertTracked(parent, value, marker = null) {
1416
- if (value === void 0 || value == null || value === false || value === true) return [];
1417
- if (Array.isArray(value)) {
1418
- const nodes = [];
1419
- for (const item of value) nodes.push(...insertTracked(parent, item, marker));
1420
- return nodes;
1421
- }
1422
- const node = value instanceof Node ? value : document.createTextNode(String(value));
1423
- parent.insertBefore(node, marker);
1424
- return [node];
1425
- }
1426
- function removeNodes$1(nodes) {
1427
- for (const node of nodes) {
1428
- var _node$parentNode2;
1429
- (_node$parentNode2 = node.parentNode) === null || _node$parentNode2 === void 0 || _node$parentNode2.removeChild(node);
1430
- }
1431
- }
1432
- function moveRangeBefore(nodes, parent, marker = null) {
1433
- for (const node of nodes) parent.insertBefore(node, marker);
1434
- }
1435
1497
  //#endregion
1436
1498
  //#region packages/core/runtime-dom/src/insert.ts
1437
1499
  function insert(parent, value, marker = null) {
@@ -1442,16 +1504,13 @@ var ZeusRuntimeDOM = (function(exports) {
1442
1504
  insertTracked(parent, value, marker);
1443
1505
  }
1444
1506
  function mountDynamic(parent, marker, value) {
1445
- const range = new DynamicRange(parent, marker);
1446
- const hostContext = captureCurrentHostContext();
1447
- const owner = getCurrentOwner();
1507
+ const subtree = new ScopedSubtree(parent, marker, captureScopedSubtreeContext());
1448
1508
  const runner = effect(() => {
1449
- const next = runWithOwner(owner, () => withHostContext(hostContext, value));
1450
- range.replace(next);
1509
+ subtree.replace(value);
1451
1510
  });
1452
1511
  onScopeDispose(() => {
1453
1512
  stop(runner);
1454
- range.clear();
1513
+ subtree.dispose();
1455
1514
  }, true);
1456
1515
  }
1457
1516
  //#endregion
@@ -1748,11 +1807,11 @@ var ZeusRuntimeDOM = (function(exports) {
1748
1807
  function patchStyle(el, prev, next) {
1749
1808
  const style = el.style;
1750
1809
  if (prev) {
1751
- for (const key in prev) if (!(key in next)) style.setProperty(toKebabCase$1(key), "");
1810
+ for (const key in prev) if (!(key in next)) style.setProperty(toKebabCase$2(key), "");
1752
1811
  }
1753
1812
  for (const key in next) {
1754
1813
  const value = next[key];
1755
- const name = toKebabCase$1(key);
1814
+ const name = toKebabCase$2(key);
1756
1815
  if (value == null) style.setProperty(name, "");
1757
1816
  else style.setProperty(name, normalizeStyleValue(key, value));
1758
1817
  }
@@ -1774,7 +1833,7 @@ var ZeusRuntimeDOM = (function(exports) {
1774
1833
  function isUnitlessNumber(key) {
1775
1834
  return unitlessNumbers.has(key);
1776
1835
  }
1777
- function toKebabCase$1(value) {
1836
+ function toKebabCase$2(value) {
1778
1837
  return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
1779
1838
  }
1780
1839
  //#endregion
@@ -1883,6 +1942,9 @@ var ZeusRuntimeDOM = (function(exports) {
1883
1942
  }
1884
1943
  //#endregion
1885
1944
  //#region packages/core/runtime-dom/src/list.ts
1945
+ function disposeListRecord(record) {
1946
+ record.subtree.dispose();
1947
+ }
1886
1948
  function mountFor$1(parent, marker, each, key, render) {
1887
1949
  if (!key) {
1888
1950
  mountIndexFor(parent, marker, each, render);
@@ -1891,24 +1953,20 @@ var ZeusRuntimeDOM = (function(exports) {
1891
1953
  mountKeyedFor(parent, marker, each, key, render);
1892
1954
  }
1893
1955
  function mountIndexFor(parent, marker, each, render) {
1894
- let current = [];
1895
- const owner = getCurrentOwner();
1956
+ const subtree = new ScopedSubtree(parent, marker, captureScopedSubtreeContext());
1896
1957
  const runner = effect(() => {
1897
1958
  var _each;
1898
- removeNodes$1(current);
1899
- current = [];
1900
1959
  const list = (_each = each()) !== null && _each !== void 0 ? _each : [];
1901
- for (let i = 0; i < list.length; i++) current.push(...insertTracked(parent, runWithOwner(owner, () => render(list[i], i)), marker));
1960
+ subtree.replace(() => list.map((item, index) => render(item, index)));
1902
1961
  });
1903
1962
  onScopeDispose(() => {
1904
1963
  stop(runner);
1905
- removeNodes$1(current);
1906
- current = [];
1964
+ subtree.dispose();
1907
1965
  }, true);
1908
1966
  }
1909
1967
  function mountKeyedFor(parent, marker, each, key, render) {
1910
1968
  let records = [];
1911
- const owner = getCurrentOwner();
1969
+ const subtreeContext = captureScopedSubtreeContext();
1912
1970
  const runner = effect(() => {
1913
1971
  var _each2;
1914
1972
  const nextItems = (_each2 = each()) !== null && _each2 !== void 0 ? _each2 : [];
@@ -1924,19 +1982,23 @@ var ZeusRuntimeDOM = (function(exports) {
1924
1982
  oldRecord.item = item;
1925
1983
  oldRecord.index = i;
1926
1984
  nextRecords.push(oldRecord);
1927
- } else nextRecords.push({
1928
- key: itemKey,
1929
- item,
1930
- index: i,
1931
- nodes: insertTracked(parent, runWithOwner(owner, () => render(item, i)), marker)
1932
- });
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
+ });
1994
+ }
1933
1995
  }
1934
- for (const record of oldMap.values()) removeNodes$1(record.nodes);
1996
+ for (const record of oldMap.values()) disposeListRecord(record);
1935
1997
  for (let i = nextRecords.length - 1; i >= 0; i--) {
1936
- var _nextRecords$nodes$;
1998
+ var _nextRecords$subtree$;
1937
1999
  const record = nextRecords[i];
1938
- const anchor = i === nextRecords.length - 1 ? marker : (_nextRecords$nodes$ = nextRecords[i + 1].nodes[0]) !== null && _nextRecords$nodes$ !== void 0 ? _nextRecords$nodes$ : marker;
1939
- moveRangeBefore(record.nodes, parent, anchor);
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);
1940
2002
  }
1941
2003
  emitDevtoolsEvent({
1942
2004
  type: "mount-for",
@@ -1946,7 +2008,7 @@ var ZeusRuntimeDOM = (function(exports) {
1946
2008
  });
1947
2009
  onScopeDispose(() => {
1948
2010
  stop(runner);
1949
- for (const record of records) removeNodes$1(record.nodes);
2011
+ for (const record of records) disposeListRecord(record);
1950
2012
  records = [];
1951
2013
  }, true);
1952
2014
  }
@@ -1970,6 +2032,254 @@ var ZeusRuntimeDOM = (function(exports) {
1970
2032
  mountFor$1(parent, marker, each, key, render);
1971
2033
  }
1972
2034
  //#endregion
2035
+ //#region packages/core/runtime-dom/src/customElementContract.ts
2036
+ function getCustomElementAttributeName(prop) {
2037
+ var _prop$attrName;
2038
+ if (prop.attrName === false) return void 0;
2039
+ if (!isAttributeBackedType(prop.type) && !prop.deserialize) return;
2040
+ return normalizeAttributeName((_prop$attrName = prop.attrName) !== null && _prop$attrName !== void 0 ? _prop$attrName : toKebabCase$1(prop.name));
2041
+ }
2042
+ function getCustomElementObservedAttributes(props) {
2043
+ const attributes = /* @__PURE__ */ new Set();
2044
+ for (const prop of props) {
2045
+ const attrName = getCustomElementAttributeName(prop);
2046
+ if (attrName) attributes.add(attrName);
2047
+ }
2048
+ return Array.from(attributes);
2049
+ }
2050
+ function findCustomElementPropByAttribute(props, attrName) {
2051
+ const normalizedName = normalizeAttributeName(attrName);
2052
+ return props.find((prop) => {
2053
+ return getCustomElementAttributeName(prop) === normalizedName;
2054
+ });
2055
+ }
2056
+ function coerceCustomElementAttribute(prop, value) {
2057
+ if (typeof prop.deserialize === "function") return prop.deserialize(value);
2058
+ if (prop.deserialize === true) return value;
2059
+ switch (prop.type) {
2060
+ case "boolean": return value !== null;
2061
+ case "number": return value === null ? void 0 : Number(value);
2062
+ case "string": return value !== null && value !== void 0 ? value : void 0;
2063
+ case "object":
2064
+ case "array": return coerceStructuredAttribute(prop, value);
2065
+ case "function": return;
2066
+ default: return value;
2067
+ }
2068
+ }
2069
+ function reflectCustomElementProperty(element, prop, value, reflectingAttrs) {
2070
+ const attrName = getCustomElementAttributeName(prop);
2071
+ if (!attrName || prop.serialize === true) return;
2072
+ reflectingAttrs === null || reflectingAttrs === void 0 || reflectingAttrs.add(attrName);
2073
+ try {
2074
+ const serialized = serializeCustomElementProperty(prop, value);
2075
+ if (serialized == null) element.removeAttribute(attrName);
2076
+ else element.setAttribute(attrName, serialized);
2077
+ } finally {
2078
+ reflectingAttrs === null || reflectingAttrs === void 0 || reflectingAttrs.delete(attrName);
2079
+ }
2080
+ }
2081
+ function createCustomElementMountLifecycle(mount) {
2082
+ let mounted;
2083
+ return {
2084
+ connect() {
2085
+ var _mounted;
2086
+ (_mounted = mounted) !== null && _mounted !== void 0 || (mounted = mount());
2087
+ return mounted;
2088
+ },
2089
+ disconnect() {
2090
+ const current = mounted;
2091
+ mounted = void 0;
2092
+ current === null || current === void 0 || current.dispose();
2093
+ },
2094
+ current() {
2095
+ return mounted;
2096
+ }
2097
+ };
2098
+ }
2099
+ function serializeCustomElementProperty(prop, value) {
2100
+ if (typeof prop.serialize === "function") return prop.serialize(value);
2101
+ if (prop.type === "boolean") return value ? "" : null;
2102
+ if (value == null) return null;
2103
+ if (prop.type === "object" || prop.type === "array") return JSON.stringify(value);
2104
+ if (prop.type === "function") return void 0;
2105
+ return String(value);
2106
+ }
2107
+ function coerceStructuredAttribute(prop, value) {
2108
+ if (value === null) return void 0;
2109
+ try {
2110
+ return JSON.parse(value);
2111
+ } catch (_unused) {
2112
+ console.warn(`[Zeus custom-element] Failed to parse JSON attribute "${getCustomElementAttributeName(prop)}".`);
2113
+ return prop.type === "array" ? [] : {};
2114
+ }
2115
+ }
2116
+ function isAttributeBackedType(type) {
2117
+ return type === "string" || type === "number" || type === "boolean";
2118
+ }
2119
+ function normalizeAttributeName(value) {
2120
+ return value.toLowerCase();
2121
+ }
2122
+ function toKebabCase$1(value) {
2123
+ return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
2124
+ }
2125
+ //#endregion
2126
+ //#region packages/core/runtime-dom/src/slot.ts
2127
+ function createSlot(name, fallback) {
2128
+ const context = getCurrentHostContext();
2129
+ if (!context) return createNativeSlot(name, fallback);
2130
+ if (context.mode === "shadow") return createNativeSlot(name, fallback);
2131
+ if (context.projection) return context.projection.createSlot(name, fallback);
2132
+ const assigned = findLightSlotNodes(context.lightChildren, name);
2133
+ if (assigned.length > 0) return Array.from(assigned);
2134
+ return fallback ? fallback() : null;
2135
+ }
2136
+ function createLightDomProjection(host, lightChildren) {
2137
+ const outlets = [];
2138
+ let observer;
2139
+ let unregisterHost;
2140
+ const observe = () => {
2141
+ observer === null || observer === void 0 || observer.observe(host, {
2142
+ attributes: true,
2143
+ attributeFilter: ["slot"],
2144
+ childList: true,
2145
+ subtree: true
2146
+ });
2147
+ for (const node of lightChildren) {
2148
+ if (node.nodeType !== Node.ELEMENT_NODE || host.contains(node)) continue;
2149
+ observer === null || observer === void 0 || observer.observe(node, {
2150
+ attributes: true,
2151
+ attributeFilter: ["slot"]
2152
+ });
2153
+ }
2154
+ };
2155
+ const reconcile = () => {
2156
+ observer === null || observer === void 0 || observer.disconnect();
2157
+ const claimed = /* @__PURE__ */ new Set();
2158
+ for (const outlet of outlets) {
2159
+ const assigned = lightChildren.filter((node) => {
2160
+ if (claimed.has(node) || !matchesLightSlot(node, outlet.name)) return false;
2161
+ claimed.add(node);
2162
+ return true;
2163
+ });
2164
+ replaceOutletNodes(outlet, assigned.length > 0 ? assigned : outlet.fallbackNodes);
2165
+ }
2166
+ for (const node of lightChildren) if (!claimed.has(node) && host.contains(node)) {
2167
+ var _node$parentNode;
2168
+ (_node$parentNode = node.parentNode) === null || _node$parentNode === void 0 || _node$parentNode.removeChild(node);
2169
+ }
2170
+ observer === null || observer === void 0 || observer.takeRecords();
2171
+ observe();
2172
+ };
2173
+ const handleMutations = (records) => {
2174
+ const added = /* @__PURE__ */ new Set();
2175
+ const removed = /* @__PURE__ */ new Set();
2176
+ let changed = false;
2177
+ for (const record of records) {
2178
+ if (record.type === "attributes") {
2179
+ if (lightChildren.includes(record.target)) changed = true;
2180
+ continue;
2181
+ }
2182
+ for (const node of record.removedNodes) if (lightChildren.includes(node)) removed.add(node);
2183
+ if (record.target !== host) continue;
2184
+ const additions = Array.from(record.addedNodes).filter((node) => {
2185
+ return !isRuntimeOwnedNode(node);
2186
+ });
2187
+ if (additions.length === 0) continue;
2188
+ for (const node of additions) added.add(node);
2189
+ insertLightChildren(lightChildren, additions, record);
2190
+ changed = true;
2191
+ }
2192
+ for (const node of removed) {
2193
+ if (added.has(node) || host.contains(node)) continue;
2194
+ const index = lightChildren.indexOf(node);
2195
+ if (index >= 0) {
2196
+ lightChildren.splice(index, 1);
2197
+ changed = true;
2198
+ }
2199
+ }
2200
+ if (changed) reconcile();
2201
+ };
2202
+ return {
2203
+ createSlot(name, fallback) {
2204
+ const fragment = document.createDocumentFragment();
2205
+ const start = document.createComment(name ? `zeus-slot:${name}` : "zeus-slot");
2206
+ const end = document.createComment("/zeus-slot");
2207
+ fragment.append(start, end);
2208
+ const outlet = {
2209
+ name,
2210
+ start,
2211
+ end,
2212
+ fallbackNodes: fallback ? insertTracked(fragment, fallback(), end) : []
2213
+ };
2214
+ outlets.push(outlet);
2215
+ reconcile();
2216
+ return fragment;
2217
+ },
2218
+ connect() {
2219
+ var _host$ownerDocument$d;
2220
+ if (observer) return;
2221
+ const Observer = (_host$ownerDocument$d = host.ownerDocument.defaultView) === null || _host$ownerDocument$d === void 0 ? void 0 : _host$ownerDocument$d.MutationObserver;
2222
+ if (!Observer) return;
2223
+ unregisterHost = registerLightDomHost(host, lightChildren);
2224
+ observer = new Observer(handleMutations);
2225
+ observe();
2226
+ },
2227
+ disconnect() {
2228
+ observer === null || observer === void 0 || observer.disconnect();
2229
+ observer = void 0;
2230
+ unregisterHost === null || unregisterHost === void 0 || unregisterHost();
2231
+ unregisterHost = void 0;
2232
+ }
2233
+ };
2234
+ }
2235
+ function replaceOutletNodes(outlet, nextNodes) {
2236
+ const parent = outlet.end.parentNode;
2237
+ if (!parent || parent !== outlet.start.parentNode) return;
2238
+ let current = outlet.start.nextSibling;
2239
+ while (current && current !== outlet.end) {
2240
+ const next = current.nextSibling;
2241
+ parent.removeChild(current);
2242
+ current = next;
2243
+ }
2244
+ for (const node of nextNodes) parent.insertBefore(node, outlet.end);
2245
+ }
2246
+ function insertLightChildren(lightChildren, additions, record) {
2247
+ for (const node of additions) {
2248
+ const currentIndex = lightChildren.indexOf(node);
2249
+ if (currentIndex >= 0) lightChildren.splice(currentIndex, 1);
2250
+ }
2251
+ let insertionIndex = lightChildren.length;
2252
+ const previousIndex = record.previousSibling ? lightChildren.indexOf(record.previousSibling) : -1;
2253
+ const nextIndex = record.nextSibling ? lightChildren.indexOf(record.nextSibling) : -1;
2254
+ if (previousIndex >= 0) insertionIndex = previousIndex + 1;
2255
+ else if (nextIndex >= 0) insertionIndex = nextIndex;
2256
+ else if (record.previousSibling === null) insertionIndex = 0;
2257
+ lightChildren.splice(insertionIndex, 0, ...additions);
2258
+ }
2259
+ function createNativeSlot(name, fallback) {
2260
+ const slot = document.createElement("slot");
2261
+ if (name) slot.setAttribute("name", name);
2262
+ const fallbackValue = fallback === null || fallback === void 0 ? void 0 : fallback();
2263
+ if (fallbackValue != null) insert(slot, fallbackValue);
2264
+ return slot;
2265
+ }
2266
+ function findLightSlotNodes(nodes, name) {
2267
+ return nodes.filter((node) => matchesLightSlot(node, name));
2268
+ }
2269
+ function matchesLightSlot(node, name) {
2270
+ if (name) {
2271
+ if (node.nodeType !== Node.ELEMENT_NODE) return false;
2272
+ return node.getAttribute("slot") === name;
2273
+ }
2274
+ if (node.nodeType === Node.ELEMENT_NODE) return !node.hasAttribute("slot");
2275
+ return isMeaningfulTextNode(node);
2276
+ }
2277
+ function isMeaningfulTextNode(node) {
2278
+ var _node$textContent;
2279
+ if (node.nodeType !== Node.TEXT_NODE) return false;
2280
+ return Boolean((_node$textContent = node.textContent) === null || _node$textContent === void 0 ? void 0 : _node$textContent.trim());
2281
+ }
2282
+ //#endregion
1973
2283
  //#region packages/core/runtime-dom/src/defineElement.ts
1974
2284
  const ZEUS_ELEMENT_DEFINITION = Symbol.for("zeus.element.definition");
1975
2285
  function prop(input, options = {}) {
@@ -2011,8 +2321,8 @@ var ZeusRuntimeDOM = (function(exports) {
2011
2321
  const props = {};
2012
2322
  for (const def of defs) {
2013
2323
  const slot = state();
2014
- slots.set(def.key, slot);
2015
- Object.defineProperty(props, def.key, {
2324
+ slots.set(def.name, slot);
2325
+ Object.defineProperty(props, def.name, {
2016
2326
  configurable: false,
2017
2327
  enumerable: true,
2018
2328
  get() {
@@ -2051,7 +2361,7 @@ var ZeusRuntimeDOM = (function(exports) {
2051
2361
  setup,
2052
2362
  propDefs
2053
2363
  };
2054
- const observedAttributes = propDefs.filter((def) => def.attr !== false).map((def) => def.attr);
2364
+ const observedAttributes = getCustomElementObservedAttributes(propDefs);
2055
2365
  class ZeusElement extends HTMLElement {
2056
2366
  static get observedAttributes() {
2057
2367
  return observedAttributes;
@@ -2060,7 +2370,8 @@ var ZeusRuntimeDOM = (function(exports) {
2060
2370
  super();
2061
2371
  this.lightChildren = [];
2062
2372
  this.capturedLightChildren = false;
2063
- this.reflecting = false;
2373
+ this.attributeProps = /* @__PURE__ */ new Set();
2374
+ this.reflectingAttrs = /* @__PURE__ */ new Set();
2064
2375
  this.propStore = createPropStore(propDefs);
2065
2376
  this.props = this.propStore.props;
2066
2377
  applyPropDefaults(this.propStore, propDefs);
@@ -2072,17 +2383,23 @@ var ZeusRuntimeDOM = (function(exports) {
2072
2383
  emit: createEmitApi(this, options.emits),
2073
2384
  expose: createExpose(this)
2074
2385
  };
2386
+ this.mountLifecycle = createCustomElementMountLifecycle(() => this.mountElement());
2075
2387
  }
2076
2388
  connectedCallback() {
2389
+ this.mountLifecycle.connect();
2390
+ }
2391
+ disconnectedCallback() {
2392
+ this.mountLifecycle.disconnect();
2393
+ }
2394
+ mountElement() {
2077
2395
  var _options$shadow, _options$consumes;
2078
- if (this.dispose) return;
2079
2396
  const shadow = (_options$shadow = options.shadow) !== null && _options$shadow !== void 0 ? _options$shadow : false;
2080
2397
  const mode = shadow ? "shadow" : "light";
2081
2398
  if (mode === "light" && !this.capturedLightChildren) {
2082
2399
  this.lightChildren = Array.from(this.childNodes);
2083
2400
  this.capturedLightChildren = true;
2084
2401
  }
2085
- this.syncAttributesToProps(propDefs);
2402
+ const projection = mode === "light" ? createLightDomProjection(this, this.lightChildren) : void 0;
2086
2403
  const owner = createOwner();
2087
2404
  for (const context of (_options$consumes = options.consumes) !== null && _options$consumes !== void 0 ? _options$consumes : []) {
2088
2405
  const resolved = resolveDOMContext(this, context);
@@ -2093,18 +2410,19 @@ var ZeusRuntimeDOM = (function(exports) {
2093
2410
  const hostContext = {
2094
2411
  host: this,
2095
2412
  mode,
2096
- lightChildren: this.lightChildren
2413
+ lightChildren: this.lightChildren,
2414
+ projection
2097
2415
  };
2098
- this.dispose = render(() => runWithOwner(owner, () => withHostContext(hostContext, () => {
2416
+ const dispose = render(() => runWithOwner(owner, () => withHostContext(hostContext, () => {
2099
2417
  syncFormValue(this.props, this.setupContext, options.form);
2100
2418
  return setup(this.props, this.setupContext);
2101
2419
  })), target, { owner });
2102
2420
  mountStyles(target, options.styles);
2103
- }
2104
- disconnectedCallback() {
2105
- var _this$dispose;
2106
- (_this$dispose = this.dispose) === null || _this$dispose === void 0 || _this$dispose.call(this);
2107
- this.dispose = void 0;
2421
+ projection === null || projection === void 0 || projection.connect();
2422
+ return { dispose() {
2423
+ projection === null || projection === void 0 || projection.disconnect();
2424
+ dispose();
2425
+ } };
2108
2426
  }
2109
2427
  formAssociatedCallback(form) {
2110
2428
  var _options$form, _options$form$associa;
@@ -2123,10 +2441,11 @@ var ZeusRuntimeDOM = (function(exports) {
2123
2441
  (_options$form4 = options.form) === null || _options$form4 === void 0 || (_options$form4$stateR = _options$form4.stateRestore) === null || _options$form4$stateR === void 0 || _options$form4$stateR.call(_options$form4, state, mode, this.props, this.setupContext);
2124
2442
  }
2125
2443
  attributeChangedCallback(name, oldValue, newValue) {
2126
- if (oldValue === newValue || this.reflecting) return;
2127
- const def = propDefs.find((item) => item.attr === name);
2444
+ if (oldValue === newValue || this.reflectingAttrs.has(name)) return;
2445
+ const def = propDefs.find((item) => item.attrName === name);
2128
2446
  if (!def) return;
2129
- this.propStore.set(def.key, castAttributeValue(newValue, def));
2447
+ this.attributeProps.add(def.name);
2448
+ this.propStore.set(def.name, coerceCustomElementAttribute(def, newValue));
2130
2449
  }
2131
2450
  resolveRenderTarget(shadow) {
2132
2451
  if (this.target) return this.target;
@@ -2137,24 +2456,11 @@ var ZeusRuntimeDOM = (function(exports) {
2137
2456
  this.target = this.attachShadow(typeof shadow === "object" ? shadow : { mode: "open" });
2138
2457
  return this.target;
2139
2458
  }
2140
- syncAttributesToProps(defs) {
2141
- for (const def of defs) {
2142
- if (def.attr === false) continue;
2143
- const value = this.getAttribute(def.attr);
2144
- if (value !== null || def.type === Boolean) this.propStore.set(def.key, castAttributeValue(value, def));
2145
- }
2146
- }
2147
2459
  _writePropFromProperty(key, value) {
2148
- const def = propDefs.find((item) => item.key === key);
2460
+ const def = propDefs.find((item) => item.name === key);
2461
+ this.attributeProps.delete(key);
2149
2462
  this.propStore.set(key, value);
2150
- if ((def === null || def === void 0 ? void 0 : def.reflect) && def.attr !== false) {
2151
- this.reflecting = true;
2152
- try {
2153
- reflectPropToAttribute(this, def, value);
2154
- } finally {
2155
- this.reflecting = false;
2156
- }
2157
- }
2463
+ if (def === null || def === void 0 ? void 0 : def.reflect) reflectCustomElementProperty(this, def, value, this.reflectingAttrs);
2158
2464
  }
2159
2465
  }
2160
2466
  ZeusElement.formAssociated = Boolean(options.formAssociated);
@@ -2177,13 +2483,13 @@ var ZeusRuntimeDOM = (function(exports) {
2177
2483
  applyPropDefaults(propStore, propDefs);
2178
2484
  for (const def of propDefs) {
2179
2485
  var _mountState$attribute;
2180
- if (def.attr !== false && ((_mountState$attribute = mountState.attributeProps) === null || _mountState$attribute === void 0 ? void 0 : _mountState$attribute.has(def.key))) {
2181
- propStore.set(def.key, castAttributeValue(host.getAttribute(def.attr), def));
2182
- initialValues.set(def.key, propStore.get(def.key));
2486
+ if (def.attrName !== false && ((_mountState$attribute = mountState.attributeProps) === null || _mountState$attribute === void 0 ? void 0 : _mountState$attribute.has(def.name))) {
2487
+ propStore.set(def.name, coerceCustomElementAttribute(def, host.getAttribute(def.attrName)));
2488
+ initialValues.set(def.name, propStore.get(def.name));
2183
2489
  continue;
2184
2490
  }
2185
- if (initialValues.has(def.key)) {
2186
- propStore.set(def.key, initialValues.get(def.key));
2491
+ if (initialValues.has(def.name)) {
2492
+ propStore.set(def.name, initialValues.get(def.name));
2187
2493
  continue;
2188
2494
  }
2189
2495
  /**
@@ -2191,11 +2497,11 @@ var ZeusRuntimeDOM = (function(exports) {
2191
2497
  * back to the lazy host value map so that `element.propName` returns the
2192
2498
  * correct default value rather than undefined.
2193
2499
  */
2194
- initialValues.set(def.key, propStore.get(def.key));
2500
+ initialValues.set(def.name, propStore.get(def.name));
2195
2501
  }
2196
2502
  for (const def of propDefs) {
2197
2503
  var _mountState$attribute2;
2198
- if (def.reflect && def.serialize && !((_mountState$attribute2 = mountState.attributeProps) === null || _mountState$attribute2 === void 0 ? void 0 : _mountState$attribute2.has(def.key))) reflectExternalProp(host, def, propStore.get(def.key), mountState.reflectingAttrs);
2504
+ if (def.reflect && def.serialize && !((_mountState$attribute2 = mountState.attributeProps) === null || _mountState$attribute2 === void 0 ? void 0 : _mountState$attribute2.has(def.name))) reflectCustomElementProperty(host, def, propStore.get(def.name), mountState.reflectingAttrs);
2199
2505
  }
2200
2506
  const shadow = (_options$shadow2 = options.shadow) !== null && _options$shadow2 !== void 0 ? _options$shadow2 : false;
2201
2507
  const mode = shadow ? "shadow" : "light";
@@ -2204,6 +2510,7 @@ var ZeusRuntimeDOM = (function(exports) {
2204
2510
  mountState.capturedLightChildren = true;
2205
2511
  }
2206
2512
  const lightChildren = (_mountState$lightChil = mountState.lightChildren) !== null && _mountState$lightChil !== void 0 ? _mountState$lightChil : [];
2513
+ const projection = mode === "light" ? createLightDomProjection(host, lightChildren) : void 0;
2207
2514
  const owner = createOwner();
2208
2515
  for (const context of (_options$consumes2 = options.consumes) !== null && _options$consumes2 !== void 0 ? _options$consumes2 : []) {
2209
2516
  const resolved = resolveDOMContext(host, context);
@@ -2214,7 +2521,8 @@ var ZeusRuntimeDOM = (function(exports) {
2214
2521
  const hostContext = {
2215
2522
  host,
2216
2523
  mode,
2217
- lightChildren
2524
+ lightChildren,
2525
+ projection
2218
2526
  };
2219
2527
  const setupContext = {
2220
2528
  host,
@@ -2228,15 +2536,16 @@ var ZeusRuntimeDOM = (function(exports) {
2228
2536
  return setup(propStore.props, setupContext);
2229
2537
  })), target, { owner });
2230
2538
  mountStyles(target, options.styles);
2539
+ projection === null || projection === void 0 || projection.connect();
2231
2540
  return {
2232
2541
  propertyChanged(name, _oldValue, newValue) {
2233
2542
  var _mountState$attribute3;
2234
- const def = propDefs.find((item) => item.key === name);
2235
- const fromAttribute = Boolean((def === null || def === void 0 ? void 0 : def.attr) !== false && ((_mountState$attribute3 = mountState.attributeProps) === null || _mountState$attribute3 === void 0 ? void 0 : _mountState$attribute3.has(name)));
2236
- const value = fromAttribute && def ? castAttributeValue(typeof newValue === "string" ? newValue : null, def) : newValue;
2543
+ const def = propDefs.find((item) => item.name === name);
2544
+ const fromAttribute = Boolean((def === null || def === void 0 ? void 0 : def.attrName) !== false && ((_mountState$attribute3 = mountState.attributeProps) === null || _mountState$attribute3 === void 0 ? void 0 : _mountState$attribute3.has(name)));
2545
+ const value = fromAttribute && def ? coerceCustomElementAttribute(def, typeof newValue === "string" ? newValue : null) : newValue;
2237
2546
  propStore.set(name, value);
2238
2547
  initialValues.set(name, value);
2239
- if ((def === null || def === void 0 ? void 0 : def.reflect) && !fromAttribute) reflectExternalProp(host, def, value, mountState.reflectingAttrs);
2548
+ if ((def === null || def === void 0 ? void 0 : def.reflect) && !fromAttribute) reflectCustomElementProperty(host, def, value, mountState.reflectingAttrs);
2240
2549
  },
2241
2550
  formAssociated(form) {
2242
2551
  var _options$form5, _options$form5$associ;
@@ -2255,6 +2564,7 @@ var ZeusRuntimeDOM = (function(exports) {
2255
2564
  (_options$form8 = options.form) === null || _options$form8 === void 0 || (_options$form8$stateR = _options$form8.stateRestore) === null || _options$form8$stateR === void 0 || _options$form8$stateR.call(_options$form8, state, mode, propStore.props, setupContext);
2256
2565
  },
2257
2566
  dispose() {
2567
+ projection === null || projection === void 0 || projection.disconnect();
2258
2568
  dispose();
2259
2569
  }
2260
2570
  };
@@ -2266,18 +2576,18 @@ var ZeusRuntimeDOM = (function(exports) {
2266
2576
  if (typeof input === "function") {
2267
2577
  const type = input;
2268
2578
  return {
2269
- key: propKey,
2270
- attr: isAttributeBackedConstructor(type) ? toKebabCase(propKey) : false,
2271
- type,
2579
+ name: propKey,
2580
+ attrName: isAttributeBackedConstructor(type) ? toKebabCase(propKey) : false,
2581
+ type: normalizePropType(type),
2272
2582
  reflect: false
2273
2583
  };
2274
2584
  }
2275
2585
  const type = input === null || input === void 0 ? void 0 : input.type;
2276
2586
  const defaultAttr = isAttributeBackedConstructor(type) ? toKebabCase(propKey) : false;
2277
2587
  return {
2278
- key: propKey,
2279
- attr: (input === null || input === void 0 ? void 0 : input.attr) === void 0 ? defaultAttr : input.attr,
2280
- type,
2588
+ name: propKey,
2589
+ attrName: (input === null || input === void 0 ? void 0 : input.attr) === void 0 ? defaultAttr : input.attr,
2590
+ type: normalizePropType(type),
2281
2591
  reflect: Boolean(input === null || input === void 0 ? void 0 : input.reflect),
2282
2592
  default: input === null || input === void 0 ? void 0 : input.default,
2283
2593
  serialize: input === null || input === void 0 ? void 0 : input.serialize,
@@ -2289,12 +2599,12 @@ var ZeusRuntimeDOM = (function(exports) {
2289
2599
  for (const def of defs) {
2290
2600
  if (!("default" in def)) continue;
2291
2601
  const value = typeof def.default === "function" ? def.default() : def.default;
2292
- store.set(def.key, value);
2602
+ store.set(def.name, value);
2293
2603
  }
2294
2604
  }
2295
2605
  function definePropAccessors(element, store, defs) {
2296
2606
  for (const def of defs) {
2297
- const key = def.key;
2607
+ const key = def.name;
2298
2608
  const hadOwnValue = Object.prototype.hasOwnProperty.call(element, key);
2299
2609
  const ownValue = hadOwnValue ? element[key] : void 0;
2300
2610
  if (hadOwnValue) delete element[key];
@@ -2316,54 +2626,6 @@ var ZeusRuntimeDOM = (function(exports) {
2316
2626
  if (hadOwnValue) element._writePropFromProperty(key, ownValue);
2317
2627
  }
2318
2628
  }
2319
- function castAttributeValue(value, def) {
2320
- if (def.deserialize) return def.deserialize(value);
2321
- if (def.type === Boolean) return value !== null;
2322
- if (value === null) return;
2323
- if (def.type === Number) return Number(value);
2324
- if (def.type === Object || def.type === Array) try {
2325
- return JSON.parse(value);
2326
- } catch (_unused) {
2327
- console.warn(`[Zeus custom-element] Failed to parse JSON attribute "${def.attr}".`);
2328
- return def.type === Array ? [] : {};
2329
- }
2330
- if (def.type === Function) return;
2331
- return value;
2332
- }
2333
- function reflectPropToAttribute(element, def, value) {
2334
- if (def.attr === false) return;
2335
- if (def.serialize) {
2336
- const serialized = def.serialize(value);
2337
- if (serialized == null) element.removeAttribute(def.attr);
2338
- else element.setAttribute(def.attr, serialized);
2339
- return;
2340
- }
2341
- if (def.type === Boolean) {
2342
- if (value) element.setAttribute(def.attr, "");
2343
- else element.removeAttribute(def.attr);
2344
- return;
2345
- }
2346
- if (value == null) {
2347
- element.removeAttribute(def.attr);
2348
- return;
2349
- }
2350
- if (def.type === Object || def.type === Array) {
2351
- element.setAttribute(def.attr, JSON.stringify(value));
2352
- return;
2353
- }
2354
- if (def.type === Function) return;
2355
- element.setAttribute(def.attr, String(value));
2356
- }
2357
- function reflectExternalProp(element, def, value, reflectingAttrs) {
2358
- if (def.attr === false) return;
2359
- const attrName = def.attr.toLowerCase();
2360
- reflectingAttrs === null || reflectingAttrs === void 0 || reflectingAttrs.add(attrName);
2361
- try {
2362
- reflectPropToAttribute(element, def, value);
2363
- } finally {
2364
- reflectingAttrs === null || reflectingAttrs === void 0 || reflectingAttrs.delete(attrName);
2365
- }
2366
- }
2367
2629
  function syncFormValue(props, context, form) {
2368
2630
  const valueResolver = form === null || form === void 0 ? void 0 : form.value;
2369
2631
  const stateResolver = form === null || form === void 0 ? void 0 : form.state;
@@ -2425,6 +2687,15 @@ var ZeusRuntimeDOM = (function(exports) {
2425
2687
  function isAttributeBackedConstructor(type) {
2426
2688
  return type === String || type === Number || type === Boolean;
2427
2689
  }
2690
+ function normalizePropType(type) {
2691
+ if (type === String) return "string";
2692
+ if (type === Number) return "number";
2693
+ if (type === Boolean) return "boolean";
2694
+ if (type === Object) return "object";
2695
+ if (type === Array) return "array";
2696
+ if (type === Function) return "function";
2697
+ return "unknown";
2698
+ }
2428
2699
  function resolveExternalRenderTarget(host, shadow) {
2429
2700
  var _host$shadowRoot;
2430
2701
  if (!shadow) return host;
@@ -2443,38 +2714,6 @@ var ZeusRuntimeDOM = (function(exports) {
2443
2714
  return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
2444
2715
  }
2445
2716
  //#endregion
2446
- //#region packages/core/runtime-dom/src/slot.ts
2447
- function createSlot(name, fallback) {
2448
- const context = getCurrentHostContext();
2449
- if (!context) return createNativeSlot(name, fallback);
2450
- if (context.mode === "shadow") return createNativeSlot(name, fallback);
2451
- const assigned = findLightSlotNodes(context.lightChildren, name);
2452
- if (assigned.length > 0) return Array.from(assigned);
2453
- return fallback ? fallback() : null;
2454
- }
2455
- function createNativeSlot(name, fallback) {
2456
- const slot = document.createElement("slot");
2457
- if (name) slot.setAttribute("name", name);
2458
- const fallbackValue = fallback === null || fallback === void 0 ? void 0 : fallback();
2459
- if (fallbackValue != null) insert(slot, fallbackValue);
2460
- return slot;
2461
- }
2462
- function findLightSlotNodes(nodes, name) {
2463
- if (name) return nodes.filter((node) => {
2464
- if (node.nodeType !== Node.ELEMENT_NODE) return false;
2465
- return node.getAttribute("slot") === name;
2466
- });
2467
- return nodes.filter((node) => {
2468
- if (node.nodeType === Node.ELEMENT_NODE) return !node.hasAttribute("slot");
2469
- return isMeaningfulTextNode(node);
2470
- });
2471
- }
2472
- function isMeaningfulTextNode(node) {
2473
- var _node$textContent;
2474
- if (node.nodeType !== Node.TEXT_NODE) return false;
2475
- return Boolean((_node$textContent = node.textContent) === null || _node$textContent === void 0 ? void 0 : _node$textContent.trim());
2476
- }
2477
- //#endregion
2478
2717
  //#region packages/core/runtime-dom/src/webComponents.ts
2479
2718
  const HOST_RESERVED_KEYS = /* @__PURE__ */ new Set([
2480
2719
  "children",
@@ -2582,16 +2821,21 @@ var ZeusRuntimeDOM = (function(exports) {
2582
2821
  exports.bindTextContent = bindTextContent;
2583
2822
  exports.captureCurrentHostContext = captureCurrentHostContext;
2584
2823
  exports.child = child;
2824
+ exports.coerceCustomElementAttribute = coerceCustomElementAttribute;
2585
2825
  exports.createComponent = createComponent;
2586
2826
  exports.createContext = createContext;
2827
+ exports.createCustomElementMountLifecycle = createCustomElementMountLifecycle;
2587
2828
  exports.createDOMContextBoundary = createDOMContextBoundary;
2588
2829
  exports.createOwner = createOwner;
2589
2830
  exports.createSlot = createSlot;
2590
2831
  exports.defineElement = defineElement;
2591
2832
  exports.delegateEvents = delegateEvents;
2592
2833
  exports.event = event;
2834
+ exports.findCustomElementPropByAttribute = findCustomElementPropByAttribute;
2593
2835
  exports.getCurrentHostContext = getCurrentHostContext;
2594
2836
  exports.getCurrentOwner = getCurrentOwner;
2837
+ exports.getCustomElementAttributeName = getCustomElementAttributeName;
2838
+ exports.getCustomElementObservedAttributes = getCustomElementObservedAttributes;
2595
2839
  exports.getElementDefinition = getElementDefinition;
2596
2840
  exports.inject = inject;
2597
2841
  exports.insert = insert;
@@ -2605,6 +2849,7 @@ var ZeusRuntimeDOM = (function(exports) {
2605
2849
  exports.prop = prop;
2606
2850
  exports.provide = provide;
2607
2851
  exports.provideDOMContext = provideDOMContext;
2852
+ exports.reflectCustomElementProperty = reflectCustomElementProperty;
2608
2853
  exports.removeNodes = removeNodes;
2609
2854
  exports.render = render;
2610
2855
  exports.resolveDOMContext = resolveDOMContext;