sibujs 3.3.0 → 3.3.2

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 (60) hide show
  1. package/dist/browser.cjs +230 -40
  2. package/dist/browser.js +5 -5
  3. package/dist/build.cjs +240 -108
  4. package/dist/build.js +13 -13
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-BEIKESVL.js → chunk-2ARSB7NG.js} +36 -13
  7. package/dist/{chunk-X3NHE2DK.js → chunk-4NJEAPLI.js} +83 -17
  8. package/dist/{chunk-JBXNCZSC.js → chunk-5VH3GIDX.js} +1 -1
  9. package/dist/{chunk-6G6UNHZI.js → chunk-62V653X2.js} +16 -21
  10. package/dist/{chunk-S4FHR5ZZ.js → chunk-655B7MMR.js} +3 -3
  11. package/dist/{chunk-24DBWDTK.js → chunk-6TCOWMGY.js} +1 -1
  12. package/dist/{chunk-USDR2GFV.js → chunk-A7CZH3GN.js} +3 -3
  13. package/dist/{chunk-SLCUP2EK.js → chunk-AEOLHSSQ.js} +3 -3
  14. package/dist/chunk-CCSJMTRN.js +15 -0
  15. package/dist/{chunk-R3QEDXFS.js → chunk-EX77FXTT.js} +1 -1
  16. package/dist/{chunk-ZUVLC7TM.js → chunk-FJIRS3FM.js} +1 -1
  17. package/dist/{chunk-4WXWJ4SW.js → chunk-FJO2ZL4Q.js} +4 -4
  18. package/dist/{chunk-CVMMULHO.js → chunk-G6N3LMO2.js} +4 -4
  19. package/dist/{chunk-XQ7XSGYP.js → chunk-IQJ36UTJ.js} +1 -1
  20. package/dist/{chunk-5K72I3UQ.js → chunk-JCQG2I2G.js} +21 -4
  21. package/dist/{chunk-7JHWAGRQ.js → chunk-N5TQVEKE.js} +2 -2
  22. package/dist/{chunk-IHBVTURX.js → chunk-P7C7SEJV.js} +4 -4
  23. package/dist/{chunk-M6WSIGYW.js → chunk-Q46YIQYW.js} +2 -2
  24. package/dist/{chunk-Q2ERM6NT.js → chunk-QCFBIVIQ.js} +1 -1
  25. package/dist/{chunk-F4UM7QBJ.js → chunk-RLTFJYDN.js} +2 -2
  26. package/dist/{chunk-GOJMFRBL.js → chunk-S3NFJO6L.js} +20 -14
  27. package/dist/{chunk-MWZFOIBG.js → chunk-YUBEOWII.js} +5 -5
  28. package/dist/{chunk-WVJJUFPC.js → chunk-YUR5SX7F.js} +2 -2
  29. package/dist/{chunk-NUWKIEHE.js → chunk-ZEUP4TUD.js} +2 -2
  30. package/dist/data.cjs +181 -37
  31. package/dist/data.js +7 -7
  32. package/dist/devtools.cjs +265 -45
  33. package/dist/devtools.js +5 -5
  34. package/dist/ecosystem.cjs +203 -59
  35. package/dist/ecosystem.js +8 -8
  36. package/dist/extras.cjs +216 -116
  37. package/dist/extras.js +22 -22
  38. package/dist/index.cjs +242 -108
  39. package/dist/index.d.cts +78 -14
  40. package/dist/index.d.ts +78 -14
  41. package/dist/index.js +17 -13
  42. package/dist/motion.cjs +329 -13
  43. package/dist/motion.js +3 -3
  44. package/dist/patterns.cjs +181 -37
  45. package/dist/patterns.js +6 -6
  46. package/dist/performance.cjs +278 -37
  47. package/dist/performance.js +6 -6
  48. package/dist/plugins.cjs +353 -153
  49. package/dist/plugins.js +95 -94
  50. package/dist/{ssr-6D67RAVB.js → ssr-2PPULEK2.js} +2 -2
  51. package/dist/ssr.cjs +203 -58
  52. package/dist/ssr.js +9 -9
  53. package/dist/testing.cjs +416 -19
  54. package/dist/testing.js +3 -3
  55. package/dist/ui.cjs +256 -65
  56. package/dist/ui.js +8 -8
  57. package/dist/widgets.cjs +166 -40
  58. package/dist/widgets.js +7 -7
  59. package/package.json +1 -1
  60. package/dist/chunk-YT6HQ6AM.js +0 -14
package/dist/plugins.cjs CHANGED
@@ -140,6 +140,25 @@ var init_sanitize = __esm({
140
140
  });
141
141
 
142
142
  // src/core/ssr-context.ts
143
+ function detectSSRShared() {
144
+ let detected = null;
145
+ try {
146
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
147
+ let mod = null;
148
+ const getBuiltin = process.getBuiltinModule;
149
+ if (typeof getBuiltin === "function") {
150
+ mod = getBuiltin("node:async_hooks");
151
+ } else {
152
+ const req = Function("return typeof require==='function'?require:null")();
153
+ if (req) mod = req("node:async_hooks");
154
+ }
155
+ if (mod) detected = new mod.AsyncLocalStorage();
156
+ }
157
+ } catch {
158
+ detected = null;
159
+ }
160
+ return { als: detected, fallbackStore: { ssr: false, suspenseIdCounter: 0 } };
161
+ }
143
162
  function getSSRStore() {
144
163
  if (als) {
145
164
  const s2 = als.getStore();
@@ -150,27 +169,14 @@ function getSSRStore() {
150
169
  function isSSR() {
151
170
  return getSSRStore().ssr;
152
171
  }
153
- var als, fallbackStore;
172
+ var SSR_KEY, _shared, als, fallbackStore;
154
173
  var init_ssr_context = __esm({
155
174
  "src/core/ssr-context.ts"() {
156
175
  "use strict";
157
- als = null;
158
- try {
159
- if (typeof process !== "undefined" && process.versions && process.versions.node) {
160
- let mod = null;
161
- const getBuiltin = process.getBuiltinModule;
162
- if (typeof getBuiltin === "function") {
163
- mod = getBuiltin("node:async_hooks");
164
- } else {
165
- const req = Function("return typeof require==='function'?require:null")();
166
- if (req) mod = req("node:async_hooks");
167
- }
168
- if (mod) als = new mod.AsyncLocalStorage();
169
- }
170
- } catch {
171
- als = null;
172
- }
173
- fallbackStore = { ssr: false, suspenseIdCounter: 0 };
176
+ SSR_KEY = /* @__PURE__ */ Symbol.for("sibujs.ssr.v1");
177
+ _shared = globalThis[SSR_KEY] ?? (globalThis[SSR_KEY] = detectSSRShared());
178
+ als = _shared.als;
179
+ fallbackStore = _shared.fallbackStore;
174
180
  }
175
181
  });
176
182
 
@@ -203,7 +209,7 @@ function isSafeAttrName(name) {
203
209
  return SAFE_ATTR_NAME.test(name);
204
210
  }
205
211
  function ssrErrorComment(err) {
206
- if (_isDev8) {
212
+ if (_isDev9) {
207
213
  const msg = escapeHtml(err instanceof Error ? err.message : String(err));
208
214
  return `<!--SSR error: ${safeCommentText(msg)}-->`;
209
215
  }
@@ -233,10 +239,10 @@ function renderToString(element) {
233
239
  }
234
240
  const tag = element.tagName.toLowerCase();
235
241
  if (tag === "script" || tag === "style") {
236
- return _isDev8 ? `<!--ssr:${tag}-stripped-->` : "";
242
+ return _isDev9 ? `<!--ssr:${tag}-stripped-->` : "";
237
243
  }
238
244
  if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
239
- return _isDev8 ? "<!--ssr:invalid-tag-->" : "";
245
+ return _isDev9 ? "<!--ssr:invalid-tag-->" : "";
240
246
  }
241
247
  let html2 = `<${tag}`;
242
248
  for (const attr of Array.from(element.attributes)) {
@@ -277,7 +283,7 @@ function hydrate(component, container, options = {}) {
277
283
  const first = mismatches[0];
278
284
  if (options.onMismatch) {
279
285
  options.onMismatch(first);
280
- } else if (_isDev8) {
286
+ } else if (_isDev9) {
281
287
  console.warn(
282
288
  `[SibuJS hydration] ${first.message}
283
289
  at ${first.path}
@@ -472,11 +478,11 @@ async function* renderToStream(element) {
472
478
  }
473
479
  const tag = element.tagName.toLowerCase();
474
480
  if (tag === "script" || tag === "style") {
475
- if (_isDev8) yield `<!--ssr:${tag}-stripped-->`;
481
+ if (_isDev9) yield `<!--ssr:${tag}-stripped-->`;
476
482
  return;
477
483
  }
478
484
  if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
479
- if (_isDev8) yield "<!--ssr:invalid-tag-->";
485
+ if (_isDev9) yield "<!--ssr:invalid-tag-->";
480
486
  return;
481
487
  }
482
488
  let openTag = `<${tag}`;
@@ -579,7 +585,7 @@ function hydrateProgressively(container, islands, options) {
579
585
  }
580
586
  container.setAttribute("data-sibu-hydrated", "progressive");
581
587
  return () => {
582
- for (const cleanup2 of cleanups) cleanup2();
588
+ for (const cleanup3 of cleanups) cleanup3();
583
589
  };
584
590
  }
585
591
  function resetSSRState() {
@@ -608,7 +614,7 @@ function ssrSuspense(props) {
608
614
  },
609
615
  (err) => {
610
616
  if (timer) clearTimeout(timer);
611
- if (_isDev8) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
617
+ if (_isDev9) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
612
618
  return { id, html: fallbackHtml };
613
619
  }
614
620
  );
@@ -651,7 +657,7 @@ function serializeState(state, nonce, options) {
651
657
  }
652
658
  function deserializeState(validate) {
653
659
  if (typeof window === "undefined") return void 0;
654
- if (_isDev8 && !validate) {
660
+ if (_isDev9 && !validate) {
655
661
  console.warn(
656
662
  "[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
657
663
  );
@@ -668,14 +674,14 @@ function escapeHtml(str) {
668
674
  function escapeAttr(str) {
669
675
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
670
676
  }
671
- var _isDev8, SAFE_ATTR_NAME, URL_ATTRS, VOID_ELEMENTS, SAFE_ID, SAFE_SUSPENSE_ID, SSR_DATA_ATTR, DEFAULT_MAX_SSR_BYTES;
677
+ var _isDev9, SAFE_ATTR_NAME, URL_ATTRS, VOID_ELEMENTS, SAFE_ID, SAFE_SUSPENSE_ID, SSR_DATA_ATTR, DEFAULT_MAX_SSR_BYTES;
672
678
  var init_ssr = __esm({
673
679
  "src/platform/ssr.ts"() {
674
680
  "use strict";
675
681
  init_dev();
676
682
  init_ssr_context();
677
683
  init_sanitize();
678
- _isDev8 = isDev();
684
+ _isDev9 = isDev();
679
685
  SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
680
686
  URL_ATTRS = /* @__PURE__ */ new Set([
681
687
  "href",
@@ -804,6 +810,9 @@ init_sanitize();
804
810
 
805
811
  // src/reactivity/track.ts
806
812
  init_dev();
813
+
814
+ // src/reactivity/track-core.ts
815
+ init_dev();
807
816
  var _isDev2 = isDev();
808
817
  var POOL_MAX = 4096;
809
818
  var nodePool = [];
@@ -887,6 +896,7 @@ function unlinkSub(node) {
887
896
  else sub2.depsTail = prev;
888
897
  }
889
898
  var currentSubscriber = null;
899
+ var suspendSavedSub = null;
890
900
  var notifyDepth = 0;
891
901
  var pendingQueue = [];
892
902
  var pendingSet = /* @__PURE__ */ new Set();
@@ -898,6 +908,35 @@ function safeInvoke(sub2) {
898
908
  if (_isDev2) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
899
909
  }
900
910
  }
911
+ var suspendDepth = 0;
912
+ var trackingSuspended = false;
913
+ function suspendTracking() {
914
+ if (suspendDepth === 0) {
915
+ suspendSavedSub = currentSubscriber;
916
+ currentSubscriber = null;
917
+ trackingSuspended = true;
918
+ }
919
+ suspendDepth++;
920
+ }
921
+ function resumeTracking() {
922
+ suspendDepth--;
923
+ if (suspendDepth === 0) {
924
+ currentSubscriber = suspendSavedSub;
925
+ suspendSavedSub = null;
926
+ trackingSuspended = false;
927
+ }
928
+ }
929
+ function isTrackingSuspended() {
930
+ return trackingSuspended;
931
+ }
932
+ function untracked(fn) {
933
+ suspendTracking();
934
+ try {
935
+ return fn();
936
+ } finally {
937
+ resumeTracking();
938
+ }
939
+ }
901
940
  var subscriberEpochCounter = 0;
902
941
  function retrack(effectFn, subscriber) {
903
942
  const prev = currentSubscriber;
@@ -1007,6 +1046,16 @@ function cleanup(subscriber) {
1007
1046
  var maxSubscriberRepeats = 50;
1008
1047
  var maxDrainIterations = 1e6;
1009
1048
  var drainEpoch = 0;
1049
+ function setMaxSubscriberRepeats(n) {
1050
+ const prev = maxSubscriberRepeats;
1051
+ if (Number.isFinite(n) && n > 0) maxSubscriberRepeats = Math.floor(n);
1052
+ return prev;
1053
+ }
1054
+ function setMaxDrainIterations(n) {
1055
+ const prev = maxDrainIterations;
1056
+ if (Number.isFinite(n) && n > 0) maxDrainIterations = Math.floor(n);
1057
+ return prev;
1058
+ }
1010
1059
  function tickRepeat(sub2) {
1011
1060
  const s2 = sub2;
1012
1061
  if (s2._runEpoch !== drainEpoch) {
@@ -1048,6 +1097,20 @@ function drainQueue() {
1048
1097
  safeInvoke(sub2);
1049
1098
  }
1050
1099
  }
1100
+ function drainNotificationQueue() {
1101
+ if (notifyDepth > 0) return;
1102
+ notifyDepth++;
1103
+ drainEpoch++;
1104
+ try {
1105
+ drainQueue();
1106
+ } finally {
1107
+ notifyDepth--;
1108
+ if (notifyDepth === 0) {
1109
+ pendingQueue.length = 0;
1110
+ pendingSet.clear();
1111
+ }
1112
+ }
1113
+ }
1051
1114
  function propagateDirty(sub2) {
1052
1115
  sub2();
1053
1116
  const rootSig = sub2._sig;
@@ -1080,6 +1143,22 @@ function propagateDirty(sub2) {
1080
1143
  }
1081
1144
  }
1082
1145
  }
1146
+ function queueSignalNotification(signal2) {
1147
+ const sig = signal2;
1148
+ let node = sig.subsHead ?? null;
1149
+ while (node) {
1150
+ const s2 = node.sub;
1151
+ if (s2) {
1152
+ if (s2._c) {
1153
+ propagateDirty(s2);
1154
+ } else if (!pendingSet.has(s2)) {
1155
+ pendingSet.add(s2);
1156
+ pendingQueue.push(s2);
1157
+ }
1158
+ }
1159
+ node = node.sigNext;
1160
+ }
1161
+ }
1083
1162
  function notifySubscribers(signal2) {
1084
1163
  const sig = signal2;
1085
1164
  const head2 = sig.subsHead;
@@ -1125,15 +1204,94 @@ function notifySubscribers(signal2) {
1125
1204
  }
1126
1205
  }
1127
1206
  }
1207
+ function getSubscriberCount(signal2) {
1208
+ return signal2.__sc ?? 0;
1209
+ }
1210
+ function getSubscriberDeps(subscriber) {
1211
+ const sub2 = subscriber;
1212
+ const out = [];
1213
+ let node = sub2.depsHead ?? null;
1214
+ while (node) {
1215
+ if (node.sig) out.push(node.sig);
1216
+ node = node.subNext;
1217
+ }
1218
+ return out;
1219
+ }
1220
+ function forEachSubscriber(signal2, visit) {
1221
+ let node = signal2.subsHead ?? null;
1222
+ while (node) {
1223
+ const s2 = node.sub;
1224
+ if (s2) visit(s2);
1225
+ node = node.sigNext;
1226
+ }
1227
+ }
1128
1228
 
1129
- // src/reactivity/bindAttribute.ts
1229
+ // src/reactivity/track.ts
1130
1230
  var _isDev3 = isDev();
1231
+ var _runtimeVersion = true ? "3.3.2" : "dev";
1232
+ var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
1233
+ function resolveReactiveApi() {
1234
+ const g2 = globalThis;
1235
+ const existing = g2[REGISTRY_KEY];
1236
+ if (existing) {
1237
+ if (_isDev3 && !existing.__dupWarned) {
1238
+ existing.__dupWarned = true;
1239
+ devWarn(
1240
+ `Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity still works \u2014 all copies share the first one \u2014 but de-duplicate sibujs in your bundler (e.g. Vite optimizeDeps.exclude: ['sibujs'] or resolve.dedupe: ['sibujs']).`
1241
+ );
1242
+ }
1243
+ return existing;
1244
+ }
1245
+ const local = {
1246
+ suspendTracking,
1247
+ resumeTracking,
1248
+ isTrackingSuspended,
1249
+ untracked,
1250
+ retrack,
1251
+ track,
1252
+ reactiveBinding,
1253
+ recordDependency,
1254
+ cleanup,
1255
+ setMaxSubscriberRepeats,
1256
+ setMaxDrainIterations,
1257
+ drainNotificationQueue,
1258
+ queueSignalNotification,
1259
+ notifySubscribers,
1260
+ getSubscriberCount,
1261
+ getSubscriberDeps,
1262
+ forEachSubscriber,
1263
+ version: _runtimeVersion
1264
+ };
1265
+ g2[REGISTRY_KEY] = local;
1266
+ return local;
1267
+ }
1268
+ var API = resolveReactiveApi();
1269
+ var suspendTracking2 = API.suspendTracking;
1270
+ var resumeTracking2 = API.resumeTracking;
1271
+ var isTrackingSuspended2 = API.isTrackingSuspended;
1272
+ var untracked2 = API.untracked;
1273
+ var retrack2 = API.retrack;
1274
+ var track2 = API.track;
1275
+ var reactiveBinding2 = API.reactiveBinding;
1276
+ var recordDependency2 = API.recordDependency;
1277
+ var cleanup2 = API.cleanup;
1278
+ var setMaxSubscriberRepeats2 = API.setMaxSubscriberRepeats;
1279
+ var setMaxDrainIterations2 = API.setMaxDrainIterations;
1280
+ var drainNotificationQueue2 = API.drainNotificationQueue;
1281
+ var queueSignalNotification2 = API.queueSignalNotification;
1282
+ var notifySubscribers2 = API.notifySubscribers;
1283
+ var getSubscriberCount2 = API.getSubscriberCount;
1284
+ var getSubscriberDeps2 = API.getSubscriberDeps;
1285
+ var forEachSubscriber2 = API.forEachSubscriber;
1286
+
1287
+ // src/reactivity/bindAttribute.ts
1288
+ var _isDev4 = isDev();
1131
1289
  function setProp(el, key, val) {
1132
1290
  el[key] = val;
1133
1291
  }
1134
1292
  function bindAttribute(el, attr, getter) {
1135
1293
  if (isEventHandlerAttr(attr)) {
1136
- if (_isDev3)
1294
+ if (_isDev4)
1137
1295
  devWarn(
1138
1296
  `bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
1139
1297
  );
@@ -1145,7 +1303,7 @@ function bindAttribute(el, attr, getter) {
1145
1303
  try {
1146
1304
  value = getter();
1147
1305
  } catch (err) {
1148
- if (_isDev3)
1306
+ if (_isDev4)
1149
1307
  devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
1150
1308
  return;
1151
1309
  }
@@ -1166,7 +1324,7 @@ function bindAttribute(el, attr, getter) {
1166
1324
  el.setAttribute(attr, sanitizeAttributeString(attr, str));
1167
1325
  }
1168
1326
  }
1169
- return reactiveBinding(commit);
1327
+ return reactiveBinding2(commit);
1170
1328
  }
1171
1329
 
1172
1330
  // src/reactivity/bindChildNode.ts
@@ -1175,7 +1333,7 @@ init_dev();
1175
1333
  // src/core/rendering/dispose.ts
1176
1334
  init_dev();
1177
1335
  var elementDisposers = /* @__PURE__ */ new WeakMap();
1178
- var _isDev4 = isDev();
1336
+ var _isDev5 = isDev();
1179
1337
  var activeBindingCount = 0;
1180
1338
  function registerDisposer(node, teardown) {
1181
1339
  let disposers = elementDisposers.get(node);
@@ -1184,7 +1342,7 @@ function registerDisposer(node, teardown) {
1184
1342
  elementDisposers.set(node, disposers);
1185
1343
  }
1186
1344
  disposers.push(teardown);
1187
- if (_isDev4) activeBindingCount++;
1345
+ if (_isDev5) activeBindingCount++;
1188
1346
  }
1189
1347
  function dispose(node) {
1190
1348
  const stack = [node];
@@ -1203,12 +1361,12 @@ function dispose(node) {
1203
1361
  if (disposers) {
1204
1362
  const snapshot = disposers.slice();
1205
1363
  elementDisposers.delete(current);
1206
- if (_isDev4) activeBindingCount -= snapshot.length;
1364
+ if (_isDev5) activeBindingCount -= snapshot.length;
1207
1365
  for (const d of snapshot) {
1208
1366
  try {
1209
1367
  d();
1210
1368
  } catch (err) {
1211
- if (_isDev4 && typeof console !== "undefined") {
1369
+ if (_isDev5 && typeof console !== "undefined") {
1212
1370
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
1213
1371
  }
1214
1372
  }
@@ -1219,12 +1377,12 @@ function dispose(node) {
1219
1377
  if (!added || added.length === 0) break;
1220
1378
  const moreSnapshot = added.slice();
1221
1379
  elementDisposers.delete(current);
1222
- if (_isDev4) activeBindingCount -= moreSnapshot.length;
1380
+ if (_isDev5) activeBindingCount -= moreSnapshot.length;
1223
1381
  for (const d of moreSnapshot) {
1224
1382
  try {
1225
1383
  d();
1226
1384
  } catch (err) {
1227
- if (_isDev4 && typeof console !== "undefined") {
1385
+ if (_isDev5 && typeof console !== "undefined") {
1228
1386
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
1229
1387
  }
1230
1388
  }
@@ -1235,7 +1393,7 @@ function dispose(node) {
1235
1393
  }
1236
1394
 
1237
1395
  // src/reactivity/bindChildNode.ts
1238
- var _isDev5 = isDev();
1396
+ var _isDev6 = isDev();
1239
1397
  function bindChildNode(placeholder, getter) {
1240
1398
  let lastNodes = [];
1241
1399
  function commit() {
@@ -1243,7 +1401,7 @@ function bindChildNode(placeholder, getter) {
1243
1401
  try {
1244
1402
  result = getter();
1245
1403
  } catch (err) {
1246
- if (_isDev5) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
1404
+ if (_isDev6) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
1247
1405
  return;
1248
1406
  }
1249
1407
  if (result == null || typeof result === "boolean") {
@@ -1269,7 +1427,7 @@ function bindChildNode(placeholder, getter) {
1269
1427
  if (item == null || typeof item === "boolean") continue;
1270
1428
  const node = item instanceof Node ? item : document.createTextNode(String(item));
1271
1429
  if (seen.has(node)) {
1272
- if (_isDev5)
1430
+ if (_isDev6)
1273
1431
  devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
1274
1432
  continue;
1275
1433
  }
@@ -1304,13 +1462,13 @@ function bindChildNode(placeholder, getter) {
1304
1462
  }
1305
1463
  lastNodes = newNodes;
1306
1464
  }
1307
- return reactiveBinding(commit);
1465
+ return reactiveBinding2(commit);
1308
1466
  }
1309
1467
 
1310
1468
  // src/core/rendering/tagFactory.ts
1311
1469
  init_sanitize();
1312
1470
  var SVG_NS = "http://www.w3.org/2000/svg";
1313
- var _isDev6 = isDev();
1471
+ var _isDev7 = isDev();
1314
1472
  var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
1315
1473
  function isBlockedTag(tag) {
1316
1474
  return BLOCKED_TAGS.has(tag.toLowerCase());
@@ -1353,7 +1511,7 @@ function toKebab(prop) {
1353
1511
  }
1354
1512
  function applyStyle(el, style2) {
1355
1513
  if (typeof style2 === "function") {
1356
- const teardown = track(() => {
1514
+ const teardown = track2(() => {
1357
1515
  el.setAttribute("style", style2());
1358
1516
  });
1359
1517
  registerDisposer(el, teardown);
@@ -1369,7 +1527,7 @@ function applyStyle(el, style2) {
1369
1527
  const name = toKebab(prop);
1370
1528
  if (typeof val === "function") {
1371
1529
  const getter = val;
1372
- const teardown = track(() => {
1530
+ const teardown = track2(() => {
1373
1531
  htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
1374
1532
  });
1375
1533
  registerDisposer(el, teardown);
@@ -1384,7 +1542,7 @@ function applyClass(el, cls) {
1384
1542
  return;
1385
1543
  }
1386
1544
  if (typeof cls === "function") {
1387
- const teardown = track(() => {
1545
+ const teardown = track2(() => {
1388
1546
  el.setAttribute("class", cls());
1389
1547
  });
1390
1548
  registerDisposer(el, teardown);
@@ -1411,7 +1569,7 @@ function applyClass(el, cls) {
1411
1569
  }
1412
1570
  el.setAttribute("class", r);
1413
1571
  };
1414
- const teardown = track(update);
1572
+ const teardown = track2(update);
1415
1573
  registerDisposer(el, teardown);
1416
1574
  } else {
1417
1575
  el.setAttribute("class", result);
@@ -1481,7 +1639,7 @@ var tagFactory = (tag, ns) => {
1481
1639
  appendChildren(el, second);
1482
1640
  return el;
1483
1641
  }
1484
- if (_isDev6 && looksLikeClassList(first)) {
1642
+ if (_isDev7 && looksLikeClassList(first)) {
1485
1643
  devWarn(
1486
1644
  `tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`
1487
1645
  );
@@ -1502,7 +1660,7 @@ var tagFactory = (tag, ns) => {
1502
1660
  if (pClass != null) applyClass(el, pClass);
1503
1661
  const pId = props.id;
1504
1662
  if (pId != null) {
1505
- if (_isDev6 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
1663
+ if (_isDev7 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
1506
1664
  devWarn(
1507
1665
  `tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
1508
1666
  );
@@ -1517,7 +1675,7 @@ var tagFactory = (tag, ns) => {
1517
1675
  const handler = pOn[ev];
1518
1676
  if (typeof handler === "function") {
1519
1677
  el.addEventListener(ev, handler);
1520
- } else if (_isDev6) {
1678
+ } else if (_isDev7) {
1521
1679
  devWarn(
1522
1680
  `tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
1523
1681
  );
@@ -1630,7 +1788,7 @@ var area = tagFactory("area");
1630
1788
  var audio = tagFactory("audio");
1631
1789
  var img = tagFactory("img");
1632
1790
  var map = tagFactory("map");
1633
- var track2 = tagFactory("track");
1791
+ var track3 = tagFactory("track");
1634
1792
  var video = tagFactory("video");
1635
1793
  var embed = tagFactory("embed");
1636
1794
  var iframe = tagFactory("iframe");
@@ -1707,16 +1865,57 @@ var marquee = tagFactory("marquee");
1707
1865
  // src/reactivity/batch.ts
1708
1866
  var batchDepth = 0;
1709
1867
  var pendingSignals = /* @__PURE__ */ new Set();
1710
- function enqueueBatchedSignal(signal2) {
1868
+ function batchImpl(fn) {
1869
+ batchDepth++;
1870
+ try {
1871
+ return fn();
1872
+ } finally {
1873
+ batchDepth--;
1874
+ if (batchDepth === 0) {
1875
+ flushBatch();
1876
+ }
1877
+ }
1878
+ }
1879
+ function enqueueBatchedSignalImpl(signal2) {
1711
1880
  if (batchDepth === 0) return false;
1712
1881
  pendingSignals.add(signal2);
1713
1882
  return true;
1714
1883
  }
1884
+ function isBatchingImpl() {
1885
+ return batchDepth > 0;
1886
+ }
1887
+ function flushBatch() {
1888
+ try {
1889
+ for (const signal2 of pendingSignals) {
1890
+ queueSignalNotification2(signal2);
1891
+ }
1892
+ } finally {
1893
+ pendingSignals.clear();
1894
+ }
1895
+ drainNotificationQueue2();
1896
+ }
1897
+ var BATCH_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.batch.v1");
1898
+ function resolveBatchApi() {
1899
+ const g2 = globalThis;
1900
+ const existing = g2[BATCH_REGISTRY_KEY];
1901
+ if (existing) return existing;
1902
+ const local = {
1903
+ batch: batchImpl,
1904
+ enqueueBatchedSignal: enqueueBatchedSignalImpl,
1905
+ isBatching: isBatchingImpl
1906
+ };
1907
+ g2[BATCH_REGISTRY_KEY] = local;
1908
+ return local;
1909
+ }
1910
+ var API2 = resolveBatchApi();
1911
+ var batch = API2.batch;
1912
+ var enqueueBatchedSignal = API2.enqueueBatchedSignal;
1913
+ var isBatching = API2.isBatching;
1715
1914
 
1716
1915
  // src/core/signals/signal.ts
1717
1916
  init_dev();
1718
1917
  var _g = globalThis;
1719
- var _isDev7 = isDev();
1918
+ var _isDev8 = isDev();
1720
1919
  function signal(initial, options) {
1721
1920
  const state = {
1722
1921
  value: initial,
@@ -1727,11 +1926,11 @@ function signal(initial, options) {
1727
1926
  __activeNode: null,
1728
1927
  __name: void 0
1729
1928
  };
1730
- const debugName = _isDev7 ? options?.name : void 0;
1929
+ const debugName = _isDev8 ? options?.name : void 0;
1731
1930
  const equalsFn = options?.equals;
1732
1931
  if (debugName) state.__name = debugName;
1733
1932
  function get() {
1734
- recordDependency(state);
1933
+ recordDependency2(state);
1735
1934
  return state.value;
1736
1935
  }
1737
1936
  get.__signal = state;
@@ -1744,15 +1943,15 @@ function signal(initial, options) {
1744
1943
  if (equalsFn(prev, newValue)) return;
1745
1944
  state.value = newValue;
1746
1945
  state.__v++;
1747
- if (_isDev7) {
1946
+ if (_isDev8) {
1748
1947
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1749
1948
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
1750
1949
  }
1751
1950
  if (!enqueueBatchedSignal(state)) {
1752
- notifySubscribers(state);
1951
+ notifySubscribers2(state);
1753
1952
  }
1754
1953
  };
1755
- } else if (_isDev7) {
1954
+ } else if (_isDev8) {
1756
1955
  set = (next) => {
1757
1956
  const prev = state.value;
1758
1957
  const newValue = typeof next === "function" ? next(prev) : next;
@@ -1762,7 +1961,7 @@ function signal(initial, options) {
1762
1961
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1763
1962
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
1764
1963
  if (!enqueueBatchedSignal(state)) {
1765
- notifySubscribers(state);
1964
+ notifySubscribers2(state);
1766
1965
  }
1767
1966
  };
1768
1967
  } else {
@@ -1773,11 +1972,11 @@ function signal(initial, options) {
1773
1972
  state.value = newValue;
1774
1973
  state.__v++;
1775
1974
  if (!enqueueBatchedSignal(state)) {
1776
- notifySubscribers(state);
1975
+ notifySubscribers2(state);
1777
1976
  }
1778
1977
  };
1779
1978
  }
1780
- if (_isDev7) {
1979
+ if (_isDev8) {
1781
1980
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1782
1981
  if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
1783
1982
  }
@@ -1834,7 +2033,7 @@ function drainReruns(ctx) {
1834
2033
  do {
1835
2034
  ctx.rerunPending = false;
1836
2035
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1837
- retrack(ctx.bodyFn, ctx.subscriber);
2036
+ retrack2(ctx.bodyFn, ctx.subscriber);
1838
2037
  } while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
1839
2038
  if (ctx.rerunPending) {
1840
2039
  ctx.rerunPending = false;
@@ -1863,7 +2062,7 @@ function disposeEffect(ctx) {
1863
2062
  }
1864
2063
  }
1865
2064
  try {
1866
- cleanup(ctx.subscriber);
2065
+ cleanup2(ctx.subscriber);
1867
2066
  } catch (err) {
1868
2067
  if (typeof console !== "undefined") {
1869
2068
  console.warn("[SibuJS effect] dispose threw:", err);
@@ -1908,7 +2107,7 @@ function effect(effectFn, options) {
1908
2107
  try {
1909
2108
  ctx.rerunPending = false;
1910
2109
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
1911
- retrack(ctx.bodyFn, sub2);
2110
+ retrack2(ctx.bodyFn, sub2);
1912
2111
  if (ctx.rerunPending) drainReruns(ctx);
1913
2112
  } finally {
1914
2113
  ctx.running = false;
@@ -1924,7 +2123,7 @@ function effect(effectFn, options) {
1924
2123
  ctx.subscriber = sub2;
1925
2124
  ctx.running = true;
1926
2125
  try {
1927
- retrack(ctx.bodyFn, ctx.subscriber);
2126
+ retrack2(ctx.bodyFn, ctx.subscriber);
1928
2127
  if (ctx.rerunPending) drainReruns(ctx);
1929
2128
  } finally {
1930
2129
  ctx.running = false;
@@ -2707,7 +2906,8 @@ var NavigationFailureError = class extends Error {
2707
2906
  };
2708
2907
  }
2709
2908
  };
2710
- var globalRouter = null;
2909
+ var ROUTER_KEY = /* @__PURE__ */ Symbol.for("sibujs.router.v1");
2910
+ var _routerRef = globalThis[ROUTER_KEY] ?? (globalThis[ROUTER_KEY] = { current: null });
2711
2911
  function normalizeRoutes(routes) {
2712
2912
  return routes.map((route2) => {
2713
2913
  const normalizedChildren = route2.children && route2.children.length > 0 ? normalizeRoutes(route2.children) : route2.children;
@@ -2727,8 +2927,8 @@ function normalizeRoutes(routes) {
2727
2927
  });
2728
2928
  }
2729
2929
  function createRouter(routesOrOptions, options = {}) {
2730
- if (globalRouter) {
2731
- globalRouter.destroy();
2930
+ if (_routerRef.current) {
2931
+ _routerRef.current.destroy();
2732
2932
  }
2733
2933
  let routes;
2734
2934
  if (Array.isArray(routesOrOptions)) {
@@ -2737,69 +2937,69 @@ function createRouter(routesOrOptions, options = {}) {
2737
2937
  options = routesOrOptions;
2738
2938
  routes = [];
2739
2939
  }
2740
- globalRouter = new SibuRouter(routes, options);
2940
+ _routerRef.current = new SibuRouter(routes, options);
2741
2941
  ensureRouterPagehide();
2742
- return globalRouter;
2942
+ return _routerRef.current;
2743
2943
  }
2744
2944
  function setRoutes(routes) {
2745
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2746
- globalRouter.updateRoutes(normalizeRoutes(routes));
2945
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2946
+ _routerRef.current.updateRoutes(normalizeRoutes(routes));
2747
2947
  }
2748
2948
  function route() {
2749
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2750
- return globalRouter.currentRoute;
2949
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2950
+ return _routerRef.current.currentRoute;
2751
2951
  }
2752
2952
  function router() {
2753
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2953
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2754
2954
  return {
2755
- currentRoute: globalRouter.currentRoute,
2756
- isReady: globalRouter.isReady,
2757
- isNavigating: globalRouter.isNavigating,
2758
- push: (to) => globalRouter?.push(to),
2759
- replace: (to) => globalRouter?.replace(to),
2760
- go: (delta) => globalRouter?.go(delta),
2761
- back: () => globalRouter?.back(),
2762
- forward: () => globalRouter?.forward(),
2763
- beforeEach: (guard) => globalRouter?.beforeEach(guard),
2764
- beforeResolve: (guard) => globalRouter?.beforeResolve(guard),
2765
- afterEach: (hook) => globalRouter?.afterEach(hook)
2955
+ currentRoute: _routerRef.current.currentRoute,
2956
+ isReady: _routerRef.current.isReady,
2957
+ isNavigating: _routerRef.current.isNavigating,
2958
+ push: (to) => _routerRef.current?.push(to),
2959
+ replace: (to) => _routerRef.current?.replace(to),
2960
+ go: (delta) => _routerRef.current?.go(delta),
2961
+ back: () => _routerRef.current?.back(),
2962
+ forward: () => _routerRef.current?.forward(),
2963
+ beforeEach: (guard) => _routerRef.current?.beforeEach(guard),
2964
+ beforeResolve: (guard) => _routerRef.current?.beforeResolve(guard),
2965
+ afterEach: (hook) => _routerRef.current?.afterEach(hook)
2766
2966
  };
2767
2967
  }
2768
2968
  function navigate(to, options) {
2769
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2770
- return globalRouter.navigate(to, options);
2969
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2970
+ return _routerRef.current.navigate(to, options);
2771
2971
  }
2772
2972
  function push(to) {
2773
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2774
- return globalRouter.push(to);
2973
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2974
+ return _routerRef.current.push(to);
2775
2975
  }
2776
2976
  function replace(to) {
2777
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2778
- return globalRouter.replace(to);
2977
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2978
+ return _routerRef.current.replace(to);
2779
2979
  }
2780
2980
  function go(delta) {
2781
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2782
- globalRouter.go(delta);
2981
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2982
+ _routerRef.current.go(delta);
2783
2983
  }
2784
2984
  function back() {
2785
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2786
- globalRouter.back();
2985
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2986
+ _routerRef.current.back();
2787
2987
  }
2788
2988
  function forward() {
2789
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2790
- globalRouter.forward();
2989
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2990
+ _routerRef.current.forward();
2791
2991
  }
2792
2992
  function beforeEach(guard) {
2793
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2794
- return globalRouter.beforeEach(guard);
2993
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2994
+ return _routerRef.current.beforeEach(guard);
2795
2995
  }
2796
2996
  function beforeResolve(guard) {
2797
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2798
- return globalRouter.beforeResolve(guard);
2997
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2998
+ return _routerRef.current.beforeResolve(guard);
2799
2999
  }
2800
3000
  function afterEach(hook) {
2801
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2802
- return globalRouter.afterEach(hook);
3001
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3002
+ return _routerRef.current.afterEach(hook);
2803
3003
  }
2804
3004
  var routeCleanups = [];
2805
3005
  function Route() {
@@ -2873,8 +3073,8 @@ function Route() {
2873
3073
  retryButton.className = "route-error-retry";
2874
3074
  retryButton.type = "button";
2875
3075
  const onRetryClick = () => {
2876
- if (globalRouter) {
2877
- globalRouter.clearErrorCache();
3076
+ if (_routerRef.current) {
3077
+ _routerRef.current.clearErrorCache();
2878
3078
  update();
2879
3079
  }
2880
3080
  };
@@ -2886,11 +3086,11 @@ function Route() {
2886
3086
  anchor.parentNode.insertBefore(errorNode, anchor.nextSibling);
2887
3087
  };
2888
3088
  const update = async () => {
2889
- if (!globalRouter) return;
3089
+ if (!_routerRef.current) return;
2890
3090
  const seq = ++navSeq;
2891
- const route2 = globalRouter.currentRoute;
3091
+ const route2 = _routerRef.current.currentRoute;
2892
3092
  try {
2893
- const match = globalRouter["matcher"].match(route2.path);
3093
+ const match = _routerRef.current["matcher"].match(route2.path);
2894
3094
  if (!match) {
2895
3095
  currentTopRoute = null;
2896
3096
  cleanupNodes();
@@ -2903,7 +3103,7 @@ function Route() {
2903
3103
  if ("redirect" in routeDef) {
2904
3104
  const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
2905
3105
  queueMicrotask(() => {
2906
- globalRouter?.navigate(redirectPath).catch((err) => {
3106
+ _routerRef.current?.navigate(redirectPath).catch((err) => {
2907
3107
  if (typeof console !== "undefined") console.error("[router] redirect failed:", err);
2908
3108
  });
2909
3109
  });
@@ -2915,7 +3115,7 @@ function Route() {
2915
3115
  if (isAsync) {
2916
3116
  showLoading();
2917
3117
  }
2918
- const component = await globalRouter.loadComponent(routeDef, route2.path);
3118
+ const component = await _routerRef.current.loadComponent(routeDef, route2.path);
2919
3119
  if (seq !== navSeq) return;
2920
3120
  const node = component();
2921
3121
  if (node && anchor.parentNode) {
@@ -2943,7 +3143,7 @@ function Route() {
2943
3143
  await originalUpdate();
2944
3144
  routeInitialized = true;
2945
3145
  };
2946
- const routeTeardown = track(wrappedUpdate);
3146
+ const routeTeardown = track2(wrappedUpdate);
2947
3147
  if (!routeInitialized) {
2948
3148
  queueMicrotask(() => {
2949
3149
  if (!routeInitialized && anchor.parentNode) wrappedUpdate();
@@ -2956,11 +3156,11 @@ function Route() {
2956
3156
  return anchor;
2957
3157
  }
2958
3158
  function KeepAliveRoute(options) {
2959
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3159
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2960
3160
  const anchor = document.createComment("keep-alive-route");
2961
3161
  const cache = /* @__PURE__ */ new Map();
2962
3162
  const lruOrder = [];
2963
- const routerOpts = globalRouter["options"];
3163
+ const routerOpts = _routerRef.current["options"];
2964
3164
  const keepAliveOpt = routerOpts.keepAlive;
2965
3165
  const maxCache = options?.max ?? (typeof keepAliveOpt === "number" ? keepAliveOpt : 20);
2966
3166
  const includeNames = options?.include ?? (Array.isArray(keepAliveOpt) ? keepAliveOpt : void 0);
@@ -2970,19 +3170,19 @@ function KeepAliveRoute(options) {
2970
3170
  let isUpdating = false;
2971
3171
  let pendingUpdate = false;
2972
3172
  const update = async () => {
2973
- if (!globalRouter) return;
3173
+ if (!_routerRef.current) return;
2974
3174
  if (isUpdating) {
2975
3175
  pendingUpdate = true;
2976
3176
  return;
2977
3177
  }
2978
- const route2 = globalRouter.currentRoute;
2979
- const match = globalRouter["matcher"].match(route2.path);
3178
+ const route2 = _routerRef.current.currentRoute;
3179
+ const match = _routerRef.current["matcher"].match(route2.path);
2980
3180
  if (!match) return;
2981
3181
  const { route: routeDef } = match;
2982
3182
  if ("redirect" in routeDef) {
2983
3183
  const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
2984
3184
  queueMicrotask(() => {
2985
- globalRouter?.navigate(redirectPath).catch((err) => {
3185
+ _routerRef.current?.navigate(redirectPath).catch((err) => {
2986
3186
  if (typeof console !== "undefined") console.error("[router] redirect failed:", err);
2987
3187
  });
2988
3188
  });
@@ -3015,9 +3215,9 @@ function KeepAliveRoute(options) {
3015
3215
  }
3016
3216
  lruOrder.push(cacheKey);
3017
3217
  } else {
3018
- const component = await globalRouter.loadComponent(routeDef, route2.path);
3218
+ const component = await _routerRef.current.loadComponent(routeDef, route2.path);
3019
3219
  const node = component();
3020
- if (!node || route2.path !== globalRouter.currentRoute.path) {
3220
+ if (!node || route2.path !== _routerRef.current.currentRoute.path) {
3021
3221
  isUpdating = false;
3022
3222
  return;
3023
3223
  }
@@ -3056,7 +3256,7 @@ function KeepAliveRoute(options) {
3056
3256
  await update();
3057
3257
  initialized = true;
3058
3258
  };
3059
- const kaTeardown = track(wrappedUpdate);
3259
+ const kaTeardown = track2(wrappedUpdate);
3060
3260
  if (!initialized) {
3061
3261
  queueMicrotask(() => {
3062
3262
  if (!initialized && anchor.parentNode) wrappedUpdate();
@@ -3076,11 +3276,11 @@ function KeepAliveRoute(options) {
3076
3276
  return anchor;
3077
3277
  }
3078
3278
  function RouterLink(props) {
3079
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3279
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3080
3280
  const { to, replace: replace2 = false, activeClass, exactActiveClass, nodes, target, rel, class: classAttr, ...attrs } = props;
3081
3281
  const baseClass = typeof classAttr === "string" ? classAttr : "";
3082
- const routeGetter = globalRouter.routeGetter;
3083
- const rawHref = globalRouter["resolvePath"](to);
3282
+ const routeGetter = _routerRef.current.routeGetter;
3283
+ const rawHref = _routerRef.current["resolvePath"](to);
3084
3284
  const href = isSafeNavigationTarget(rawHref) ? rawHref : "#";
3085
3285
  const hrefPath = href.split("?")[0].split("#")[0];
3086
3286
  const link2 = document.createElement("a");
@@ -3095,7 +3295,7 @@ function RouterLink(props) {
3095
3295
  } else if (rel) {
3096
3296
  link2.rel = rel;
3097
3297
  }
3098
- const options = globalRouter["options"];
3298
+ const options = _routerRef.current["options"];
3099
3299
  const effectCleanup = effect(() => {
3100
3300
  const route2 = routeGetter();
3101
3301
  const isActive = route2.path.startsWith(hrefPath);
@@ -3145,7 +3345,7 @@ function RouterLink(props) {
3145
3345
  return;
3146
3346
  }
3147
3347
  e.preventDefault();
3148
- globalRouter?.navigate(to, { replace: replace2 }).catch((err) => {
3348
+ _routerRef.current?.navigate(to, { replace: replace2 }).catch((err) => {
3149
3349
  if (typeof console !== "undefined") console.error("[router] link navigate failed:", err);
3150
3350
  });
3151
3351
  };
@@ -3231,35 +3431,35 @@ function lazy(importFn) {
3231
3431
  return importFn;
3232
3432
  }
3233
3433
  async function preloadRoute(to) {
3234
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3235
- const path2 = globalRouter["resolvePath"](to);
3236
- const match = globalRouter["matcher"].match(path2.split("?")[0].split("#")[0]);
3434
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3435
+ const path2 = _routerRef.current["resolvePath"](to);
3436
+ const match = _routerRef.current["matcher"].match(path2.split("?")[0].split("#")[0]);
3237
3437
  if (match && "component" in match.route) {
3238
3438
  try {
3239
- await globalRouter.loadComponent(match.route, path2);
3439
+ await _routerRef.current.loadComponent(match.route, path2);
3240
3440
  } catch (error) {
3241
3441
  console.warn("[Router] Preload failed:", error);
3242
3442
  }
3243
3443
  }
3244
3444
  }
3245
3445
  function hasRoute(name) {
3246
- if (!globalRouter) return false;
3247
- return globalRouter["matcher"].findByName(name) !== null;
3446
+ if (!_routerRef.current) return false;
3447
+ return _routerRef.current["matcher"].findByName(name) !== null;
3248
3448
  }
3249
3449
  function getRouteInfo(name) {
3250
- if (!globalRouter) return null;
3251
- return globalRouter["matcher"].findByName(name);
3450
+ if (!_routerRef.current) return null;
3451
+ return _routerRef.current["matcher"].findByName(name);
3252
3452
  }
3253
3453
  function buildURL(to) {
3254
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3255
- return globalRouter["resolvePath"](to);
3454
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3455
+ return _routerRef.current["resolvePath"](to);
3256
3456
  }
3257
3457
  function destroyRouter() {
3258
3458
  for (const fn of routeCleanups) fn();
3259
3459
  routeCleanups.length = 0;
3260
- if (globalRouter) {
3261
- globalRouter.destroy();
3262
- globalRouter = null;
3460
+ if (_routerRef.current) {
3461
+ _routerRef.current.destroy();
3462
+ _routerRef.current = null;
3263
3463
  }
3264
3464
  }
3265
3465
  var _routerPagehideHandler = null;
@@ -3292,9 +3492,9 @@ function Outlet() {
3292
3492
  currentChild = null;
3293
3493
  };
3294
3494
  const update = async () => {
3295
- if (!globalRouter) return;
3495
+ if (!_routerRef.current) return;
3296
3496
  const seq = ++navSeq;
3297
- const route2 = globalRouter.currentRoute;
3497
+ const route2 = _routerRef.current.currentRoute;
3298
3498
  if (route2.matched.length < 2) {
3299
3499
  clearCurrent();
3300
3500
  return;
@@ -3307,7 +3507,7 @@ function Outlet() {
3307
3507
  if (childRoute === currentChild && currentNode) return;
3308
3508
  try {
3309
3509
  const cacheKey = `${route2.path}\0${childRoute.path}`;
3310
- const component = await globalRouter.loadComponent(childRoute, cacheKey);
3510
+ const component = await _routerRef.current.loadComponent(childRoute, cacheKey);
3311
3511
  if (seq !== navSeq) return;
3312
3512
  const node = component();
3313
3513
  if (node && anchor.parentNode) {
@@ -3321,7 +3521,7 @@ function Outlet() {
3321
3521
  console.error("[Outlet] Failed to render child route:", error);
3322
3522
  }
3323
3523
  };
3324
- const outletTeardown = track(update);
3524
+ const outletTeardown = track2(update);
3325
3525
  if (!anchor.parentNode) {
3326
3526
  queueMicrotask(() => {
3327
3527
  if (anchor.parentNode) update();
@@ -3338,16 +3538,16 @@ function Outlet() {
3338
3538
  return anchor;
3339
3539
  }
3340
3540
  function addRoute(route2, parentPath) {
3341
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3342
- globalRouter.addRoute(route2, parentPath);
3541
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3542
+ _routerRef.current.addRoute(route2, parentPath);
3343
3543
  }
3344
3544
  function removeRoute(path2) {
3345
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3346
- globalRouter.removeRoute(path2);
3545
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3546
+ _routerRef.current.removeRoute(path2);
3347
3547
  }
3348
3548
  function routerState() {
3349
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3350
- const router2 = globalRouter;
3549
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3550
+ const router2 = _routerRef.current;
3351
3551
  return {
3352
3552
  currentPath: () => router2.currentRoute.path,
3353
3553
  params: () => router2.currentRoute.params,
@@ -3361,12 +3561,12 @@ function routerState() {
3361
3561
  var routerPlugins = [];
3362
3562
  function routerPlugin(plugin2) {
3363
3563
  routerPlugins.push(plugin2);
3364
- if (globalRouter?.isReady && plugin2.onReady) {
3564
+ if (_routerRef.current?.isReady && plugin2.onReady) {
3365
3565
  plugin2.onReady();
3366
3566
  }
3367
3567
  let removeGuard = null;
3368
- if (globalRouter && plugin2.onNavigate) {
3369
- removeGuard = globalRouter.afterEach((to, from) => {
3568
+ if (_routerRef.current && plugin2.onNavigate) {
3569
+ removeGuard = _routerRef.current.afterEach((to, from) => {
3370
3570
  plugin2.onNavigate?.(to, from);
3371
3571
  });
3372
3572
  }