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
package/dist/plugins.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ MigrationStorageError,
2
3
  VERSION,
3
4
  bundlerMetadata,
4
5
  checkCompatibility,
@@ -18,74 +19,83 @@ import {
18
19
  preloadCritical,
19
20
  prerenderRoutes,
20
21
  satisfies
21
- } from "./chunk-KKLW7YWL.js";
22
+ } from "./chunk-4AWA2PVD.js";
22
23
  import {
23
24
  isUnsafeKey
24
25
  } from "./chunk-H3SRKIYX.js";
25
26
  import {
27
+ PluginInstallCancelledError,
26
28
  createPlugin,
27
29
  createPluginRegistry,
28
30
  inject,
31
+ isPluginInstallCancelledError,
29
32
  plugin,
30
33
  resetPlugins,
31
34
  setDefaultPluginRegistry,
32
35
  triggerPluginError,
33
36
  triggerPluginMount,
34
37
  triggerPluginUnmount
35
- } from "./chunk-WWV3SJ3L.js";
38
+ } from "./chunk-J6FW5TV6.js";
36
39
  import {
37
40
  span
38
- } from "./chunk-PCT43HW3.js";
41
+ } from "./chunk-7LUJQAOJ.js";
39
42
  import {
40
43
  escapeScriptJson,
41
44
  renderToString,
42
45
  serializeHeadEntry
43
- } from "./chunk-NIOYEGBQ.js";
46
+ } from "./chunk-HURREPU2.js";
44
47
  import {
48
+ appendChildren,
45
49
  resolveClassValue
46
- } from "./chunk-KEISJXBU.js";
47
- import "./chunk-ONOHFDLG.js";
50
+ } from "./chunk-UOL2ECCS.js";
51
+ import "./chunk-FNJXNGYZ.js";
48
52
  import {
49
53
  isUrlAttribute,
50
54
  sanitizeStyleAttribute,
51
55
  sanitizeUrl,
52
56
  stripControlChars
53
- } from "./chunk-IXKSNWV5.js";
57
+ } from "./chunk-2INLLLMZ.js";
54
58
  import {
55
59
  globalSingleton
56
60
  } from "./chunk-7ZHH77QA.js";
57
61
  import {
58
62
  effect
59
- } from "./chunk-RIXRAYIU.js";
63
+ } from "./chunk-WEQ3DMVL.js";
60
64
  import {
61
65
  getRequestStore
62
- } from "./chunk-5DXA2J44.js";
63
- import {
64
- dispose,
65
- registerDisposer
66
- } from "./chunk-QKRPLZ2V.js";
66
+ } from "./chunk-7XHATCIH.js";
67
+ import "./chunk-5HZXGZ6T.js";
67
68
  import {
68
69
  signal
69
- } from "./chunk-XZZOBQAY.js";
70
+ } from "./chunk-FQRUXCEE.js";
70
71
  import {
71
- track
72
- } from "./chunk-UGRX3S57.js";
72
+ track,
73
+ untracked
74
+ } from "./chunk-JWKYU5GV.js";
73
75
  import {
74
76
  devWarn,
75
- isDev
76
- } from "./chunk-2WLZ6757.js";
77
+ dispose,
78
+ isDev,
79
+ registerDisposer
80
+ } from "./chunk-NYNYSPK7.js";
77
81
 
78
82
  // src/plugins/i18n.ts
79
83
  var _i18n = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.i18n.v1"), () => ({
80
84
  locale: signal("en"),
81
- locales: /* @__PURE__ */ Object.create(null)
85
+ locales: /* @__PURE__ */ Object.create(null),
86
+ revision: signal(0)
82
87
  }));
83
88
  var [clientLocale, setClientLocale] = _i18n.locale;
84
89
  var locales = _i18n.locales;
90
+ var [revision, setRevision] = _i18n.revision ?? (_i18n.revision = signal(0));
85
91
  function dictionaryFor(locale) {
86
92
  return Object.hasOwn(locales, locale) ? locales[locale] : void 0;
87
93
  }
94
+ function trackDictionaries() {
95
+ if (!getRequestStore()) revision();
96
+ }
88
97
  function lookup(key) {
98
+ trackDictionaries();
89
99
  const dictionary = dictionaryFor(getLocale());
90
100
  if (dictionary === void 0 || !Object.hasOwn(dictionary, key)) return void 0;
91
101
  const message = dictionary[key];
@@ -115,22 +125,42 @@ function registerTranslations(locale, messages) {
115
125
  enumerable: true,
116
126
  configurable: true
117
127
  });
128
+ setRevision((n) => n + 1);
129
+ }
130
+ function resolveParam(params, name) {
131
+ if (!Object.hasOwn(params, name)) return "";
132
+ const raw = params[name];
133
+ const value = typeof raw === "function" ? raw() : raw;
134
+ return value == null ? "" : String(value);
118
135
  }
119
136
  function t(key, params) {
120
137
  const message = lookup(key) ?? key;
121
- return params ? message.replace(/\{(\w+)\}/g, (_, p) => String(params[p] ?? "")) : message;
138
+ return params ? message.replace(/\{(\w+)\}/g, (_, p) => resolveParam(params, p)) : message;
139
+ }
140
+ function translated(key, params) {
141
+ return () => t(key, params);
122
142
  }
123
143
  function Trans(key, params) {
124
- return span(() => t(key, params));
144
+ return span(translated(key, params));
125
145
  }
126
146
  function hasTranslation(key) {
127
147
  return lookup(key) !== void 0;
128
148
  }
129
149
  function getAvailableLocales() {
150
+ trackDictionaries();
130
151
  return Object.keys(locales);
131
152
  }
132
153
 
133
154
  // src/plugins/router.ts
155
+ function splitRouteUrl(url) {
156
+ const hashIndex = url.indexOf("#");
157
+ const beforeHash = hashIndex === -1 ? url : url.slice(0, hashIndex);
158
+ const hash = hashIndex === -1 ? "" : url.slice(hashIndex + 1);
159
+ const queryIndex = beforeHash.indexOf("?");
160
+ const path = queryIndex === -1 ? beforeHash : beforeHash.slice(0, queryIndex);
161
+ const query = queryIndex === -1 ? "" : beforeHash.slice(queryIndex + 1);
162
+ return { path, query, hash };
163
+ }
134
164
  function classifyNavigationTarget(path) {
135
165
  if (path === "") return "internal";
136
166
  const normalized = stripControlChars(path).replace(/\\/g, "/");
@@ -849,8 +879,7 @@ var _SibuRouter = class _SibuRouter {
849
879
  return (path || "/") + window.location.search + window.location.hash;
850
880
  }
851
881
  createRouteContext(fullPath) {
852
- const [pathWithQuery, hash = ""] = fullPath.split("#");
853
- const [path, queryString = ""] = pathWithQuery.split("?");
882
+ const { path, query: queryString, hash } = splitRouteUrl(fullPath);
854
883
  const query = Object.fromEntries(new URLSearchParams(queryString));
855
884
  const match = this.matcher.match(path || "/");
856
885
  const params = match?.params || {};
@@ -1292,6 +1321,30 @@ function afterEach(hook) {
1292
1321
  return _routerRef.current.afterEach(hook);
1293
1322
  }
1294
1323
  var routeCleanups = [];
1324
+ var ownParamNamesCache = /* @__PURE__ */ new WeakMap();
1325
+ function ownParamNames(record) {
1326
+ const cached = ownParamNamesCache.get(record);
1327
+ if (cached) return cached;
1328
+ const aliases = record.alias == null ? [] : Array.isArray(record.alias) ? record.alias : [record.alias];
1329
+ const names = /* @__PURE__ */ new Set();
1330
+ for (const pattern of [record.path, ...aliases]) {
1331
+ for (const m of pattern.matchAll(/\/:([^/]+)/g)) {
1332
+ names.add(m[1].endsWith("?") ? m[1].slice(0, -1) : m[1]);
1333
+ }
1334
+ }
1335
+ const result = [...names];
1336
+ ownParamNamesCache.set(record, result);
1337
+ return result;
1338
+ }
1339
+ function instanceKey(owner, records, route2) {
1340
+ const custom = owner.key;
1341
+ if (custom) return untracked(() => String(custom(route2)));
1342
+ const parts = [];
1343
+ for (const record of records) {
1344
+ for (const name of ownParamNames(record)) parts.push(name, route2.params[name] ?? null);
1345
+ }
1346
+ return JSON.stringify(parts);
1347
+ }
1295
1348
  function Route() {
1296
1349
  const anchor = document.createComment("route-outlet");
1297
1350
  let currentNode = null;
@@ -1299,6 +1352,7 @@ function Route() {
1299
1352
  let errorNode = null;
1300
1353
  let navSeq = 0;
1301
1354
  let currentTopRoute = null;
1355
+ let currentKey = null;
1302
1356
  let routeTorn = false;
1303
1357
  const commitTarget = (seq) => routeTorn || seq !== navSeq ? null : anchor.parentNode;
1304
1358
  const release = (node) => {
@@ -1390,11 +1444,13 @@ function Route() {
1390
1444
  const match = _routerRef.current["matcher"].match(route2.path);
1391
1445
  if (!match) {
1392
1446
  currentTopRoute = null;
1447
+ currentKey = null;
1393
1448
  cleanupNodes();
1394
1449
  return;
1395
1450
  }
1396
1451
  const routeDef = match.matched[0] || match.route;
1397
- if (routeDef === currentTopRoute && currentNode) {
1452
+ const key = instanceKey(routeDef, [routeDef], route2);
1453
+ if (routeDef === currentTopRoute && key === currentKey && currentNode) {
1398
1454
  return;
1399
1455
  }
1400
1456
  if ("redirect" in routeDef) {
@@ -1422,6 +1478,7 @@ function Route() {
1422
1478
  }
1423
1479
  if (node) {
1424
1480
  currentTopRoute = routeDef;
1481
+ currentKey = key;
1425
1482
  cleanupNodes();
1426
1483
  parent.insertBefore(node, anchor.nextSibling);
1427
1484
  currentNode = node;
@@ -1459,6 +1516,7 @@ function Route() {
1459
1516
  routeTeardown();
1460
1517
  cleanupNodes();
1461
1518
  currentTopRoute = null;
1519
+ currentKey = null;
1462
1520
  };
1463
1521
  registerDisposer(anchor, routeCleanup);
1464
1522
  routeCleanups.push(routeCleanup);
@@ -1597,8 +1655,7 @@ function RouterLink(props, children) {
1597
1655
  const rawHref = _routerRef.current["resolvePath"](to);
1598
1656
  const kind = classifyNavigationTarget(rawHref);
1599
1657
  const href = kind === "unsafe" ? "#" : rawHref;
1600
- const [hrefBeforeHash, hrefHash = ""] = href.split("#");
1601
- const [hrefPathRaw, hrefQueryRaw = ""] = hrefBeforeHash.split("?");
1658
+ const { path: hrefPathRaw, query: hrefQueryRaw, hash: hrefHash } = splitRouteUrl(href);
1602
1659
  const targetPath = normalizePathname(hrefPathRaw);
1603
1660
  const targetQuery = normalizeQuery(hrefQueryRaw);
1604
1661
  const link = document.createElement("a");
@@ -1646,19 +1703,7 @@ function RouterLink(props, children) {
1646
1703
  }
1647
1704
  }
1648
1705
  });
1649
- if (typeof content === "string") {
1650
- link.textContent = content;
1651
- } else if (content instanceof Node) {
1652
- link.appendChild(content);
1653
- } else if (Array.isArray(content)) {
1654
- content.forEach((child) => {
1655
- if (typeof child === "string") {
1656
- link.appendChild(document.createTextNode(child));
1657
- } else if (child instanceof Node) {
1658
- link.appendChild(child);
1659
- }
1660
- });
1661
- }
1706
+ if (content !== void 0) appendChildren(link, content);
1662
1707
  const onLinkClick = (e) => {
1663
1708
  if (e.defaultPrevented || target || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) {
1664
1709
  return;
@@ -1820,6 +1865,7 @@ function Outlet() {
1820
1865
  const anchor = document.createComment("route-outlet-nested");
1821
1866
  let currentNode = null;
1822
1867
  let currentChild = null;
1868
+ let currentKey = null;
1823
1869
  let navSeq = 0;
1824
1870
  let outletTorn = false;
1825
1871
  const clearCurrent = () => {
@@ -1829,6 +1875,7 @@ function Outlet() {
1829
1875
  currentNode = null;
1830
1876
  }
1831
1877
  currentChild = null;
1878
+ currentKey = null;
1832
1879
  };
1833
1880
  const commitTarget = (seq) => outletTorn || seq !== navSeq ? null : anchor.parentNode;
1834
1881
  const release = (node) => {
@@ -1849,7 +1896,8 @@ function Outlet() {
1849
1896
  clearCurrent();
1850
1897
  return;
1851
1898
  }
1852
- if (childRoute === currentChild && currentNode) return;
1899
+ const key = instanceKey(childRoute, route2.matched.slice(1), route2);
1900
+ if (childRoute === currentChild && key === currentKey && currentNode) return;
1853
1901
  try {
1854
1902
  const cacheKey = `${route2.path}\0${childRoute.path}`;
1855
1903
  const plan = await _routerRef.current.loadPlan(childRoute, cacheKey);
@@ -1865,6 +1913,7 @@ function Outlet() {
1865
1913
  parent.insertBefore(node, anchor.nextSibling);
1866
1914
  currentNode = node;
1867
1915
  currentChild = childRoute;
1916
+ currentKey = key;
1868
1917
  } catch (error) {
1869
1918
  if (outletTorn || seq !== navSeq) return;
1870
1919
  console.error("[Outlet] Failed to render child route:", error);
@@ -1887,6 +1936,7 @@ function Outlet() {
1887
1936
  currentNode = null;
1888
1937
  }
1889
1938
  currentChild = null;
1939
+ currentKey = null;
1890
1940
  };
1891
1941
  registerDisposer(anchor, outletCleanup);
1892
1942
  routeCleanups.push(outletCleanup);
@@ -2193,8 +2243,8 @@ function hydrateRouter(routes, options) {
2193
2243
  const liveUrl = `${window.location.pathname}${window.location.search}${window.location.hash}`;
2194
2244
  const resolved = resolveServerRoute(liveUrl, routes);
2195
2245
  const bootstrapEpoch = __getNavigationEpoch();
2196
- import("./ssr-Y7XOEPEN.js").then(async ({ hydrate }) => {
2197
- const { replaceChildrenSafely } = await import("./dispose-46BOMMQJ.js");
2246
+ import("./ssr-XOTUASDO.js").then(async ({ hydrate }) => {
2247
+ const { replaceChildrenSafely } = await import("./dispose-GEIG2KOF.js");
2198
2248
  if (__getNavigationEpoch() !== bootstrapEpoch) return;
2199
2249
  if (resolved.component) {
2200
2250
  hydrate(resolved.component, container);
@@ -2228,7 +2278,9 @@ function escapeAttrLocal(str) {
2228
2278
  }
2229
2279
  export {
2230
2280
  KeepAliveRoute,
2281
+ MigrationStorageError,
2231
2282
  Outlet,
2283
+ PluginInstallCancelledError,
2232
2284
  Route,
2233
2285
  RouterLink,
2234
2286
  SibuRouter,
@@ -2272,6 +2324,7 @@ export {
2272
2324
  healthCheck,
2273
2325
  hydrateRouter,
2274
2326
  inject,
2327
+ isPluginInstallCancelledError,
2275
2328
  lazy,
2276
2329
  lazyModule,
2277
2330
  navigate,
@@ -2300,6 +2353,7 @@ export {
2300
2353
  setRouteTransition,
2301
2354
  setRoutes,
2302
2355
  t,
2356
+ translated,
2303
2357
  triggerPluginError,
2304
2358
  triggerPluginMount,
2305
2359
  triggerPluginUnmount
@@ -0,0 +1,110 @@
1
+ declare const __accessor: unique symbol;
2
+ /**
3
+ * A reactive signal getter returned by signal(), derived(), and similar primitives.
4
+ *
5
+ * Pass an Accessor directly into reactive prop positions — never call it there:
6
+ * ```ts
7
+ * const [count, setCount] = signal(0);
8
+ *
9
+ * div(count) // ✓ reactive — Accessor passed directly
10
+ * div(() => count()) // ✓ reactive — explicit arrow wrapper
11
+ * div(count()) // ✗ static — evaluated once, not reactive
12
+ * ```
13
+ */
14
+ type Accessor<T> = (() => T) & {
15
+ readonly [__accessor]?: never;
16
+ };
17
+ /**
18
+ * An {@link Accessor} that owns a subscription, timer or listener and must be
19
+ * released when its consumer goes away. Returned by helpers such as `debounce`,
20
+ * `throttle` and `previous`.
21
+ */
22
+ type DisposableAccessor<T> = Accessor<T> & {
23
+ /** Stop the underlying subscription and cancel pending work. The accessor keeps its last value. */
24
+ dispose(): void;
25
+ };
26
+ type SetState<T> = (next: T | ((prev: T) => T)) => void;
27
+ type StateTuple<T> = [Accessor<T>, SetState<T>];
28
+ /** Options for signal */
29
+ interface SignalOptions<T = unknown> {
30
+ /** Debug name for devtools inspection. Only used in development. */
31
+ name?: string;
32
+ /** Custom equality function. Defaults to Object.is(). */
33
+ equals?: (prev: T, next: T) => boolean;
34
+ }
35
+ /**
36
+ * signal creates a reactive signal that holds a value of type T.
37
+ * Returns a tuple: [getter, setter].
38
+ *
39
+ * @param initial Initial value
40
+ * @param options Optional config: `{ name: "count" }` for devtools labeling
41
+ * @returns A `[getter, setter]` tuple. Calling the getter inside a reactive
42
+ * context subscribes to the signal; the setter accepts a value or an updater.
43
+ */
44
+ declare function signal<T>(initial: T, options?: SignalOptions<T>): StateTuple<T>;
45
+ /**
46
+ * A valueless reactive token standing in for state SibuJS does not own.
47
+ *
48
+ * See {@link external}.
49
+ */
50
+ interface ExternalSource {
51
+ /**
52
+ * Declare, from inside a reactive computation, that it reads the external
53
+ * state this source represents. Call it in the same places you would read a
54
+ * signal — the top of a binding getter, a `derived()` body, an `effect()`.
55
+ *
56
+ * Outside a tracking context it is a no-op, exactly like reading a signal.
57
+ */
58
+ track(): void;
59
+ /**
60
+ * Declare that the external state changed. Every consumer that called
61
+ * {@link ExternalSource.track} is invalidated.
62
+ *
63
+ * Participates in `batch()` like any signal write: inside a batch, consumers
64
+ * are notified once when the outermost batch flushes.
65
+ */
66
+ invalidate(): void;
67
+ }
68
+ /**
69
+ * Create a reactive source for state that lives outside SibuJS — a domain
70
+ * engine, a media element, a canvas scene, an editor document, a cache a
71
+ * socket writes into.
72
+ *
73
+ * The pattern is two lines: `track()` where you read, `invalidate()` after you
74
+ * mutate.
75
+ *
76
+ * ```ts
77
+ * import { Chess } from "chess.js";
78
+ * import { external } from "sibujs";
79
+ *
80
+ * const game = new Chess(); // owns the rules and the mutable state
81
+ * const moved = external(); // owns "something changed"
82
+ *
83
+ * ctx.text("@status", () => {
84
+ * moved.track(); // this binding reads the engine
85
+ * return game.isCheckmate() ? "Checkmate" : `${game.turn()} to move`;
86
+ * });
87
+ *
88
+ * game.move({ from: "e2", to: "e4" });
89
+ * moved.invalidate(); // every consumer above re-reads
90
+ * ```
91
+ *
92
+ * **One source is one invalidation domain.** Every consumer of a source
93
+ * re-runs on every `invalidate()`, so the granularity of your updates is
94
+ * exactly the granularity of your sources: one for a whole engine is the
95
+ * cheapest to write, several (`board`, `clock`, `history`) let an update touch
96
+ * only what it affects. See `docs/architecture/external-state.md` for the
97
+ * trade-offs and when subdividing is worth it.
98
+ *
99
+ * Ownership, disposal and error routing are the consumer's, not the source's:
100
+ * a disposed binding or effect is never invalidated, and a consumer that
101
+ * throws is reported through the normal runtime error pipeline with its own
102
+ * phase and node.
103
+ *
104
+ * @param options `name` labels the source in devtools (development only).
105
+ */
106
+ declare function external(options?: {
107
+ name?: string;
108
+ }): ExternalSource;
109
+
110
+ export { type Accessor as A, type DisposableAccessor as D, type ExternalSource as E, type SignalOptions as S, external as e, signal as s };
@@ -0,0 +1,110 @@
1
+ declare const __accessor: unique symbol;
2
+ /**
3
+ * A reactive signal getter returned by signal(), derived(), and similar primitives.
4
+ *
5
+ * Pass an Accessor directly into reactive prop positions — never call it there:
6
+ * ```ts
7
+ * const [count, setCount] = signal(0);
8
+ *
9
+ * div(count) // ✓ reactive — Accessor passed directly
10
+ * div(() => count()) // ✓ reactive — explicit arrow wrapper
11
+ * div(count()) // ✗ static — evaluated once, not reactive
12
+ * ```
13
+ */
14
+ type Accessor<T> = (() => T) & {
15
+ readonly [__accessor]?: never;
16
+ };
17
+ /**
18
+ * An {@link Accessor} that owns a subscription, timer or listener and must be
19
+ * released when its consumer goes away. Returned by helpers such as `debounce`,
20
+ * `throttle` and `previous`.
21
+ */
22
+ type DisposableAccessor<T> = Accessor<T> & {
23
+ /** Stop the underlying subscription and cancel pending work. The accessor keeps its last value. */
24
+ dispose(): void;
25
+ };
26
+ type SetState<T> = (next: T | ((prev: T) => T)) => void;
27
+ type StateTuple<T> = [Accessor<T>, SetState<T>];
28
+ /** Options for signal */
29
+ interface SignalOptions<T = unknown> {
30
+ /** Debug name for devtools inspection. Only used in development. */
31
+ name?: string;
32
+ /** Custom equality function. Defaults to Object.is(). */
33
+ equals?: (prev: T, next: T) => boolean;
34
+ }
35
+ /**
36
+ * signal creates a reactive signal that holds a value of type T.
37
+ * Returns a tuple: [getter, setter].
38
+ *
39
+ * @param initial Initial value
40
+ * @param options Optional config: `{ name: "count" }` for devtools labeling
41
+ * @returns A `[getter, setter]` tuple. Calling the getter inside a reactive
42
+ * context subscribes to the signal; the setter accepts a value or an updater.
43
+ */
44
+ declare function signal<T>(initial: T, options?: SignalOptions<T>): StateTuple<T>;
45
+ /**
46
+ * A valueless reactive token standing in for state SibuJS does not own.
47
+ *
48
+ * See {@link external}.
49
+ */
50
+ interface ExternalSource {
51
+ /**
52
+ * Declare, from inside a reactive computation, that it reads the external
53
+ * state this source represents. Call it in the same places you would read a
54
+ * signal — the top of a binding getter, a `derived()` body, an `effect()`.
55
+ *
56
+ * Outside a tracking context it is a no-op, exactly like reading a signal.
57
+ */
58
+ track(): void;
59
+ /**
60
+ * Declare that the external state changed. Every consumer that called
61
+ * {@link ExternalSource.track} is invalidated.
62
+ *
63
+ * Participates in `batch()` like any signal write: inside a batch, consumers
64
+ * are notified once when the outermost batch flushes.
65
+ */
66
+ invalidate(): void;
67
+ }
68
+ /**
69
+ * Create a reactive source for state that lives outside SibuJS — a domain
70
+ * engine, a media element, a canvas scene, an editor document, a cache a
71
+ * socket writes into.
72
+ *
73
+ * The pattern is two lines: `track()` where you read, `invalidate()` after you
74
+ * mutate.
75
+ *
76
+ * ```ts
77
+ * import { Chess } from "chess.js";
78
+ * import { external } from "sibujs";
79
+ *
80
+ * const game = new Chess(); // owns the rules and the mutable state
81
+ * const moved = external(); // owns "something changed"
82
+ *
83
+ * ctx.text("@status", () => {
84
+ * moved.track(); // this binding reads the engine
85
+ * return game.isCheckmate() ? "Checkmate" : `${game.turn()} to move`;
86
+ * });
87
+ *
88
+ * game.move({ from: "e2", to: "e4" });
89
+ * moved.invalidate(); // every consumer above re-reads
90
+ * ```
91
+ *
92
+ * **One source is one invalidation domain.** Every consumer of a source
93
+ * re-runs on every `invalidate()`, so the granularity of your updates is
94
+ * exactly the granularity of your sources: one for a whole engine is the
95
+ * cheapest to write, several (`board`, `clock`, `history`) let an update touch
96
+ * only what it affects. See `docs/architecture/external-state.md` for the
97
+ * trade-offs and when subdividing is worth it.
98
+ *
99
+ * Ownership, disposal and error routing are the consumer's, not the source's:
100
+ * a disposed binding or effect is never invalidated, and a consumer that
101
+ * throws is reported through the normal runtime error pipeline with its own
102
+ * phase and node.
103
+ *
104
+ * @param options `name` labels the source in devtools (development only).
105
+ */
106
+ declare function external(options?: {
107
+ name?: string;
108
+ }): ExternalSource;
109
+
110
+ export { type Accessor as A, type DisposableAccessor as D, type ExternalSource as E, type SignalOptions as S, external as e, signal as s };
@@ -166,6 +166,11 @@ declare function resetSSRState(): void;
166
166
  *
167
167
  * The returned element contains the fallback UI with a `data-sibu-suspense-id`
168
168
  * marker. The promise resolves to `{ id, html }` once async content is ready.
169
+ *
170
+ * The promise never rejects. Any failure to produce the content HTML — the
171
+ * content factory throwing synchronously, its promise rejecting, the timeout,
172
+ * or rendering the resolved element throwing — resolves it with the fallback
173
+ * HTML, so the stream still produces a deterministic swap payload.
169
174
  */
170
175
  declare function ssrSuspense(props: {
171
176
  fallback: () => HTMLElement;
@@ -166,6 +166,11 @@ declare function resetSSRState(): void;
166
166
  *
167
167
  * The returned element contains the fallback UI with a `data-sibu-suspense-id`
168
168
  * marker. The promise resolves to `{ id, html }` once async content is ready.
169
+ *
170
+ * The promise never rejects. Any failure to produce the content HTML — the
171
+ * content factory throwing synchronously, its promise rejecting, the timeout,
172
+ * or rendering the resolved element throwing — resolves it with the fallback
173
+ * HTML, so the stream still produces a deterministic swap payload.
169
174
  */
170
175
  declare function ssrSuspense(props: {
171
176
  fallback: () => HTMLElement;
@@ -17,11 +17,10 @@ import {
17
17
  ssrSuspense,
18
18
  suspenseSwapScript,
19
19
  trustHTML
20
- } from "./chunk-NIOYEGBQ.js";
21
- import "./chunk-IXKSNWV5.js";
22
- import "./chunk-5DXA2J44.js";
23
- import "./chunk-QKRPLZ2V.js";
24
- import "./chunk-2WLZ6757.js";
20
+ } from "./chunk-HURREPU2.js";
21
+ import "./chunk-2INLLLMZ.js";
22
+ import "./chunk-7XHATCIH.js";
23
+ import "./chunk-NYNYSPK7.js";
25
24
  export {
26
25
  collectStream,
27
26
  deserializeState,