sibujs 3.3.0 → 3.3.1

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 (54) hide show
  1. package/dist/browser.cjs +210 -26
  2. package/dist/browser.js +4 -4
  3. package/dist/build.cjs +193 -89
  4. package/dist/build.js +10 -10
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-24DBWDTK.js → chunk-37BUKSLH.js} +1 -1
  7. package/dist/{chunk-IHBVTURX.js → chunk-4UUMSLSL.js} +4 -4
  8. package/dist/{chunk-USDR2GFV.js → chunk-6LTFHJQG.js} +3 -3
  9. package/dist/{chunk-MWZFOIBG.js → chunk-AMIKDMLP.js} +4 -4
  10. package/dist/{chunk-JBXNCZSC.js → chunk-F7FXQ3QS.js} +1 -1
  11. package/dist/{chunk-BEIKESVL.js → chunk-IKLYI3RF.js} +9 -9
  12. package/dist/{chunk-NUWKIEHE.js → chunk-LU2MQXQQ.js} +2 -2
  13. package/dist/{chunk-WVJJUFPC.js → chunk-M5KBNOSJ.js} +2 -2
  14. package/dist/{chunk-7JHWAGRQ.js → chunk-MHBCEJQO.js} +1 -1
  15. package/dist/{chunk-Q2ERM6NT.js → chunk-NHKQKKZU.js} +1 -1
  16. package/dist/{chunk-6G6UNHZI.js → chunk-RYMOSG5B.js} +5 -5
  17. package/dist/{chunk-F4UM7QBJ.js → chunk-SLMFA3ZZ.js} +1 -1
  18. package/dist/{chunk-X3NHE2DK.js → chunk-TEFZT5PJ.js} +83 -17
  19. package/dist/{chunk-SLCUP2EK.js → chunk-ULLTNDRA.js} +3 -3
  20. package/dist/{chunk-M6WSIGYW.js → chunk-VOVVTOEA.js} +2 -2
  21. package/dist/{chunk-XQ7XSGYP.js → chunk-WL7BIR6O.js} +1 -1
  22. package/dist/{chunk-CVMMULHO.js → chunk-WW6DAGGR.js} +4 -4
  23. package/dist/{chunk-5K72I3UQ.js → chunk-WZG2SZOT.js} +21 -4
  24. package/dist/{chunk-S4FHR5ZZ.js → chunk-XH2RTYEQ.js} +3 -3
  25. package/dist/{chunk-4WXWJ4SW.js → chunk-Z37APKBV.js} +4 -4
  26. package/dist/data.cjs +161 -23
  27. package/dist/data.js +6 -6
  28. package/dist/devtools.cjs +245 -31
  29. package/dist/devtools.js +4 -4
  30. package/dist/ecosystem.cjs +183 -45
  31. package/dist/ecosystem.js +7 -7
  32. package/dist/extras.cjs +185 -86
  33. package/dist/extras.js +19 -19
  34. package/dist/index.cjs +193 -89
  35. package/dist/index.d.cts +59 -8
  36. package/dist/index.d.ts +59 -8
  37. package/dist/index.js +10 -10
  38. package/dist/motion.cjs +329 -13
  39. package/dist/motion.js +3 -3
  40. package/dist/patterns.cjs +161 -23
  41. package/dist/patterns.js +5 -5
  42. package/dist/performance.cjs +258 -23
  43. package/dist/performance.js +4 -4
  44. package/dist/plugins.cjs +244 -51
  45. package/dist/plugins.js +6 -6
  46. package/dist/ssr.cjs +183 -44
  47. package/dist/ssr.js +7 -7
  48. package/dist/testing.cjs +396 -5
  49. package/dist/testing.js +2 -2
  50. package/dist/ui.cjs +221 -32
  51. package/dist/ui.js +6 -6
  52. package/dist/widgets.cjs +146 -26
  53. package/dist/widgets.js +6 -6
  54. package/package.json +1 -1
package/dist/build.cjs CHANGED
@@ -1207,7 +1207,7 @@ __export(index_exports, {
1207
1207
  registerComponent: () => registerComponent,
1208
1208
  registerDisposer: () => registerDisposer,
1209
1209
  resolveComponent: () => resolveComponent,
1210
- retrack: () => retrack,
1210
+ retrack: () => retrack2,
1211
1211
  rp: () => rp,
1212
1212
  rt: () => rt,
1213
1213
  ruby: () => ruby,
@@ -1218,7 +1218,7 @@ __export(index_exports, {
1218
1218
  section: () => section,
1219
1219
  select: () => select,
1220
1220
  setGlobalErrorHandler: () => setGlobalErrorHandler,
1221
- setMaxDrainIterations: () => setMaxDrainIterations,
1221
+ setMaxDrainIterations: () => setMaxDrainIterations2,
1222
1222
  show: () => show,
1223
1223
  signal: () => signal,
1224
1224
  slot: () => slot,
@@ -1250,7 +1250,7 @@ __export(index_exports, {
1250
1250
  time: () => time,
1251
1251
  title: () => title,
1252
1252
  tr: () => tr,
1253
- track: () => track2,
1253
+ track: () => track3,
1254
1254
  transition: () => transition,
1255
1255
  trapFocus: () => trapFocus,
1256
1256
  trustHTML: () => trustHTML,
@@ -1258,7 +1258,7 @@ __export(index_exports, {
1258
1258
  u: () => u,
1259
1259
  ul: () => ul,
1260
1260
  unregisterComponent: () => unregisterComponent,
1261
- untracked: () => untracked,
1261
+ untracked: () => untracked2,
1262
1262
  use: () => use,
1263
1263
  var_: () => var_,
1264
1264
  video: () => video,
@@ -1375,7 +1375,7 @@ function sanitizeAttributeString(attr, value) {
1375
1375
  return value;
1376
1376
  }
1377
1377
 
1378
- // src/reactivity/track.ts
1378
+ // src/reactivity/track-core.ts
1379
1379
  var _isDev2 = isDev();
1380
1380
  var POOL_MAX = 4096;
1381
1381
  var nodePool = [];
@@ -1489,6 +1489,9 @@ function resumeTracking() {
1489
1489
  trackingSuspended = false;
1490
1490
  }
1491
1491
  }
1492
+ function isTrackingSuspended() {
1493
+ return trackingSuspended;
1494
+ }
1492
1495
  function untracked(fn) {
1493
1496
  suspendTracking();
1494
1497
  try {
@@ -1606,6 +1609,11 @@ function cleanup(subscriber) {
1606
1609
  var maxSubscriberRepeats = 50;
1607
1610
  var maxDrainIterations = 1e6;
1608
1611
  var drainEpoch = 0;
1612
+ function setMaxSubscriberRepeats(n) {
1613
+ const prev = maxSubscriberRepeats;
1614
+ if (Number.isFinite(n) && n > 0) maxSubscriberRepeats = Math.floor(n);
1615
+ return prev;
1616
+ }
1609
1617
  function setMaxDrainIterations(n) {
1610
1618
  const prev = maxDrainIterations;
1611
1619
  if (Number.isFinite(n) && n > 0) maxDrainIterations = Math.floor(n);
@@ -1759,15 +1767,94 @@ function notifySubscribers(signal2) {
1759
1767
  }
1760
1768
  }
1761
1769
  }
1770
+ function getSubscriberCount(signal2) {
1771
+ return signal2.__sc ?? 0;
1772
+ }
1773
+ function getSubscriberDeps(subscriber) {
1774
+ const sub2 = subscriber;
1775
+ const out = [];
1776
+ let node = sub2.depsHead ?? null;
1777
+ while (node) {
1778
+ if (node.sig) out.push(node.sig);
1779
+ node = node.subNext;
1780
+ }
1781
+ return out;
1782
+ }
1783
+ function forEachSubscriber(signal2, visit) {
1784
+ let node = signal2.subsHead ?? null;
1785
+ while (node) {
1786
+ const s2 = node.sub;
1787
+ if (s2) visit(s2);
1788
+ node = node.sigNext;
1789
+ }
1790
+ }
1762
1791
 
1763
- // src/reactivity/bindAttribute.ts
1792
+ // src/reactivity/track.ts
1764
1793
  var _isDev3 = isDev();
1794
+ var _runtimeVersion = typeof __SIBU_VERSION__ !== "undefined" ? __SIBU_VERSION__ : "dev";
1795
+ var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
1796
+ function resolveReactiveApi() {
1797
+ const g2 = globalThis;
1798
+ const existing = g2[REGISTRY_KEY];
1799
+ if (existing) {
1800
+ if (_isDev3 && !existing.__dupWarned) {
1801
+ existing.__dupWarned = true;
1802
+ devWarn(
1803
+ `Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity still works \u2014 all copies share the first one \u2014 but de-duplicate sibujs in your bundler (e.g. Vite optimizeDeps.exclude: ['sibujs'] or resolve.dedupe: ['sibujs']).`
1804
+ );
1805
+ }
1806
+ return existing;
1807
+ }
1808
+ const local = {
1809
+ suspendTracking,
1810
+ resumeTracking,
1811
+ isTrackingSuspended,
1812
+ untracked,
1813
+ retrack,
1814
+ track,
1815
+ reactiveBinding,
1816
+ recordDependency,
1817
+ cleanup,
1818
+ setMaxSubscriberRepeats,
1819
+ setMaxDrainIterations,
1820
+ drainNotificationQueue,
1821
+ queueSignalNotification,
1822
+ notifySubscribers,
1823
+ getSubscriberCount,
1824
+ getSubscriberDeps,
1825
+ forEachSubscriber,
1826
+ version: _runtimeVersion
1827
+ };
1828
+ g2[REGISTRY_KEY] = local;
1829
+ return local;
1830
+ }
1831
+ var API = resolveReactiveApi();
1832
+ var suspendTracking2 = API.suspendTracking;
1833
+ var resumeTracking2 = API.resumeTracking;
1834
+ var isTrackingSuspended2 = API.isTrackingSuspended;
1835
+ var untracked2 = API.untracked;
1836
+ var retrack2 = API.retrack;
1837
+ var track2 = API.track;
1838
+ var reactiveBinding2 = API.reactiveBinding;
1839
+ var recordDependency2 = API.recordDependency;
1840
+ var cleanup2 = API.cleanup;
1841
+ var setMaxSubscriberRepeats2 = API.setMaxSubscriberRepeats;
1842
+ var setMaxDrainIterations2 = API.setMaxDrainIterations;
1843
+ var drainNotificationQueue2 = API.drainNotificationQueue;
1844
+ var queueSignalNotification2 = API.queueSignalNotification;
1845
+ var notifySubscribers2 = API.notifySubscribers;
1846
+ var getSubscriberCount2 = API.getSubscriberCount;
1847
+ var getSubscriberDeps2 = API.getSubscriberDeps;
1848
+ var forEachSubscriber2 = API.forEachSubscriber;
1849
+
1850
+ // src/reactivity/bindAttribute.ts
1851
+ var _isDev4 = isDev();
1765
1852
  function setProp(el, key, val) {
1766
1853
  el[key] = val;
1767
1854
  }
1768
1855
  function bindAttribute(el, attr, getter) {
1769
1856
  if (isEventHandlerAttr(attr)) {
1770
- if (_isDev3)
1857
+ if (_isDev4)
1771
1858
  devWarn(
1772
1859
  `bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
1773
1860
  );
@@ -1779,7 +1866,7 @@ function bindAttribute(el, attr, getter) {
1779
1866
  try {
1780
1867
  value = getter();
1781
1868
  } catch (err) {
1782
- if (_isDev3)
1869
+ if (_isDev4)
1783
1870
  devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
1784
1871
  return;
1785
1872
  }
@@ -1800,7 +1887,7 @@ function bindAttribute(el, attr, getter) {
1800
1887
  el.setAttribute(attr, sanitizeAttributeString(attr, str));
1801
1888
  }
1802
1889
  }
1803
- return reactiveBinding(commit);
1890
+ return reactiveBinding2(commit);
1804
1891
  }
1805
1892
  function bindDynamic(el, nameGetter, valueGetter) {
1806
1893
  let prevName = null;
@@ -1809,14 +1896,14 @@ function bindDynamic(el, nameGetter, valueGetter) {
1809
1896
  try {
1810
1897
  name = typeof nameGetter === "function" ? nameGetter() : nameGetter;
1811
1898
  } catch (err) {
1812
- if (_isDev3) devWarn(`bindDynamic: name getter threw: ${err instanceof Error ? err.message : String(err)}`);
1899
+ if (_isDev4) devWarn(`bindDynamic: name getter threw: ${err instanceof Error ? err.message : String(err)}`);
1813
1900
  return;
1814
1901
  }
1815
1902
  let value;
1816
1903
  try {
1817
1904
  value = typeof valueGetter === "function" ? valueGetter() : valueGetter;
1818
1905
  } catch (err) {
1819
- if (_isDev3) devWarn(`bindDynamic: value getter threw: ${err instanceof Error ? err.message : String(err)}`);
1906
+ if (_isDev4) devWarn(`bindDynamic: value getter threw: ${err instanceof Error ? err.message : String(err)}`);
1820
1907
  return;
1821
1908
  }
1822
1909
  if (isEventHandlerAttr(name)) return;
@@ -1831,7 +1918,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
1831
1918
  }
1832
1919
  prevName = name;
1833
1920
  }
1834
- const teardown = reactiveBinding(commit);
1921
+ const teardown = reactiveBinding2(commit);
1835
1922
  return () => {
1836
1923
  teardown();
1837
1924
  if (prevName !== null) {
@@ -1842,7 +1929,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
1842
1929
 
1843
1930
  // src/core/rendering/dispose.ts
1844
1931
  var elementDisposers = /* @__PURE__ */ new WeakMap();
1845
- var _isDev4 = isDev();
1932
+ var _isDev5 = isDev();
1846
1933
  var activeBindingCount = 0;
1847
1934
  function registerDisposer(node, teardown) {
1848
1935
  let disposers = elementDisposers.get(node);
@@ -1851,7 +1938,7 @@ function registerDisposer(node, teardown) {
1851
1938
  elementDisposers.set(node, disposers);
1852
1939
  }
1853
1940
  disposers.push(teardown);
1854
- if (_isDev4) activeBindingCount++;
1941
+ if (_isDev5) activeBindingCount++;
1855
1942
  }
1856
1943
  function dispose(node) {
1857
1944
  const stack = [node];
@@ -1870,12 +1957,12 @@ function dispose(node) {
1870
1957
  if (disposers) {
1871
1958
  const snapshot = disposers.slice();
1872
1959
  elementDisposers.delete(current);
1873
- if (_isDev4) activeBindingCount -= snapshot.length;
1960
+ if (_isDev5) activeBindingCount -= snapshot.length;
1874
1961
  for (const d of snapshot) {
1875
1962
  try {
1876
1963
  d();
1877
1964
  } catch (err) {
1878
- if (_isDev4 && typeof console !== "undefined") {
1965
+ if (_isDev5 && typeof console !== "undefined") {
1879
1966
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
1880
1967
  }
1881
1968
  }
@@ -1886,12 +1973,12 @@ function dispose(node) {
1886
1973
  if (!added || added.length === 0) break;
1887
1974
  const moreSnapshot = added.slice();
1888
1975
  elementDisposers.delete(current);
1889
- if (_isDev4) activeBindingCount -= moreSnapshot.length;
1976
+ if (_isDev5) activeBindingCount -= moreSnapshot.length;
1890
1977
  for (const d of moreSnapshot) {
1891
1978
  try {
1892
1979
  d();
1893
1980
  } catch (err) {
1894
- if (_isDev4 && typeof console !== "undefined") {
1981
+ if (_isDev5 && typeof console !== "undefined") {
1895
1982
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
1896
1983
  }
1897
1984
  }
@@ -1901,7 +1988,7 @@ function dispose(node) {
1901
1988
  }
1902
1989
  }
1903
1990
  function checkLeaks(warnThreshold = 0) {
1904
- if (!_isDev4) return 0;
1991
+ if (!_isDev5) return 0;
1905
1992
  if (warnThreshold > 0 && activeBindingCount > warnThreshold) {
1906
1993
  devWarn(
1907
1994
  `checkLeaks: ${activeBindingCount} active DOM bindings detected. Expected \u2264${warnThreshold}. This may indicate a component was removed from the DOM without calling dispose().`
@@ -1911,7 +1998,7 @@ function checkLeaks(warnThreshold = 0) {
1911
1998
  }
1912
1999
 
1913
2000
  // src/reactivity/bindChildNode.ts
1914
- var _isDev5 = isDev();
2001
+ var _isDev6 = isDev();
1915
2002
  function bindChildNode(placeholder, getter) {
1916
2003
  let lastNodes = [];
1917
2004
  function commit() {
@@ -1919,7 +2006,7 @@ function bindChildNode(placeholder, getter) {
1919
2006
  try {
1920
2007
  result = getter();
1921
2008
  } catch (err) {
1922
- if (_isDev5) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
2009
+ if (_isDev6) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
1923
2010
  return;
1924
2011
  }
1925
2012
  if (result == null || typeof result === "boolean") {
@@ -1945,7 +2032,7 @@ function bindChildNode(placeholder, getter) {
1945
2032
  if (item == null || typeof item === "boolean") continue;
1946
2033
  const node = item instanceof Node ? item : document.createTextNode(String(item));
1947
2034
  if (seen.has(node)) {
1948
- if (_isDev5)
2035
+ if (_isDev6)
1949
2036
  devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
1950
2037
  continue;
1951
2038
  }
@@ -1980,12 +2067,12 @@ function bindChildNode(placeholder, getter) {
1980
2067
  }
1981
2068
  lastNodes = newNodes;
1982
2069
  }
1983
- return reactiveBinding(commit);
2070
+ return reactiveBinding2(commit);
1984
2071
  }
1985
2072
 
1986
2073
  // src/core/rendering/tagFactory.ts
1987
2074
  var SVG_NS = "http://www.w3.org/2000/svg";
1988
- var _isDev6 = isDev();
2075
+ var _isDev7 = isDev();
1989
2076
  var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
1990
2077
  function isBlockedTag(tag) {
1991
2078
  return BLOCKED_TAGS.has(tag.toLowerCase());
@@ -2028,7 +2115,7 @@ function toKebab(prop) {
2028
2115
  }
2029
2116
  function applyStyle(el, style2) {
2030
2117
  if (typeof style2 === "function") {
2031
- const teardown = track(() => {
2118
+ const teardown = track2(() => {
2032
2119
  el.setAttribute("style", style2());
2033
2120
  });
2034
2121
  registerDisposer(el, teardown);
@@ -2044,7 +2131,7 @@ function applyStyle(el, style2) {
2044
2131
  const name = toKebab(prop);
2045
2132
  if (typeof val === "function") {
2046
2133
  const getter = val;
2047
- const teardown = track(() => {
2134
+ const teardown = track2(() => {
2048
2135
  htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
2049
2136
  });
2050
2137
  registerDisposer(el, teardown);
@@ -2059,7 +2146,7 @@ function applyClass(el, cls) {
2059
2146
  return;
2060
2147
  }
2061
2148
  if (typeof cls === "function") {
2062
- const teardown = track(() => {
2149
+ const teardown = track2(() => {
2063
2150
  el.setAttribute("class", cls());
2064
2151
  });
2065
2152
  registerDisposer(el, teardown);
@@ -2086,7 +2173,7 @@ function applyClass(el, cls) {
2086
2173
  }
2087
2174
  el.setAttribute("class", r);
2088
2175
  };
2089
- const teardown = track(update);
2176
+ const teardown = track2(update);
2090
2177
  registerDisposer(el, teardown);
2091
2178
  } else {
2092
2179
  el.setAttribute("class", result);
@@ -2156,7 +2243,7 @@ var tagFactory = (tag, ns) => {
2156
2243
  appendChildren(el, second);
2157
2244
  return el;
2158
2245
  }
2159
- if (_isDev6 && looksLikeClassList(first)) {
2246
+ if (_isDev7 && looksLikeClassList(first)) {
2160
2247
  devWarn(
2161
2248
  `tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`
2162
2249
  );
@@ -2177,7 +2264,7 @@ var tagFactory = (tag, ns) => {
2177
2264
  if (pClass != null) applyClass(el, pClass);
2178
2265
  const pId = props.id;
2179
2266
  if (pId != null) {
2180
- if (_isDev6 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
2267
+ if (_isDev7 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
2181
2268
  devWarn(
2182
2269
  `tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
2183
2270
  );
@@ -2192,7 +2279,7 @@ var tagFactory = (tag, ns) => {
2192
2279
  const handler = pOn[ev];
2193
2280
  if (typeof handler === "function") {
2194
2281
  el.addEventListener(ev, handler);
2195
- } else if (_isDev6) {
2282
+ } else if (_isDev7) {
2196
2283
  devWarn(
2197
2284
  `tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
2198
2285
  );
@@ -2305,7 +2392,7 @@ var area = tagFactory("area");
2305
2392
  var audio = tagFactory("audio");
2306
2393
  var img = tagFactory("img");
2307
2394
  var map = tagFactory("map");
2308
- var track2 = tagFactory("track");
2395
+ var track3 = tagFactory("track");
2309
2396
  var video = tagFactory("video");
2310
2397
  var embed = tagFactory("embed");
2311
2398
  var iframe = tagFactory("iframe");
@@ -2381,7 +2468,7 @@ var marquee = tagFactory("marquee");
2381
2468
  var customElement = (tagName) => tagFactory(tagName);
2382
2469
 
2383
2470
  // src/core/rendering/htm.ts
2384
- var _isDev7 = isDev();
2471
+ var _isDev8 = isDev();
2385
2472
  var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
2386
2473
  var VOID_ELEMENTS3 = /* @__PURE__ */ new Set([
2387
2474
  "area",
@@ -2677,7 +2764,7 @@ function executeElement(tmpl, values) {
2677
2764
  const fn = values[attr.idx];
2678
2765
  if (typeof fn === "function") {
2679
2766
  el.addEventListener(attr.name, fn);
2680
- } else if (_isDev7) {
2767
+ } else if (_isDev8) {
2681
2768
  devWarn(
2682
2769
  `html: on:${attr.name} handler is not a function (got ${typeof fn}). Event listener was not attached.`
2683
2770
  );
@@ -2805,7 +2892,7 @@ function mount(component, container) {
2805
2892
  }
2806
2893
 
2807
2894
  // src/core/rendering/each.ts
2808
- var _isDev8 = isDev();
2895
+ var _isDev9 = isDev();
2809
2896
  function resolveNodeChild(child) {
2810
2897
  if (typeof child === "function") {
2811
2898
  return resolveNodeChild(child());
@@ -2890,7 +2977,7 @@ function each(getArray, render, options) {
2890
2977
  workMap.clear();
2891
2978
  keyIndexMap.clear();
2892
2979
  for (let i2 = 0; i2 < newLen; i2++) {
2893
- if (_isDev8 && keyIndexMap.has(newKeys[i2])) {
2980
+ if (_isDev9 && keyIndexMap.has(newKeys[i2])) {
2894
2981
  devWarn(
2895
2982
  `each: duplicate key "${String(newKeys[i2])}" at index ${i2} (first seen at ${keyIndexMap.get(newKeys[i2])}). Keys must be unique \u2014 duplicates cause rows to be dropped or mis-ordered.`
2896
2983
  );
@@ -2905,12 +2992,12 @@ function each(getArray, render, options) {
2905
2992
  node = existing;
2906
2993
  } else {
2907
2994
  const itemKey = key;
2908
- const itemGetter = () => untracked(() => getArray()[keyIndexMap.get(itemKey)]);
2995
+ const itemGetter = () => untracked2(() => getArray()[keyIndexMap.get(itemKey)]);
2909
2996
  const indexGetter = () => keyIndexMap.get(itemKey);
2910
2997
  try {
2911
2998
  node = resolveNodeChild(render(itemGetter, indexGetter));
2912
2999
  } catch (err) {
2913
- if (_isDev8) {
3000
+ if (_isDev9) {
2914
3001
  devWarn(
2915
3002
  `each: render threw for item at index ${i2} (key="${newKeys[i2]}"): ${err instanceof Error ? err.message : String(err)}`
2916
3003
  );
@@ -2924,7 +3011,7 @@ function each(getArray, render, options) {
2924
3011
  target.dispatchEvent(
2925
3012
  new CustomEvent("sibu:error-propagate", { bubbles: true, detail: { error: errorObj } })
2926
3013
  );
2927
- } else if (_isDev8) {
3014
+ } else if (_isDev9) {
2928
3015
  devWarn(`each: error not surfaced \u2014 anchor detached: ${errorObj.message}`);
2929
3016
  }
2930
3017
  } catch {
@@ -2998,7 +3085,7 @@ function each(getArray, render, options) {
2998
3085
  workMap = tmp;
2999
3086
  initialized = true;
3000
3087
  };
3001
- const untrack = track(update);
3088
+ const untrack = track2(update);
3002
3089
  registerDisposer(anchor, untrack);
3003
3090
  if (!initialized) {
3004
3091
  queueMicrotask(() => {
@@ -3111,7 +3198,7 @@ function DynamicComponent(is) {
3111
3198
  }
3112
3199
  container.replaceChildren(el);
3113
3200
  }
3114
- const untrack = track(render);
3201
+ const untrack = track2(render);
3115
3202
  registerDisposer(container, untrack);
3116
3203
  return container;
3117
3204
  }
@@ -3126,7 +3213,7 @@ function show(condition, element) {
3126
3213
  const update = () => {
3127
3214
  element.style.display = condition() ? "" : "none";
3128
3215
  };
3129
- registerDisposer(element, track(update));
3216
+ registerDisposer(element, track2(update));
3130
3217
  return element;
3131
3218
  }
3132
3219
  function when(condition, thenBranch, elseBranch) {
@@ -3153,7 +3240,7 @@ function when(condition, thenBranch, elseBranch) {
3153
3240
  }
3154
3241
  initialized = true;
3155
3242
  };
3156
- registerDisposer(anchor, track(update));
3243
+ registerDisposer(anchor, track2(update));
3157
3244
  if (!initialized) {
3158
3245
  queueMicrotask(() => {
3159
3246
  if (!initialized && anchor.parentNode) update();
@@ -3188,7 +3275,7 @@ function match(value, cases, fallback) {
3188
3275
  }
3189
3276
  initialized = true;
3190
3277
  };
3191
- registerDisposer(anchor, track(update));
3278
+ registerDisposer(anchor, track2(update));
3192
3279
  if (!initialized) {
3193
3280
  queueMicrotask(() => {
3194
3281
  if (!initialized && anchor.parentNode) update();
@@ -3257,7 +3344,7 @@ function KeepAlive(activeKey, cases, options) {
3257
3344
  currentNode = node;
3258
3345
  initialized = true;
3259
3346
  };
3260
- const untrack = track(update);
3347
+ const untrack = track2(update);
3261
3348
  if (!initialized) {
3262
3349
  queueMicrotask(() => {
3263
3350
  if (!initialized && anchor.parentNode) update();
@@ -3279,9 +3366,9 @@ function KeepAlive(activeKey, cases, options) {
3279
3366
 
3280
3367
  // src/core/rendering/action.ts
3281
3368
  function action(element, actionFn, param2) {
3282
- const cleanup2 = actionFn(element, param2);
3283
- if (typeof cleanup2 === "function") {
3284
- registerDisposer(element, cleanup2);
3369
+ const cleanup3 = actionFn(element, param2);
3370
+ if (typeof cleanup3 === "function") {
3371
+ registerDisposer(element, cleanup3);
3285
3372
  }
3286
3373
  }
3287
3374
  var clickOutside = (element, callback) => {
@@ -3415,7 +3502,7 @@ function __resetIdCounter() {
3415
3502
  // src/reactivity/batch.ts
3416
3503
  var batchDepth = 0;
3417
3504
  var pendingSignals = /* @__PURE__ */ new Set();
3418
- function batch(fn) {
3505
+ function batchImpl(fn) {
3419
3506
  batchDepth++;
3420
3507
  try {
3421
3508
  return fn();
@@ -3426,28 +3513,45 @@ function batch(fn) {
3426
3513
  }
3427
3514
  }
3428
3515
  }
3429
- function enqueueBatchedSignal(signal2) {
3516
+ function enqueueBatchedSignalImpl(signal2) {
3430
3517
  if (batchDepth === 0) return false;
3431
3518
  pendingSignals.add(signal2);
3432
3519
  return true;
3433
3520
  }
3434
- function isBatching() {
3521
+ function isBatchingImpl() {
3435
3522
  return batchDepth > 0;
3436
3523
  }
3437
3524
  function flushBatch() {
3438
3525
  try {
3439
3526
  for (const signal2 of pendingSignals) {
3440
- queueSignalNotification(signal2);
3527
+ queueSignalNotification2(signal2);
3441
3528
  }
3442
3529
  } finally {
3443
3530
  pendingSignals.clear();
3444
3531
  }
3445
- drainNotificationQueue();
3532
+ drainNotificationQueue2();
3533
+ }
3534
+ var BATCH_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.batch.v1");
3535
+ function resolveBatchApi() {
3536
+ const g2 = globalThis;
3537
+ const existing = g2[BATCH_REGISTRY_KEY];
3538
+ if (existing) return existing;
3539
+ const local = {
3540
+ batch: batchImpl,
3541
+ enqueueBatchedSignal: enqueueBatchedSignalImpl,
3542
+ isBatching: isBatchingImpl
3543
+ };
3544
+ g2[BATCH_REGISTRY_KEY] = local;
3545
+ return local;
3446
3546
  }
3547
+ var API2 = resolveBatchApi();
3548
+ var batch = API2.batch;
3549
+ var enqueueBatchedSignal = API2.enqueueBatchedSignal;
3550
+ var isBatching = API2.isBatching;
3447
3551
 
3448
3552
  // src/core/signals/signal.ts
3449
3553
  var _g = globalThis;
3450
- var _isDev9 = isDev();
3554
+ var _isDev10 = isDev();
3451
3555
  function signal(initial, options) {
3452
3556
  const state = {
3453
3557
  value: initial,
@@ -3458,11 +3562,11 @@ function signal(initial, options) {
3458
3562
  __activeNode: null,
3459
3563
  __name: void 0
3460
3564
  };
3461
- const debugName = _isDev9 ? options?.name : void 0;
3565
+ const debugName = _isDev10 ? options?.name : void 0;
3462
3566
  const equalsFn = options?.equals;
3463
3567
  if (debugName) state.__name = debugName;
3464
3568
  function get() {
3465
- recordDependency(state);
3569
+ recordDependency2(state);
3466
3570
  return state.value;
3467
3571
  }
3468
3572
  get.__signal = state;
@@ -3475,15 +3579,15 @@ function signal(initial, options) {
3475
3579
  if (equalsFn(prev, newValue)) return;
3476
3580
  state.value = newValue;
3477
3581
  state.__v++;
3478
- if (_isDev9) {
3582
+ if (_isDev10) {
3479
3583
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
3480
3584
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
3481
3585
  }
3482
3586
  if (!enqueueBatchedSignal(state)) {
3483
- notifySubscribers(state);
3587
+ notifySubscribers2(state);
3484
3588
  }
3485
3589
  };
3486
- } else if (_isDev9) {
3590
+ } else if (_isDev10) {
3487
3591
  set = (next) => {
3488
3592
  const prev = state.value;
3489
3593
  const newValue = typeof next === "function" ? next(prev) : next;
@@ -3493,7 +3597,7 @@ function signal(initial, options) {
3493
3597
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
3494
3598
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
3495
3599
  if (!enqueueBatchedSignal(state)) {
3496
- notifySubscribers(state);
3600
+ notifySubscribers2(state);
3497
3601
  }
3498
3602
  };
3499
3603
  } else {
@@ -3504,11 +3608,11 @@ function signal(initial, options) {
3504
3608
  state.value = newValue;
3505
3609
  state.__v++;
3506
3610
  if (!enqueueBatchedSignal(state)) {
3507
- notifySubscribers(state);
3611
+ notifySubscribers2(state);
3508
3612
  }
3509
3613
  };
3510
3614
  }
3511
- if (_isDev9) {
3615
+ if (_isDev10) {
3512
3616
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
3513
3617
  if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
3514
3618
  }
@@ -3597,11 +3701,11 @@ function on(deps, handler) {
3597
3701
  if (first) {
3598
3702
  first = false;
3599
3703
  prev = value;
3600
- untracked(() => handler(value, void 0));
3704
+ untracked2(() => handler(value, void 0));
3601
3705
  } else {
3602
3706
  const p2 = prev;
3603
3707
  prev = value;
3604
- untracked(() => handler(value, p2));
3708
+ untracked2(() => handler(value, p2));
3605
3709
  }
3606
3710
  };
3607
3711
  }
@@ -3623,7 +3727,7 @@ function drainReruns(ctx) {
3623
3727
  do {
3624
3728
  ctx.rerunPending = false;
3625
3729
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
3626
- retrack(ctx.bodyFn, ctx.subscriber);
3730
+ retrack2(ctx.bodyFn, ctx.subscriber);
3627
3731
  } while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
3628
3732
  if (ctx.rerunPending) {
3629
3733
  ctx.rerunPending = false;
@@ -3652,7 +3756,7 @@ function disposeEffect(ctx) {
3652
3756
  }
3653
3757
  }
3654
3758
  try {
3655
- cleanup(ctx.subscriber);
3759
+ cleanup2(ctx.subscriber);
3656
3760
  } catch (err) {
3657
3761
  if (typeof console !== "undefined") {
3658
3762
  console.warn("[SibuJS effect] dispose threw:", err);
@@ -3697,7 +3801,7 @@ function effect(effectFn, options) {
3697
3801
  try {
3698
3802
  ctx.rerunPending = false;
3699
3803
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
3700
- retrack(ctx.bodyFn, sub2);
3804
+ retrack2(ctx.bodyFn, sub2);
3701
3805
  if (ctx.rerunPending) drainReruns(ctx);
3702
3806
  } finally {
3703
3807
  ctx.running = false;
@@ -3713,7 +3817,7 @@ function effect(effectFn, options) {
3713
3817
  ctx.subscriber = sub2;
3714
3818
  ctx.running = true;
3715
3819
  try {
3716
- retrack(ctx.bodyFn, ctx.subscriber);
3820
+ retrack2(ctx.bodyFn, ctx.subscriber);
3717
3821
  if (ctx.rerunPending) drainReruns(ctx);
3718
3822
  } finally {
3719
3823
  ctx.running = false;
@@ -3746,7 +3850,7 @@ function derived(getter, options) {
3746
3850
  cs._d = false;
3747
3851
  cs._init = true;
3748
3852
  };
3749
- track(() => {
3853
+ track2(() => {
3750
3854
  let threw = true;
3751
3855
  try {
3752
3856
  cs._v = getter();
@@ -3765,12 +3869,12 @@ function derived(getter, options) {
3765
3869
  `[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
3766
3870
  );
3767
3871
  }
3768
- if (trackingSuspended) {
3872
+ if (isTrackingSuspended2()) {
3769
3873
  if (cs._d) {
3770
3874
  const prev = cs._v;
3771
3875
  evaluating = true;
3772
3876
  try {
3773
- retrack(recompute, markDirty);
3877
+ retrack2(recompute, markDirty);
3774
3878
  if (!Object.is(prev, cs._v)) cs.__v++;
3775
3879
  } finally {
3776
3880
  evaluating = false;
@@ -3778,12 +3882,12 @@ function derived(getter, options) {
3778
3882
  }
3779
3883
  return cs._v;
3780
3884
  }
3781
- recordDependency(cs);
3885
+ recordDependency2(cs);
3782
3886
  if (cs._d) {
3783
3887
  const oldValue = cs._v;
3784
3888
  evaluating = true;
3785
3889
  try {
3786
- retrack(recompute, markDirty);
3890
+ retrack2(recompute, markDirty);
3787
3891
  if (!Object.is(oldValue, cs._v)) cs.__v++;
3788
3892
  } finally {
3789
3893
  evaluating = false;
@@ -3821,15 +3925,15 @@ function watch(getter, callback) {
3821
3925
  if (!Object.is(newValue, oldValue)) {
3822
3926
  const prev = oldValue;
3823
3927
  oldValue = newValue;
3824
- suspendTracking();
3928
+ suspendTracking2();
3825
3929
  try {
3826
3930
  callback(newValue, prev);
3827
3931
  } finally {
3828
- resumeTracking();
3932
+ resumeTracking2();
3829
3933
  }
3830
3934
  }
3831
3935
  };
3832
- const teardown = track(subscriber);
3936
+ const teardown = track2(subscriber);
3833
3937
  return teardown;
3834
3938
  }
3835
3939
 
@@ -3892,11 +3996,11 @@ function store(initialState) {
3892
3996
  first = false;
3893
3997
  return;
3894
3998
  }
3895
- suspendTracking();
3999
+ suspendTracking2();
3896
4000
  try {
3897
4001
  callback(snapshot);
3898
4002
  } finally {
3899
- resumeTracking();
4003
+ resumeTracking2();
3900
4004
  }
3901
4005
  });
3902
4006
  };
@@ -3913,11 +4017,11 @@ function store(initialState) {
3913
4017
  if (!Object.is(current, prev)) {
3914
4018
  const oldPrev = prev;
3915
4019
  prev = current;
3916
- suspendTracking();
4020
+ suspendTracking2();
3917
4021
  try {
3918
4022
  callback(current, oldPrev);
3919
4023
  } finally {
3920
- resumeTracking();
4024
+ resumeTracking2();
3921
4025
  }
3922
4026
  }
3923
4027
  });
@@ -4019,11 +4123,11 @@ function reactiveArray(initial = []) {
4019
4123
  function notify() {
4020
4124
  snapshot = null;
4021
4125
  if (!enqueueBatchedSignal(signal2)) {
4022
- notifySubscribers(signal2);
4126
+ notifySubscribers2(signal2);
4023
4127
  }
4024
4128
  }
4025
4129
  function get() {
4026
- recordDependency(signal2);
4130
+ recordDependency2(signal2);
4027
4131
  if (snapshot === null) {
4028
4132
  const copy = data2.slice();
4029
4133
  snapshot = Object.freeze(copy);
@@ -4279,9 +4383,9 @@ function safeCall(cb, hookName) {
4279
4383
  }
4280
4384
  }
4281
4385
  function runMountCallback(callback, hookName, element) {
4282
- const cleanup2 = safeCall(callback, hookName);
4283
- if (typeof cleanup2 === "function" && element) {
4284
- registerDisposer(element, cleanup2);
4386
+ const cleanup3 = safeCall(callback, hookName);
4387
+ if (typeof cleanup3 === "function" && element) {
4388
+ registerDisposer(element, cleanup3);
4285
4389
  }
4286
4390
  }
4287
4391
  var mountWatchers = /* @__PURE__ */ new WeakMap();
@@ -4597,7 +4701,7 @@ function defer(getter) {
4597
4701
  }
4598
4702
  });
4599
4703
  };
4600
- const teardown = track(() => {
4704
+ const teardown = track2(() => {
4601
4705
  latest = getter();
4602
4706
  schedule();
4603
4707
  });
@@ -4749,14 +4853,14 @@ function Suspense({ nodes, fallback }) {
4749
4853
  }
4750
4854
 
4751
4855
  // src/platform/ssr.ts
4752
- var _isDev10 = isDev();
4856
+ var _isDev11 = isDev();
4753
4857
  function trustHTML(html3) {
4754
4858
  return html3;
4755
4859
  }
4756
4860
  var DEFAULT_MAX_SSR_BYTES = 1024 * 1024;
4757
4861
 
4758
4862
  // src/components/ErrorDisplay.ts
4759
- var _isDev11 = isDev();
4863
+ var _isDev12 = isDev();
4760
4864
  var STYLES = `
4761
4865
  .sibu-error-display {
4762
4866
  border: 1px solid var(--sibu-err-border, #e5484d);
@@ -5067,7 +5171,7 @@ function ErrorDisplay(props) {
5067
5171
  injectStyles();
5068
5172
  const severity = props.severity ?? "error";
5069
5173
  const normalized = normalizeError(props.error);
5070
- const showDetails = props.alwaysShowDetails ?? _isDev11;
5174
+ const showDetails = props.alwaysShowDetails ?? _isDev12;
5071
5175
  const headline = props.title ?? normalized.message;
5072
5176
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
5073
5177
  const [copyLabel, setCopyLabel] = signal("Copy");