sibujs 3.3.1 → 3.3.3

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 (78) hide show
  1. package/dist/browser.cjs +41 -18
  2. package/dist/browser.js +5 -5
  3. package/dist/build.cjs +57 -22
  4. package/dist/build.js +14 -14
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-MHBCEJQO.js → chunk-23VT3KZB.js} +2 -2
  7. package/dist/{chunk-WL7BIR6O.js → chunk-25LY5SRH.js} +31 -24
  8. package/dist/{chunk-37BUKSLH.js → chunk-5K6RVA2S.js} +1 -1
  9. package/dist/{chunk-AMIKDMLP.js → chunk-5Y34FWED.js} +17 -6
  10. package/dist/chunk-7ZHH77QA.js +9 -0
  11. package/dist/chunk-CCSJMTRN.js +15 -0
  12. package/dist/{chunk-R3QEDXFS.js → chunk-EX77FXTT.js} +1 -1
  13. package/dist/{chunk-WW6DAGGR.js → chunk-F3HO2MP7.js} +1 -1
  14. package/dist/{chunk-ZUVLC7TM.js → chunk-F7HW2NI5.js} +2 -4
  15. package/dist/{chunk-ULLTNDRA.js → chunk-IEYFHN5V.js} +72 -25
  16. package/dist/{chunk-Z37APKBV.js → chunk-IQN5W7GE.js} +73 -16
  17. package/dist/{chunk-WZG2SZOT.js → chunk-IWFE4AHO.js} +1 -1
  18. package/dist/{chunk-IKLYI3RF.js → chunk-MYXEBADX.js} +53 -23
  19. package/dist/{chunk-6LTFHJQG.js → chunk-QCQQ2N5H.js} +41 -20
  20. package/dist/{chunk-VOVVTOEA.js → chunk-QTOOBABV.js} +22 -5
  21. package/dist/{chunk-LU2MQXQQ.js → chunk-RZKGMHH4.js} +6 -6
  22. package/dist/{chunk-GOJMFRBL.js → chunk-S3NFJO6L.js} +20 -14
  23. package/dist/{chunk-NHKQKKZU.js → chunk-SBPUXWCE.js} +1 -1
  24. package/dist/{chunk-SLMFA3ZZ.js → chunk-TBDTU7UO.js} +2 -2
  25. package/dist/{chunk-4UUMSLSL.js → chunk-TVCCXPU2.js} +5 -5
  26. package/dist/{chunk-TEFZT5PJ.js → chunk-UOMYIAG6.js} +1 -1
  27. package/dist/{chunk-XH2RTYEQ.js → chunk-WFUUT6TG.js} +15 -8
  28. package/dist/{chunk-M5KBNOSJ.js → chunk-WTFMV2RU.js} +70 -59
  29. package/dist/{chunk-3JHCYHWN.js → chunk-WWV3SJ3L.js} +19 -13
  30. package/dist/{chunk-RYMOSG5B.js → chunk-Y35NQNLG.js} +90 -60
  31. package/dist/{chunk-F7FXQ3QS.js → chunk-ZXCZWMZT.js} +1 -1
  32. package/dist/data.cjs +36 -16
  33. package/dist/data.js +8 -7
  34. package/dist/devtools.cjs +91 -35
  35. package/dist/devtools.d.cts +12 -5
  36. package/dist/devtools.d.ts +12 -5
  37. package/dist/devtools.js +7 -6
  38. package/dist/ecosystem.cjs +31 -16
  39. package/dist/ecosystem.js +11 -10
  40. package/dist/extras.cjs +485 -280
  41. package/dist/extras.d.cts +1 -1
  42. package/dist/extras.d.ts +1 -1
  43. package/dist/extras.js +28 -24
  44. package/dist/index.cjs +59 -22
  45. package/dist/index.d.cts +24 -8
  46. package/dist/index.d.ts +24 -8
  47. package/dist/index.js +25 -21
  48. package/dist/motion.cjs +223 -204
  49. package/dist/motion.d.cts +8 -1
  50. package/dist/motion.d.ts +8 -1
  51. package/dist/motion.js +6 -3
  52. package/dist/patterns.cjs +33 -20
  53. package/dist/patterns.d.cts +4 -1
  54. package/dist/patterns.d.ts +4 -1
  55. package/dist/patterns.js +6 -6
  56. package/dist/performance.cjs +90 -70
  57. package/dist/performance.js +8 -7
  58. package/dist/plugins.cjs +207 -144
  59. package/dist/plugins.d.cts +2 -1
  60. package/dist/plugins.d.ts +2 -1
  61. package/dist/plugins.js +178 -124
  62. package/dist/{ssr-6D67RAVB.js → ssr-2PPULEK2.js} +2 -2
  63. package/dist/ssr.cjs +132 -105
  64. package/dist/ssr.d.cts +8 -1
  65. package/dist/ssr.d.ts +8 -1
  66. package/dist/ssr.js +11 -10
  67. package/dist/testing.cjs +38 -18
  68. package/dist/testing.js +19 -8
  69. package/dist/ui.cjs +337 -294
  70. package/dist/ui.d.cts +0 -20
  71. package/dist/ui.d.ts +0 -20
  72. package/dist/ui.js +30 -24
  73. package/dist/widgets.cjs +95 -27
  74. package/dist/widgets.d.cts +6 -1
  75. package/dist/widgets.d.ts +6 -1
  76. package/dist/widgets.js +8 -7
  77. package/package.json +1 -1
  78. 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
 
@@ -1222,7 +1228,7 @@ function forEachSubscriber(signal2, visit) {
1222
1228
 
1223
1229
  // src/reactivity/track.ts
1224
1230
  var _isDev3 = isDev();
1225
- var _runtimeVersion = typeof __SIBU_VERSION__ !== "undefined" ? __SIBU_VERSION__ : "dev";
1231
+ var _runtimeVersion = true ? "3.3.3" : "dev";
1226
1232
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
1227
1233
  function resolveReactiveApi() {
1228
1234
  const g2 = globalThis;
@@ -1977,9 +1983,19 @@ function signal(initial, options) {
1977
1983
  return [get, set];
1978
1984
  }
1979
1985
 
1986
+ // src/utils/globalSingleton.ts
1987
+ function globalSingleton(key, create) {
1988
+ const g2 = globalThis;
1989
+ return g2[key] ?? (g2[key] = create());
1990
+ }
1991
+
1980
1992
  // src/plugins/i18n.ts
1981
- var [currentLocale, setLocaleInternal] = signal("en");
1982
- var locales = {};
1993
+ var _i18n = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.i18n.v1"), () => ({
1994
+ locale: signal("en"),
1995
+ locales: {}
1996
+ }));
1997
+ var [currentLocale, setLocaleInternal] = _i18n.locale;
1998
+ var locales = _i18n.locales;
1983
1999
  function setLocale(locale) {
1984
2000
  setLocaleInternal(locale);
1985
2001
  }
@@ -2206,14 +2222,39 @@ var NavigationController = class {
2206
2222
  return this.currentController !== null;
2207
2223
  }
2208
2224
  };
2209
- var RouteMatcher = class {
2225
+ var RouteMatcher = class _RouteMatcher {
2210
2226
  constructor(routes) {
2211
2227
  this.routeTrie = /* @__PURE__ */ new Map();
2212
2228
  this.parentChain = /* @__PURE__ */ new Map();
2213
2229
  this.namedRoutes = /* @__PURE__ */ new Map();
2214
2230
  this.compiledPatterns = new LRUCache(50);
2231
+ // Pattern routes (those with params/wildcards) ordered most-specific-first,
2232
+ // rebuilt lazily after any mutation. Static full paths are served by the
2233
+ // exact-match map and excluded here.
2234
+ this.patternOrder = null;
2215
2235
  this.buildIndex(routes);
2216
2236
  }
2237
+ // Specificity per segment: static (2) > param `:x` (1) > wildcard `*` (0).
2238
+ static specificity(path2) {
2239
+ return path2.split("/").filter(Boolean).map((seg) => seg.startsWith(":") ? 1 : seg.includes("*") ? 0 : 2);
2240
+ }
2241
+ getPatternOrder() {
2242
+ if (this.patternOrder) return this.patternOrder;
2243
+ const patterns = [...this.routeTrie].filter(([p2]) => p2.includes(":") || p2.includes("*"));
2244
+ patterns.sort(([a2], [b2]) => {
2245
+ const ka = _RouteMatcher.specificity(a2);
2246
+ const kb = _RouteMatcher.specificity(b2);
2247
+ const len = Math.max(ka.length, kb.length);
2248
+ for (let i2 = 0; i2 < len; i2++) {
2249
+ const va = ka[i2] ?? -1;
2250
+ const vb = kb[i2] ?? -1;
2251
+ if (va !== vb) return vb - va;
2252
+ }
2253
+ return 0;
2254
+ });
2255
+ this.patternOrder = patterns;
2256
+ return patterns;
2257
+ }
2217
2258
  buildIndex(routes, parentPath = "", ancestors = []) {
2218
2259
  for (const route2 of routes) {
2219
2260
  const fullPath = parentPath + route2.path;
@@ -2240,7 +2281,7 @@ var RouteMatcher = class {
2240
2281
  if (exactMatch) {
2241
2282
  return { route: exactMatch, params: {}, matched: this.parentChain.get(path2) || [exactMatch] };
2242
2283
  }
2243
- for (const [routePath, route2] of this.routeTrie) {
2284
+ for (const [routePath, route2] of this.getPatternOrder()) {
2244
2285
  const match = this.matchPattern(path2, routePath);
2245
2286
  if (match) {
2246
2287
  return { route: route2, params: match.params, matched: this.parentChain.get(routePath) || [route2] };
@@ -2312,9 +2353,11 @@ var RouteMatcher = class {
2312
2353
  this.parentChain.clear();
2313
2354
  this.namedRoutes.clear();
2314
2355
  this.compiledPatterns.clear();
2356
+ this.patternOrder = null;
2315
2357
  this.buildIndex(routes);
2316
2358
  }
2317
2359
  addRoute(route2, parentPath = "") {
2360
+ this.patternOrder = null;
2318
2361
  const fullPath = parentPath + route2.path;
2319
2362
  const parentAncestors = this.parentChain.get(parentPath) || [];
2320
2363
  const chain = [...parentAncestors, route2];
@@ -2329,6 +2372,7 @@ var RouteMatcher = class {
2329
2372
  }
2330
2373
  removeRoute(path2) {
2331
2374
  this.compiledPatterns.clear();
2375
+ this.patternOrder = null;
2332
2376
  const root = this.routeTrie.get(path2);
2333
2377
  if (!root) return;
2334
2378
  const removed = /* @__PURE__ */ new Set();
@@ -2595,14 +2639,16 @@ var _SibuRouter = class _SibuRouter {
2595
2639
  this.initialize();
2596
2640
  }
2597
2641
  initialize() {
2598
- if (this.options.mode === "history") {
2599
- const popstateHandler = () => this.handleLocationChange(true);
2600
- window.addEventListener("popstate", popstateHandler);
2601
- this.cleanup.push(() => window.removeEventListener("popstate", popstateHandler));
2602
- } else {
2603
- const hashHandler = () => this.handleLocationChange(true);
2604
- window.addEventListener("hashchange", hashHandler);
2605
- this.cleanup.push(() => window.removeEventListener("hashchange", hashHandler));
2642
+ if (typeof window !== "undefined") {
2643
+ if (this.options.mode === "history") {
2644
+ const popstateHandler = () => this.handleLocationChange(true);
2645
+ window.addEventListener("popstate", popstateHandler);
2646
+ this.cleanup.push(() => window.removeEventListener("popstate", popstateHandler));
2647
+ } else {
2648
+ const hashHandler = () => this.handleLocationChange(true);
2649
+ window.addEventListener("hashchange", hashHandler);
2650
+ this.cleanup.push(() => window.removeEventListener("hashchange", hashHandler));
2651
+ }
2606
2652
  }
2607
2653
  queueMicrotask(() => {
2608
2654
  this.handleLocationChange(true);
@@ -2900,7 +2946,8 @@ var NavigationFailureError = class extends Error {
2900
2946
  };
2901
2947
  }
2902
2948
  };
2903
- var globalRouter = null;
2949
+ var ROUTER_KEY = /* @__PURE__ */ Symbol.for("sibujs.router.v1");
2950
+ var _routerRef = globalThis[ROUTER_KEY] ?? (globalThis[ROUTER_KEY] = { current: null });
2904
2951
  function normalizeRoutes(routes) {
2905
2952
  return routes.map((route2) => {
2906
2953
  const normalizedChildren = route2.children && route2.children.length > 0 ? normalizeRoutes(route2.children) : route2.children;
@@ -2920,8 +2967,8 @@ function normalizeRoutes(routes) {
2920
2967
  });
2921
2968
  }
2922
2969
  function createRouter(routesOrOptions, options = {}) {
2923
- if (globalRouter) {
2924
- globalRouter.destroy();
2970
+ if (_routerRef.current) {
2971
+ _routerRef.current.destroy();
2925
2972
  }
2926
2973
  let routes;
2927
2974
  if (Array.isArray(routesOrOptions)) {
@@ -2930,69 +2977,69 @@ function createRouter(routesOrOptions, options = {}) {
2930
2977
  options = routesOrOptions;
2931
2978
  routes = [];
2932
2979
  }
2933
- globalRouter = new SibuRouter(routes, options);
2980
+ _routerRef.current = new SibuRouter(routes, options);
2934
2981
  ensureRouterPagehide();
2935
- return globalRouter;
2982
+ return _routerRef.current;
2936
2983
  }
2937
2984
  function setRoutes(routes) {
2938
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2939
- globalRouter.updateRoutes(normalizeRoutes(routes));
2985
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2986
+ _routerRef.current.updateRoutes(normalizeRoutes(routes));
2940
2987
  }
2941
2988
  function route() {
2942
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2943
- return globalRouter.currentRoute;
2989
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2990
+ return _routerRef.current.currentRoute;
2944
2991
  }
2945
2992
  function router() {
2946
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2993
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
2947
2994
  return {
2948
- currentRoute: globalRouter.currentRoute,
2949
- isReady: globalRouter.isReady,
2950
- isNavigating: globalRouter.isNavigating,
2951
- push: (to) => globalRouter?.push(to),
2952
- replace: (to) => globalRouter?.replace(to),
2953
- go: (delta) => globalRouter?.go(delta),
2954
- back: () => globalRouter?.back(),
2955
- forward: () => globalRouter?.forward(),
2956
- beforeEach: (guard) => globalRouter?.beforeEach(guard),
2957
- beforeResolve: (guard) => globalRouter?.beforeResolve(guard),
2958
- afterEach: (hook) => globalRouter?.afterEach(hook)
2995
+ currentRoute: _routerRef.current.currentRoute,
2996
+ isReady: _routerRef.current.isReady,
2997
+ isNavigating: _routerRef.current.isNavigating,
2998
+ push: (to) => _routerRef.current?.push(to),
2999
+ replace: (to) => _routerRef.current?.replace(to),
3000
+ go: (delta) => _routerRef.current?.go(delta),
3001
+ back: () => _routerRef.current?.back(),
3002
+ forward: () => _routerRef.current?.forward(),
3003
+ beforeEach: (guard) => _routerRef.current?.beforeEach(guard),
3004
+ beforeResolve: (guard) => _routerRef.current?.beforeResolve(guard),
3005
+ afterEach: (hook) => _routerRef.current?.afterEach(hook)
2959
3006
  };
2960
3007
  }
2961
3008
  function navigate(to, options) {
2962
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2963
- return globalRouter.navigate(to, options);
3009
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3010
+ return _routerRef.current.navigate(to, options);
2964
3011
  }
2965
3012
  function push(to) {
2966
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2967
- return globalRouter.push(to);
3013
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3014
+ return _routerRef.current.push(to);
2968
3015
  }
2969
3016
  function replace(to) {
2970
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2971
- return globalRouter.replace(to);
3017
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3018
+ return _routerRef.current.replace(to);
2972
3019
  }
2973
3020
  function go(delta) {
2974
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2975
- globalRouter.go(delta);
3021
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3022
+ _routerRef.current.go(delta);
2976
3023
  }
2977
3024
  function back() {
2978
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2979
- globalRouter.back();
3025
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3026
+ _routerRef.current.back();
2980
3027
  }
2981
3028
  function forward() {
2982
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2983
- globalRouter.forward();
3029
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3030
+ _routerRef.current.forward();
2984
3031
  }
2985
3032
  function beforeEach(guard) {
2986
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2987
- return globalRouter.beforeEach(guard);
3033
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3034
+ return _routerRef.current.beforeEach(guard);
2988
3035
  }
2989
3036
  function beforeResolve(guard) {
2990
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2991
- return globalRouter.beforeResolve(guard);
3037
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3038
+ return _routerRef.current.beforeResolve(guard);
2992
3039
  }
2993
3040
  function afterEach(hook) {
2994
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
2995
- return globalRouter.afterEach(hook);
3041
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3042
+ return _routerRef.current.afterEach(hook);
2996
3043
  }
2997
3044
  var routeCleanups = [];
2998
3045
  function Route() {
@@ -3066,8 +3113,8 @@ function Route() {
3066
3113
  retryButton.className = "route-error-retry";
3067
3114
  retryButton.type = "button";
3068
3115
  const onRetryClick = () => {
3069
- if (globalRouter) {
3070
- globalRouter.clearErrorCache();
3116
+ if (_routerRef.current) {
3117
+ _routerRef.current.clearErrorCache();
3071
3118
  update();
3072
3119
  }
3073
3120
  };
@@ -3079,11 +3126,11 @@ function Route() {
3079
3126
  anchor.parentNode.insertBefore(errorNode, anchor.nextSibling);
3080
3127
  };
3081
3128
  const update = async () => {
3082
- if (!globalRouter) return;
3129
+ if (!_routerRef.current) return;
3083
3130
  const seq = ++navSeq;
3084
- const route2 = globalRouter.currentRoute;
3131
+ const route2 = _routerRef.current.currentRoute;
3085
3132
  try {
3086
- const match = globalRouter["matcher"].match(route2.path);
3133
+ const match = _routerRef.current["matcher"].match(route2.path);
3087
3134
  if (!match) {
3088
3135
  currentTopRoute = null;
3089
3136
  cleanupNodes();
@@ -3096,7 +3143,7 @@ function Route() {
3096
3143
  if ("redirect" in routeDef) {
3097
3144
  const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
3098
3145
  queueMicrotask(() => {
3099
- globalRouter?.navigate(redirectPath).catch((err) => {
3146
+ _routerRef.current?.navigate(redirectPath).catch((err) => {
3100
3147
  if (typeof console !== "undefined") console.error("[router] redirect failed:", err);
3101
3148
  });
3102
3149
  });
@@ -3108,7 +3155,7 @@ function Route() {
3108
3155
  if (isAsync) {
3109
3156
  showLoading();
3110
3157
  }
3111
- const component = await globalRouter.loadComponent(routeDef, route2.path);
3158
+ const component = await _routerRef.current.loadComponent(routeDef, route2.path);
3112
3159
  if (seq !== navSeq) return;
3113
3160
  const node = component();
3114
3161
  if (node && anchor.parentNode) {
@@ -3142,18 +3189,23 @@ function Route() {
3142
3189
  if (!routeInitialized && anchor.parentNode) wrappedUpdate();
3143
3190
  });
3144
3191
  }
3145
- routeCleanups.push(() => {
3192
+ let routeTorn = false;
3193
+ const routeCleanup = () => {
3194
+ if (routeTorn) return;
3195
+ routeTorn = true;
3146
3196
  routeTeardown();
3147
3197
  cleanupNodes();
3148
- });
3198
+ };
3199
+ registerDisposer(anchor, routeCleanup);
3200
+ routeCleanups.push(routeCleanup);
3149
3201
  return anchor;
3150
3202
  }
3151
3203
  function KeepAliveRoute(options) {
3152
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3204
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3153
3205
  const anchor = document.createComment("keep-alive-route");
3154
3206
  const cache = /* @__PURE__ */ new Map();
3155
3207
  const lruOrder = [];
3156
- const routerOpts = globalRouter["options"];
3208
+ const routerOpts = _routerRef.current["options"];
3157
3209
  const keepAliveOpt = routerOpts.keepAlive;
3158
3210
  const maxCache = options?.max ?? (typeof keepAliveOpt === "number" ? keepAliveOpt : 20);
3159
3211
  const includeNames = options?.include ?? (Array.isArray(keepAliveOpt) ? keepAliveOpt : void 0);
@@ -3163,19 +3215,19 @@ function KeepAliveRoute(options) {
3163
3215
  let isUpdating = false;
3164
3216
  let pendingUpdate = false;
3165
3217
  const update = async () => {
3166
- if (!globalRouter) return;
3218
+ if (!_routerRef.current) return;
3167
3219
  if (isUpdating) {
3168
3220
  pendingUpdate = true;
3169
3221
  return;
3170
3222
  }
3171
- const route2 = globalRouter.currentRoute;
3172
- const match = globalRouter["matcher"].match(route2.path);
3223
+ const route2 = _routerRef.current.currentRoute;
3224
+ const match = _routerRef.current["matcher"].match(route2.path);
3173
3225
  if (!match) return;
3174
3226
  const { route: routeDef } = match;
3175
3227
  if ("redirect" in routeDef) {
3176
3228
  const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
3177
3229
  queueMicrotask(() => {
3178
- globalRouter?.navigate(redirectPath).catch((err) => {
3230
+ _routerRef.current?.navigate(redirectPath).catch((err) => {
3179
3231
  if (typeof console !== "undefined") console.error("[router] redirect failed:", err);
3180
3232
  });
3181
3233
  });
@@ -3208,9 +3260,9 @@ function KeepAliveRoute(options) {
3208
3260
  }
3209
3261
  lruOrder.push(cacheKey);
3210
3262
  } else {
3211
- const component = await globalRouter.loadComponent(routeDef, route2.path);
3263
+ const component = await _routerRef.current.loadComponent(routeDef, route2.path);
3212
3264
  const node = component();
3213
- if (!node || route2.path !== globalRouter.currentRoute.path) {
3265
+ if (!node || route2.path !== _routerRef.current.currentRoute.path) {
3214
3266
  isUpdating = false;
3215
3267
  return;
3216
3268
  }
@@ -3255,7 +3307,10 @@ function KeepAliveRoute(options) {
3255
3307
  if (!initialized && anchor.parentNode) wrappedUpdate();
3256
3308
  });
3257
3309
  }
3258
- routeCleanups.push(() => {
3310
+ let kaTorn = false;
3311
+ const kaCleanup = () => {
3312
+ if (kaTorn) return;
3313
+ kaTorn = true;
3259
3314
  kaTeardown();
3260
3315
  for (const node of cache.values()) {
3261
3316
  dispose(node);
@@ -3265,15 +3320,18 @@ function KeepAliveRoute(options) {
3265
3320
  lruOrder.length = 0;
3266
3321
  if (currentNode?.parentNode) currentNode.parentNode.removeChild(currentNode);
3267
3322
  currentNode = null;
3268
- });
3323
+ };
3324
+ registerDisposer(anchor, kaCleanup);
3325
+ routeCleanups.push(kaCleanup);
3269
3326
  return anchor;
3270
3327
  }
3271
- function RouterLink(props) {
3272
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3328
+ function RouterLink(props, children) {
3329
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3273
3330
  const { to, replace: replace2 = false, activeClass, exactActiveClass, nodes, target, rel, class: classAttr, ...attrs } = props;
3331
+ const content = children !== void 0 ? children : nodes;
3274
3332
  const baseClass = typeof classAttr === "string" ? classAttr : "";
3275
- const routeGetter = globalRouter.routeGetter;
3276
- const rawHref = globalRouter["resolvePath"](to);
3333
+ const routeGetter = _routerRef.current.routeGetter;
3334
+ const rawHref = _routerRef.current["resolvePath"](to);
3277
3335
  const href = isSafeNavigationTarget(rawHref) ? rawHref : "#";
3278
3336
  const hrefPath = href.split("?")[0].split("#")[0];
3279
3337
  const link2 = document.createElement("a");
@@ -3288,7 +3346,7 @@ function RouterLink(props) {
3288
3346
  } else if (rel) {
3289
3347
  link2.rel = rel;
3290
3348
  }
3291
- const options = globalRouter["options"];
3349
+ const options = _routerRef.current["options"];
3292
3350
  const effectCleanup = effect(() => {
3293
3351
  const route2 = routeGetter();
3294
3352
  const isActive = route2.path.startsWith(hrefPath);
@@ -3320,12 +3378,12 @@ function RouterLink(props) {
3320
3378
  }
3321
3379
  }
3322
3380
  });
3323
- if (typeof nodes === "string") {
3324
- link2.textContent = nodes;
3325
- } else if (nodes instanceof Node) {
3326
- link2.appendChild(nodes);
3327
- } else if (Array.isArray(nodes)) {
3328
- nodes.forEach((child) => {
3381
+ if (typeof content === "string") {
3382
+ link2.textContent = content;
3383
+ } else if (content instanceof Node) {
3384
+ link2.appendChild(content);
3385
+ } else if (Array.isArray(content)) {
3386
+ content.forEach((child) => {
3329
3387
  if (typeof child === "string") {
3330
3388
  link2.appendChild(document.createTextNode(child));
3331
3389
  } else if (child instanceof Node) {
@@ -3338,7 +3396,7 @@ function RouterLink(props) {
3338
3396
  return;
3339
3397
  }
3340
3398
  e.preventDefault();
3341
- globalRouter?.navigate(to, { replace: replace2 }).catch((err) => {
3399
+ _routerRef.current?.navigate(to, { replace: replace2 }).catch((err) => {
3342
3400
  if (typeof console !== "undefined") console.error("[router] link navigate failed:", err);
3343
3401
  });
3344
3402
  };
@@ -3424,35 +3482,35 @@ function lazy(importFn) {
3424
3482
  return importFn;
3425
3483
  }
3426
3484
  async function preloadRoute(to) {
3427
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3428
- const path2 = globalRouter["resolvePath"](to);
3429
- const match = globalRouter["matcher"].match(path2.split("?")[0].split("#")[0]);
3485
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3486
+ const path2 = _routerRef.current["resolvePath"](to);
3487
+ const match = _routerRef.current["matcher"].match(path2.split("?")[0].split("#")[0]);
3430
3488
  if (match && "component" in match.route) {
3431
3489
  try {
3432
- await globalRouter.loadComponent(match.route, path2);
3490
+ await _routerRef.current.loadComponent(match.route, path2);
3433
3491
  } catch (error) {
3434
3492
  console.warn("[Router] Preload failed:", error);
3435
3493
  }
3436
3494
  }
3437
3495
  }
3438
3496
  function hasRoute(name) {
3439
- if (!globalRouter) return false;
3440
- return globalRouter["matcher"].findByName(name) !== null;
3497
+ if (!_routerRef.current) return false;
3498
+ return _routerRef.current["matcher"].findByName(name) !== null;
3441
3499
  }
3442
3500
  function getRouteInfo(name) {
3443
- if (!globalRouter) return null;
3444
- return globalRouter["matcher"].findByName(name);
3501
+ if (!_routerRef.current) return null;
3502
+ return _routerRef.current["matcher"].findByName(name);
3445
3503
  }
3446
3504
  function buildURL(to) {
3447
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3448
- return globalRouter["resolvePath"](to);
3505
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3506
+ return _routerRef.current["resolvePath"](to);
3449
3507
  }
3450
3508
  function destroyRouter() {
3451
3509
  for (const fn of routeCleanups) fn();
3452
3510
  routeCleanups.length = 0;
3453
- if (globalRouter) {
3454
- globalRouter.destroy();
3455
- globalRouter = null;
3511
+ if (_routerRef.current) {
3512
+ _routerRef.current.destroy();
3513
+ _routerRef.current = null;
3456
3514
  }
3457
3515
  }
3458
3516
  var _routerPagehideHandler = null;
@@ -3485,9 +3543,9 @@ function Outlet() {
3485
3543
  currentChild = null;
3486
3544
  };
3487
3545
  const update = async () => {
3488
- if (!globalRouter) return;
3546
+ if (!_routerRef.current) return;
3489
3547
  const seq = ++navSeq;
3490
- const route2 = globalRouter.currentRoute;
3548
+ const route2 = _routerRef.current.currentRoute;
3491
3549
  if (route2.matched.length < 2) {
3492
3550
  clearCurrent();
3493
3551
  return;
@@ -3500,7 +3558,7 @@ function Outlet() {
3500
3558
  if (childRoute === currentChild && currentNode) return;
3501
3559
  try {
3502
3560
  const cacheKey = `${route2.path}\0${childRoute.path}`;
3503
- const component = await globalRouter.loadComponent(childRoute, cacheKey);
3561
+ const component = await _routerRef.current.loadComponent(childRoute, cacheKey);
3504
3562
  if (seq !== navSeq) return;
3505
3563
  const node = component();
3506
3564
  if (node && anchor.parentNode) {
@@ -3520,27 +3578,32 @@ function Outlet() {
3520
3578
  if (anchor.parentNode) update();
3521
3579
  });
3522
3580
  }
3523
- routeCleanups.push(() => {
3581
+ let outletTorn = false;
3582
+ const outletCleanup = () => {
3583
+ if (outletTorn) return;
3584
+ outletTorn = true;
3524
3585
  outletTeardown();
3525
3586
  if (currentNode) {
3526
3587
  dispose(currentNode);
3527
3588
  if (currentNode.parentNode) currentNode.parentNode.removeChild(currentNode);
3528
3589
  currentNode = null;
3529
3590
  }
3530
- });
3591
+ };
3592
+ registerDisposer(anchor, outletCleanup);
3593
+ routeCleanups.push(outletCleanup);
3531
3594
  return anchor;
3532
3595
  }
3533
3596
  function addRoute(route2, parentPath) {
3534
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3535
- globalRouter.addRoute(route2, parentPath);
3597
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3598
+ _routerRef.current.addRoute(route2, parentPath);
3536
3599
  }
3537
3600
  function removeRoute(path2) {
3538
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3539
- globalRouter.removeRoute(path2);
3601
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3602
+ _routerRef.current.removeRoute(path2);
3540
3603
  }
3541
3604
  function routerState() {
3542
- if (!globalRouter) throw new Error("Router not initialized. Call createRouter() first.");
3543
- const router2 = globalRouter;
3605
+ if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
3606
+ const router2 = _routerRef.current;
3544
3607
  return {
3545
3608
  currentPath: () => router2.currentRoute.path,
3546
3609
  params: () => router2.currentRoute.params,
@@ -3554,12 +3617,12 @@ function routerState() {
3554
3617
  var routerPlugins = [];
3555
3618
  function routerPlugin(plugin2) {
3556
3619
  routerPlugins.push(plugin2);
3557
- if (globalRouter?.isReady && plugin2.onReady) {
3620
+ if (_routerRef.current?.isReady && plugin2.onReady) {
3558
3621
  plugin2.onReady();
3559
3622
  }
3560
3623
  let removeGuard = null;
3561
- if (globalRouter && plugin2.onNavigate) {
3562
- removeGuard = globalRouter.afterEach((to, from) => {
3624
+ if (_routerRef.current && plugin2.onNavigate) {
3625
+ removeGuard = _routerRef.current.afterEach((to, from) => {
3563
3626
  plugin2.onNavigate?.(to, from);
3564
3627
  });
3565
3628
  }
@@ -4004,39 +4067,41 @@ function createPluginRegistry() {
4004
4067
  };
4005
4068
  return registry;
4006
4069
  }
4007
- var defaultRegistry = createPluginRegistry();
4008
- var defaultRegistryTouched = false;
4070
+ var _defaults = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.plugins.defaultRegistry.v1"), () => ({
4071
+ registry: createPluginRegistry(),
4072
+ touched: false
4073
+ }));
4009
4074
  function createPlugin(name, install) {
4010
4075
  return { name, install };
4011
4076
  }
4012
4077
  function plugin(plugin2, options) {
4013
- defaultRegistryTouched = true;
4014
- defaultRegistry.plugin(plugin2, options);
4078
+ _defaults.touched = true;
4079
+ _defaults.registry.plugin(plugin2, options);
4015
4080
  }
4016
4081
  function inject(key, defaultValue) {
4017
- return defaultRegistry.inject(key, defaultValue);
4082
+ return _defaults.registry.inject(key, defaultValue);
4018
4083
  }
4019
4084
  function triggerPluginMount(element) {
4020
- defaultRegistry.triggerMount(element);
4085
+ _defaults.registry.triggerMount(element);
4021
4086
  }
4022
4087
  function triggerPluginUnmount(element) {
4023
- defaultRegistry.triggerUnmount(element);
4088
+ _defaults.registry.triggerUnmount(element);
4024
4089
  }
4025
4090
  function triggerPluginError(error) {
4026
- defaultRegistry.triggerError(error);
4091
+ _defaults.registry.triggerError(error);
4027
4092
  }
4028
4093
  function resetPlugins() {
4029
- defaultRegistry.reset();
4030
- defaultRegistryTouched = false;
4094
+ _defaults.registry.reset();
4095
+ _defaults.touched = false;
4031
4096
  }
4032
4097
  function setDefaultPluginRegistry(registry) {
4033
- if (defaultRegistryTouched && defaultRegistry.installedPlugins.size > 0) {
4098
+ if (_defaults.touched && _defaults.registry.installedPlugins.size > 0) {
4034
4099
  console.warn(
4035
4100
  "[Plugin] Replacing default plugin registry while plugins are already installed on the singleton. This may indicate mixed singleton/registry usage."
4036
4101
  );
4037
4102
  }
4038
- defaultRegistry = registry;
4039
- defaultRegistryTouched = true;
4103
+ _defaults.registry = registry;
4104
+ _defaults.touched = true;
4040
4105
  }
4041
4106
 
4042
4107
  // src/plugins/modular.ts
@@ -4138,9 +4203,7 @@ function lazyModule(loader) {
4138
4203
  return loadedFlag;
4139
4204
  },
4140
4205
  async get() {
4141
- if (loadedFlag && cached !== void 0) {
4142
- return cached;
4143
- }
4206
+ if (loadedFlag) return cached;
4144
4207
  cached = await loader();
4145
4208
  loadedFlag = true;
4146
4209
  return cached;