sibujs 1.4.0 → 2.0.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 (190) hide show
  1. package/README.md +105 -119
  2. package/dist/browser.cjs +288 -80
  3. package/dist/browser.d.cts +19 -9
  4. package/dist/browser.d.ts +19 -9
  5. package/dist/browser.js +6 -6
  6. package/dist/build.cjs +1019 -313
  7. package/dist/build.d.cts +1 -1
  8. package/dist/build.d.ts +1 -1
  9. package/dist/build.js +15 -13
  10. package/dist/cdn.global.js +17 -16
  11. package/dist/chunk-2RA7SHDA.js +65 -0
  12. package/dist/chunk-2UPRY23K.js +80 -0
  13. package/dist/chunk-3JHCYHWN.js +125 -0
  14. package/dist/{chunk-ZWKZCBO6.js → chunk-3LR7GLWQ.js} +154 -33
  15. package/dist/{chunk-3AIRKM3B.js → chunk-3NSGB5JN.js} +115 -34
  16. package/dist/{chunk-3ARAQO7B.js → chunk-52YJLLRO.js} +29 -6
  17. package/dist/chunk-54EDRCEF.js +93 -0
  18. package/dist/chunk-7JDB7I65.js +1327 -0
  19. package/dist/{chunk-WZSPOOER.js → chunk-CC65Y57T.js} +8 -5
  20. package/dist/{chunk-23VV7YD3.js → chunk-DFPFITST.js} +25 -30
  21. package/dist/{chunk-WR5D4EGH.js → chunk-GTBNNBJ6.js} +14 -2
  22. package/dist/chunk-HB24TBAF.js +121 -0
  23. package/dist/{chunk-CZUGLNJS.js → chunk-ITX6OO3F.js} +3 -3
  24. package/dist/{chunk-JAKHTMQU.js → chunk-JA6667UN.js} +206 -46
  25. package/dist/{chunk-77L6NL3X.js → chunk-JXMMDLBY.js} +306 -183
  26. package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
  27. package/dist/{chunk-F3FA4F32.js → chunk-KLRMB5ZS.js} +135 -79
  28. package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
  29. package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
  30. package/dist/{chunk-TSOKIX5Z.js → chunk-MIUAXB7K.js} +126 -74
  31. package/dist/{chunk-QWZG56ET.js → chunk-ND2664SF.js} +558 -190
  32. package/dist/{chunk-JCI5M6U6.js → chunk-O2MNQFLP.js} +261 -79
  33. package/dist/{chunk-EWFVA3TJ.js → chunk-R73P76YZ.js} +1 -1
  34. package/dist/{chunk-2BYQDGN3.js → chunk-SAHNHTFC.js} +234 -63
  35. package/dist/chunk-UCS6AMJ7.js +79 -0
  36. package/dist/{chunk-ZD6OAMTH.js → chunk-VLPPXTYG.js} +90 -35
  37. package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
  38. package/dist/{contracts-xo5ckdRP.d.cts → contracts-ey_Qh8ef.d.cts} +7 -8
  39. package/dist/{contracts-xo5ckdRP.d.ts → contracts-ey_Qh8ef.d.ts} +7 -8
  40. package/dist/{customElement-D2DJp_xn.d.cts → customElement-CPfIrbvg.d.cts} +18 -9
  41. package/dist/{customElement-D2DJp_xn.d.ts → customElement-CPfIrbvg.d.ts} +18 -9
  42. package/dist/data.cjs +452 -100
  43. package/dist/data.d.cts +20 -2
  44. package/dist/data.d.ts +20 -2
  45. package/dist/data.js +11 -9
  46. package/dist/devtools.cjs +535 -247
  47. package/dist/devtools.d.cts +1 -1
  48. package/dist/devtools.d.ts +1 -1
  49. package/dist/devtools.js +34 -30
  50. package/dist/ecosystem.cjs +499 -143
  51. package/dist/ecosystem.d.cts +13 -11
  52. package/dist/ecosystem.d.ts +13 -11
  53. package/dist/ecosystem.js +12 -11
  54. package/dist/extras.cjs +3639 -1629
  55. package/dist/extras.d.cts +11 -11
  56. package/dist/extras.d.ts +11 -11
  57. package/dist/extras.js +58 -45
  58. package/dist/index.cjs +1023 -313
  59. package/dist/index.d.cts +128 -55
  60. package/dist/index.d.ts +128 -55
  61. package/dist/index.js +28 -16
  62. package/dist/{introspect-BumjnBKr.d.cts → introspect-BWNjNw64.d.cts} +22 -2
  63. package/dist/{introspect-CZrlcaYy.d.ts → introspect-cY2pg9pW.d.ts} +22 -2
  64. package/dist/motion.cjs +90 -36
  65. package/dist/motion.d.cts +1 -1
  66. package/dist/motion.d.ts +1 -1
  67. package/dist/motion.js +4 -4
  68. package/dist/patterns.cjs +414 -81
  69. package/dist/patterns.d.cts +53 -20
  70. package/dist/patterns.d.ts +53 -20
  71. package/dist/patterns.js +7 -7
  72. package/dist/performance.cjs +364 -108
  73. package/dist/performance.d.cts +29 -17
  74. package/dist/performance.d.ts +29 -17
  75. package/dist/performance.js +13 -6
  76. package/dist/plugin-D30wlGW5.d.cts +71 -0
  77. package/dist/plugin-D30wlGW5.d.ts +71 -0
  78. package/dist/plugins.cjs +652 -271
  79. package/dist/plugins.d.cts +13 -6
  80. package/dist/plugins.d.ts +13 -6
  81. package/dist/plugins.js +116 -50
  82. package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
  83. package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
  84. package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
  85. package/dist/ssr.cjs +648 -219
  86. package/dist/ssr.d.cts +27 -7
  87. package/dist/ssr.d.ts +27 -7
  88. package/dist/ssr.js +12 -11
  89. package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.cts} +9 -1
  90. package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.ts} +9 -1
  91. package/dist/testing.cjs +252 -63
  92. package/dist/testing.d.cts +17 -4
  93. package/dist/testing.d.ts +17 -4
  94. package/dist/testing.js +100 -44
  95. package/dist/ui.cjs +576 -168
  96. package/dist/ui.d.cts +13 -16
  97. package/dist/ui.d.ts +13 -16
  98. package/dist/ui.js +20 -17
  99. package/dist/widgets.cjs +1001 -93
  100. package/dist/widgets.d.cts +104 -2
  101. package/dist/widgets.d.ts +104 -2
  102. package/dist/widgets.js +9 -7
  103. package/package.json +8 -2
  104. package/dist/chunk-32DY64NT.js +0 -282
  105. package/dist/chunk-3CRQALYP.js +0 -877
  106. package/dist/chunk-4EI4AG32.js +0 -482
  107. package/dist/chunk-4MYMUBRS.js +0 -21
  108. package/dist/chunk-6HLLIF3K.js +0 -398
  109. package/dist/chunk-6LSNVCS2.js +0 -937
  110. package/dist/chunk-6SA3QQES.js +0 -61
  111. package/dist/chunk-7BF6TK55.js +0 -1097
  112. package/dist/chunk-7TQKR4PP.js +0 -294
  113. package/dist/chunk-7V26P53V.js +0 -712
  114. package/dist/chunk-AZ3ISID5.js +0 -298
  115. package/dist/chunk-B7SWRFUT.js +0 -332
  116. package/dist/chunk-BGN5ZMP4.js +0 -26
  117. package/dist/chunk-BTU3TJDS.js +0 -365
  118. package/dist/chunk-BW3WT46K.js +0 -937
  119. package/dist/chunk-C6KFWOFV.js +0 -616
  120. package/dist/chunk-CHF5OHIA.js +0 -61
  121. package/dist/chunk-CHJ27IGK.js +0 -26
  122. package/dist/chunk-CMBFNA7L.js +0 -27
  123. package/dist/chunk-DAHRH4ON.js +0 -331
  124. package/dist/chunk-DKOHBI74.js +0 -924
  125. package/dist/chunk-DTCOOBMX.js +0 -725
  126. package/dist/chunk-EBGIRKQY.js +0 -616
  127. package/dist/chunk-EUZND3CB.js +0 -27
  128. package/dist/chunk-EVCZO745.js +0 -365
  129. package/dist/chunk-FGOEVHY3.js +0 -60
  130. package/dist/chunk-G3BOQPVO.js +0 -365
  131. package/dist/chunk-GCOK2LC3.js +0 -282
  132. package/dist/chunk-HGMJFBC7.js +0 -654
  133. package/dist/chunk-K5ZUMYVS.js +0 -89
  134. package/dist/chunk-KQPDEVVS.js +0 -398
  135. package/dist/chunk-L6JRBDNS.js +0 -60
  136. package/dist/chunk-LA6KQEDU.js +0 -712
  137. package/dist/chunk-MDVXJWFN.js +0 -304
  138. package/dist/chunk-MEZVEBPN.js +0 -2008
  139. package/dist/chunk-MK4ERFYL.js +0 -2249
  140. package/dist/chunk-MLKGABMK.js +0 -9
  141. package/dist/chunk-MQ5GOYPH.js +0 -2249
  142. package/dist/chunk-N6IZB6KJ.js +0 -567
  143. package/dist/chunk-NEKUBFPT.js +0 -60
  144. package/dist/chunk-NHUC2QWH.js +0 -282
  145. package/dist/chunk-NMRUZALC.js +0 -1097
  146. package/dist/chunk-NYVAC6P5.js +0 -37
  147. package/dist/chunk-OF7UZIVB.js +0 -725
  148. package/dist/chunk-P6W3STU4.js +0 -2249
  149. package/dist/chunk-PBHF5WKN.js +0 -616
  150. package/dist/chunk-PTQJDMRT.js +0 -146
  151. package/dist/chunk-PZEGYCF5.js +0 -61
  152. package/dist/chunk-QBMDLBU2.js +0 -975
  153. package/dist/chunk-RQGQSLQK.js +0 -725
  154. package/dist/chunk-SDLZDHKP.js +0 -107
  155. package/dist/chunk-TNQWPPE6.js +0 -37
  156. package/dist/chunk-UHNL42EF.js +0 -2730
  157. package/dist/chunk-UNXCEF6S.js +0 -21
  158. package/dist/chunk-V2XTI523.js +0 -347
  159. package/dist/chunk-VAU366PN.js +0 -2241
  160. package/dist/chunk-VMVDTCXB.js +0 -712
  161. package/dist/chunk-VRW3FULF.js +0 -725
  162. package/dist/chunk-WADYRCO2.js +0 -304
  163. package/dist/chunk-WILQZRO4.js +0 -282
  164. package/dist/chunk-WUHJISPP.js +0 -298
  165. package/dist/chunk-XYU6TZOW.js +0 -182
  166. package/dist/chunk-Y6GP4QGG.js +0 -276
  167. package/dist/chunk-YECR7UIA.js +0 -347
  168. package/dist/chunk-YUTWTI4B.js +0 -654
  169. package/dist/chunk-Z65KYU7I.js +0 -26
  170. package/dist/chunk-Z6POF5YC.js +0 -975
  171. package/dist/chunk-ZBJP6WFL.js +0 -482
  172. package/dist/contracts-DDrwxvJ-.d.cts +0 -245
  173. package/dist/contracts-DDrwxvJ-.d.ts +0 -245
  174. package/dist/contracts-DOrhwbke.d.cts +0 -245
  175. package/dist/contracts-DOrhwbke.d.ts +0 -245
  176. package/dist/customElement-BKQfbSZQ.d.cts +0 -262
  177. package/dist/customElement-BKQfbSZQ.d.ts +0 -262
  178. package/dist/customElement-yz8uyk-0.d.cts +0 -308
  179. package/dist/customElement-yz8uyk-0.d.ts +0 -308
  180. package/dist/introspect-Cb0zgpi2.d.cts +0 -477
  181. package/dist/introspect-Y2xNXGSf.d.ts +0 -477
  182. package/dist/plugin-Bek4RhJY.d.cts +0 -43
  183. package/dist/plugin-Bek4RhJY.d.ts +0 -43
  184. package/dist/ssr-3RXHP5ES.js +0 -38
  185. package/dist/ssr-6GIMY5MX.js +0 -38
  186. package/dist/ssr-BA6sxxUd.d.cts +0 -135
  187. package/dist/ssr-BA6sxxUd.d.ts +0 -135
  188. package/dist/ssr-WKUPVSSK.js +0 -36
  189. package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
  190. package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
@@ -1,12 +1,18 @@
1
+ import {
2
+ dispose
3
+ } from "./chunk-2UPRY23K.js";
4
+ import {
5
+ stripHtml
6
+ } from "./chunk-UCS6AMJ7.js";
1
7
  import {
2
8
  effect
3
- } from "./chunk-CHF5OHIA.js";
9
+ } from "./chunk-HB24TBAF.js";
4
10
  import {
5
11
  signal
6
- } from "./chunk-WZSPOOER.js";
12
+ } from "./chunk-CC65Y57T.js";
7
13
  import {
8
14
  isDev
9
- } from "./chunk-5X6PP2UK.js";
15
+ } from "./chunk-LMLD24FC.js";
10
16
 
11
17
  // src/devtools/debug.ts
12
18
  var debugEnabled = false;
@@ -90,7 +96,10 @@ function runCleanups(component) {
90
96
  for (const cleanup of cleanups) {
91
97
  try {
92
98
  cleanup();
93
- } catch {
99
+ } catch (err) {
100
+ if (typeof console !== "undefined") {
101
+ console.warn("[SibuJS debug] cleanup threw:", err);
102
+ }
94
103
  }
95
104
  }
96
105
  trackedCleanups.delete(component);
@@ -110,6 +119,11 @@ function checkLeaks() {
110
119
  }
111
120
 
112
121
  // src/devtools/devtools.ts
122
+ function getSibuNamespace() {
123
+ const g = globalThis;
124
+ if (!g.__SIBU__) g.__SIBU__ = { version: "1.0.0" };
125
+ return g.__SIBU__;
126
+ }
113
127
  function createGlobalHook() {
114
128
  const listeners = /* @__PURE__ */ new Map();
115
129
  const events = [];
@@ -154,13 +168,16 @@ function getOrCreateHook() {
154
168
  }
155
169
  var activeDevTools = null;
156
170
  var nextNodeId = 0;
171
+ var inferNameArmed = false;
157
172
  function getActiveDevTools() {
158
173
  return activeDevTools;
159
174
  }
160
175
  function initDevTools(config) {
161
176
  const maxEvents = config?.maxEvents ?? 1e3;
162
177
  const enabled = config?.enabled ?? isDev();
178
+ const expose = config?.expose ?? isDev();
163
179
  if (!enabled) return createNoopApi();
180
+ inferNameArmed = true;
164
181
  const hook = getOrCreateHook();
165
182
  nextNodeId = 0;
166
183
  const eventLog = [];
@@ -177,6 +194,7 @@ function initDevTools(config) {
177
194
  createdAt: Date.now()
178
195
  };
179
196
  hook.nodes.set(nextNodeId, node);
197
+ emit();
180
198
  });
181
199
  hook.on("signal:update", (payload) => {
182
200
  if (!isActive) return;
@@ -191,6 +209,7 @@ function initDevTools(config) {
191
209
  newValue: p.newValue,
192
210
  timestamp: Date.now()
193
211
  });
212
+ emit();
194
213
  });
195
214
  hook.on("computed:create", (payload) => {
196
215
  const p = payload;
@@ -205,6 +224,7 @@ function initDevTools(config) {
205
224
  createdAt: Date.now()
206
225
  };
207
226
  hook.nodes.set(nextNodeId, node);
227
+ emit();
208
228
  });
209
229
  hook.on("computed:update", (payload) => {
210
230
  const p = payload;
@@ -217,6 +237,7 @@ function initDevTools(config) {
217
237
  newValue: p.newValue,
218
238
  timestamp: Date.now()
219
239
  });
240
+ emit();
220
241
  });
221
242
  hook.on("effect:create", (payload) => {
222
243
  nextNodeId++;
@@ -224,6 +245,7 @@ function initDevTools(config) {
224
245
  const p = payload;
225
246
  const node = { id: nextNodeId, type: "effect", name, ref: p.effectFn, createdAt: Date.now() };
226
247
  hook.nodes.set(nextNodeId, node);
248
+ emit();
227
249
  });
228
250
  hook.on("effect:run", (payload) => {
229
251
  const p = payload;
@@ -234,6 +256,7 @@ function initDevTools(config) {
234
256
  duration: 0,
235
257
  timestamp: Date.now()
236
258
  });
259
+ emit();
237
260
  });
238
261
  hook.on("app:init", (payload) => {
239
262
  const p = payload;
@@ -243,12 +266,19 @@ function initDevTools(config) {
243
266
  duration: p.duration,
244
267
  timestamp: Date.now()
245
268
  });
269
+ emit();
246
270
  if (typeof document !== "undefined") {
247
- queueMicrotask(() => discoverComponents(hook, eventLog, maxEvents));
271
+ queueMicrotask(() => {
272
+ discoverComponents(hook, eventLog, maxEvents);
273
+ emit();
274
+ });
248
275
  }
249
276
  });
250
277
  function record(event) {
251
- if (isActive) pushEvent(eventLog, maxEvents, event);
278
+ if (isActive) {
279
+ pushEvent(eventLog, maxEvents, event);
280
+ emit();
281
+ }
252
282
  }
253
283
  function getEvents(filter) {
254
284
  if (!filter) return eventLog.slice();
@@ -263,9 +293,11 @@ function initDevTools(config) {
263
293
  }
264
294
  function registerComponent(name, element, state) {
265
295
  hook.components.set(name, { element, state });
296
+ emit();
266
297
  }
267
298
  function unregisterComponent(name) {
268
299
  hook.components.delete(name);
300
+ emit();
269
301
  }
270
302
  function getComponents() {
271
303
  return new Map(hook.components);
@@ -292,6 +324,12 @@ function initDevTools(config) {
292
324
  }
293
325
  return result;
294
326
  }
327
+ let domObserver = null;
328
+ const activeHighlightTimers = /* @__PURE__ */ new Set();
329
+ let changeVersion = 0;
330
+ function emit() {
331
+ changeVersion++;
332
+ }
295
333
  let isActive = enabled;
296
334
  function isEnabled() {
297
335
  return isActive;
@@ -304,32 +342,75 @@ function initDevTools(config) {
304
342
  for (const [name, entry] of hook.components) snap[name] = entry.state ? { ...entry.state } : {};
305
343
  return snap;
306
344
  }
345
+ function restoreHighlight(el) {
346
+ const prevOutline = el.dataset.sibuHighlightPrevOutline;
347
+ const prevOffset = el.dataset.sibuHighlightPrevOffset;
348
+ el.style.outline = prevOutline ?? "";
349
+ el.style.outlineOffset = prevOffset ?? "";
350
+ delete el.dataset.sibuHighlightPrevOutline;
351
+ delete el.dataset.sibuHighlightPrevOffset;
352
+ el.removeAttribute("data-sibu-highlight");
353
+ }
307
354
  function highlightElement(name) {
308
355
  const prev = document.querySelector("[data-sibu-highlight]");
309
- if (prev) {
310
- prev.style.outline = "";
311
- prev.removeAttribute("data-sibu-highlight");
312
- }
356
+ if (prev instanceof HTMLElement) restoreHighlight(prev);
313
357
  const entry = hook.components.get(name);
314
- if (entry?.element?.isConnected) {
315
- entry.element.style.outline = "2px solid #89b4fa";
316
- entry.element.setAttribute("data-sibu-highlight", "true");
317
- entry.element.scrollIntoView({ behavior: "smooth", block: "center" });
318
- setTimeout(() => {
319
- entry.element.style.outline = "";
320
- entry.element.removeAttribute("data-sibu-highlight");
321
- }, 3e3);
358
+ const el = entry?.element;
359
+ if (!el || !el.isConnected) return;
360
+ el.dataset.sibuHighlightPrevOutline = el.style.outline || "";
361
+ el.dataset.sibuHighlightPrevOffset = el.style.outlineOffset || "";
362
+ el.style.outline = "2px solid #89b4fa";
363
+ el.setAttribute("data-sibu-highlight", "true");
364
+ el.scrollIntoView({ behavior: "smooth", block: "center" });
365
+ const timer = setTimeout(() => {
366
+ activeHighlightTimers.delete(timer);
367
+ if (!el.isConnected) return;
368
+ restoreHighlight(el);
369
+ }, 3e3);
370
+ activeHighlightTimers.add(timer);
371
+ }
372
+ function getElementHTML(name, max = 2e3) {
373
+ const entry = hook.components.get(name);
374
+ const el = entry?.element;
375
+ if (!el) return null;
376
+ try {
377
+ const raw = el.outerHTML || "";
378
+ const cleaned = stripHtml(raw);
379
+ return cleaned.length > max ? `${cleaned.substring(0, max)}...` : cleaned;
380
+ } catch (err) {
381
+ if (typeof console !== "undefined") {
382
+ console.warn("[SibuJS devtools] getElementHTML failed:", err);
383
+ }
384
+ return null;
322
385
  }
323
386
  }
324
387
  function destroy() {
388
+ if (domObserver) {
389
+ domObserver.disconnect();
390
+ domObserver = null;
391
+ }
392
+ for (const t of activeHighlightTimers) clearTimeout(t);
393
+ activeHighlightTimers.clear();
394
+ if (typeof document !== "undefined") {
395
+ const prev = document.querySelector("[data-sibu-highlight]");
396
+ if (prev instanceof HTMLElement) restoreHighlight(prev);
397
+ }
325
398
  eventLog.length = 0;
326
399
  hook.nodes.clear();
327
400
  hook.components.clear();
328
401
  hook.events.length = 0;
329
402
  isActive = false;
403
+ inferNameArmed = false;
330
404
  activeDevTools = null;
331
405
  const g = globalThis;
406
+ if (g.__SIBU__) {
407
+ delete g.__SIBU__.devtools;
408
+ delete g.__SIBU__.data;
409
+ delete g.__SIBU__.changeVersion;
410
+ }
332
411
  if (g.__SIBU_DEVTOOLS__ === api) delete g.__SIBU_DEVTOOLS__;
412
+ delete g.__SIBU_DEVTOOLS_VERSION__;
413
+ delete g.__SIBU_DEVTOOLS_DATA__;
333
414
  if (g.__SIBU_DEVTOOLS_GLOBAL_HOOK__ === hook) delete g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
334
415
  }
335
416
  const api = {
@@ -344,164 +425,155 @@ function initDevTools(config) {
344
425
  setEnabled,
345
426
  snapshot,
346
427
  highlightElement,
428
+ getElementHTML,
347
429
  destroy
348
430
  };
349
- if (typeof window !== "undefined") {
350
- window.__SIBU_DEVTOOLS__ = api;
351
- let changeVersion = 0;
352
- const origPush = eventLog.push.bind(eventLog);
353
- eventLog.push = (...args) => {
354
- changeVersion++;
355
- return origPush(...args);
356
- };
357
- const origNodeSet = hook.nodes.set.bind(hook.nodes);
358
- hook.nodes.set = (k, v) => {
359
- changeVersion++;
360
- return origNodeSet(k, v);
361
- };
362
- const origCompSet = hook.components.set.bind(hook.components);
363
- hook.components.set = (k, v) => {
364
- changeVersion++;
365
- return origCompSet(k, v);
366
- };
367
- window.__SIBU_DEVTOOLS_VERSION__ = () => changeVersion;
368
- window.__SIBU_DEVTOOLS_DATA__ = () => {
369
- const sArr = [];
370
- for (const [, node] of hook.nodes) {
371
- let val = "";
372
- try {
373
- let raw;
374
- if (node.type === "signal" && node.ref && "value" in node.ref) {
375
- raw = node.ref.value;
376
- } else if (node.type === "computed" && node.ref) {
377
- if (node.ref._d && node.ref._g) {
378
- try {
379
- raw = node.ref._g();
380
- } catch {
381
- raw = node.ref._v;
382
- }
383
- } else {
431
+ function buildData() {
432
+ const sArr = [];
433
+ for (const [, node] of hook.nodes) {
434
+ let val = "";
435
+ try {
436
+ let raw;
437
+ if (node.type === "signal" && node.ref && "value" in node.ref) {
438
+ raw = node.ref.value;
439
+ } else if (node.type === "computed" && node.ref) {
440
+ if (node.ref._d && node.ref._g) {
441
+ try {
442
+ raw = node.ref._g();
443
+ } catch {
384
444
  raw = node.ref._v;
385
445
  }
386
- } else if (node.type === "effect") {
387
- raw = void 0;
388
- } else if (node.ref && "value" in node.ref) {
389
- raw = node.ref.value;
446
+ } else {
447
+ raw = node.ref._v;
390
448
  }
391
- if (raw === void 0) val = "undefined";
392
- else if (raw === null) val = "null";
393
- else if (typeof raw === "object") val = JSON.stringify(raw);
394
- else val = String(raw);
395
- } catch {
396
- val = "?";
449
+ } else if (node.type === "effect") {
450
+ raw = void 0;
451
+ } else if (node.ref && "value" in node.ref) {
452
+ raw = node.ref.value;
397
453
  }
398
- const fullVal = val;
399
- const shortVal = val.length > 80 ? `${val.substring(0, 80)}...` : val;
400
- const subs = node.ref?.__s;
401
- sArr.push({
402
- id: node.id,
403
- n: node.name,
404
- tp: node.type,
405
- v: shortVal,
406
- fv: fullVal,
407
- sc: subs instanceof Set ? subs.size : 0
408
- });
454
+ if (raw === void 0) val = "undefined";
455
+ else if (raw === null) val = "null";
456
+ else if (typeof raw === "object") val = JSON.stringify(raw);
457
+ else val = String(raw);
458
+ } catch {
459
+ val = "?";
409
460
  }
410
- function walkElement(el, depth) {
411
- if (depth > 8) return [];
412
- const result = [];
413
- const max = Math.min(el.children.length, 50);
414
- for (let i = 0; i < max; i++) {
415
- const child = el.children[i];
416
- const txtParts = [];
417
- for (let ti = 0; ti < child.childNodes.length; ti++) {
418
- const cn = child.childNodes[ti];
419
- if (cn.nodeType === 3) {
420
- const t = cn.textContent?.trim();
421
- if (t) txtParts.push(t);
422
- } else if (cn.nodeType === 1) {
423
- const el2 = cn;
424
- let directTxt = "";
425
- for (let ci = 0; ci < el2.childNodes.length; ci++) {
426
- if (el2.childNodes[ci].nodeType === 3) {
427
- const t2 = el2.childNodes[ci].textContent?.trim();
428
- if (t2) {
429
- directTxt = t2;
430
- break;
431
- }
461
+ const fullVal = val;
462
+ const shortVal = val.length > 80 ? `${val.substring(0, 80)}...` : val;
463
+ const subs = node.ref?.__s;
464
+ sArr.push({
465
+ id: node.id,
466
+ n: node.name,
467
+ tp: node.type,
468
+ v: shortVal,
469
+ fv: fullVal,
470
+ sc: subs instanceof Set ? subs.size : 0
471
+ });
472
+ }
473
+ function walkElement(el, depth) {
474
+ if (depth > 8) return [];
475
+ const result = [];
476
+ const max = Math.min(el.children.length, 50);
477
+ for (let i = 0; i < max; i++) {
478
+ const child = el.children[i];
479
+ const txtParts = [];
480
+ for (let ti = 0; ti < child.childNodes.length; ti++) {
481
+ const cn = child.childNodes[ti];
482
+ if (cn.nodeType === 3) {
483
+ const t = cn.textContent?.trim();
484
+ if (t) txtParts.push(t);
485
+ } else if (cn.nodeType === 1) {
486
+ const el2 = cn;
487
+ let directTxt = "";
488
+ for (let ci = 0; ci < el2.childNodes.length; ci++) {
489
+ if (el2.childNodes[ci].nodeType === 3) {
490
+ const t2 = el2.childNodes[ci].textContent?.trim();
491
+ if (t2) {
492
+ directTxt = t2;
493
+ break;
432
494
  }
433
495
  }
434
- if (directTxt) txtParts.push(directTxt);
435
496
  }
497
+ if (directTxt) txtParts.push(directTxt);
436
498
  }
437
- let txt = txtParts.join(" | ");
438
- if (txt.length > 120) txt = `${txt.substring(0, 120)}...`;
439
- let html = "";
440
- try {
441
- const outer = child.outerHTML || "";
442
- html = outer.length > 500 ? `${outer.substring(0, 500)}...` : outer;
443
- } catch {
444
- html = "";
445
- }
446
- const ev = child.__sibu_events__ || [];
447
- result.push({
448
- tg: child.tagName ? child.tagName.toLowerCase() : "?",
449
- id: child.id || "",
450
- cl: (child.className || "").toString().split(" ").slice(0, 3).join(" "),
451
- txt: txt.length > 60 ? `${txt.substring(0, 60)}...` : txt,
452
- html,
453
- ev,
454
- ch: child.childElementCount > 0 ? walkElement(child, depth + 1) : []
455
- });
456
499
  }
457
- return result;
458
- }
459
- const cArr = [];
460
- for (const [name, entry] of hook.components) {
461
- const el = entry.element;
462
- cArr.push({
463
- n: name,
464
- tg: el?.tagName ? el.tagName.toLowerCase() : "?",
465
- ch: el?.childElementCount || 0,
466
- cn: !!el?.isConnected,
467
- kids: el ? walkElement(el, 0) : []
500
+ let txt = txtParts.join(" | ");
501
+ if (txt.length > 120) txt = `${txt.substring(0, 120)}...`;
502
+ const attrs = [];
503
+ try {
504
+ const al = child.attributes;
505
+ for (let ai = 0; ai < al.length && ai < 20; ai++) attrs.push(al[ai].name);
506
+ } catch {
507
+ }
508
+ const ev = child.__sibu_events__ || [];
509
+ result.push({
510
+ tg: child.tagName ? child.tagName.toLowerCase() : "?",
511
+ id: child.id || "",
512
+ cl: (child.className || "").toString().split(" ").slice(0, 3).join(" "),
513
+ txt: txt.length > 60 ? `${txt.substring(0, 60)}...` : txt,
514
+ attrs,
515
+ ev,
516
+ ch: child.childElementCount > 0 ? walkElement(child, depth + 1) : []
468
517
  });
469
518
  }
470
- const eArr = [];
471
- const start = eventLog.length > 500 ? eventLog.length - 500 : 0;
472
- for (let i = start; i < eventLog.length; i++) {
473
- const e = eventLog[i];
474
- let detail = "";
475
- let ov = "";
476
- let nv = "";
477
- let key = "";
478
- if (e.type === "state-change") {
479
- const sc = e;
480
- key = sc.key || "";
481
- try {
482
- ov = sc.oldValue === void 0 ? "undefined" : sc.oldValue === null ? "null" : typeof sc.oldValue === "object" ? JSON.stringify(sc.oldValue, null, 2) : String(sc.oldValue);
483
- } catch {
484
- ov = "?";
485
- }
486
- try {
487
- nv = sc.newValue === void 0 ? "undefined" : sc.newValue === null ? "null" : typeof sc.newValue === "object" ? JSON.stringify(sc.newValue, null, 2) : String(sc.newValue);
488
- } catch {
489
- nv = "?";
490
- }
491
- const ovShort = ov.length > 40 ? `${ov.substring(0, 40)}...` : ov;
492
- const nvShort = nv.length > 40 ? `${nv.substring(0, 40)}...` : nv;
493
- detail = `${ovShort} \u2192 ${nvShort}`;
494
- } else if (e.type === "render") {
495
- detail = `${e.duration.toFixed(1)}ms`;
519
+ return result;
520
+ }
521
+ const cArr = [];
522
+ for (const [name, entry] of hook.components) {
523
+ const el = entry.element;
524
+ cArr.push({
525
+ n: name,
526
+ tg: el?.tagName ? el.tagName.toLowerCase() : "?",
527
+ ch: el?.childElementCount || 0,
528
+ cn: !!el?.isConnected,
529
+ kids: el ? walkElement(el, 0) : []
530
+ });
531
+ }
532
+ const eArr = [];
533
+ const start = eventLog.length > 500 ? eventLog.length - 500 : 0;
534
+ for (let i = start; i < eventLog.length; i++) {
535
+ const e = eventLog[i];
536
+ let detail = "";
537
+ let ov = "";
538
+ let nv = "";
539
+ let key = "";
540
+ if (e.type === "state-change") {
541
+ const sc = e;
542
+ key = sc.key || "";
543
+ try {
544
+ ov = sc.oldValue === void 0 ? "undefined" : sc.oldValue === null ? "null" : typeof sc.oldValue === "object" ? JSON.stringify(sc.oldValue, null, 2) : String(sc.oldValue);
545
+ } catch {
546
+ ov = "?";
496
547
  }
497
- eArr.push({ t: e.type, c: e.component, ts: e.timestamp, d: detail, ov, nv, k: key });
548
+ try {
549
+ nv = sc.newValue === void 0 ? "undefined" : sc.newValue === null ? "null" : typeof sc.newValue === "object" ? JSON.stringify(sc.newValue, null, 2) : String(sc.newValue);
550
+ } catch {
551
+ nv = "?";
552
+ }
553
+ const ovShort = ov.length > 40 ? `${ov.substring(0, 40)}...` : ov;
554
+ const nvShort = nv.length > 40 ? `${nv.substring(0, 40)}...` : nv;
555
+ detail = `${ovShort} \u2192 ${nvShort}`;
556
+ } else if (e.type === "render") {
557
+ detail = `${e.duration.toFixed(1)}ms`;
498
558
  }
499
- return JSON.stringify({ s: sArr, c: cArr, e: eArr });
500
- };
559
+ eArr.push({ t: e.type, c: e.component, ts: e.timestamp, d: detail, ov, nv, k: key });
560
+ }
561
+ return JSON.stringify({ s: sArr, c: cArr, e: eArr });
562
+ }
563
+ if (expose && typeof window !== "undefined") {
564
+ const ns = getSibuNamespace();
565
+ ns.devtools = api;
566
+ ns.data = buildData;
567
+ ns.changeVersion = () => changeVersion;
568
+ const w = window;
569
+ w.__SIBU_DEVTOOLS__ = api;
570
+ w.__SIBU_DEVTOOLS_VERSION__ = () => changeVersion;
571
+ w.__SIBU_DEVTOOLS_DATA__ = buildData;
501
572
  }
502
573
  activeDevTools = api;
503
574
  if (typeof document !== "undefined") {
504
- const observer = new MutationObserver((mutations) => {
575
+ domObserver = new MutationObserver((mutations) => {
576
+ let changed = false;
505
577
  for (const m of mutations) {
506
578
  for (const node of m.addedNodes) {
507
579
  if (node instanceof HTMLElement) {
@@ -509,6 +581,7 @@ function initDevTools(config) {
509
581
  if (name && !hook.components.has(name)) {
510
582
  hook.components.set(name, { element: node });
511
583
  pushEvent(eventLog, maxEvents, { type: "mount", component: name, element: node, timestamp: Date.now() });
584
+ changed = true;
512
585
  }
513
586
  }
514
587
  }
@@ -518,11 +591,14 @@ function initDevTools(config) {
518
591
  if (name && hook.components.has(name)) {
519
592
  pushEvent(eventLog, maxEvents, { type: "unmount", component: name, timestamp: Date.now() });
520
593
  hook.components.delete(name);
594
+ changed = true;
521
595
  }
522
596
  }
523
597
  }
524
598
  }
599
+ if (changed) emit();
525
600
  });
601
+ const observer = domObserver;
526
602
  queueMicrotask(() => {
527
603
  if (!document.body) return;
528
604
  observer.observe(document.body, { childList: true, subtree: true });
@@ -564,11 +640,13 @@ function initDevTools(config) {
564
640
  }
565
641
  });
566
642
  }
643
+ emit();
567
644
  });
568
645
  }
569
646
  return api;
570
647
  }
571
648
  function inferName() {
649
+ if (!inferNameArmed || !isDev()) return "anonymous";
572
650
  try {
573
651
  const stack = new Error().stack || "";
574
652
  for (const line of stack.split("\n")) {
@@ -625,6 +703,7 @@ function createNoopApi() {
625
703
  setEnabled: noop,
626
704
  snapshot: () => ({}),
627
705
  highlightElement: noop,
706
+ getElementHTML: ((_n) => null),
628
707
  destroy: noop
629
708
  };
630
709
  }
@@ -657,16 +736,37 @@ function devState(name, initial) {
657
736
  }
658
737
 
659
738
  // src/devtools/hmr.ts
739
+ var HMR_STORE_MAX_SIZE = 200;
660
740
  var hmrStateStore = /* @__PURE__ */ new Map();
741
+ var hmrStoreOverflowWarned = false;
742
+ function hmrStoreSet(id, value) {
743
+ if (hmrStateStore.has(id)) hmrStateStore.delete(id);
744
+ hmrStateStore.set(id, value);
745
+ if (hmrStateStore.size > HMR_STORE_MAX_SIZE) {
746
+ const oldestKey = hmrStateStore.keys().next().value;
747
+ if (oldestKey !== void 0) hmrStateStore.delete(oldestKey);
748
+ if (!hmrStoreOverflowWarned) {
749
+ hmrStoreOverflowWarned = true;
750
+ console.warn(
751
+ `[sibujs/hmr] HMR state store exceeded ${HMR_STORE_MAX_SIZE} entries \u2014 oldest entries are being evicted. Call clearHMRModule(id) from your module's accept/dispose handlers to avoid this.`
752
+ );
753
+ }
754
+ }
755
+ }
756
+ function clearHMRModule(id) {
757
+ hmrStateStore.delete(id);
758
+ hmrRegistry.delete(id);
759
+ hmrRegistry.delete(`boundary:${id}`);
760
+ }
661
761
  var hmrRegistry = /* @__PURE__ */ new Map();
662
762
  function hmrState(id, initial) {
663
763
  const restored = hmrStateStore.has(id) ? hmrStateStore.get(id) : initial;
664
764
  const [get, set] = signal(restored);
665
765
  function hmrSet(next) {
666
766
  set(next);
667
- hmrStateStore.set(id, get());
767
+ hmrStoreSet(id, get());
668
768
  }
669
- hmrStateStore.set(id, restored);
769
+ hmrStoreSet(id, restored);
670
770
  return [get, hmrSet];
671
771
  }
672
772
  function registerHMR(id, component, container) {
@@ -692,13 +792,15 @@ function registerHMR(id, component, container) {
692
792
  }
693
793
  reg.disposeCallbacks.length = 0;
694
794
  const newElement = newComponent();
695
- if (reg.currentElement?.parentNode) {
696
- reg.currentElement.parentNode.replaceChild(newElement, reg.currentElement);
795
+ const oldElement = reg.currentElement;
796
+ if (oldElement?.parentNode) {
797
+ oldElement.parentNode.replaceChild(newElement, oldElement);
697
798
  }
799
+ if (oldElement) dispose(oldElement);
698
800
  reg.component = newComponent;
699
801
  reg.currentElement = newElement;
700
802
  }
701
- function dispose() {
803
+ function dispose2() {
702
804
  const reg = hmrRegistry.get(id);
703
805
  if (!reg) return;
704
806
  for (const cb of reg.disposeCallbacks) {
@@ -707,12 +809,14 @@ function registerHMR(id, component, container) {
707
809
  } catch {
708
810
  }
709
811
  }
710
- if (reg.currentElement?.parentNode) {
711
- reg.currentElement.parentNode.removeChild(reg.currentElement);
812
+ if (reg.currentElement) {
813
+ const el = reg.currentElement;
814
+ if (el.parentNode) el.parentNode.removeChild(el);
815
+ dispose(el);
712
816
  }
713
817
  hmrRegistry.delete(id);
714
818
  }
715
- return { update, dispose };
819
+ return { update, dispose: dispose2 };
716
820
  }
717
821
  function createHMRBoundary(id) {
718
822
  let currentElement = null;
@@ -749,10 +853,15 @@ function createHMRBoundary(id) {
749
853
  }
750
854
  }
751
855
  disposeCallbacks.length = 0;
752
- if (currentComponent && currentElement?.parentNode) {
753
- const newElement = currentComponent();
754
- currentElement.parentNode.replaceChild(newElement, currentElement);
755
- currentElement = newElement;
856
+ if (currentComponent && currentElement) {
857
+ const oldEl = currentElement;
858
+ const parent = oldEl.parentNode;
859
+ if (parent) {
860
+ const newElement = currentComponent();
861
+ parent.replaceChild(newElement, oldEl);
862
+ dispose(oldEl);
863
+ currentElement = newElement;
864
+ }
756
865
  }
757
866
  for (const cb of acceptCallbacks) {
758
867
  try {
@@ -772,6 +881,19 @@ function createHMRBoundary(id) {
772
881
  function clearHMRState() {
773
882
  hmrStateStore.clear();
774
883
  hmrRegistry.clear();
884
+ hmrStoreOverflowWarned = false;
885
+ }
886
+ function exposeHMR() {
887
+ const g = globalThis;
888
+ if (!g.__SIBU__) g.__SIBU__ = { version: "1.0.0" };
889
+ g.__SIBU__.hmr = {
890
+ hmrState,
891
+ registerHMR,
892
+ createHMRBoundary,
893
+ clearHMRState,
894
+ clearHMRModule,
895
+ isHMRAvailable
896
+ };
775
897
  }
776
898
  function isHMRAvailable() {
777
899
  const g = globalThis;
@@ -912,13 +1034,13 @@ function debugValue(value, formatter) {
912
1034
  const format = formatter ?? ((v) => String(v));
913
1035
  const entry = { value: void 0, label: "" };
914
1036
  debugValues.push(entry);
915
- const dispose = effect(() => {
1037
+ const dispose2 = effect(() => {
916
1038
  const resolved = value();
917
1039
  entry.value = resolved;
918
1040
  entry.label = format(resolved);
919
1041
  });
920
1042
  return () => {
921
- dispose();
1043
+ dispose2();
922
1044
  const idx = debugValues.indexOf(entry);
923
1045
  if (idx !== -1) debugValues.splice(idx, 1);
924
1046
  };
@@ -998,11 +1120,11 @@ function createDevtoolsOverlay(options) {
998
1120
  const getPanels = () => {
999
1121
  return [...panels];
1000
1122
  };
1001
- const dispose = () => {
1123
+ const dispose2 = () => {
1002
1124
  panels.length = 0;
1003
1125
  setEnabled(false);
1004
1126
  };
1005
- return { isEnabled, toggle, addPanel, removePanel, getPanels, dispose };
1127
+ return { isEnabled, toggle, addPanel, removePanel, getPanels, dispose: dispose2 };
1006
1128
  }
1007
1129
 
1008
1130
  // src/devtools/introspect.ts
@@ -1030,25 +1152,24 @@ function inspectSignal(getter) {
1030
1152
  subscriberCount: subs ? subs.size : 0
1031
1153
  };
1032
1154
  }
1033
- function walkDependencyGraph(getter, maxDepth = 10) {
1155
+ function walkDependencyGraph(getter, maxDepth = 10, visited = /* @__PURE__ */ new WeakSet()) {
1034
1156
  const signal2 = getter.__signal;
1035
- if (!signal2 || maxDepth <= 0) {
1157
+ if (!signal2 || maxDepth <= 0 || visited.has(signal2)) {
1036
1158
  return { name: getSignalName(getter), subscribers: 0, downstream: [] };
1037
1159
  }
1160
+ visited.add(signal2);
1038
1161
  const subs = signal2[SUBS];
1039
1162
  const downstream = [];
1040
1163
  if (subs) {
1041
1164
  for (const sub of subs) {
1042
1165
  const subSig = sub._sig;
1043
- if (subSig) {
1166
+ if (subSig && !visited.has(subSig)) {
1044
1167
  const subName = subSig.__name;
1045
- const subSubs = subSig[SUBS];
1046
- downstream.push({
1047
- name: subName,
1048
- subscribers: subSubs ? subSubs.size : 0,
1049
- downstream: []
1050
- // Could recurse but we keep it simple
1051
- });
1168
+ const fakeGetter = (() => void 0);
1169
+ const tag = fakeGetter;
1170
+ tag.__signal = subSig;
1171
+ if (subName !== void 0) tag.__name = subName;
1172
+ downstream.push(walkDependencyGraph(fakeGetter, maxDepth - 1, visited));
1052
1173
  }
1053
1174
  }
1054
1175
  }
@@ -1074,10 +1195,12 @@ export {
1074
1195
  getActiveDevTools,
1075
1196
  initDevTools,
1076
1197
  devState,
1198
+ clearHMRModule,
1077
1199
  hmrState,
1078
1200
  registerHMR,
1079
1201
  createHMRBoundary,
1080
1202
  clearHMRState,
1203
+ exposeHMR,
1081
1204
  isHMRAvailable,
1082
1205
  SibuError,
1083
1206
  createErrorReporter,