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/index.cjs CHANGED
@@ -383,6 +383,23 @@ function reportDrainRunaway(label2, executed, remaining) {
383
383
  );
384
384
  }
385
385
  var activeBindingCount = 0;
386
+ function resolveCapture(capture) {
387
+ let frame = capture;
388
+ while (frame?.closed) frame = frame.forwardTo;
389
+ return frame ?? null;
390
+ }
391
+ var registrationCaptures = [];
392
+ function currentDisposerCapture() {
393
+ return resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
394
+ }
395
+ function beginDisposerCapture(capture) {
396
+ if (capture === null && registrationCaptures.length === 0) return false;
397
+ registrationCaptures.push(resolveCapture(capture));
398
+ return true;
399
+ }
400
+ function endDisposerCapture() {
401
+ registrationCaptures.pop();
402
+ }
386
403
  function registerDisposer(node, teardown) {
387
404
  let disposers = elementDisposers.get(node);
388
405
  if (!disposers) {
@@ -391,15 +408,61 @@ function registerDisposer(node, teardown) {
391
408
  }
392
409
  disposers.push(teardown);
393
410
  if (DEV) activeBindingCount++;
411
+ const capture = resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
412
+ if (capture) capture.entries.push([node, teardown]);
413
+ }
414
+ function withDisposerRollback(build) {
415
+ const frame = { entries: [], closed: false };
416
+ const captured = frame.entries;
417
+ registrationCaptures.push(frame);
418
+ let result;
419
+ try {
420
+ result = build();
421
+ } catch (err) {
422
+ let executed = 0;
423
+ try {
424
+ while (captured.length > 0) {
425
+ if (executed >= MAX_DRAIN_TEARDOWNS) {
426
+ reportDrainRunaway("rollback", executed, captured.length);
427
+ break;
428
+ }
429
+ const [node, teardown] = captured.pop();
430
+ if (!unregisterDisposer(node, teardown)) continue;
431
+ executed++;
432
+ try {
433
+ teardown();
434
+ } catch (cleanupErr) {
435
+ reportError(cleanupErr, { phase: "cleanup", name: "disposer" });
436
+ }
437
+ }
438
+ } finally {
439
+ frame.closed = true;
440
+ captured.length = 0;
441
+ registrationCaptures.pop();
442
+ }
443
+ throw err;
444
+ }
445
+ frame.closed = true;
446
+ registrationCaptures.pop();
447
+ const parent = resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
448
+ if (parent) {
449
+ for (const entry of captured) {
450
+ if (elementDisposers.get(entry[0])?.includes(entry[1])) parent.entries.push(entry);
451
+ }
452
+ frame.forwardTo = parent;
453
+ }
454
+ captured.length = 0;
455
+ return result;
394
456
  }
395
457
  function unregisterDisposer(node, teardown) {
396
458
  const disposers = elementDisposers.get(node);
397
- if (!disposers) return;
459
+ if (!disposers) return false;
398
460
  const index = disposers.indexOf(teardown);
399
- if (index === -1) return;
461
+ if (index === -1) return false;
400
462
  disposers.splice(index, 1);
401
463
  if (DEV) activeBindingCount--;
402
464
  if (disposers.length === 0) elementDisposers.delete(node);
465
+ return true;
403
466
  }
404
467
  function dispose(node) {
405
468
  const stack = [node];
@@ -413,33 +476,34 @@ function dispose(node) {
413
476
  }
414
477
  }
415
478
  for (let i2 = order.length - 1; i2 >= 0; i2--) {
416
- const current = order[i2];
417
- if (elementDisposers.has(current)) {
418
- let executed = 0;
419
- let runaway = false;
420
- while (!runaway) {
421
- const pending = elementDisposers.get(current);
422
- if (!pending || pending.length === 0) break;
423
- const snapshot = pending.slice();
424
- elementDisposers.delete(current);
425
- if (DEV) activeBindingCount -= snapshot.length;
426
- for (let i3 = 0; i3 < snapshot.length; i3++) {
427
- if (executed >= MAX_DRAIN_TEARDOWNS) {
428
- const rest = snapshot.slice(i3);
429
- const added = elementDisposers.get(current);
430
- elementDisposers.set(current, added ? rest.concat(added) : rest);
431
- if (DEV) activeBindingCount += rest.length;
432
- reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
433
- runaway = true;
434
- break;
435
- }
436
- executed++;
437
- try {
438
- snapshot[i3]();
439
- } catch (err) {
440
- reportError(err, { phase: "cleanup", name: "disposer" });
441
- }
442
- }
479
+ disposeNodeOwn(order[i2]);
480
+ }
481
+ }
482
+ function disposeNodeOwn(node) {
483
+ if (!elementDisposers.has(node)) return;
484
+ let executed = 0;
485
+ let runaway = false;
486
+ while (!runaway) {
487
+ const pending = elementDisposers.get(node);
488
+ if (!pending || pending.length === 0) break;
489
+ const snapshot = pending.slice();
490
+ elementDisposers.delete(node);
491
+ if (DEV) activeBindingCount -= snapshot.length;
492
+ for (let i2 = 0; i2 < snapshot.length; i2++) {
493
+ if (executed >= MAX_DRAIN_TEARDOWNS) {
494
+ const rest = snapshot.slice(i2);
495
+ const added = elementDisposers.get(node);
496
+ elementDisposers.set(node, added ? rest.concat(added) : rest);
497
+ if (DEV) activeBindingCount += rest.length;
498
+ reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
499
+ runaway = true;
500
+ break;
501
+ }
502
+ executed++;
503
+ try {
504
+ snapshot[i2]();
505
+ } catch (err) {
506
+ reportError(err, { phase: "cleanup", name: "disposer" });
443
507
  }
444
508
  }
445
509
  }
@@ -920,6 +984,7 @@ function retrack(effectFn, subscriber) {
920
984
  }
921
985
  currentSubscriber = subscriber;
922
986
  const sub2 = subscriber;
987
+ if (sub2._cap === void 0) sub2._cap = currentDisposerCapture();
923
988
  const epoch = ++subscriberEpochCounter;
924
989
  sub2._epoch = epoch;
925
990
  sub2._structDirty = false;
@@ -1111,7 +1176,12 @@ function drainQueue() {
1111
1176
  quarantined.add(sub2);
1112
1177
  continue;
1113
1178
  }
1114
- safeInvoke(sub2);
1179
+ const pushed = beginDisposerCapture(sub2._cap ?? null);
1180
+ try {
1181
+ safeInvoke(sub2);
1182
+ } finally {
1183
+ if (pushed) endDisposerCapture();
1184
+ }
1115
1185
  }
1116
1186
  }
1117
1187
  function drainNotificationQueue() {
@@ -1247,7 +1317,7 @@ function forEachSubscriber(signal2, visit) {
1247
1317
  }
1248
1318
 
1249
1319
  // src/reactivity/track.ts
1250
- var _runtimeVersion = true ? "4.5.0" : "dev";
1320
+ var _runtimeVersion = true ? "4.7.0" : "dev";
1251
1321
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
1252
1322
  function resolveReactiveApi() {
1253
1323
  const g2 = globalThis;
@@ -1555,8 +1625,34 @@ function toKebab(prop) {
1555
1625
  }
1556
1626
  function applyStyle(el, style2) {
1557
1627
  if (typeof style2 === "function") {
1628
+ const getter = style2;
1629
+ let written = [];
1630
+ let wroteString = false;
1558
1631
  const teardown = reactiveBinding2(() => {
1559
- el.setAttribute("style", sanitizeStyleAttribute(String(style2()), { element: el }));
1632
+ const value = getter();
1633
+ if (value === null || typeof value !== "object") {
1634
+ written = [];
1635
+ wroteString = true;
1636
+ el.setAttribute("style", sanitizeStyleAttribute(String(value), { element: el }));
1637
+ return;
1638
+ }
1639
+ const decl = el.style;
1640
+ if (wroteString) {
1641
+ el.removeAttribute("style");
1642
+ wroteString = false;
1643
+ }
1644
+ const next = [];
1645
+ for (const prop in value) {
1646
+ const val = value[prop];
1647
+ if (val == null) continue;
1648
+ const name = toKebab(prop);
1649
+ next.push(name);
1650
+ decl.setProperty(name, sanitizeCSSValue(String(val), { property: name, element: el }));
1651
+ }
1652
+ for (let i2 = 0; i2 < written.length; i2++) {
1653
+ if (next.indexOf(written[i2]) === -1) decl.removeProperty(written[i2]);
1654
+ }
1655
+ written = next;
1560
1656
  }, el);
1561
1657
  registerDisposer(el, teardown);
1562
1658
  return;
@@ -1587,7 +1683,9 @@ function applyClass(el, cls) {
1587
1683
  }
1588
1684
  if (typeof cls === "function") {
1589
1685
  const teardown = reactiveBinding2(() => {
1590
- el.setAttribute("class", cls());
1686
+ const value = cls();
1687
+ if (value == null || value === false) el.removeAttribute("class");
1688
+ else el.setAttribute("class", value);
1591
1689
  }, el);
1592
1690
  registerDisposer(el, teardown);
1593
1691
  return;
@@ -1669,7 +1767,7 @@ function appendChildren(el, nodes) {
1669
1767
  }
1670
1768
  }
1671
1769
  }
1672
- var tagFactory = (tag, ns) => {
1770
+ function tagFactory(tag, ns) {
1673
1771
  const blocked = isBlockedTag(tag);
1674
1772
  return (first, second) => {
1675
1773
  if (blocked) {
@@ -1718,7 +1816,9 @@ var tagFactory = (tag, ns) => {
1718
1816
  const pClass = props.class;
1719
1817
  if (pClass != null) applyClass(el, pClass);
1720
1818
  const pId = props.id;
1721
- if (pId != null) {
1819
+ if (typeof pId === "function") {
1820
+ registerDisposer(el, bindAttribute(el, "id", pId));
1821
+ } else if (pId != null) {
1722
1822
  if (DEV && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
1723
1823
  devWarn(
1724
1824
  `tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
@@ -1768,12 +1868,10 @@ var tagFactory = (tag, ns) => {
1768
1868
  }
1769
1869
  }
1770
1870
  }
1771
- if (props.onElement && typeof props.onElement === "function") {
1772
- props.onElement(el);
1773
- }
1871
+ if (typeof props.onElement === "function") props.onElement(el);
1774
1872
  return el;
1775
1873
  };
1776
- };
1874
+ }
1777
1875
 
1778
1876
  // src/core/rendering/html.ts
1779
1877
  var html = tagFactory("html");
@@ -2022,10 +2120,13 @@ function safeCall(cb, hookName) {
2022
2120
  return void 0;
2023
2121
  }
2024
2122
  }
2025
- function runMountCallback(callback, hookName, element) {
2123
+ function runMountCallback(callback, hookName, element, isDisposed) {
2026
2124
  const cleanup3 = safeCall(callback, hookName);
2027
- if (typeof cleanup3 === "function" && element) {
2028
- registerDisposer(element, cleanup3);
2125
+ if (typeof cleanup3 !== "function") return;
2126
+ if (isDisposed() || !element.isConnected) {
2127
+ safeCall(cleanup3, "onUnmount");
2128
+ } else {
2129
+ onUnmount(cleanup3, element);
2029
2130
  }
2030
2131
  }
2031
2132
  var mountWatchers = /* @__PURE__ */ new WeakMap();
@@ -2187,25 +2288,26 @@ function onMount(callback, element) {
2187
2288
  if (typeof document === "undefined") return;
2188
2289
  if (element) {
2189
2290
  let disposed = false;
2291
+ const isDisposed = () => disposed;
2190
2292
  registerDisposer(element, () => {
2191
2293
  disposed = true;
2192
2294
  });
2193
2295
  if (element.isConnected) {
2194
2296
  queueMicrotask(() => {
2195
2297
  if (disposed) return;
2196
- runMountCallback(callback, "onMount", element);
2298
+ runMountCallback(callback, "onMount", element, isDisposed);
2197
2299
  });
2198
2300
  return;
2199
2301
  }
2200
2302
  queueMicrotask(() => {
2201
2303
  if (disposed) return;
2202
2304
  if (element.isConnected) {
2203
- runMountCallback(callback, "onMount", element);
2305
+ runMountCallback(callback, "onMount", element, isDisposed);
2204
2306
  return;
2205
2307
  }
2206
2308
  const unregister = registerMountWatcher(element, () => {
2207
2309
  if (disposed) return;
2208
- runMountCallback(callback, "onMount", element);
2310
+ runMountCallback(callback, "onMount", element, isDisposed);
2209
2311
  });
2210
2312
  registerDisposer(element, unregister);
2211
2313
  });
@@ -2242,6 +2344,14 @@ function onCleanup(callback, element) {
2242
2344
  registerDisposer(element, callback);
2243
2345
  }
2244
2346
 
2347
+ // src/core/devtoolsHook.ts
2348
+ function emitDevtools(hook, event, payload) {
2349
+ try {
2350
+ hook.emit(event, payload);
2351
+ } catch {
2352
+ }
2353
+ }
2354
+
2245
2355
  // src/core/ssr-context.ts
2246
2356
  var SSR_KEY = /* @__PURE__ */ Symbol.for("sibujs.ssr.v1");
2247
2357
  function detectSSRShared() {
@@ -2288,6 +2398,10 @@ function getSSRStore() {
2288
2398
  }
2289
2399
  return fallbackStore;
2290
2400
  }
2401
+ function getRequestStore() {
2402
+ if (als) return als.getStore() ?? null;
2403
+ return _shared.fallbackDepth > 0 ? fallbackStore : null;
2404
+ }
2291
2405
  function isSSR() {
2292
2406
  return getSSRStore().ssr;
2293
2407
  }
@@ -2309,16 +2423,18 @@ function disableSSR() {
2309
2423
  getSSRStore().ssr = false;
2310
2424
  }
2311
2425
  function runInSSRContext(fn) {
2312
- const store2 = { ssr: true, suspenseIdCounter: 0, locale: void 0 };
2426
+ const store2 = { ssr: true, suspenseIdCounter: 0, idCounter: 0, locale: void 0 };
2313
2427
  if (als) {
2314
2428
  return als.run(store2, fn);
2315
2429
  }
2316
2430
  warnMissingAsyncLocalStorage();
2317
2431
  const prevSSR = fallbackStore.ssr;
2318
2432
  const prevCounter = fallbackStore.suspenseIdCounter;
2433
+ const prevIdCounter = fallbackStore.idCounter;
2319
2434
  const prevLocale = fallbackStore.locale;
2320
2435
  fallbackStore.ssr = true;
2321
2436
  fallbackStore.suspenseIdCounter = 0;
2437
+ fallbackStore.idCounter = 0;
2322
2438
  fallbackStore.locale = void 0;
2323
2439
  _shared.fallbackDepth++;
2324
2440
  try {
@@ -2327,6 +2443,7 @@ function runInSSRContext(fn) {
2327
2443
  _shared.fallbackDepth--;
2328
2444
  fallbackStore.ssr = prevSSR;
2329
2445
  fallbackStore.suspenseIdCounter = prevCounter;
2446
+ fallbackStore.idCounter = prevIdCounter;
2330
2447
  fallbackStore.locale = prevLocale;
2331
2448
  }
2332
2449
  }
@@ -2472,12 +2589,17 @@ function effect(effectFn, options) {
2472
2589
  try {
2473
2590
  retrack2(ctx.bodyFn, ctx.subscriber);
2474
2591
  if (ctx.rerunPending) drainReruns(ctx);
2592
+ } catch (err) {
2593
+ ctx.disposed = true;
2594
+ if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
2595
+ cleanup2(ctx.subscriber);
2596
+ throw err;
2475
2597
  } finally {
2476
2598
  ctx.running = false;
2477
2599
  ctx.rerunPending = false;
2478
2600
  }
2479
2601
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
2480
- if (hook) hook.emit("effect:create", { effectFn });
2602
+ if (hook) emitDevtools(hook, "effect:create", { effectFn });
2481
2603
  return () => disposeEffect(ctx);
2482
2604
  }
2483
2605
 
@@ -2564,7 +2686,7 @@ function signal(initial, options) {
2564
2686
  state2.__v++;
2565
2687
  if (DEV) {
2566
2688
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
2567
- if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
2689
+ if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
2568
2690
  }
2569
2691
  if (!enqueueBatchedSignal(state2)) {
2570
2692
  notifySubscribers2(state2);
@@ -2578,7 +2700,7 @@ function signal(initial, options) {
2578
2700
  state2.value = newValue;
2579
2701
  state2.__v++;
2580
2702
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
2581
- if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
2703
+ if (hook) emitDevtools(hook, "signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
2582
2704
  if (!enqueueBatchedSignal(state2)) {
2583
2705
  notifySubscribers2(state2);
2584
2706
  }
@@ -2597,7 +2719,7 @@ function signal(initial, options) {
2597
2719
  }
2598
2720
  if (DEV) {
2599
2721
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
2600
- if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
2722
+ if (hook) emitDevtools(hook, "signal:create", { signal: state2, name: debugName, getter: get, initial });
2601
2723
  }
2602
2724
  return [get, set];
2603
2725
  }
@@ -3410,36 +3532,34 @@ function Loading(props = {}) {
3410
3532
  const { text: text2, variant = "spinner", size = "md" } = props;
3411
3533
  const sizeClass = size !== "md" ? ` sibu-loading-${size}` : "";
3412
3534
  if (variant === "dots") {
3413
- return div({
3535
+ return div(
3536
+ {
3537
+ class: `sibu-loading${sizeClass}`,
3538
+ role: "status",
3539
+ "aria-live": "polite",
3540
+ // When there's no visible text, give the live region an accessible name
3541
+ // so it isn't announced as an empty status.
3542
+ "aria-label": text2 ? void 0 : "Loading"
3543
+ },
3544
+ [
3545
+ div({ class: "sibu-loading-dots" }, [
3546
+ span({ class: "sibu-loading-dot" }),
3547
+ span({ class: "sibu-loading-dot" }),
3548
+ span({ class: "sibu-loading-dot" })
3549
+ ]),
3550
+ text2 ? span({ class: "sibu-loading-text" }, text2) : null
3551
+ ]
3552
+ );
3553
+ }
3554
+ return div(
3555
+ {
3414
3556
  class: `sibu-loading${sizeClass}`,
3415
3557
  role: "status",
3416
3558
  "aria-live": "polite",
3417
- // When there's no visible text, give the live region an accessible name
3418
- // so it isn't announced as an empty status.
3419
- "aria-label": text2 ? void 0 : "Loading",
3420
- nodes: [
3421
- div({
3422
- class: "sibu-loading-dots",
3423
- nodes: [
3424
- span({ class: "sibu-loading-dot" }),
3425
- span({ class: "sibu-loading-dot" }),
3426
- span({ class: "sibu-loading-dot" })
3427
- ]
3428
- }),
3429
- text2 ? span({ class: "sibu-loading-text", nodes: text2 }) : null
3430
- ].filter(Boolean)
3431
- });
3432
- }
3433
- return div({
3434
- class: `sibu-loading${sizeClass}`,
3435
- role: "status",
3436
- "aria-live": "polite",
3437
- "aria-label": text2 ? void 0 : "Loading",
3438
- nodes: [
3439
- div({ class: "sibu-loading-spinner" }),
3440
- text2 ? span({ class: "sibu-loading-text", nodes: text2 }) : null
3441
- ].filter(Boolean)
3442
- });
3559
+ "aria-label": text2 ? void 0 : "Loading"
3560
+ },
3561
+ [div({ class: "sibu-loading-spinner" }), text2 ? span({ class: "sibu-loading-text" }, text2) : null]
3562
+ );
3443
3563
  }
3444
3564
 
3445
3565
  // src/core/rendering/action.ts
@@ -3498,9 +3618,14 @@ var longPress = (element, options) => {
3498
3618
  };
3499
3619
  };
3500
3620
  var copyOnClick = (element, getText) => {
3621
+ const report = (error) => reportError(error, { phase: "async", name: "copyOnClick", node: element });
3501
3622
  const handler = () => {
3502
- const text2 = typeof getText === "function" ? getText() : element.textContent ?? "";
3503
- navigator.clipboard.writeText(text2);
3623
+ try {
3624
+ const text2 = typeof getText === "function" ? getText() : element.textContent ?? "";
3625
+ Promise.resolve(navigator.clipboard.writeText(text2)).catch(report);
3626
+ } catch (error) {
3627
+ report(error);
3628
+ }
3504
3629
  };
3505
3630
  element.addEventListener("click", handler);
3506
3631
  return () => element.removeEventListener("click", handler);
@@ -3540,13 +3665,35 @@ registerAction("copyOnClick", copyOnClick);
3540
3665
  registerAction("autoResize", autoResize);
3541
3666
  registerAction("trapFocus", trapFocus);
3542
3667
 
3668
+ // src/utils/adoptThenable.ts
3669
+ function adoptThenable(value) {
3670
+ if (value === null || typeof value !== "object" && typeof value !== "function") return null;
3671
+ let then;
3672
+ try {
3673
+ then = value.then;
3674
+ } catch (error) {
3675
+ return Promise.reject(error);
3676
+ }
3677
+ if (typeof then !== "function") return null;
3678
+ return new Promise((resolve, reject) => {
3679
+ queueMicrotask(() => {
3680
+ try {
3681
+ Reflect.apply(then, value, [resolve, reject]);
3682
+ } catch (error) {
3683
+ reject(error);
3684
+ }
3685
+ });
3686
+ });
3687
+ }
3688
+
3543
3689
  // src/core/rendering/catch.ts
3544
3690
  var globalErrorHandler = null;
3545
3691
  function catchError(fn, onError) {
3546
3692
  try {
3547
3693
  const result = fn();
3548
- if (result && typeof result.then === "function") {
3549
- result.catch((err) => {
3694
+ const adopted = adoptThenable(result);
3695
+ if (adopted) {
3696
+ adopted.then(void 0, (err) => {
3550
3697
  if (onError) {
3551
3698
  onError(err, "async");
3552
3699
  } else if (globalErrorHandler) {
@@ -3636,6 +3783,11 @@ function context(defaultValue) {
3636
3783
  var COUNTER_KEY = /* @__PURE__ */ Symbol.for("sibujs.createId.v1");
3637
3784
  var _counter = globalThis[COUNTER_KEY] ?? (globalThis[COUNTER_KEY] = { n: 0 });
3638
3785
  function createId(prefix = "sibu") {
3786
+ const request = getRequestStore();
3787
+ if (request) {
3788
+ request.idCounter = (request.idCounter ?? 0) + 1;
3789
+ return `${prefix}-${request.idCounter}`;
3790
+ }
3639
3791
  _counter.n++;
3640
3792
  return `${prefix}-${_counter.n}`;
3641
3793
  }
@@ -3673,13 +3825,15 @@ function when(condition, thenBranch, elseBranch) {
3673
3825
  let currentNode = null;
3674
3826
  let lastCondition;
3675
3827
  let initialized = false;
3828
+ let disposed = false;
3676
3829
  const attachedOnce = /* @__PURE__ */ new WeakSet();
3677
3830
  let currentNodeOwned = false;
3678
3831
  const update = () => {
3832
+ if (disposed) return;
3679
3833
  const show2 = condition();
3680
3834
  const parent = anchor.parentNode;
3681
3835
  if (!parent) return;
3682
- if (initialized && show2 === lastCondition) return;
3836
+ if (initialized && Object.is(show2, lastCondition)) return;
3683
3837
  lastCondition = show2;
3684
3838
  const focused = currentNode ? captureFocusWithin([currentNode]) : null;
3685
3839
  if (currentNode?.parentNode) {
@@ -3688,16 +3842,20 @@ function when(condition, thenBranch, elseBranch) {
3688
3842
  currentNode = null;
3689
3843
  }
3690
3844
  const branch = show2 ? thenBranch : elseBranch !== void 0 ? elseBranch : null;
3691
- const attached = attachBranch(parent, anchor, branch, attachedOnce, "when");
3845
+ const attached = untracked2(() => attachBranch(parent, anchor, branch, attachedOnce, "when"));
3692
3846
  currentNode = attached.node;
3693
3847
  currentNodeOwned = attached.owned;
3694
3848
  restoreFocusWithin(focused, currentNode ? [currentNode] : [], "when");
3695
3849
  initialized = true;
3696
3850
  };
3697
- registerDisposer(anchor, reactiveBinding2(update, anchor));
3851
+ const stopBinding = reactiveBinding2(update, anchor);
3852
+ registerDisposer(anchor, () => {
3853
+ disposed = true;
3854
+ stopBinding();
3855
+ });
3698
3856
  if (!initialized) {
3699
3857
  queueMicrotask(() => {
3700
- if (!initialized && anchor.parentNode) update();
3858
+ if (!disposed && !initialized && anchor.parentNode) update();
3701
3859
  });
3702
3860
  }
3703
3861
  return anchor;
@@ -3707,9 +3865,11 @@ function match(value, cases, fallback) {
3707
3865
  let currentNode = null;
3708
3866
  let lastKey;
3709
3867
  let initialized = false;
3868
+ let disposed = false;
3710
3869
  const attachedOnce = /* @__PURE__ */ new WeakSet();
3711
3870
  let currentNodeOwned = false;
3712
3871
  const update = () => {
3872
+ if (disposed) return;
3713
3873
  const key = String(value());
3714
3874
  const parent = anchor.parentNode;
3715
3875
  if (!parent) return;
@@ -3722,46 +3882,72 @@ function match(value, cases, fallback) {
3722
3882
  currentNode = null;
3723
3883
  }
3724
3884
  const branch = Object.hasOwn(cases, key) ? cases[key] : fallback;
3725
- const attached = attachBranch(parent, anchor, branch ?? null, attachedOnce, "match");
3885
+ const attached = untracked2(() => attachBranch(parent, anchor, branch ?? null, attachedOnce, "match"));
3726
3886
  currentNode = attached.node;
3727
3887
  currentNodeOwned = attached.owned;
3728
3888
  restoreFocusWithin(focused, currentNode ? [currentNode] : [], "match");
3729
3889
  initialized = true;
3730
3890
  };
3731
- registerDisposer(anchor, reactiveBinding2(update, anchor));
3891
+ const stopBinding = reactiveBinding2(update, anchor);
3892
+ registerDisposer(anchor, () => {
3893
+ disposed = true;
3894
+ stopBinding();
3895
+ });
3732
3896
  if (!initialized) {
3733
3897
  queueMicrotask(() => {
3734
- if (!initialized && anchor.parentNode) update();
3898
+ if (!disposed && !initialized && anchor.parentNode) update();
3735
3899
  });
3736
3900
  }
3737
3901
  return anchor;
3738
3902
  }
3739
3903
 
3904
+ // src/utils/globalSingleton.ts
3905
+ function globalSingleton(key, create) {
3906
+ const g2 = globalThis;
3907
+ return g2[key] ?? (g2[key] = create());
3908
+ }
3909
+
3740
3910
  // src/core/rendering/dynamic.ts
3741
- var componentRegistry = /* @__PURE__ */ new Map();
3911
+ var componentRegistry = globalSingleton(
3912
+ /* @__PURE__ */ Symbol.for("sibujs.components.registry.v1"),
3913
+ () => /* @__PURE__ */ new Map()
3914
+ );
3915
+ var registryVersion = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.components.registryVersion.v1"), () => signal(0));
3916
+ function bumpRegistry() {
3917
+ const [read, write] = registryVersion;
3918
+ write(untracked2(read) + 1);
3919
+ }
3742
3920
  function registerComponent(name, component) {
3743
3921
  componentRegistry.set(name, component);
3922
+ bumpRegistry();
3744
3923
  }
3745
3924
  function unregisterComponent(name) {
3746
- componentRegistry.delete(name);
3925
+ if (componentRegistry.delete(name)) bumpRegistry();
3747
3926
  }
3748
3927
  function resolveComponent(name) {
3749
3928
  const component = componentRegistry.get(name);
3750
3929
  if (component) {
3751
3930
  return component();
3752
3931
  }
3753
- return div({ nodes: `[Component "${name}" not found]` });
3932
+ return div(`[Component "${name}" not found]`);
3754
3933
  }
3755
3934
  function DynamicComponent(is) {
3756
3935
  const container = div({ class: "sibu-dynamic" });
3936
+ const NONE = {};
3937
+ let shown = NONE;
3757
3938
  function render() {
3758
3939
  const target = is();
3759
- let el;
3940
+ let component;
3760
3941
  if (typeof target === "function") {
3761
- el = target();
3942
+ component = target;
3762
3943
  } else {
3763
- el = resolveComponent(target);
3944
+ registryVersion[0]();
3945
+ component = componentRegistry.get(target);
3764
3946
  }
3947
+ const next = component ?? `missing:${target}`;
3948
+ if (next === shown) return;
3949
+ const el = untracked2(() => component ? component() : div(`[Component "${target}" not found]`));
3950
+ shown = next;
3765
3951
  replaceChildrenSafely(container, el);
3766
3952
  }
3767
3953
  const untrack = track2(render);
@@ -4025,27 +4211,26 @@ function Fragment(nodes) {
4025
4211
  if (Array.isArray(child)) {
4026
4212
  for (const nested of child) {
4027
4213
  if (nested == null || typeof nested === "boolean") continue;
4028
- frag.appendChild(resolveChild(nested));
4214
+ appendChild(frag, nested);
4029
4215
  }
4030
4216
  } else {
4031
- frag.appendChild(resolveChild(child));
4217
+ appendChild(frag, child);
4032
4218
  }
4033
4219
  }
4034
4220
  return frag;
4035
4221
  }
4036
- function resolveChild(child) {
4037
- if (child == null) {
4038
- return document.createTextNode("");
4039
- }
4222
+ function appendChild(frag, child) {
4040
4223
  if (child instanceof Node) {
4041
- return child;
4224
+ frag.appendChild(child);
4225
+ return;
4042
4226
  }
4043
4227
  if (typeof child === "function") {
4044
- const result = child();
4045
- if (result instanceof Node) return result;
4046
- return document.createTextNode(String(result ?? ""));
4228
+ const placeholder = document.createComment("");
4229
+ frag.appendChild(placeholder);
4230
+ registerDisposer(placeholder, bindChildNode(placeholder, child));
4231
+ return;
4047
4232
  }
4048
- return document.createTextNode(String(child));
4233
+ frag.appendChild(document.createTextNode(String(child)));
4049
4234
  }
4050
4235
 
4051
4236
  // src/core/rendering/htm.ts
@@ -4515,25 +4700,77 @@ function mount(component, container) {
4515
4700
  typeof component === "function" || component instanceof Node,
4516
4701
  "mount: first argument must be a component function or a DOM Node."
4517
4702
  );
4518
- const startTime = typeof performance !== "undefined" ? performance.now() : 0;
4519
- const node = typeof component === "function" ? component() : component;
4520
- const duration = typeof performance !== "undefined" ? performance.now() - startTime : 0;
4521
- container.appendChild(node);
4522
- const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
4523
- if (hook) {
4524
- hook.emit("app:init", { rootElement: node, container, duration });
4703
+ const now = () => typeof performance !== "undefined" ? performance.now() : 0;
4704
+ const startTime = now();
4705
+ let range = null;
4706
+ const attach = (built) => {
4707
+ if (built instanceof DocumentFragment) {
4708
+ const start = document.createComment("");
4709
+ const end = document.createComment("");
4710
+ built.insertBefore(start, built.firstChild);
4711
+ built.appendChild(end);
4712
+ range = { start, end };
4713
+ }
4714
+ container.appendChild(built);
4715
+ };
4716
+ let node;
4717
+ if (typeof component === "function") {
4718
+ node = withDisposerRollback(() => {
4719
+ const built = component();
4720
+ attach(built);
4721
+ return built;
4722
+ });
4723
+ } else {
4724
+ node = component;
4725
+ attach(node);
4525
4726
  }
4727
+ const duration = now() - startTime;
4728
+ const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
4729
+ if (hook) emitDevtools(hook, "app:init", { rootElement: node, container, duration });
4730
+ const mounted = range;
4526
4731
  return {
4527
4732
  node,
4528
4733
  unmount() {
4529
- if (hook) hook.emit("app:unmount", { rootElement: node });
4530
- dispose(node);
4531
- if (node.parentNode) {
4532
- node.parentNode.removeChild(node);
4734
+ if (hook) emitDevtools(hook, "app:unmount", { rootElement: node });
4735
+ if (mounted) {
4736
+ unmountRange(mounted.start, mounted.end);
4737
+ return;
4533
4738
  }
4739
+ dispose(node);
4740
+ node.parentNode?.removeChild(node);
4534
4741
  }
4535
4742
  };
4536
4743
  }
4744
+ function unmountRange(start, end) {
4745
+ const parent = start.parentNode;
4746
+ if (!parent && !end.parentNode) return;
4747
+ let budget = MAX_DRAIN_TEARDOWNS;
4748
+ for (let n = start.nextSibling; n && n !== end; n = n.nextSibling) budget++;
4749
+ let before = start;
4750
+ let after = null;
4751
+ let intact = true;
4752
+ for (; ; ) {
4753
+ if (start.parentNode !== parent || end.parentNode !== parent) intact = false;
4754
+ else if (start.previousSibling !== before || end.nextSibling !== after) {
4755
+ before = start.previousSibling;
4756
+ after = end.nextSibling;
4757
+ intact = !!(start.compareDocumentPosition(end) & 4);
4758
+ }
4759
+ const n = start.nextSibling;
4760
+ if (!intact || n === end) break;
4761
+ if (budget-- <= 0) {
4762
+ reportDrainRunaway("mount", MAX_DRAIN_TEARDOWNS, 1);
4763
+ return;
4764
+ }
4765
+ dispose(n);
4766
+ if (n.parentNode === parent) parent.removeChild(n);
4767
+ }
4768
+ if (!intact) {
4769
+ reportError(new Error("[SibuJS mount] fragment markers lost"), { phase: "cleanup", name: "mount" });
4770
+ }
4771
+ start.parentNode?.removeChild(start);
4772
+ end.parentNode?.removeChild(end);
4773
+ }
4537
4774
 
4538
4775
  // src/core/rendering/portal.ts
4539
4776
  function Portal(nodes, target) {
@@ -4569,10 +4806,15 @@ function Portal(nodes, target) {
4569
4806
 
4570
4807
  // src/core/rendering/slots.ts
4571
4808
  function getSlot(slots, name = "default") {
4572
- return slots?.[name];
4809
+ if (slots == null || !Object.hasOwn(slots, name)) return void 0;
4810
+ const slot2 = slots[name];
4811
+ return typeof slot2 === "function" ? slot2 : void 0;
4573
4812
  }
4574
4813
 
4575
4814
  // src/core/signals/array.ts
4815
+ function nativeSplice(target, start, rest) {
4816
+ return rest.length === 0 ? target.splice(start) : target.splice(start, ...rest);
4817
+ }
4576
4818
  function array(initial = []) {
4577
4819
  const [arr, setArr] = signal([...initial]);
4578
4820
  const actions = {
@@ -4600,12 +4842,12 @@ function array(initial = []) {
4600
4842
  unshift(...items) {
4601
4843
  setArr((prev) => [...items, ...prev]);
4602
4844
  },
4603
- splice(start, deleteCount = 0, ...items) {
4845
+ splice(start, ...rest) {
4604
4846
  let removed = [];
4605
4847
  setArr((prev) => {
4606
4848
  const copy = [...prev];
4607
- removed = copy.splice(start, deleteCount, ...items);
4608
- return copy;
4849
+ removed = nativeSplice(copy, start, rest);
4850
+ return removed.length === 0 && rest.length <= 1 ? prev : copy;
4609
4851
  });
4610
4852
  return removed;
4611
4853
  },
@@ -4688,9 +4930,9 @@ function reactiveArray(initial = []) {
4688
4930
  data2.unshift(...items);
4689
4931
  notify();
4690
4932
  },
4691
- splice(start, deleteCount = 0, ...items) {
4692
- const removed = data2.splice(start, deleteCount, ...items);
4693
- if (removed.length > 0 || items.length > 0) {
4933
+ splice(start, ...rest) {
4934
+ const removed = nativeSplice(data2, start, rest);
4935
+ if (removed.length > 0 || rest.length > 1) {
4694
4936
  notify();
4695
4937
  }
4696
4938
  return removed;
@@ -4912,6 +5154,21 @@ function deepEqual(a2, b2, seen) {
4912
5154
  if (a2.length !== b2.length) return false;
4913
5155
  return a2.every((val, i2) => deepEqual(val, b2[i2], seen));
4914
5156
  }
5157
+ if (a2 instanceof Number || a2 instanceof String || a2 instanceof Boolean) {
5158
+ return Object.is(a2.valueOf(), b2.valueOf());
5159
+ }
5160
+ if (typeof URL !== "undefined" && a2 instanceof URL) {
5161
+ return a2.href === b2.href;
5162
+ }
5163
+ if (a2 instanceof Error) {
5164
+ const eb = b2;
5165
+ return a2.name === eb.name && a2.message === eb.message && deepEqual(a2.cause, eb.cause, seen) && plainKeysEqual(objA, objB, seen);
5166
+ }
5167
+ const proto = Object.getPrototypeOf(objA);
5168
+ if (proto !== Object.prototype && proto !== null) return false;
5169
+ return plainKeysEqual(objA, objB, seen);
5170
+ }
5171
+ function plainKeysEqual(objA, objB, seen) {
4915
5172
  const keysA = Object.keys(objA);
4916
5173
  const keysB = Object.keys(objB);
4917
5174
  if (keysA.length !== keysB.length) return false;
@@ -4949,17 +5206,17 @@ function derived(getter, options) {
4949
5206
  cs._d = false;
4950
5207
  cs._init = true;
4951
5208
  };
4952
- track2(() => {
4953
- let threw = true;
4954
- try {
5209
+ try {
5210
+ track2(() => {
4955
5211
  cs._v = getter();
4956
5212
  cs._d = false;
4957
5213
  cs._init = true;
4958
- threw = false;
4959
- } finally {
4960
- if (threw) cs._d = true;
4961
- }
4962
- }, markDirty);
5214
+ }, markDirty);
5215
+ } catch (err) {
5216
+ disposed = true;
5217
+ cleanup2(markDirty);
5218
+ throw err;
5219
+ }
4963
5220
  const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
4964
5221
  const validate = () => {
4965
5222
  if (!cs._d || disposed || pendingError !== void 0) return;
@@ -4978,7 +5235,7 @@ function derived(getter, options) {
4978
5235
  if (disposed) cleanup2(markDirty);
4979
5236
  }
4980
5237
  if (hook && !disposed && !Object.is(oldValue, cs._v)) {
4981
- hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
5238
+ emitDevtools(hook, "computed:update", { signal: cs, oldValue, newValue: cs._v });
4982
5239
  }
4983
5240
  };
4984
5241
  cs._validate = validate;
@@ -5029,7 +5286,7 @@ function derived(getter, options) {
5029
5286
  }
5030
5287
  }
5031
5288
  };
5032
- if (hook) hook.emit("computed:create", { signal: cs, name: debugName, getter: computedGetter });
5289
+ if (hook) emitDevtools(hook, "computed:create", { signal: cs, name: debugName, getter: computedGetter });
5033
5290
  return computedGetter;
5034
5291
  }
5035
5292
 
@@ -5047,15 +5304,18 @@ function ref(initial) {
5047
5304
  }
5048
5305
 
5049
5306
  // src/core/signals/store.ts
5307
+ function defineOwn(obj, key, value) {
5308
+ Object.defineProperty(obj, key, { value, writable: true, enumerable: true, configurable: true });
5309
+ }
5050
5310
  function store(initialState) {
5051
5311
  devAssert(
5052
5312
  initialState !== null && typeof initialState === "object" && !Array.isArray(initialState),
5053
5313
  "store: argument must be a plain object. For arrays, use array() instead."
5054
5314
  );
5055
- const signals = {};
5315
+ const signals = /* @__PURE__ */ Object.create(null);
5056
5316
  Object.keys(initialState).forEach((key) => {
5057
5317
  const [getter, setter] = signal(initialState[key]);
5058
- signals[key] = [getter, setter];
5318
+ defineOwn(signals, key, [getter, setter]);
5059
5319
  });
5060
5320
  const store2 = new Proxy({}, {
5061
5321
  get(target, prop) {
@@ -5074,7 +5334,7 @@ function store(initialState) {
5074
5334
  const getSnapshot = () => {
5075
5335
  const snapshot = {};
5076
5336
  Object.keys(signals).forEach((key) => {
5077
- snapshot[key] = signals[key][0]();
5337
+ defineOwn(snapshot, key, signals[key][0]());
5078
5338
  });
5079
5339
  return snapshot;
5080
5340
  };
@@ -5210,6 +5470,13 @@ function strictEffect(fn) {
5210
5470
  };
5211
5471
  }
5212
5472
 
5473
+ // src/reactivity/domBinding.ts
5474
+ function domBinding(commit, ownerNode) {
5475
+ if (isSSR()) return () => {
5476
+ };
5477
+ return reactiveBinding2(commit, ownerNode);
5478
+ }
5479
+
5213
5480
  // src/platform/enhance.ts
5214
5481
  var ENHANCED_ATTR = "data-sibu-enhanced";
5215
5482
  var enhancementOwner = /* @__PURE__ */ new WeakMap();
@@ -5245,9 +5512,7 @@ function resolveTarget(root, target) {
5245
5512
  }
5246
5513
  }
5247
5514
  function bindNode(el, commit) {
5248
- if (isSSR()) return () => {
5249
- };
5250
- return reactiveBinding2(commit, el);
5515
+ return domBinding(commit, el);
5251
5516
  }
5252
5517
  function readControlValue(el) {
5253
5518
  if (el instanceof HTMLInputElement) {
@@ -5505,12 +5770,6 @@ function enhanceAll(selector, setup) {
5505
5770
  };
5506
5771
  }
5507
5772
 
5508
- // src/utils/globalSingleton.ts
5509
- function globalSingleton(key, create) {
5510
- const g2 = globalThis;
5511
- return g2[key] ?? (g2[key] = create());
5512
- }
5513
-
5514
5773
  // src/platform/islands.ts
5515
5774
  var SAFE_NAME = /^[A-Za-z0-9_-]+$/;
5516
5775
  var LAZY = /* @__PURE__ */ Symbol.for("sibujs.islands.lazy");
@@ -5716,23 +5975,27 @@ function scheduleIdle(fn) {
5716
5975
  }
5717
5976
  function transition() {
5718
5977
  const [pending, setPending] = signal(false);
5978
+ let outstanding = 0;
5719
5979
  function start(fn) {
5980
+ outstanding++;
5720
5981
  setPending(true);
5982
+ let settled = false;
5983
+ const finish = () => {
5984
+ if (settled) return;
5985
+ settled = true;
5986
+ outstanding--;
5987
+ if (outstanding === 0) setPending(false);
5988
+ };
5989
+ const fail = (error) => {
5990
+ finish();
5991
+ reportError(error, { phase: "async", name: "transition" });
5992
+ };
5721
5993
  scheduleIdle(() => {
5722
- let result;
5723
5994
  try {
5724
- result = fn();
5725
- } catch {
5726
- setPending(false);
5727
- return;
5728
- }
5729
- if (result && typeof result.then === "function") {
5730
- result.then(
5731
- () => setPending(false),
5732
- () => setPending(false)
5733
- );
5734
- } else {
5735
- setPending(false);
5995
+ const adopted = adoptThenable(fn());
5996
+ adopted ? adopted.then(finish, fail) : finish();
5997
+ } catch (error) {
5998
+ fail(error);
5736
5999
  }
5737
6000
  });
5738
6001
  }