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