sibujs 4.5.0 → 4.7.0

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.
Files changed (116) hide show
  1. package/README.md +1 -1
  2. package/dist/browser.cjs +326 -133
  3. package/dist/browser.d.cts +46 -14
  4. package/dist/browser.d.ts +46 -14
  5. package/dist/browser.js +8 -6
  6. package/dist/build.cjs +2094 -1033
  7. package/dist/build.d.cts +133 -44
  8. package/dist/build.d.ts +133 -44
  9. package/dist/build.js +1372 -574
  10. package/dist/cdn.dev.global.js +10 -10
  11. package/dist/cdn.full.dev.global.js +11 -11
  12. package/dist/cdn.full.global.js +10 -10
  13. package/dist/cdn.global.js +10 -10
  14. package/dist/{chunk-2DCGACUU.js → chunk-2BPG2XDA.js} +251 -66
  15. package/dist/{chunk-IXKSNWV5.js → chunk-2INLLLMZ.js} +1 -1
  16. package/dist/{chunk-4PMLNECI.js → chunk-3QWBSL5R.js} +98 -29
  17. package/dist/{chunk-KKLW7YWL.js → chunk-4AWA2PVD.js} +275 -144
  18. package/dist/chunk-5HZXGZ6T.js +24 -0
  19. package/dist/{chunk-PCT43HW3.js → chunk-7LUJQAOJ.js} +1 -1
  20. package/dist/{chunk-5DXA2J44.js → chunk-7XHATCIH.js} +5 -2
  21. package/dist/chunk-BC2SECJD.js +44 -0
  22. package/dist/{chunk-TBYTO6BS.js → chunk-BSY63EM6.js} +136 -80
  23. package/dist/{chunk-FTIR4QW2.js → chunk-DKXRACVN.js} +6 -8
  24. package/dist/{chunk-ONOHFDLG.js → chunk-FNJXNGYZ.js} +3 -3
  25. package/dist/{chunk-XZZOBQAY.js → chunk-FQRUXCEE.js} +6 -5
  26. package/dist/{chunk-NIOYEGBQ.js → chunk-HURREPU2.js} +27 -13
  27. package/dist/chunk-J6FW5TV6.js +233 -0
  28. package/dist/{chunk-UGRX3S57.js → chunk-JWKYU5GV.js} +22 -4
  29. package/dist/chunk-NYNYSPK7.js +318 -0
  30. package/dist/{chunk-RBTPLM32.js → chunk-RUSSKG6G.js} +13 -12
  31. package/dist/{chunk-7LN645I6.js → chunk-SLM3IA34.js} +3 -3
  32. package/dist/{chunk-R25EFXXC.js → chunk-TUCPL2HB.js} +3 -3
  33. package/dist/{chunk-B3WHI2QA.js → chunk-UNWRJRKC.js} +55 -31
  34. package/dist/{chunk-KEISJXBU.js → chunk-UOL2ECCS.js} +44 -17
  35. package/dist/{chunk-RJE2BNI4.js → chunk-VZSG24LS.js} +108 -45
  36. package/dist/{chunk-RIXRAYIU.js → chunk-WEQ3DMVL.js} +10 -4
  37. package/dist/{chunk-3JZ4L5TJ.js → chunk-WOLJZUFQ.js} +354 -90
  38. package/dist/{chunk-S373NSMK.js → chunk-XYV3EDB7.js} +283 -123
  39. package/dist/{chunk-VZKNK2V7.js → chunk-XZR4PXRE.js} +296 -38
  40. package/dist/{chunk-GW3SCCZG.js → chunk-Z3OHK6QT.js} +153 -110
  41. package/dist/{chunk-OMJJM3KM.js → chunk-ZVL7TY4K.js} +287 -130
  42. package/dist/{contracts-DBdg9J_a.d.ts → contracts-CLqzJnOV.d.ts} +36 -17
  43. package/dist/{contracts-DBdg9J_a.d.cts → contracts-CTOJXu-x.d.cts} +36 -17
  44. package/dist/{customElement-OB9CIsc5.d.cts → customElement-MmInOW1U.d.cts} +21 -0
  45. package/dist/{customElement-OB9CIsc5.d.ts → customElement-MmInOW1U.d.ts} +21 -0
  46. package/dist/data.cjs +410 -155
  47. package/dist/data.d.cts +166 -12
  48. package/dist/data.d.ts +166 -12
  49. package/dist/data.js +12 -9
  50. package/dist/devtools.cjs +98 -61
  51. package/dist/devtools.js +7 -8
  52. package/dist/dispose-GEIG2KOF.js +28 -0
  53. package/dist/ecosystem.cjs +372 -126
  54. package/dist/ecosystem.d.cts +20 -3
  55. package/dist/ecosystem.d.ts +20 -3
  56. package/dist/ecosystem.js +12 -12
  57. package/dist/extras.cjs +2366 -909
  58. package/dist/extras.d.cts +11 -9
  59. package/dist/extras.d.ts +11 -9
  60. package/dist/extras.js +39 -28
  61. package/dist/index.cjs +421 -158
  62. package/dist/index.d.cts +213 -171
  63. package/dist/index.d.ts +213 -171
  64. package/dist/index.js +24 -27
  65. package/dist/motion.cjs +118 -44
  66. package/dist/motion.js +5 -5
  67. package/dist/patterns.cjs +344 -53
  68. package/dist/patterns.d.cts +28 -9
  69. package/dist/patterns.d.ts +28 -9
  70. package/dist/patterns.js +8 -8
  71. package/dist/performance.cjs +325 -220
  72. package/dist/performance.d.cts +2 -2
  73. package/dist/performance.d.ts +2 -2
  74. package/dist/performance.js +8 -9
  75. package/dist/plugin-DVgSnTfK.d.cts +112 -0
  76. package/dist/plugin-DVgSnTfK.d.ts +112 -0
  77. package/dist/plugins.cjs +664 -233
  78. package/dist/plugins.d.cts +127 -14
  79. package/dist/plugins.d.ts +127 -14
  80. package/dist/plugins.js +96 -42
  81. package/dist/signal-EotCj4hS.d.cts +110 -0
  82. package/dist/signal-EotCj4hS.d.ts +110 -0
  83. package/dist/{ssr-BiPRdZ6n.d.cts → ssr-Bli9XRW5.d.cts} +5 -0
  84. package/dist/{ssr-BiPRdZ6n.d.ts → ssr-Bli9XRW5.d.ts} +5 -0
  85. package/dist/{ssr-Y7XOEPEN.js → ssr-XOTUASDO.js} +4 -5
  86. package/dist/ssr.cjs +229 -84
  87. package/dist/ssr.d.cts +9 -3
  88. package/dist/ssr.d.ts +9 -3
  89. package/dist/ssr.js +11 -12
  90. package/dist/{startup-BMpaiMhP.d.ts → startup-BLfSeL15.d.cts} +73 -22
  91. package/dist/{startup-BMpaiMhP.d.cts → startup-BLfSeL15.d.ts} +73 -22
  92. package/dist/tagFactory-8qL9LCIx.d.cts +156 -0
  93. package/dist/tagFactory-BL2fymez.d.ts +156 -0
  94. package/dist/testing.cjs +2503 -2191
  95. package/dist/testing.d.cts +56 -5
  96. package/dist/testing.d.ts +56 -5
  97. package/dist/testing.js +580 -307
  98. package/dist/types-CJFViL6Q.d.cts +26 -0
  99. package/dist/types-CJFViL6Q.d.ts +26 -0
  100. package/dist/ui.cjs +732 -329
  101. package/dist/ui.d.cts +41 -7
  102. package/dist/ui.d.ts +41 -7
  103. package/dist/ui.js +151 -56
  104. package/dist/widgets.cjs +267 -291
  105. package/dist/widgets.js +9 -10
  106. package/package.json +4 -2
  107. package/dist/chunk-2WLZ6757.js +0 -149
  108. package/dist/chunk-CCSJMTRN.js +0 -15
  109. package/dist/chunk-QKRPLZ2V.js +0 -108
  110. package/dist/chunk-VUF4ALSW.js +0 -60
  111. package/dist/chunk-WWV3SJ3L.js +0 -131
  112. package/dist/dispose-46BOMMQJ.js +0 -19
  113. package/dist/plugin-D30wlGW5.d.cts +0 -71
  114. package/dist/plugin-D30wlGW5.d.ts +0 -71
  115. package/dist/tagFactory-DVoDpHye.d.cts +0 -215
  116. package/dist/tagFactory-DVoDpHye.d.ts +0 -215
@@ -135,42 +135,40 @@ import {
135
135
  use,
136
136
  var_,
137
137
  video
138
- } from "./chunk-PCT43HW3.js";
138
+ } from "./chunk-7LUJQAOJ.js";
139
139
  import {
140
140
  trustHTML
141
- } from "./chunk-NIOYEGBQ.js";
141
+ } from "./chunk-HURREPU2.js";
142
142
  import {
143
143
  watch
144
- } from "./chunk-7LN645I6.js";
144
+ } from "./chunk-SLM3IA34.js";
145
145
  import {
146
146
  __resetIdCounter,
147
- createId
148
- } from "./chunk-CCSJMTRN.js";
149
- import {
150
- context
151
- } from "./chunk-VUF4ALSW.js";
147
+ createId,
148
+ domBinding
149
+ } from "./chunk-BC2SECJD.js";
152
150
  import {
153
151
  SVG_NS,
154
152
  bindChildNode,
155
153
  captureFocusWithin,
156
154
  restoreFocusWithin,
157
155
  tagFactory
158
- } from "./chunk-KEISJXBU.js";
156
+ } from "./chunk-UOL2ECCS.js";
159
157
  import {
160
158
  bindAttribute,
161
159
  bindDynamic,
162
160
  setSafeAttribute
163
- } from "./chunk-ONOHFDLG.js";
161
+ } from "./chunk-FNJXNGYZ.js";
164
162
  import {
165
163
  derived
166
- } from "./chunk-RBTPLM32.js";
164
+ } from "./chunk-RUSSKG6G.js";
167
165
  import {
168
166
  globalSingleton
169
167
  } from "./chunk-7ZHH77QA.js";
170
168
  import {
171
169
  effect,
172
170
  on
173
- } from "./chunk-RIXRAYIU.js";
171
+ } from "./chunk-WEQ3DMVL.js";
174
172
  import {
175
173
  disableSSR,
176
174
  enableSSR,
@@ -179,24 +177,19 @@ import {
179
177
  isSSR,
180
178
  runInSSRContext,
181
179
  withSSR
182
- } from "./chunk-5DXA2J44.js";
180
+ } from "./chunk-7XHATCIH.js";
183
181
  import {
184
- MAX_DRAIN_TEARDOWNS,
185
- checkLeaks,
186
- dispose,
187
- registerDisposer,
188
- replaceChildrenSafely,
189
- reportDrainRunaway,
190
- unregisterDisposer
191
- } from "./chunk-QKRPLZ2V.js";
182
+ adoptThenable
183
+ } from "./chunk-5HZXGZ6T.js";
192
184
  import {
193
185
  batch,
194
186
  enqueueBatchedSignal,
195
187
  external,
196
188
  isBatching,
197
189
  signal
198
- } from "./chunk-XZZOBQAY.js";
190
+ } from "./chunk-FQRUXCEE.js";
199
191
  import {
192
+ emitDevtools,
200
193
  notifySubscribers,
201
194
  reactiveBinding,
202
195
  recordDependency,
@@ -206,19 +199,27 @@ import {
206
199
  suspendTracking,
207
200
  track,
208
201
  untracked
209
- } from "./chunk-UGRX3S57.js";
202
+ } from "./chunk-JWKYU5GV.js";
210
203
  import {
211
204
  DEV,
205
+ MAX_DRAIN_TEARDOWNS,
212
206
  __export,
207
+ checkLeaks,
213
208
  devAssert,
214
209
  devWarn,
215
210
  devWarnLazy,
211
+ dispose,
216
212
  getRuntimeErrorHandler,
217
213
  isDev,
218
214
  normalizeError,
215
+ registerDisposer,
216
+ replaceChildrenSafely,
217
+ reportDrainRunaway,
219
218
  reportError,
220
- setRuntimeErrorHandler
221
- } from "./chunk-2WLZ6757.js";
219
+ setRuntimeErrorHandler,
220
+ unregisterDisposer,
221
+ withDisposerRollback
222
+ } from "./chunk-NYNYSPK7.js";
222
223
 
223
224
  // index.ts
224
225
  var index_exports = {};
@@ -558,10 +559,13 @@ function safeCall(cb, hookName) {
558
559
  return void 0;
559
560
  }
560
561
  }
561
- function runMountCallback(callback, hookName, element) {
562
+ function runMountCallback(callback, hookName, element, isDisposed) {
562
563
  const cleanup = safeCall(callback, hookName);
563
- if (typeof cleanup === "function" && element) {
564
- registerDisposer(element, cleanup);
564
+ if (typeof cleanup !== "function") return;
565
+ if (isDisposed() || !element.isConnected) {
566
+ safeCall(cleanup, "onUnmount");
567
+ } else {
568
+ onUnmount(cleanup, element);
565
569
  }
566
570
  }
567
571
  var mountWatchers = /* @__PURE__ */ new WeakMap();
@@ -723,25 +727,26 @@ function onMount(callback, element) {
723
727
  if (typeof document === "undefined") return;
724
728
  if (element) {
725
729
  let disposed = false;
730
+ const isDisposed = () => disposed;
726
731
  registerDisposer(element, () => {
727
732
  disposed = true;
728
733
  });
729
734
  if (element.isConnected) {
730
735
  queueMicrotask(() => {
731
736
  if (disposed) return;
732
- runMountCallback(callback, "onMount", element);
737
+ runMountCallback(callback, "onMount", element, isDisposed);
733
738
  });
734
739
  return;
735
740
  }
736
741
  queueMicrotask(() => {
737
742
  if (disposed) return;
738
743
  if (element.isConnected) {
739
- runMountCallback(callback, "onMount", element);
744
+ runMountCallback(callback, "onMount", element, isDisposed);
740
745
  return;
741
746
  }
742
747
  const unregister = registerMountWatcher(element, () => {
743
748
  if (disposed) return;
744
- runMountCallback(callback, "onMount", element);
749
+ runMountCallback(callback, "onMount", element, isDisposed);
745
750
  });
746
751
  registerDisposer(element, unregister);
747
752
  });
@@ -1575,36 +1580,34 @@ function Loading(props = {}) {
1575
1580
  const { text: text2, variant = "spinner", size = "md" } = props;
1576
1581
  const sizeClass = size !== "md" ? ` sibu-loading-${size}` : "";
1577
1582
  if (variant === "dots") {
1578
- return div({
1583
+ return div(
1584
+ {
1585
+ class: `sibu-loading${sizeClass}`,
1586
+ role: "status",
1587
+ "aria-live": "polite",
1588
+ // When there's no visible text, give the live region an accessible name
1589
+ // so it isn't announced as an empty status.
1590
+ "aria-label": text2 ? void 0 : "Loading"
1591
+ },
1592
+ [
1593
+ div({ class: "sibu-loading-dots" }, [
1594
+ span({ class: "sibu-loading-dot" }),
1595
+ span({ class: "sibu-loading-dot" }),
1596
+ span({ class: "sibu-loading-dot" })
1597
+ ]),
1598
+ text2 ? span({ class: "sibu-loading-text" }, text2) : null
1599
+ ]
1600
+ );
1601
+ }
1602
+ return div(
1603
+ {
1579
1604
  class: `sibu-loading${sizeClass}`,
1580
1605
  role: "status",
1581
1606
  "aria-live": "polite",
1582
- // When there's no visible text, give the live region an accessible name
1583
- // so it isn't announced as an empty status.
1584
- "aria-label": text2 ? void 0 : "Loading",
1585
- nodes: [
1586
- div({
1587
- class: "sibu-loading-dots",
1588
- nodes: [
1589
- span({ class: "sibu-loading-dot" }),
1590
- span({ class: "sibu-loading-dot" }),
1591
- span({ class: "sibu-loading-dot" })
1592
- ]
1593
- }),
1594
- text2 ? span({ class: "sibu-loading-text", nodes: text2 }) : null
1595
- ].filter(Boolean)
1596
- });
1597
- }
1598
- return div({
1599
- class: `sibu-loading${sizeClass}`,
1600
- role: "status",
1601
- "aria-live": "polite",
1602
- "aria-label": text2 ? void 0 : "Loading",
1603
- nodes: [
1604
- div({ class: "sibu-loading-spinner" }),
1605
- text2 ? span({ class: "sibu-loading-text", nodes: text2 }) : null
1606
- ].filter(Boolean)
1607
- });
1607
+ "aria-label": text2 ? void 0 : "Loading"
1608
+ },
1609
+ [div({ class: "sibu-loading-spinner" }), text2 ? span({ class: "sibu-loading-text" }, text2) : null]
1610
+ );
1608
1611
  }
1609
1612
 
1610
1613
  // src/core/rendering/action.ts
@@ -1663,9 +1666,14 @@ var longPress = (element, options) => {
1663
1666
  };
1664
1667
  };
1665
1668
  var copyOnClick = (element, getText) => {
1669
+ const report = (error) => reportError(error, { phase: "async", name: "copyOnClick", node: element });
1666
1670
  const handler = () => {
1667
- const text2 = typeof getText === "function" ? getText() : element.textContent ?? "";
1668
- navigator.clipboard.writeText(text2);
1671
+ try {
1672
+ const text2 = typeof getText === "function" ? getText() : element.textContent ?? "";
1673
+ Promise.resolve(navigator.clipboard.writeText(text2)).catch(report);
1674
+ } catch (error) {
1675
+ report(error);
1676
+ }
1669
1677
  };
1670
1678
  element.addEventListener("click", handler);
1671
1679
  return () => element.removeEventListener("click", handler);
@@ -1710,8 +1718,9 @@ var globalErrorHandler = null;
1710
1718
  function catchError(fn, onError) {
1711
1719
  try {
1712
1720
  const result = fn();
1713
- if (result && typeof result.then === "function") {
1714
- result.catch((err) => {
1721
+ const adopted = adoptThenable(result);
1722
+ if (adopted) {
1723
+ adopted.then(void 0, (err) => {
1715
1724
  if (onError) {
1716
1725
  onError(err, "async");
1717
1726
  } else if (globalErrorHandler) {
@@ -1751,6 +1760,52 @@ function setGlobalErrorHandler(handler) {
1751
1760
  globalErrorHandler = handler;
1752
1761
  }
1753
1762
 
1763
+ // src/core/rendering/context.ts
1764
+ function context(defaultValue) {
1765
+ const [getValue, setValue] = signal(defaultValue);
1766
+ const warnIfSSR = (method) => {
1767
+ if (!DEV || !isSSR()) return;
1768
+ devWarn(
1769
+ `context.${method}() called during SSR. SibuJS context() is application-global \u2014 it is NOT isolated per request, so a concurrent request can observe this value. Do not use context() for request-specific SSR data; pass it explicitly or use request-scoped storage instead.`
1770
+ );
1771
+ };
1772
+ const ctx = {
1773
+ provide(value) {
1774
+ warnIfSSR("provide");
1775
+ const previous = getValue();
1776
+ setValue(value);
1777
+ return () => setValue(previous);
1778
+ },
1779
+ use() {
1780
+ return getValue;
1781
+ },
1782
+ get() {
1783
+ return getValue();
1784
+ },
1785
+ set(value) {
1786
+ warnIfSSR("set");
1787
+ setValue(value);
1788
+ },
1789
+ withContext(value, fn) {
1790
+ warnIfSSR("withContext");
1791
+ const previous = getValue();
1792
+ setValue(value);
1793
+ try {
1794
+ const result = fn();
1795
+ if (DEV && result !== null && typeof result?.then === "function") {
1796
+ devWarn(
1797
+ "context.withContext() received an async callback. Scoping is synchronous only \u2014 the previous value is restored as soon as the callback returns its promise, so anything after an `await` runs outside the scope."
1798
+ );
1799
+ }
1800
+ return result;
1801
+ } finally {
1802
+ setValue(previous);
1803
+ }
1804
+ }
1805
+ };
1806
+ return ctx;
1807
+ }
1808
+
1754
1809
  // src/core/rendering/directives.ts
1755
1810
  function show(condition, element) {
1756
1811
  const resolved = typeof element === "function" ? element() : element;
@@ -1781,13 +1836,15 @@ function when(condition, thenBranch, elseBranch) {
1781
1836
  let currentNode = null;
1782
1837
  let lastCondition;
1783
1838
  let initialized = false;
1839
+ let disposed = false;
1784
1840
  const attachedOnce = /* @__PURE__ */ new WeakSet();
1785
1841
  let currentNodeOwned = false;
1786
1842
  const update = () => {
1843
+ if (disposed) return;
1787
1844
  const show2 = condition();
1788
1845
  const parent = anchor.parentNode;
1789
1846
  if (!parent) return;
1790
- if (initialized && show2 === lastCondition) return;
1847
+ if (initialized && Object.is(show2, lastCondition)) return;
1791
1848
  lastCondition = show2;
1792
1849
  const focused = currentNode ? captureFocusWithin([currentNode]) : null;
1793
1850
  if (currentNode?.parentNode) {
@@ -1796,16 +1853,20 @@ function when(condition, thenBranch, elseBranch) {
1796
1853
  currentNode = null;
1797
1854
  }
1798
1855
  const branch = show2 ? thenBranch : elseBranch !== void 0 ? elseBranch : null;
1799
- const attached = attachBranch(parent, anchor, branch, attachedOnce, "when");
1856
+ const attached = untracked(() => attachBranch(parent, anchor, branch, attachedOnce, "when"));
1800
1857
  currentNode = attached.node;
1801
1858
  currentNodeOwned = attached.owned;
1802
1859
  restoreFocusWithin(focused, currentNode ? [currentNode] : [], "when");
1803
1860
  initialized = true;
1804
1861
  };
1805
- registerDisposer(anchor, reactiveBinding(update, anchor));
1862
+ const stopBinding = reactiveBinding(update, anchor);
1863
+ registerDisposer(anchor, () => {
1864
+ disposed = true;
1865
+ stopBinding();
1866
+ });
1806
1867
  if (!initialized) {
1807
1868
  queueMicrotask(() => {
1808
- if (!initialized && anchor.parentNode) update();
1869
+ if (!disposed && !initialized && anchor.parentNode) update();
1809
1870
  });
1810
1871
  }
1811
1872
  return anchor;
@@ -1815,9 +1876,11 @@ function match(value, cases, fallback) {
1815
1876
  let currentNode = null;
1816
1877
  let lastKey;
1817
1878
  let initialized = false;
1879
+ let disposed = false;
1818
1880
  const attachedOnce = /* @__PURE__ */ new WeakSet();
1819
1881
  let currentNodeOwned = false;
1820
1882
  const update = () => {
1883
+ if (disposed) return;
1821
1884
  const key = String(value());
1822
1885
  const parent = anchor.parentNode;
1823
1886
  if (!parent) return;
@@ -1830,46 +1893,66 @@ function match(value, cases, fallback) {
1830
1893
  currentNode = null;
1831
1894
  }
1832
1895
  const branch = Object.hasOwn(cases, key) ? cases[key] : fallback;
1833
- const attached = attachBranch(parent, anchor, branch ?? null, attachedOnce, "match");
1896
+ const attached = untracked(() => attachBranch(parent, anchor, branch ?? null, attachedOnce, "match"));
1834
1897
  currentNode = attached.node;
1835
1898
  currentNodeOwned = attached.owned;
1836
1899
  restoreFocusWithin(focused, currentNode ? [currentNode] : [], "match");
1837
1900
  initialized = true;
1838
1901
  };
1839
- registerDisposer(anchor, reactiveBinding(update, anchor));
1902
+ const stopBinding = reactiveBinding(update, anchor);
1903
+ registerDisposer(anchor, () => {
1904
+ disposed = true;
1905
+ stopBinding();
1906
+ });
1840
1907
  if (!initialized) {
1841
1908
  queueMicrotask(() => {
1842
- if (!initialized && anchor.parentNode) update();
1909
+ if (!disposed && !initialized && anchor.parentNode) update();
1843
1910
  });
1844
1911
  }
1845
1912
  return anchor;
1846
1913
  }
1847
1914
 
1848
1915
  // src/core/rendering/dynamic.ts
1849
- var componentRegistry = /* @__PURE__ */ new Map();
1916
+ var componentRegistry = globalSingleton(
1917
+ /* @__PURE__ */ Symbol.for("sibujs.components.registry.v1"),
1918
+ () => /* @__PURE__ */ new Map()
1919
+ );
1920
+ var registryVersion = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.components.registryVersion.v1"), () => signal(0));
1921
+ function bumpRegistry() {
1922
+ const [read, write] = registryVersion;
1923
+ write(untracked(read) + 1);
1924
+ }
1850
1925
  function registerComponent(name, component) {
1851
1926
  componentRegistry.set(name, component);
1927
+ bumpRegistry();
1852
1928
  }
1853
1929
  function unregisterComponent(name) {
1854
- componentRegistry.delete(name);
1930
+ if (componentRegistry.delete(name)) bumpRegistry();
1855
1931
  }
1856
1932
  function resolveComponent(name) {
1857
1933
  const component = componentRegistry.get(name);
1858
1934
  if (component) {
1859
1935
  return component();
1860
1936
  }
1861
- return div({ nodes: `[Component "${name}" not found]` });
1937
+ return div(`[Component "${name}" not found]`);
1862
1938
  }
1863
1939
  function DynamicComponent(is) {
1864
1940
  const container = div({ class: "sibu-dynamic" });
1941
+ const NONE = {};
1942
+ let shown = NONE;
1865
1943
  function render() {
1866
1944
  const target = is();
1867
- let el;
1945
+ let component;
1868
1946
  if (typeof target === "function") {
1869
- el = target();
1947
+ component = target;
1870
1948
  } else {
1871
- el = resolveComponent(target);
1949
+ registryVersion[0]();
1950
+ component = componentRegistry.get(target);
1872
1951
  }
1952
+ const next = component ?? `missing:${target}`;
1953
+ if (next === shown) return;
1954
+ const el = untracked(() => component ? component() : div(`[Component "${target}" not found]`));
1955
+ shown = next;
1873
1956
  replaceChildrenSafely(container, el);
1874
1957
  }
1875
1958
  const untrack = track(render);
@@ -2133,27 +2216,26 @@ function Fragment(nodes) {
2133
2216
  if (Array.isArray(child)) {
2134
2217
  for (const nested of child) {
2135
2218
  if (nested == null || typeof nested === "boolean") continue;
2136
- frag.appendChild(resolveChild(nested));
2219
+ appendChild(frag, nested);
2137
2220
  }
2138
2221
  } else {
2139
- frag.appendChild(resolveChild(child));
2222
+ appendChild(frag, child);
2140
2223
  }
2141
2224
  }
2142
2225
  return frag;
2143
2226
  }
2144
- function resolveChild(child) {
2145
- if (child == null) {
2146
- return document.createTextNode("");
2147
- }
2227
+ function appendChild(frag, child) {
2148
2228
  if (child instanceof Node) {
2149
- return child;
2229
+ frag.appendChild(child);
2230
+ return;
2150
2231
  }
2151
2232
  if (typeof child === "function") {
2152
- const result = child();
2153
- if (result instanceof Node) return result;
2154
- return document.createTextNode(String(result ?? ""));
2233
+ const placeholder = document.createComment("");
2234
+ frag.appendChild(placeholder);
2235
+ registerDisposer(placeholder, bindChildNode(placeholder, child));
2236
+ return;
2155
2237
  }
2156
- return document.createTextNode(String(child));
2238
+ frag.appendChild(document.createTextNode(String(child)));
2157
2239
  }
2158
2240
 
2159
2241
  // src/core/rendering/htm.ts
@@ -2623,25 +2705,77 @@ function mount(component, container) {
2623
2705
  typeof component === "function" || component instanceof Node,
2624
2706
  "mount: first argument must be a component function or a DOM Node."
2625
2707
  );
2626
- const startTime = typeof performance !== "undefined" ? performance.now() : 0;
2627
- const node = typeof component === "function" ? component() : component;
2628
- const duration = typeof performance !== "undefined" ? performance.now() - startTime : 0;
2629
- container.appendChild(node);
2630
- const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
2631
- if (hook) {
2632
- hook.emit("app:init", { rootElement: node, container, duration });
2708
+ const now = () => typeof performance !== "undefined" ? performance.now() : 0;
2709
+ const startTime = now();
2710
+ let range = null;
2711
+ const attach = (built) => {
2712
+ if (built instanceof DocumentFragment) {
2713
+ const start = document.createComment("");
2714
+ const end = document.createComment("");
2715
+ built.insertBefore(start, built.firstChild);
2716
+ built.appendChild(end);
2717
+ range = { start, end };
2718
+ }
2719
+ container.appendChild(built);
2720
+ };
2721
+ let node;
2722
+ if (typeof component === "function") {
2723
+ node = withDisposerRollback(() => {
2724
+ const built = component();
2725
+ attach(built);
2726
+ return built;
2727
+ });
2728
+ } else {
2729
+ node = component;
2730
+ attach(node);
2633
2731
  }
2732
+ const duration = now() - startTime;
2733
+ const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
2734
+ if (hook) emitDevtools(hook, "app:init", { rootElement: node, container, duration });
2735
+ const mounted = range;
2634
2736
  return {
2635
2737
  node,
2636
2738
  unmount() {
2637
- if (hook) hook.emit("app:unmount", { rootElement: node });
2638
- dispose(node);
2639
- if (node.parentNode) {
2640
- node.parentNode.removeChild(node);
2739
+ if (hook) emitDevtools(hook, "app:unmount", { rootElement: node });
2740
+ if (mounted) {
2741
+ unmountRange(mounted.start, mounted.end);
2742
+ return;
2641
2743
  }
2744
+ dispose(node);
2745
+ node.parentNode?.removeChild(node);
2642
2746
  }
2643
2747
  };
2644
2748
  }
2749
+ function unmountRange(start, end) {
2750
+ const parent = start.parentNode;
2751
+ if (!parent && !end.parentNode) return;
2752
+ let budget = MAX_DRAIN_TEARDOWNS;
2753
+ for (let n = start.nextSibling; n && n !== end; n = n.nextSibling) budget++;
2754
+ let before = start;
2755
+ let after = null;
2756
+ let intact = true;
2757
+ for (; ; ) {
2758
+ if (start.parentNode !== parent || end.parentNode !== parent) intact = false;
2759
+ else if (start.previousSibling !== before || end.nextSibling !== after) {
2760
+ before = start.previousSibling;
2761
+ after = end.nextSibling;
2762
+ intact = !!(start.compareDocumentPosition(end) & 4);
2763
+ }
2764
+ const n = start.nextSibling;
2765
+ if (!intact || n === end) break;
2766
+ if (budget-- <= 0) {
2767
+ reportDrainRunaway("mount", MAX_DRAIN_TEARDOWNS, 1);
2768
+ return;
2769
+ }
2770
+ dispose(n);
2771
+ if (n.parentNode === parent) parent.removeChild(n);
2772
+ }
2773
+ if (!intact) {
2774
+ reportError(new Error("[SibuJS mount] fragment markers lost"), { phase: "cleanup", name: "mount" });
2775
+ }
2776
+ start.parentNode?.removeChild(start);
2777
+ end.parentNode?.removeChild(end);
2778
+ }
2645
2779
 
2646
2780
  // src/core/rendering/portal.ts
2647
2781
  function Portal(nodes, target) {
@@ -2677,10 +2811,15 @@ function Portal(nodes, target) {
2677
2811
 
2678
2812
  // src/core/rendering/slots.ts
2679
2813
  function getSlot(slots, name = "default") {
2680
- return slots?.[name];
2814
+ if (slots == null || !Object.hasOwn(slots, name)) return void 0;
2815
+ const slot2 = slots[name];
2816
+ return typeof slot2 === "function" ? slot2 : void 0;
2681
2817
  }
2682
2818
 
2683
2819
  // src/core/signals/array.ts
2820
+ function nativeSplice(target, start, rest) {
2821
+ return rest.length === 0 ? target.splice(start) : target.splice(start, ...rest);
2822
+ }
2684
2823
  function array(initial = []) {
2685
2824
  const [arr, setArr] = signal([...initial]);
2686
2825
  const actions = {
@@ -2708,12 +2847,12 @@ function array(initial = []) {
2708
2847
  unshift(...items) {
2709
2848
  setArr((prev) => [...items, ...prev]);
2710
2849
  },
2711
- splice(start, deleteCount = 0, ...items) {
2850
+ splice(start, ...rest) {
2712
2851
  let removed = [];
2713
2852
  setArr((prev) => {
2714
2853
  const copy = [...prev];
2715
- removed = copy.splice(start, deleteCount, ...items);
2716
- return copy;
2854
+ removed = nativeSplice(copy, start, rest);
2855
+ return removed.length === 0 && rest.length <= 1 ? prev : copy;
2717
2856
  });
2718
2857
  return removed;
2719
2858
  },
@@ -2796,9 +2935,9 @@ function reactiveArray(initial = []) {
2796
2935
  data2.unshift(...items);
2797
2936
  notify();
2798
2937
  },
2799
- splice(start, deleteCount = 0, ...items) {
2800
- const removed = data2.splice(start, deleteCount, ...items);
2801
- if (removed.length > 0 || items.length > 0) {
2938
+ splice(start, ...rest) {
2939
+ const removed = nativeSplice(data2, start, rest);
2940
+ if (removed.length > 0 || rest.length > 1) {
2802
2941
  notify();
2803
2942
  }
2804
2943
  return removed;
@@ -3020,6 +3159,21 @@ function deepEqual(a2, b2, seen) {
3020
3159
  if (a2.length !== b2.length) return false;
3021
3160
  return a2.every((val, i2) => deepEqual(val, b2[i2], seen));
3022
3161
  }
3162
+ if (a2 instanceof Number || a2 instanceof String || a2 instanceof Boolean) {
3163
+ return Object.is(a2.valueOf(), b2.valueOf());
3164
+ }
3165
+ if (typeof URL !== "undefined" && a2 instanceof URL) {
3166
+ return a2.href === b2.href;
3167
+ }
3168
+ if (a2 instanceof Error) {
3169
+ const eb = b2;
3170
+ return a2.name === eb.name && a2.message === eb.message && deepEqual(a2.cause, eb.cause, seen) && plainKeysEqual(objA, objB, seen);
3171
+ }
3172
+ const proto = Object.getPrototypeOf(objA);
3173
+ if (proto !== Object.prototype && proto !== null) return false;
3174
+ return plainKeysEqual(objA, objB, seen);
3175
+ }
3176
+ function plainKeysEqual(objA, objB, seen) {
3023
3177
  const keysA = Object.keys(objA);
3024
3178
  const keysB = Object.keys(objB);
3025
3179
  if (keysA.length !== keysB.length) return false;
@@ -3045,15 +3199,18 @@ function ref(initial) {
3045
3199
  }
3046
3200
 
3047
3201
  // src/core/signals/store.ts
3202
+ function defineOwn(obj, key, value) {
3203
+ Object.defineProperty(obj, key, { value, writable: true, enumerable: true, configurable: true });
3204
+ }
3048
3205
  function store(initialState) {
3049
3206
  devAssert(
3050
3207
  initialState !== null && typeof initialState === "object" && !Array.isArray(initialState),
3051
3208
  "store: argument must be a plain object. For arrays, use array() instead."
3052
3209
  );
3053
- const signals = {};
3210
+ const signals = /* @__PURE__ */ Object.create(null);
3054
3211
  Object.keys(initialState).forEach((key) => {
3055
3212
  const [getter, setter] = signal(initialState[key]);
3056
- signals[key] = [getter, setter];
3213
+ defineOwn(signals, key, [getter, setter]);
3057
3214
  });
3058
3215
  const store2 = new Proxy({}, {
3059
3216
  get(target, prop) {
@@ -3072,7 +3229,7 @@ function store(initialState) {
3072
3229
  const getSnapshot = () => {
3073
3230
  const snapshot = {};
3074
3231
  Object.keys(signals).forEach((key) => {
3075
- snapshot[key] = signals[key][0]();
3232
+ defineOwn(snapshot, key, signals[key][0]());
3076
3233
  });
3077
3234
  return snapshot;
3078
3235
  };
@@ -3213,9 +3370,7 @@ function resolveTarget(root, target) {
3213
3370
  }
3214
3371
  }
3215
3372
  function bindNode(el, commit) {
3216
- if (isSSR()) return () => {
3217
- };
3218
- return reactiveBinding(commit, el);
3373
+ return domBinding(commit, el);
3219
3374
  }
3220
3375
  function readControlValue(el) {
3221
3376
  if (el instanceof HTMLInputElement) {
@@ -3672,23 +3827,27 @@ function scheduleIdle(fn) {
3672
3827
  }
3673
3828
  function transition() {
3674
3829
  const [pending, setPending] = signal(false);
3830
+ let outstanding = 0;
3675
3831
  function start(fn) {
3832
+ outstanding++;
3676
3833
  setPending(true);
3834
+ let settled = false;
3835
+ const finish = () => {
3836
+ if (settled) return;
3837
+ settled = true;
3838
+ outstanding--;
3839
+ if (outstanding === 0) setPending(false);
3840
+ };
3841
+ const fail = (error) => {
3842
+ finish();
3843
+ reportError(error, { phase: "async", name: "transition" });
3844
+ };
3677
3845
  scheduleIdle(() => {
3678
- let result;
3679
3846
  try {
3680
- result = fn();
3681
- } catch {
3682
- setPending(false);
3683
- return;
3684
- }
3685
- if (result && typeof result.then === "function") {
3686
- result.then(
3687
- () => setPending(false),
3688
- () => setPending(false)
3689
- );
3690
- } else {
3691
- setPending(false);
3847
+ const adopted = adoptThenable(fn());
3848
+ adopted ? adopted.then(finish, fail) : finish();
3849
+ } catch (error) {
3850
+ fail(error);
3692
3851
  }
3693
3852
  });
3694
3853
  }
@@ -3729,6 +3888,7 @@ export {
3729
3888
  catchError,
3730
3889
  catchErrorAsync,
3731
3890
  setGlobalErrorHandler,
3891
+ context,
3732
3892
  show,
3733
3893
  when,
3734
3894
  match,