@zeus-js/runtime-dom 0.1.0-beta.8 → 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.8
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
@@ -1884,8 +1943,7 @@ var ZeusRuntimeDOM = (function(exports) {
1884
1943
  //#endregion
1885
1944
  //#region packages/core/runtime-dom/src/list.ts
1886
1945
  function disposeListRecord(record) {
1887
- record.scope.stop();
1888
- removeNodes$1(record.nodes);
1946
+ record.subtree.dispose();
1889
1947
  }
1890
1948
  function mountFor$1(parent, marker, each, key, render) {
1891
1949
  if (!key) {
@@ -1895,24 +1953,20 @@ var ZeusRuntimeDOM = (function(exports) {
1895
1953
  mountKeyedFor(parent, marker, each, key, render);
1896
1954
  }
1897
1955
  function mountIndexFor(parent, marker, each, render) {
1898
- let current = [];
1899
- const owner = getCurrentOwner();
1956
+ const subtree = new ScopedSubtree(parent, marker, captureScopedSubtreeContext());
1900
1957
  const runner = effect(() => {
1901
1958
  var _each;
1902
- removeNodes$1(current);
1903
- current = [];
1904
1959
  const list = (_each = each()) !== null && _each !== void 0 ? _each : [];
1905
- 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)));
1906
1961
  });
1907
1962
  onScopeDispose(() => {
1908
1963
  stop(runner);
1909
- removeNodes$1(current);
1910
- current = [];
1964
+ subtree.dispose();
1911
1965
  }, true);
1912
1966
  }
1913
1967
  function mountKeyedFor(parent, marker, each, key, render) {
1914
1968
  let records = [];
1915
- const owner = getCurrentOwner();
1969
+ const subtreeContext = captureScopedSubtreeContext();
1916
1970
  const runner = effect(() => {
1917
1971
  var _each2;
1918
1972
  const nextItems = (_each2 = each()) !== null && _each2 !== void 0 ? _each2 : [];
@@ -1929,31 +1983,22 @@ var ZeusRuntimeDOM = (function(exports) {
1929
1983
  oldRecord.index = i;
1930
1984
  nextRecords.push(oldRecord);
1931
1985
  } else {
1932
- const itemScope = effectScope(true);
1933
- let nodes = [];
1934
- try {
1935
- itemScope.run(() => {
1936
- nodes = insertTracked(parent, runWithOwner(owner, () => render(item, i)), marker);
1937
- });
1938
- } catch (error) {
1939
- itemScope.stop();
1940
- throw error;
1941
- }
1986
+ const subtree = new ScopedSubtree(parent, marker, subtreeContext);
1987
+ subtree.replace(() => render(item, i));
1942
1988
  nextRecords.push({
1943
1989
  key: itemKey,
1944
1990
  item,
1945
1991
  index: i,
1946
- nodes,
1947
- scope: itemScope
1992
+ subtree
1948
1993
  });
1949
1994
  }
1950
1995
  }
1951
1996
  for (const record of oldMap.values()) disposeListRecord(record);
1952
1997
  for (let i = nextRecords.length - 1; i >= 0; i--) {
1953
- var _nextRecords$nodes$;
1998
+ var _nextRecords$subtree$;
1954
1999
  const record = nextRecords[i];
1955
- const anchor = i === nextRecords.length - 1 ? marker : (_nextRecords$nodes$ = nextRecords[i + 1].nodes[0]) !== null && _nextRecords$nodes$ !== void 0 ? _nextRecords$nodes$ : marker;
1956
- 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);
1957
2002
  }
1958
2003
  emitDevtoolsEvent({
1959
2004
  type: "mount-for",
@@ -1987,6 +2032,254 @@ var ZeusRuntimeDOM = (function(exports) {
1987
2032
  mountFor$1(parent, marker, each, key, render);
1988
2033
  }
1989
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
1990
2283
  //#region packages/core/runtime-dom/src/defineElement.ts
1991
2284
  const ZEUS_ELEMENT_DEFINITION = Symbol.for("zeus.element.definition");
1992
2285
  function prop(input, options = {}) {
@@ -2028,8 +2321,8 @@ var ZeusRuntimeDOM = (function(exports) {
2028
2321
  const props = {};
2029
2322
  for (const def of defs) {
2030
2323
  const slot = state();
2031
- slots.set(def.key, slot);
2032
- Object.defineProperty(props, def.key, {
2324
+ slots.set(def.name, slot);
2325
+ Object.defineProperty(props, def.name, {
2033
2326
  configurable: false,
2034
2327
  enumerable: true,
2035
2328
  get() {
@@ -2068,7 +2361,7 @@ var ZeusRuntimeDOM = (function(exports) {
2068
2361
  setup,
2069
2362
  propDefs
2070
2363
  };
2071
- const observedAttributes = propDefs.filter((def) => def.attr !== false).map((def) => def.attr);
2364
+ const observedAttributes = getCustomElementObservedAttributes(propDefs);
2072
2365
  class ZeusElement extends HTMLElement {
2073
2366
  static get observedAttributes() {
2074
2367
  return observedAttributes;
@@ -2077,7 +2370,8 @@ var ZeusRuntimeDOM = (function(exports) {
2077
2370
  super();
2078
2371
  this.lightChildren = [];
2079
2372
  this.capturedLightChildren = false;
2080
- this.reflecting = false;
2373
+ this.attributeProps = /* @__PURE__ */ new Set();
2374
+ this.reflectingAttrs = /* @__PURE__ */ new Set();
2081
2375
  this.propStore = createPropStore(propDefs);
2082
2376
  this.props = this.propStore.props;
2083
2377
  applyPropDefaults(this.propStore, propDefs);
@@ -2089,17 +2383,23 @@ var ZeusRuntimeDOM = (function(exports) {
2089
2383
  emit: createEmitApi(this, options.emits),
2090
2384
  expose: createExpose(this)
2091
2385
  };
2386
+ this.mountLifecycle = createCustomElementMountLifecycle(() => this.mountElement());
2092
2387
  }
2093
2388
  connectedCallback() {
2389
+ this.mountLifecycle.connect();
2390
+ }
2391
+ disconnectedCallback() {
2392
+ this.mountLifecycle.disconnect();
2393
+ }
2394
+ mountElement() {
2094
2395
  var _options$shadow, _options$consumes;
2095
- if (this.dispose) return;
2096
2396
  const shadow = (_options$shadow = options.shadow) !== null && _options$shadow !== void 0 ? _options$shadow : false;
2097
2397
  const mode = shadow ? "shadow" : "light";
2098
2398
  if (mode === "light" && !this.capturedLightChildren) {
2099
2399
  this.lightChildren = Array.from(this.childNodes);
2100
2400
  this.capturedLightChildren = true;
2101
2401
  }
2102
- this.syncAttributesToProps(propDefs);
2402
+ const projection = mode === "light" ? createLightDomProjection(this, this.lightChildren) : void 0;
2103
2403
  const owner = createOwner();
2104
2404
  for (const context of (_options$consumes = options.consumes) !== null && _options$consumes !== void 0 ? _options$consumes : []) {
2105
2405
  const resolved = resolveDOMContext(this, context);
@@ -2110,18 +2410,19 @@ var ZeusRuntimeDOM = (function(exports) {
2110
2410
  const hostContext = {
2111
2411
  host: this,
2112
2412
  mode,
2113
- lightChildren: this.lightChildren
2413
+ lightChildren: this.lightChildren,
2414
+ projection
2114
2415
  };
2115
- this.dispose = render(() => runWithOwner(owner, () => withHostContext(hostContext, () => {
2416
+ const dispose = render(() => runWithOwner(owner, () => withHostContext(hostContext, () => {
2116
2417
  syncFormValue(this.props, this.setupContext, options.form);
2117
2418
  return setup(this.props, this.setupContext);
2118
2419
  })), target, { owner });
2119
2420
  mountStyles(target, options.styles);
2120
- }
2121
- disconnectedCallback() {
2122
- var _this$dispose;
2123
- (_this$dispose = this.dispose) === null || _this$dispose === void 0 || _this$dispose.call(this);
2124
- 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
+ } };
2125
2426
  }
2126
2427
  formAssociatedCallback(form) {
2127
2428
  var _options$form, _options$form$associa;
@@ -2140,10 +2441,11 @@ var ZeusRuntimeDOM = (function(exports) {
2140
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);
2141
2442
  }
2142
2443
  attributeChangedCallback(name, oldValue, newValue) {
2143
- if (oldValue === newValue || this.reflecting) return;
2144
- 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);
2145
2446
  if (!def) return;
2146
- this.propStore.set(def.key, castAttributeValue(newValue, def));
2447
+ this.attributeProps.add(def.name);
2448
+ this.propStore.set(def.name, coerceCustomElementAttribute(def, newValue));
2147
2449
  }
2148
2450
  resolveRenderTarget(shadow) {
2149
2451
  if (this.target) return this.target;
@@ -2154,24 +2456,11 @@ var ZeusRuntimeDOM = (function(exports) {
2154
2456
  this.target = this.attachShadow(typeof shadow === "object" ? shadow : { mode: "open" });
2155
2457
  return this.target;
2156
2458
  }
2157
- syncAttributesToProps(defs) {
2158
- for (const def of defs) {
2159
- if (def.attr === false) continue;
2160
- const value = this.getAttribute(def.attr);
2161
- if (value !== null || def.type === Boolean) this.propStore.set(def.key, castAttributeValue(value, def));
2162
- }
2163
- }
2164
2459
  _writePropFromProperty(key, value) {
2165
- const def = propDefs.find((item) => item.key === key);
2460
+ const def = propDefs.find((item) => item.name === key);
2461
+ this.attributeProps.delete(key);
2166
2462
  this.propStore.set(key, value);
2167
- if ((def === null || def === void 0 ? void 0 : def.reflect) && def.attr !== false) {
2168
- this.reflecting = true;
2169
- try {
2170
- reflectPropToAttribute(this, def, value);
2171
- } finally {
2172
- this.reflecting = false;
2173
- }
2174
- }
2463
+ if (def === null || def === void 0 ? void 0 : def.reflect) reflectCustomElementProperty(this, def, value, this.reflectingAttrs);
2175
2464
  }
2176
2465
  }
2177
2466
  ZeusElement.formAssociated = Boolean(options.formAssociated);
@@ -2194,13 +2483,13 @@ var ZeusRuntimeDOM = (function(exports) {
2194
2483
  applyPropDefaults(propStore, propDefs);
2195
2484
  for (const def of propDefs) {
2196
2485
  var _mountState$attribute;
2197
- if (def.attr !== false && ((_mountState$attribute = mountState.attributeProps) === null || _mountState$attribute === void 0 ? void 0 : _mountState$attribute.has(def.key))) {
2198
- propStore.set(def.key, castAttributeValue(host.getAttribute(def.attr), def));
2199
- 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));
2200
2489
  continue;
2201
2490
  }
2202
- if (initialValues.has(def.key)) {
2203
- propStore.set(def.key, initialValues.get(def.key));
2491
+ if (initialValues.has(def.name)) {
2492
+ propStore.set(def.name, initialValues.get(def.name));
2204
2493
  continue;
2205
2494
  }
2206
2495
  /**
@@ -2208,11 +2497,11 @@ var ZeusRuntimeDOM = (function(exports) {
2208
2497
  * back to the lazy host value map so that `element.propName` returns the
2209
2498
  * correct default value rather than undefined.
2210
2499
  */
2211
- initialValues.set(def.key, propStore.get(def.key));
2500
+ initialValues.set(def.name, propStore.get(def.name));
2212
2501
  }
2213
2502
  for (const def of propDefs) {
2214
2503
  var _mountState$attribute2;
2215
- 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);
2216
2505
  }
2217
2506
  const shadow = (_options$shadow2 = options.shadow) !== null && _options$shadow2 !== void 0 ? _options$shadow2 : false;
2218
2507
  const mode = shadow ? "shadow" : "light";
@@ -2221,6 +2510,7 @@ var ZeusRuntimeDOM = (function(exports) {
2221
2510
  mountState.capturedLightChildren = true;
2222
2511
  }
2223
2512
  const lightChildren = (_mountState$lightChil = mountState.lightChildren) !== null && _mountState$lightChil !== void 0 ? _mountState$lightChil : [];
2513
+ const projection = mode === "light" ? createLightDomProjection(host, lightChildren) : void 0;
2224
2514
  const owner = createOwner();
2225
2515
  for (const context of (_options$consumes2 = options.consumes) !== null && _options$consumes2 !== void 0 ? _options$consumes2 : []) {
2226
2516
  const resolved = resolveDOMContext(host, context);
@@ -2231,7 +2521,8 @@ var ZeusRuntimeDOM = (function(exports) {
2231
2521
  const hostContext = {
2232
2522
  host,
2233
2523
  mode,
2234
- lightChildren
2524
+ lightChildren,
2525
+ projection
2235
2526
  };
2236
2527
  const setupContext = {
2237
2528
  host,
@@ -2245,15 +2536,16 @@ var ZeusRuntimeDOM = (function(exports) {
2245
2536
  return setup(propStore.props, setupContext);
2246
2537
  })), target, { owner });
2247
2538
  mountStyles(target, options.styles);
2539
+ projection === null || projection === void 0 || projection.connect();
2248
2540
  return {
2249
2541
  propertyChanged(name, _oldValue, newValue) {
2250
2542
  var _mountState$attribute3;
2251
- const def = propDefs.find((item) => item.key === name);
2252
- 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)));
2253
- 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;
2254
2546
  propStore.set(name, value);
2255
2547
  initialValues.set(name, value);
2256
- 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);
2257
2549
  },
2258
2550
  formAssociated(form) {
2259
2551
  var _options$form5, _options$form5$associ;
@@ -2272,6 +2564,7 @@ var ZeusRuntimeDOM = (function(exports) {
2272
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);
2273
2565
  },
2274
2566
  dispose() {
2567
+ projection === null || projection === void 0 || projection.disconnect();
2275
2568
  dispose();
2276
2569
  }
2277
2570
  };
@@ -2283,18 +2576,18 @@ var ZeusRuntimeDOM = (function(exports) {
2283
2576
  if (typeof input === "function") {
2284
2577
  const type = input;
2285
2578
  return {
2286
- key: propKey,
2287
- attr: isAttributeBackedConstructor(type) ? toKebabCase(propKey) : false,
2288
- type,
2579
+ name: propKey,
2580
+ attrName: isAttributeBackedConstructor(type) ? toKebabCase(propKey) : false,
2581
+ type: normalizePropType(type),
2289
2582
  reflect: false
2290
2583
  };
2291
2584
  }
2292
2585
  const type = input === null || input === void 0 ? void 0 : input.type;
2293
2586
  const defaultAttr = isAttributeBackedConstructor(type) ? toKebabCase(propKey) : false;
2294
2587
  return {
2295
- key: propKey,
2296
- attr: (input === null || input === void 0 ? void 0 : input.attr) === void 0 ? defaultAttr : input.attr,
2297
- type,
2588
+ name: propKey,
2589
+ attrName: (input === null || input === void 0 ? void 0 : input.attr) === void 0 ? defaultAttr : input.attr,
2590
+ type: normalizePropType(type),
2298
2591
  reflect: Boolean(input === null || input === void 0 ? void 0 : input.reflect),
2299
2592
  default: input === null || input === void 0 ? void 0 : input.default,
2300
2593
  serialize: input === null || input === void 0 ? void 0 : input.serialize,
@@ -2306,12 +2599,12 @@ var ZeusRuntimeDOM = (function(exports) {
2306
2599
  for (const def of defs) {
2307
2600
  if (!("default" in def)) continue;
2308
2601
  const value = typeof def.default === "function" ? def.default() : def.default;
2309
- store.set(def.key, value);
2602
+ store.set(def.name, value);
2310
2603
  }
2311
2604
  }
2312
2605
  function definePropAccessors(element, store, defs) {
2313
2606
  for (const def of defs) {
2314
- const key = def.key;
2607
+ const key = def.name;
2315
2608
  const hadOwnValue = Object.prototype.hasOwnProperty.call(element, key);
2316
2609
  const ownValue = hadOwnValue ? element[key] : void 0;
2317
2610
  if (hadOwnValue) delete element[key];
@@ -2333,54 +2626,6 @@ var ZeusRuntimeDOM = (function(exports) {
2333
2626
  if (hadOwnValue) element._writePropFromProperty(key, ownValue);
2334
2627
  }
2335
2628
  }
2336
- function castAttributeValue(value, def) {
2337
- if (def.deserialize) return def.deserialize(value);
2338
- if (def.type === Boolean) return value !== null;
2339
- if (value === null) return;
2340
- if (def.type === Number) return Number(value);
2341
- if (def.type === Object || def.type === Array) try {
2342
- return JSON.parse(value);
2343
- } catch (_unused) {
2344
- console.warn(`[Zeus custom-element] Failed to parse JSON attribute "${def.attr}".`);
2345
- return def.type === Array ? [] : {};
2346
- }
2347
- if (def.type === Function) return;
2348
- return value;
2349
- }
2350
- function reflectPropToAttribute(element, def, value) {
2351
- if (def.attr === false) return;
2352
- if (def.serialize) {
2353
- const serialized = def.serialize(value);
2354
- if (serialized == null) element.removeAttribute(def.attr);
2355
- else element.setAttribute(def.attr, serialized);
2356
- return;
2357
- }
2358
- if (def.type === Boolean) {
2359
- if (value) element.setAttribute(def.attr, "");
2360
- else element.removeAttribute(def.attr);
2361
- return;
2362
- }
2363
- if (value == null) {
2364
- element.removeAttribute(def.attr);
2365
- return;
2366
- }
2367
- if (def.type === Object || def.type === Array) {
2368
- element.setAttribute(def.attr, JSON.stringify(value));
2369
- return;
2370
- }
2371
- if (def.type === Function) return;
2372
- element.setAttribute(def.attr, String(value));
2373
- }
2374
- function reflectExternalProp(element, def, value, reflectingAttrs) {
2375
- if (def.attr === false) return;
2376
- const attrName = def.attr.toLowerCase();
2377
- reflectingAttrs === null || reflectingAttrs === void 0 || reflectingAttrs.add(attrName);
2378
- try {
2379
- reflectPropToAttribute(element, def, value);
2380
- } finally {
2381
- reflectingAttrs === null || reflectingAttrs === void 0 || reflectingAttrs.delete(attrName);
2382
- }
2383
- }
2384
2629
  function syncFormValue(props, context, form) {
2385
2630
  const valueResolver = form === null || form === void 0 ? void 0 : form.value;
2386
2631
  const stateResolver = form === null || form === void 0 ? void 0 : form.state;
@@ -2442,6 +2687,15 @@ var ZeusRuntimeDOM = (function(exports) {
2442
2687
  function isAttributeBackedConstructor(type) {
2443
2688
  return type === String || type === Number || type === Boolean;
2444
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
+ }
2445
2699
  function resolveExternalRenderTarget(host, shadow) {
2446
2700
  var _host$shadowRoot;
2447
2701
  if (!shadow) return host;
@@ -2460,38 +2714,6 @@ var ZeusRuntimeDOM = (function(exports) {
2460
2714
  return value.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
2461
2715
  }
2462
2716
  //#endregion
2463
- //#region packages/core/runtime-dom/src/slot.ts
2464
- function createSlot(name, fallback) {
2465
- const context = getCurrentHostContext();
2466
- if (!context) return createNativeSlot(name, fallback);
2467
- if (context.mode === "shadow") return createNativeSlot(name, fallback);
2468
- const assigned = findLightSlotNodes(context.lightChildren, name);
2469
- if (assigned.length > 0) return Array.from(assigned);
2470
- return fallback ? fallback() : null;
2471
- }
2472
- function createNativeSlot(name, fallback) {
2473
- const slot = document.createElement("slot");
2474
- if (name) slot.setAttribute("name", name);
2475
- const fallbackValue = fallback === null || fallback === void 0 ? void 0 : fallback();
2476
- if (fallbackValue != null) insert(slot, fallbackValue);
2477
- return slot;
2478
- }
2479
- function findLightSlotNodes(nodes, name) {
2480
- if (name) return nodes.filter((node) => {
2481
- if (node.nodeType !== Node.ELEMENT_NODE) return false;
2482
- return node.getAttribute("slot") === name;
2483
- });
2484
- return nodes.filter((node) => {
2485
- if (node.nodeType === Node.ELEMENT_NODE) return !node.hasAttribute("slot");
2486
- return isMeaningfulTextNode(node);
2487
- });
2488
- }
2489
- function isMeaningfulTextNode(node) {
2490
- var _node$textContent;
2491
- if (node.nodeType !== Node.TEXT_NODE) return false;
2492
- return Boolean((_node$textContent = node.textContent) === null || _node$textContent === void 0 ? void 0 : _node$textContent.trim());
2493
- }
2494
- //#endregion
2495
2717
  //#region packages/core/runtime-dom/src/webComponents.ts
2496
2718
  const HOST_RESERVED_KEYS = /* @__PURE__ */ new Set([
2497
2719
  "children",
@@ -2599,16 +2821,21 @@ var ZeusRuntimeDOM = (function(exports) {
2599
2821
  exports.bindTextContent = bindTextContent;
2600
2822
  exports.captureCurrentHostContext = captureCurrentHostContext;
2601
2823
  exports.child = child;
2824
+ exports.coerceCustomElementAttribute = coerceCustomElementAttribute;
2602
2825
  exports.createComponent = createComponent;
2603
2826
  exports.createContext = createContext;
2827
+ exports.createCustomElementMountLifecycle = createCustomElementMountLifecycle;
2604
2828
  exports.createDOMContextBoundary = createDOMContextBoundary;
2605
2829
  exports.createOwner = createOwner;
2606
2830
  exports.createSlot = createSlot;
2607
2831
  exports.defineElement = defineElement;
2608
2832
  exports.delegateEvents = delegateEvents;
2609
2833
  exports.event = event;
2834
+ exports.findCustomElementPropByAttribute = findCustomElementPropByAttribute;
2610
2835
  exports.getCurrentHostContext = getCurrentHostContext;
2611
2836
  exports.getCurrentOwner = getCurrentOwner;
2837
+ exports.getCustomElementAttributeName = getCustomElementAttributeName;
2838
+ exports.getCustomElementObservedAttributes = getCustomElementObservedAttributes;
2612
2839
  exports.getElementDefinition = getElementDefinition;
2613
2840
  exports.inject = inject;
2614
2841
  exports.insert = insert;
@@ -2622,6 +2849,7 @@ var ZeusRuntimeDOM = (function(exports) {
2622
2849
  exports.prop = prop;
2623
2850
  exports.provide = provide;
2624
2851
  exports.provideDOMContext = provideDOMContext;
2852
+ exports.reflectCustomElementProperty = reflectCustomElementProperty;
2625
2853
  exports.removeNodes = removeNodes;
2626
2854
  exports.render = render;
2627
2855
  exports.resolveDOMContext = resolveDOMContext;