sibujs 4.10.1 → 4.12.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 (79) hide show
  1. package/README.md +2 -2
  2. package/dist/browser.cjs +1 -1
  3. package/dist/browser.js +4 -4
  4. package/dist/build.cjs +19 -1
  5. package/dist/build.js +13 -12
  6. package/dist/cdn.dev.global.js +12 -12
  7. package/dist/cdn.full.dev.global.js +13 -13
  8. package/dist/cdn.full.global.js +12 -12
  9. package/dist/cdn.global.js +12 -12
  10. package/dist/{chunk-FC6KCJSA.js → chunk-2F4PSJ5Z.js} +162 -67
  11. package/dist/{chunk-JZMLRF2G.js → chunk-653KGQS2.js} +3 -3
  12. package/dist/chunk-AM6DZLBM.js +181 -0
  13. package/dist/{chunk-NROLUUCO.js → chunk-B2Y5BJSP.js} +1 -1
  14. package/dist/{chunk-WHZKRSHQ.js → chunk-CI4W6XAU.js} +4 -4
  15. package/dist/{chunk-GEQNWNYS.js → chunk-DFZL3AX7.js} +6 -6
  16. package/dist/{chunk-6DYRY2NF.js → chunk-EMB5PG7V.js} +1 -1
  17. package/dist/{chunk-3ACAAQIN.js → chunk-F2UWOZ6J.js} +4 -0
  18. package/dist/{chunk-DA2LJXK3.js → chunk-HXT2RNH5.js} +1 -1
  19. package/dist/{chunk-BNZDDNBR.js → chunk-IHA62NGJ.js} +1 -1
  20. package/dist/{chunk-42REZXE4.js → chunk-LEUEKK4G.js} +2 -2
  21. package/dist/{chunk-CYUU3XXG.js → chunk-LXBMVGVB.js} +3 -3
  22. package/dist/{chunk-LYM6TT2R.js → chunk-LYTUTXQP.js} +4 -4
  23. package/dist/{chunk-2D47RVVK.js → chunk-NAVLCP4S.js} +4 -4
  24. package/dist/{chunk-MJZUXQHR.js → chunk-NB7TFSJE.js} +5 -5
  25. package/dist/{chunk-ADJEMTRC.js → chunk-QLG5IK7F.js} +4 -4
  26. package/dist/{chunk-LK3VK47W.js → chunk-RK7EPQPG.js} +1 -1
  27. package/dist/{chunk-YNE4FSVX.js → chunk-T5O2CUHV.js} +1 -1
  28. package/dist/{chunk-GVVZPMA5.js → chunk-WFRQ6D7H.js} +1 -1
  29. package/dist/{chunk-2T73SWKF.js → chunk-WH4U2VUE.js} +5 -3
  30. package/dist/{chunk-DS6PFIZK.js → chunk-XX4BRMWF.js} +15 -3
  31. package/dist/{chunk-HZQEL575.js → chunk-ZJCHY2IB.js} +1 -1
  32. package/dist/{chunk-CID4BYBF.js → chunk-ZPY2UAKM.js} +3 -3
  33. package/dist/{chunk-CZINTERN.js → chunk-ZTYCCBU3.js} +19 -11
  34. package/dist/data.cjs +1 -1
  35. package/dist/data.js +5 -5
  36. package/dist/devtools.cjs +1 -1
  37. package/dist/devtools.js +4 -4
  38. package/dist/ecosystem.cjs +9 -1
  39. package/dist/ecosystem.d.cts +1 -1
  40. package/dist/ecosystem.d.ts +1 -1
  41. package/dist/ecosystem.js +8 -8
  42. package/dist/extras.cjs +368 -154
  43. package/dist/extras.d.cts +2 -2
  44. package/dist/extras.d.ts +2 -2
  45. package/dist/extras.js +23 -22
  46. package/dist/index.cjs +19 -1
  47. package/dist/index.d.cts +91 -90
  48. package/dist/index.d.ts +91 -90
  49. package/dist/index.js +13 -12
  50. package/dist/motion.cjs +1 -1
  51. package/dist/motion.js +3 -3
  52. package/dist/patterns.cjs +1 -1
  53. package/dist/patterns.js +5 -5
  54. package/dist/performance.cjs +1 -1
  55. package/dist/performance.d.cts +2 -2
  56. package/dist/performance.d.ts +2 -2
  57. package/dist/performance.js +7 -6
  58. package/dist/plugins.cjs +482 -120
  59. package/dist/plugins.d.cts +20 -6
  60. package/dist/plugins.d.ts +20 -6
  61. package/dist/plugins.js +153 -23
  62. package/dist/{ssr-C8hgIAw7.d.cts → ssr-Db0Sgdu3.d.cts} +7 -4
  63. package/dist/{ssr-C8hgIAw7.d.ts → ssr-Db0Sgdu3.d.ts} +7 -4
  64. package/dist/{ssr-5OWAH3U2.js → ssr-VBM6J5SJ.js} +4 -2
  65. package/dist/ssr.cjs +346 -128
  66. package/dist/ssr.d.cts +1 -1
  67. package/dist/ssr.d.ts +1 -1
  68. package/dist/ssr.js +10 -9
  69. package/dist/{tagFactory-BL2fymez.d.ts → tagFactory-Bnd_Nph9.d.ts} +1 -1
  70. package/dist/{tagFactory-8qL9LCIx.d.cts → tagFactory-DkytnJws.d.cts} +1 -1
  71. package/dist/testing.cjs +1 -1
  72. package/dist/testing.js +2 -2
  73. package/dist/ui.cjs +251 -24
  74. package/dist/ui.d.cts +111 -1
  75. package/dist/ui.d.ts +111 -1
  76. package/dist/ui.js +130 -8
  77. package/dist/widgets.cjs +1 -1
  78. package/dist/widgets.js +6 -6
  79. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { A as Accessor } from './signal-EotCj4hS.cjs';
2
2
  import { C as Component$1, N as NodeChildren } from './types-CJFViL6Q.cjs';
3
- import { T as TrustedHTML } from './ssr-C8hgIAw7.cjs';
3
+ import { T as TrustedHTML } from './ssr-Db0Sgdu3.cjs';
4
4
  export { P as PluginContext, a as PluginInstallCancelledError, b as PluginRegistry, S as SibuPlugin, c as createPlugin, d as createPluginRegistry, i as inject, e as isPluginInstallCancelledError, p as plugin, r as resetPlugins, s as setDefaultPluginRegistry, t as triggerPluginError, f as triggerPluginMount, g as triggerPluginUnmount } from './plugin-DVgSnTfK.cjs';
5
5
  export { L as LazyModule, M as Migration, a as MigrationStorageError, P as PackageExportTarget, S as SemVer, V as VERSION, b as bundlerMetadata, c as checkCompatibility, d as compareSemVer, e as createBootSequence, f as createBundle, g as createMigrationRunner, h as createModuleRegistry, i as createSSRCache, j as createTestHarness, k as deferNonCritical, l as env, m as healthCheck, n as lazyModule, p as packageInfo, o as parseSemVer, q as preloadCritical, r as prerenderRoutes, s as satisfies } from './startup-BLfSeL15.cjs';
6
6
 
@@ -177,16 +177,29 @@ type LazyComponent = () => Promise<{
177
177
  default: Component;
178
178
  }>;
179
179
  type Params = Record<string, string>;
180
+ /** Every value of every query key, in URL order: `?tag=a&tag=b` is `{ tag: ["a", "b"] }`. */
181
+ type QueryValues = Readonly<Record<string, readonly string[]>>;
182
+ /**
183
+ * The query of a navigation object. An array value repeats its key once per
184
+ * value, in order: `{ tag: ["a", "b"] }` is `?tag=a&tag=b`.
185
+ */
186
+ type NavigationQuery = Readonly<Record<string, string | readonly string[]>>;
180
187
  interface RouteContext {
181
188
  readonly path: string;
182
189
  readonly params: Params;
183
190
  /**
184
191
  * The decoded query (`+` is a space, `%XX` is decoded). A repeated key keeps
185
- * its last value: `?tag=a&tag=b` is `{ tag: "b" }`. Two locations are the
186
- * same route — for duplicate detection and `RouterLink` exact-active — when
187
- * their queries have the same entries in any order.
192
+ * its last value here: `?tag=a&tag=b` is `{ tag: "b" }`. Read
193
+ * {@link RouteContext.queryAll} for every value.
188
194
  */
189
195
  readonly query: Params;
196
+ /**
197
+ * Every value of every query key, in URL order, with the same decoding as
198
+ * `query`: `?tag=a&tag=b` is `{ tag: ["a", "b"] }`. Two locations are the
199
+ * same route — for duplicate detection and `RouterLink` exact-active — when
200
+ * these match, key order aside.
201
+ */
202
+ readonly queryAll: QueryValues;
190
203
  readonly hash: string;
191
204
  readonly meta: RouteMeta;
192
205
  readonly matched: RouteDef[];
@@ -345,7 +358,7 @@ type NavigationTarget = string | {
345
358
  path?: string;
346
359
  name?: string;
347
360
  params?: Params;
348
- query?: Params;
361
+ query?: NavigationQuery;
349
362
  hash?: string;
350
363
  };
351
364
  /**
@@ -812,6 +825,7 @@ declare function routerState(): {
812
825
  currentPath: () => string;
813
826
  params: () => Params;
814
827
  query: () => Params;
828
+ queryAll: () => QueryValues;
815
829
  hash: () => string;
816
830
  meta: () => RouteMeta;
817
831
  isNavigating: () => boolean;
@@ -960,4 +974,4 @@ declare function createSSRRouter(routes: SSRRouteDef[]): {
960
974
  }) => string;
961
975
  };
962
976
 
963
- export { type AsyncComponent, type AsyncRoute, type Component, type ComponentRoute, type Guard, type GuardResult, KeepAliveRoute, type LazyComponent, type LazyRoute, type NavigationFailure, type NavigationFailureReason, type NavigationGuard, type NavigationNext, type NavigationResult, type NavigationTarget, Outlet, type Params, type RedirectRoute, Route, type RouteBase, type RouteContext, type RouteDef, type RouteMeta, type RouteTransitionOptions, RouterLink, type RouterOptions, type RouterPlugin, type SSRRouteDef, type SSRRouteState, type ScrollBehavior, type ScrollPosition, SibuRouter, Suspense, Trans, type TranslationParams, __getNavigationEpoch, __removeRouterPagehideHandler, addRoute, afterEach, back, beforeEach, beforeResolve, buildURL, createMemoryRouter, createRouter, createSSRRouter, deserializeRouteState, destroyRouter, forward, getAvailableLocales, getLocale, getRouteInfo, getRouteTransition, go, hasRoute, hasTranslation, hydrateRouter, lazy, navigate, preloadRoute, push, registerTranslations, removeRoute, renderRouteToDocument, renderRouteToString, replace, resolveServerRoute, route, router, routerPlugin, routerState, serializeRouteState, setLocale, setRouteTransition, setRoutes, t, translated };
977
+ export { type AsyncComponent, type AsyncRoute, type Component, type ComponentRoute, type Guard, type GuardResult, KeepAliveRoute, type LazyComponent, type LazyRoute, type NavigationFailure, type NavigationFailureReason, type NavigationGuard, type NavigationNext, type NavigationQuery, type NavigationResult, type NavigationTarget, Outlet, type Params, type QueryValues, type RedirectRoute, Route, type RouteBase, type RouteContext, type RouteDef, type RouteMeta, type RouteTransitionOptions, RouterLink, type RouterOptions, type RouterPlugin, type SSRRouteDef, type SSRRouteState, type ScrollBehavior, type ScrollPosition, SibuRouter, Suspense, Trans, type TranslationParams, __getNavigationEpoch, __removeRouterPagehideHandler, addRoute, afterEach, back, beforeEach, beforeResolve, buildURL, createMemoryRouter, createRouter, createSSRRouter, deserializeRouteState, destroyRouter, forward, getAvailableLocales, getLocale, getRouteInfo, getRouteTransition, go, hasRoute, hasTranslation, hydrateRouter, lazy, navigate, preloadRoute, push, registerTranslations, removeRoute, renderRouteToDocument, renderRouteToString, replace, resolveServerRoute, route, router, routerPlugin, routerState, serializeRouteState, setLocale, setRouteTransition, setRoutes, t, translated };
package/dist/plugins.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { A as Accessor } from './signal-EotCj4hS.js';
2
2
  import { C as Component$1, N as NodeChildren } from './types-CJFViL6Q.js';
3
- import { T as TrustedHTML } from './ssr-C8hgIAw7.js';
3
+ import { T as TrustedHTML } from './ssr-Db0Sgdu3.js';
4
4
  export { P as PluginContext, a as PluginInstallCancelledError, b as PluginRegistry, S as SibuPlugin, c as createPlugin, d as createPluginRegistry, i as inject, e as isPluginInstallCancelledError, p as plugin, r as resetPlugins, s as setDefaultPluginRegistry, t as triggerPluginError, f as triggerPluginMount, g as triggerPluginUnmount } from './plugin-DVgSnTfK.js';
5
5
  export { L as LazyModule, M as Migration, a as MigrationStorageError, P as PackageExportTarget, S as SemVer, V as VERSION, b as bundlerMetadata, c as checkCompatibility, d as compareSemVer, e as createBootSequence, f as createBundle, g as createMigrationRunner, h as createModuleRegistry, i as createSSRCache, j as createTestHarness, k as deferNonCritical, l as env, m as healthCheck, n as lazyModule, p as packageInfo, o as parseSemVer, q as preloadCritical, r as prerenderRoutes, s as satisfies } from './startup-BLfSeL15.js';
6
6
 
@@ -177,16 +177,29 @@ type LazyComponent = () => Promise<{
177
177
  default: Component;
178
178
  }>;
179
179
  type Params = Record<string, string>;
180
+ /** Every value of every query key, in URL order: `?tag=a&tag=b` is `{ tag: ["a", "b"] }`. */
181
+ type QueryValues = Readonly<Record<string, readonly string[]>>;
182
+ /**
183
+ * The query of a navigation object. An array value repeats its key once per
184
+ * value, in order: `{ tag: ["a", "b"] }` is `?tag=a&tag=b`.
185
+ */
186
+ type NavigationQuery = Readonly<Record<string, string | readonly string[]>>;
180
187
  interface RouteContext {
181
188
  readonly path: string;
182
189
  readonly params: Params;
183
190
  /**
184
191
  * The decoded query (`+` is a space, `%XX` is decoded). A repeated key keeps
185
- * its last value: `?tag=a&tag=b` is `{ tag: "b" }`. Two locations are the
186
- * same route — for duplicate detection and `RouterLink` exact-active — when
187
- * their queries have the same entries in any order.
192
+ * its last value here: `?tag=a&tag=b` is `{ tag: "b" }`. Read
193
+ * {@link RouteContext.queryAll} for every value.
188
194
  */
189
195
  readonly query: Params;
196
+ /**
197
+ * Every value of every query key, in URL order, with the same decoding as
198
+ * `query`: `?tag=a&tag=b` is `{ tag: ["a", "b"] }`. Two locations are the
199
+ * same route — for duplicate detection and `RouterLink` exact-active — when
200
+ * these match, key order aside.
201
+ */
202
+ readonly queryAll: QueryValues;
190
203
  readonly hash: string;
191
204
  readonly meta: RouteMeta;
192
205
  readonly matched: RouteDef[];
@@ -345,7 +358,7 @@ type NavigationTarget = string | {
345
358
  path?: string;
346
359
  name?: string;
347
360
  params?: Params;
348
- query?: Params;
361
+ query?: NavigationQuery;
349
362
  hash?: string;
350
363
  };
351
364
  /**
@@ -812,6 +825,7 @@ declare function routerState(): {
812
825
  currentPath: () => string;
813
826
  params: () => Params;
814
827
  query: () => Params;
828
+ queryAll: () => QueryValues;
815
829
  hash: () => string;
816
830
  meta: () => RouteMeta;
817
831
  isNavigating: () => boolean;
@@ -960,4 +974,4 @@ declare function createSSRRouter(routes: SSRRouteDef[]): {
960
974
  }) => string;
961
975
  };
962
976
 
963
- export { type AsyncComponent, type AsyncRoute, type Component, type ComponentRoute, type Guard, type GuardResult, KeepAliveRoute, type LazyComponent, type LazyRoute, type NavigationFailure, type NavigationFailureReason, type NavigationGuard, type NavigationNext, type NavigationResult, type NavigationTarget, Outlet, type Params, type RedirectRoute, Route, type RouteBase, type RouteContext, type RouteDef, type RouteMeta, type RouteTransitionOptions, RouterLink, type RouterOptions, type RouterPlugin, type SSRRouteDef, type SSRRouteState, type ScrollBehavior, type ScrollPosition, SibuRouter, Suspense, Trans, type TranslationParams, __getNavigationEpoch, __removeRouterPagehideHandler, addRoute, afterEach, back, beforeEach, beforeResolve, buildURL, createMemoryRouter, createRouter, createSSRRouter, deserializeRouteState, destroyRouter, forward, getAvailableLocales, getLocale, getRouteInfo, getRouteTransition, go, hasRoute, hasTranslation, hydrateRouter, lazy, navigate, preloadRoute, push, registerTranslations, removeRoute, renderRouteToDocument, renderRouteToString, replace, resolveServerRoute, route, router, routerPlugin, routerState, serializeRouteState, setLocale, setRouteTransition, setRoutes, t, translated };
977
+ export { type AsyncComponent, type AsyncRoute, type Component, type ComponentRoute, type Guard, type GuardResult, KeepAliveRoute, type LazyComponent, type LazyRoute, type NavigationFailure, type NavigationFailureReason, type NavigationGuard, type NavigationNext, type NavigationQuery, type NavigationResult, type NavigationTarget, Outlet, type Params, type QueryValues, type RedirectRoute, Route, type RouteBase, type RouteContext, type RouteDef, type RouteMeta, type RouteTransitionOptions, RouterLink, type RouterOptions, type RouterPlugin, type SSRRouteDef, type SSRRouteState, type ScrollBehavior, type ScrollPosition, SibuRouter, Suspense, Trans, type TranslationParams, __getNavigationEpoch, __removeRouterPagehideHandler, addRoute, afterEach, back, beforeEach, beforeResolve, buildURL, createMemoryRouter, createRouter, createSSRRouter, deserializeRouteState, destroyRouter, forward, getAvailableLocales, getLocale, getRouteInfo, getRouteTransition, go, hasRoute, hasTranslation, hydrateRouter, lazy, navigate, preloadRoute, push, registerTranslations, removeRoute, renderRouteToDocument, renderRouteToString, replace, resolveServerRoute, route, router, routerPlugin, routerState, serializeRouteState, setLocale, setRouteTransition, setRoutes, t, translated };
package/dist/plugins.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  preloadCritical,
20
20
  prerenderRoutes,
21
21
  satisfies
22
- } from "./chunk-JZMLRF2G.js";
22
+ } from "./chunk-653KGQS2.js";
23
23
  import {
24
24
  PluginInstallCancelledError,
25
25
  createPlugin,
@@ -35,12 +35,13 @@ import {
35
35
  } from "./chunk-J6FW5TV6.js";
36
36
  import {
37
37
  span
38
- } from "./chunk-YNE4FSVX.js";
38
+ } from "./chunk-T5O2CUHV.js";
39
39
  import {
40
40
  escapeScriptJson,
41
41
  renderToString,
42
42
  serializeHeadEntry
43
- } from "./chunk-FC6KCJSA.js";
43
+ } from "./chunk-2F4PSJ5Z.js";
44
+ import "./chunk-AM6DZLBM.js";
44
45
  import {
45
46
  isUnsafeKey,
46
47
  readOwnGlobal
@@ -48,17 +49,17 @@ import {
48
49
  import {
49
50
  appendChildren,
50
51
  resolveClassValue
51
- } from "./chunk-2T73SWKF.js";
52
+ } from "./chunk-WH4U2VUE.js";
52
53
  import {
53
54
  setSafeAttribute
54
- } from "./chunk-DS6PFIZK.js";
55
- import "./chunk-3ACAAQIN.js";
55
+ } from "./chunk-XX4BRMWF.js";
56
+ import "./chunk-F2UWOZ6J.js";
56
57
  import {
57
58
  globalSingleton
58
59
  } from "./chunk-7ZHH77QA.js";
59
60
  import {
60
61
  effect
61
- } from "./chunk-6DYRY2NF.js";
62
+ } from "./chunk-EMB5PG7V.js";
62
63
  import {
63
64
  sanitizeUrl,
64
65
  stripControlChars
@@ -69,14 +70,14 @@ import {
69
70
  import "./chunk-5HZXGZ6T.js";
70
71
  import {
71
72
  signal
72
- } from "./chunk-BNZDDNBR.js";
73
+ } from "./chunk-IHA62NGJ.js";
73
74
  import {
74
75
  bindOwnerScope,
75
76
  getOwnerScope,
76
77
  runWithOwnerScope,
77
78
  track,
78
79
  untracked
79
- } from "./chunk-NROLUUCO.js";
80
+ } from "./chunk-B2Y5BJSP.js";
80
81
  import {
81
82
  devWarn,
82
83
  dispose,
@@ -186,11 +187,28 @@ function normalizePathname(path) {
186
187
  function parseQuery(query) {
187
188
  return Object.fromEntries(new URLSearchParams(query));
188
189
  }
190
+ function parseQueryAll(query) {
191
+ const all = /* @__PURE__ */ new Map();
192
+ for (const [key, value] of new URLSearchParams(query)) {
193
+ const values = all.get(key);
194
+ if (values) values.push(value);
195
+ else all.set(key, [value]);
196
+ }
197
+ return Object.fromEntries(all);
198
+ }
199
+ function serializeQuery(query) {
200
+ const search = new URLSearchParams();
201
+ for (const [key, value] of Object.entries(query)) {
202
+ if (Array.isArray(value)) for (const v of value) search.append(key, String(v));
203
+ else search.append(key, String(value));
204
+ }
205
+ return search.toString();
206
+ }
189
207
  function paramsIdentity(params) {
190
208
  return JSON.stringify(Object.entries(params).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
191
209
  }
192
210
  function queryIdentity(query) {
193
- return paramsIdentity(typeof query === "string" ? parseQuery(query) : query);
211
+ return paramsIdentity(typeof query === "string" ? parseQueryAll(query) : query);
194
212
  }
195
213
  function isPathnameAncestor(target, current) {
196
214
  if (target === current) return true;
@@ -866,6 +884,7 @@ var _SibuRouter = class _SibuRouter {
866
884
  path: "/",
867
885
  params: {},
868
886
  query: {},
887
+ queryAll: {},
869
888
  hash: "",
870
889
  meta: {},
871
890
  matched: []
@@ -892,6 +911,7 @@ var _SibuRouter = class _SibuRouter {
892
911
  createRouteContext(fullPath) {
893
912
  const { path, query: queryString, hash } = splitRouteUrl(fullPath);
894
913
  const query = parseQuery(queryString);
914
+ const queryAll = parseQueryAll(queryString);
895
915
  const match = this.matcher.match(path || "/");
896
916
  const params = match?.params || {};
897
917
  const meta = match?.route.meta || {};
@@ -900,6 +920,7 @@ var _SibuRouter = class _SibuRouter {
900
920
  path: path || "/",
901
921
  params,
902
922
  query,
923
+ queryAll,
903
924
  hash,
904
925
  meta,
905
926
  matched
@@ -1045,8 +1066,9 @@ var _SibuRouter = class _SibuRouter {
1045
1066
  path = path.replace(new RegExp(`:${key}(?=[/?#]|$)`, "g"), encodeURIComponent(value));
1046
1067
  }
1047
1068
  }
1048
- if (to.query && Object.keys(to.query).length > 0) {
1049
- path += `?${new URLSearchParams(to.query).toString()}`;
1069
+ const search = to.query ? serializeQuery(to.query) : "";
1070
+ if (search) {
1071
+ path += `?${search}`;
1050
1072
  }
1051
1073
  if (to.hash) {
1052
1074
  path += `#${to.hash}`;
@@ -1055,10 +1077,13 @@ var _SibuRouter = class _SibuRouter {
1055
1077
  }
1056
1078
  isSameRoute(from, to) {
1057
1079
  if (from.matched.length === 0 && to.matched.length > 0) return false;
1058
- return from.path === to.path && paramsIdentity(from.params) === paramsIdentity(to.params) && queryIdentity(from.query) === queryIdentity(to.query) && from.hash === to.hash;
1080
+ return from.path === to.path && paramsIdentity(from.params) === paramsIdentity(to.params) && queryIdentity(from.queryAll) === queryIdentity(to.queryAll) && from.hash === to.hash;
1059
1081
  }
1060
1082
  updateHistory(to, options) {
1061
- const fullPath = this.options.base + to.path + (Object.keys(to.query).length ? `?${new URLSearchParams(to.query).toString()}` : "") + (to.hash ? `#${to.hash}` : "");
1083
+ const search = serializeQuery(to.queryAll);
1084
+ const routeUrl = to.path + (search ? `?${search}` : "") + (to.hash ? `#${to.hash}` : "");
1085
+ const loc = globalThis.location;
1086
+ const fullPath = this.options.mode === "hash" ? `${loc ? loc.pathname + loc.search : ""}#${routeUrl}` : this.options.base + routeUrl;
1062
1087
  const h = globalThis.history;
1063
1088
  if (!h) return;
1064
1089
  if (options.replace) {
@@ -1241,6 +1266,65 @@ function abortReasonOf(signal2) {
1241
1266
  }
1242
1267
  var ROUTER_KEY = /* @__PURE__ */ Symbol.for("sibujs.router.v1");
1243
1268
  var _routerRef = globalThis[ROUTER_KEY] ?? (globalThis[ROUTER_KEY] = { current: null });
1269
+ var [routerRevision, setRouterRevision] = signal(0);
1270
+ var awaitingParent = /* @__PURE__ */ new Map();
1271
+ var parentObserver = null;
1272
+ function stopParentObserverIfIdle() {
1273
+ if (parentObserver && awaitingParent.size === 0) {
1274
+ parentObserver.disconnect();
1275
+ parentObserver = null;
1276
+ }
1277
+ }
1278
+ function whenAnchorAttached(anchor, run) {
1279
+ let cancelled = false;
1280
+ queueMicrotask(() => {
1281
+ if (cancelled) return;
1282
+ if (anchor.parentNode) {
1283
+ cancelled = true;
1284
+ run();
1285
+ return;
1286
+ }
1287
+ if (typeof MutationObserver === "undefined" || typeof document === "undefined") return;
1288
+ awaitingParent.set(anchor, () => {
1289
+ cancelled = true;
1290
+ run();
1291
+ });
1292
+ if (!parentObserver) {
1293
+ parentObserver = new MutationObserver(() => {
1294
+ for (const [node, cb] of awaitingParent) {
1295
+ if (!node.parentNode) continue;
1296
+ awaitingParent.delete(node);
1297
+ cb();
1298
+ }
1299
+ stopParentObserverIfIdle();
1300
+ });
1301
+ parentObserver.observe(document, { childList: true, subtree: true });
1302
+ }
1303
+ });
1304
+ return () => {
1305
+ if (cancelled) return;
1306
+ cancelled = true;
1307
+ awaitingParent.delete(anchor);
1308
+ stopParentObserverIfIdle();
1309
+ };
1310
+ }
1311
+ function attachRetry(anchor, rerun) {
1312
+ const run = bindOwnerScope(rerun);
1313
+ let cancelWait = null;
1314
+ return {
1315
+ request: () => {
1316
+ if (cancelWait) return;
1317
+ cancelWait = whenAnchorAttached(anchor, () => {
1318
+ cancelWait = null;
1319
+ run();
1320
+ });
1321
+ },
1322
+ cancel: () => {
1323
+ cancelWait?.();
1324
+ cancelWait = null;
1325
+ }
1326
+ };
1327
+ }
1244
1328
  function normalizeRoutes(routes) {
1245
1329
  return routes.map((route2) => {
1246
1330
  const normalizedChildren = route2.children && route2.children.length > 0 ? normalizeRoutes(route2.children) : route2.children;
@@ -1272,6 +1356,7 @@ function createRouter(routesOrOptions, options = {}) {
1272
1356
  }
1273
1357
  _routerRef.current = new SibuRouter(routes, options);
1274
1358
  ensureRouterPagehide();
1359
+ setRouterRevision((n) => n + 1);
1275
1360
  return _routerRef.current;
1276
1361
  }
1277
1362
  function setRoutes(routes) {
@@ -1427,6 +1512,9 @@ function Route() {
1427
1512
  let currentKey = null;
1428
1513
  let routeTorn = false;
1429
1514
  const commitTarget = (seq) => routeTorn || seq !== navSeq ? null : anchor.parentNode;
1515
+ const retryIfDetached = (seq) => {
1516
+ if (!routeTorn && seq === navSeq && !anchor.parentNode) attachWait.request();
1517
+ };
1430
1518
  const release = (node) => {
1431
1519
  if (!node) return;
1432
1520
  disposeOwned(node);
@@ -1509,6 +1597,7 @@ function Route() {
1509
1597
  anchor.parentNode.insertBefore(errorNode, anchor.nextSibling);
1510
1598
  };
1511
1599
  const update = async () => {
1600
+ routerRevision();
1512
1601
  if (routeTorn || !_routerRef.current) return;
1513
1602
  const seq = ++navSeq;
1514
1603
  const route2 = scopedRoute(_routerRef.current);
@@ -1542,11 +1631,15 @@ function Route() {
1542
1631
  showLoading();
1543
1632
  }
1544
1633
  const plan = await _routerRef.current.loadPlan(routeDef, route2.path);
1545
- if (!commitTarget(seq)) return;
1634
+ if (!commitTarget(seq)) {
1635
+ retryIfDetached(seq);
1636
+ return;
1637
+ }
1546
1638
  const node = await instantiateScoped(_routerRef.current, plan, routeDef, route2.path, route2);
1547
1639
  const parent = commitTarget(seq);
1548
1640
  if (!parent) {
1549
1641
  release(node);
1642
+ retryIfDetached(seq);
1550
1643
  return;
1551
1644
  }
1552
1645
  if (node) {
@@ -1560,15 +1653,31 @@ function Route() {
1560
1653
  if (routeTorn || seq !== navSeq) return;
1561
1654
  hideLoading();
1562
1655
  console.error("[Route] Component error:", error);
1563
- showError(error instanceof Error ? error : new Error(String(error)), routeDef);
1656
+ fail(seq, error, routeDef);
1564
1657
  }
1565
1658
  }
1566
1659
  } catch (error) {
1567
1660
  if (seq !== navSeq) return;
1568
1661
  if (routeTorn) return;
1569
1662
  console.error("[Route] Update failed:", error);
1570
- showError(error instanceof Error ? error : new Error(String(error)));
1663
+ fail(seq, error);
1664
+ }
1665
+ };
1666
+ let unshownFailure = null;
1667
+ const fail = (seq, error, routeDef) => {
1668
+ const err = error instanceof Error ? error : new Error(String(error));
1669
+ if (anchor.parentNode) {
1670
+ showError(err, routeDef);
1671
+ return;
1571
1672
  }
1673
+ unshownFailure = { seq, error: err, routeDef };
1674
+ attachWait.request();
1675
+ };
1676
+ const onAttached = () => {
1677
+ const failure = unshownFailure;
1678
+ unshownFailure = null;
1679
+ if (failure && failure.seq === navSeq) showError(failure.error, failure.routeDef);
1680
+ else update();
1572
1681
  };
1573
1682
  let routeInitialized = false;
1574
1683
  const originalUpdate = update;
@@ -1576,6 +1685,7 @@ function Route() {
1576
1685
  await originalUpdate();
1577
1686
  routeInitialized = true;
1578
1687
  };
1688
+ const attachWait = attachRetry(anchor, onAttached);
1579
1689
  const routeTeardown = track(wrappedUpdate);
1580
1690
  if (!routeInitialized) {
1581
1691
  queueMicrotask(
@@ -1589,6 +1699,8 @@ function Route() {
1589
1699
  routeTorn = true;
1590
1700
  navSeq++;
1591
1701
  routeTeardown();
1702
+ attachWait.cancel();
1703
+ unshownFailure = null;
1592
1704
  cleanupNodes();
1593
1705
  currentTopRoute = null;
1594
1706
  currentKey = null;
@@ -1612,6 +1724,7 @@ function KeepAliveRoute(options) {
1612
1724
  let updateSeq = 0;
1613
1725
  let kaTorn = false;
1614
1726
  const update = async () => {
1727
+ routerRevision();
1615
1728
  if (kaTorn || !_routerRef.current) return;
1616
1729
  const seq = ++updateSeq;
1617
1730
  const router2 = _routerRef.current;
@@ -1629,13 +1742,16 @@ function KeepAliveRoute(options) {
1629
1742
  return;
1630
1743
  }
1631
1744
  if (!("component" in routeDef)) return;
1632
- const cacheKey = JSON.stringify([route2.path, queryIdentity(route2.query), route2.hash]);
1745
+ const cacheKey = JSON.stringify([route2.path, queryIdentity(route2.queryAll), route2.hash]);
1633
1746
  const shouldCache = !includeNames || routeDef.name != null && includeNames.includes(routeDef.name);
1634
1747
  if (cacheKey === currentKey && currentNode) {
1635
1748
  updateInstanceRoute(currentNode, route2);
1636
1749
  return;
1637
1750
  }
1638
- if (!anchor.parentNode) return;
1751
+ if (!anchor.parentNode) {
1752
+ attachWait.request();
1753
+ return;
1754
+ }
1639
1755
  let node = null;
1640
1756
  let fromCache = false;
1641
1757
  if (shouldCache && cache.has(cacheKey)) {
@@ -1660,6 +1776,7 @@ function KeepAliveRoute(options) {
1660
1776
  const parent = anchor.parentNode;
1661
1777
  if (!parent) {
1662
1778
  if (!fromCache) disposeOwned(node);
1779
+ attachWait.request();
1663
1780
  return;
1664
1781
  }
1665
1782
  if (currentNode && currentNode !== node) {
@@ -1698,6 +1815,7 @@ function KeepAliveRoute(options) {
1698
1815
  await update();
1699
1816
  initialized = true;
1700
1817
  };
1818
+ const attachWait = attachRetry(anchor, update);
1701
1819
  const kaTeardown = track(wrappedUpdate);
1702
1820
  if (!initialized) {
1703
1821
  queueMicrotask(
@@ -1711,6 +1829,7 @@ function KeepAliveRoute(options) {
1711
1829
  kaTorn = true;
1712
1830
  updateSeq++;
1713
1831
  kaTeardown();
1832
+ attachWait.cancel();
1714
1833
  for (const node of cache.values()) {
1715
1834
  disposeOwned(node);
1716
1835
  if (node.parentNode) node.parentNode.removeChild(node);
@@ -1739,7 +1858,7 @@ function RouterLink(props, children) {
1739
1858
  const targetPath = normalizePathname(hrefPathRaw);
1740
1859
  const targetQuery = queryIdentity(hrefQueryRaw);
1741
1860
  const link = document.createElement("a");
1742
- link.href = href;
1861
+ link.href = kind === "internal" && _routerRef.current["options"].mode === "hash" ? `#${href}` : href;
1743
1862
  if (target) {
1744
1863
  link.target = target;
1745
1864
  if (target === "_blank") {
@@ -1755,7 +1874,7 @@ function RouterLink(props, children) {
1755
1874
  const route2 = routeGetter();
1756
1875
  const currentPath = normalizePathname(route2.path);
1757
1876
  const isActive = kind === "internal" && isPathnameAncestor(targetPath, currentPath);
1758
- const isExactActive = kind === "internal" && currentPath === targetPath && queryIdentity(route2.query) === targetQuery && route2.hash === hrefHash;
1877
+ const isExactActive = kind === "internal" && currentPath === targetPath && queryIdentity(route2.queryAll) === targetQuery && route2.hash === hrefHash;
1759
1878
  const classes = [];
1760
1879
  if (isActive) {
1761
1880
  if (activeClass) classes.push(activeClass);
@@ -1950,12 +2069,16 @@ function Outlet() {
1950
2069
  currentKey = null;
1951
2070
  };
1952
2071
  const commitTarget = (seq) => outletTorn || seq !== navSeq ? null : anchor.parentNode;
2072
+ const retryIfDetached = (seq) => {
2073
+ if (!outletTorn && seq === navSeq && !anchor.parentNode) attachWait.request();
2074
+ };
1953
2075
  const release = (node) => {
1954
2076
  if (!node) return;
1955
2077
  disposeOwned(node);
1956
2078
  node.parentNode?.removeChild(node);
1957
2079
  };
1958
2080
  const update = async () => {
2081
+ routerRevision();
1959
2082
  if (outletTorn || !_routerRef.current) return;
1960
2083
  const seq = ++navSeq;
1961
2084
  const route2 = scopedRoute(_routerRef.current);
@@ -1976,11 +2099,15 @@ function Outlet() {
1976
2099
  try {
1977
2100
  const cacheKey = `${route2.path}\0${childRoute.path}`;
1978
2101
  const plan = await _routerRef.current.loadPlan(childRoute, cacheKey);
1979
- if (!commitTarget(seq)) return;
2102
+ if (!commitTarget(seq)) {
2103
+ retryIfDetached(seq);
2104
+ return;
2105
+ }
1980
2106
  const node = await instantiateScoped(_routerRef.current, plan, childRoute, cacheKey, route2);
1981
2107
  const parent = commitTarget(seq);
1982
2108
  if (!parent) {
1983
2109
  release(node);
2110
+ retryIfDetached(seq);
1984
2111
  return;
1985
2112
  }
1986
2113
  if (!node) return;
@@ -1994,6 +2121,7 @@ function Outlet() {
1994
2121
  console.error("[Outlet] Failed to render child route:", error);
1995
2122
  }
1996
2123
  };
2124
+ const attachWait = attachRetry(anchor, update);
1997
2125
  const outletTeardown = track(update);
1998
2126
  if (!anchor.parentNode) {
1999
2127
  queueMicrotask(
@@ -2007,6 +2135,7 @@ function Outlet() {
2007
2135
  outletTorn = true;
2008
2136
  navSeq++;
2009
2137
  outletTeardown();
2138
+ attachWait.cancel();
2010
2139
  if (currentNode) {
2011
2140
  disposeOwned(currentNode);
2012
2141
  if (currentNode.parentNode) currentNode.parentNode.removeChild(currentNode);
@@ -2034,6 +2163,7 @@ function routerState() {
2034
2163
  currentPath: () => scopedRoute(router2).path,
2035
2164
  params: () => scopedRoute(router2).params,
2036
2165
  query: () => scopedRoute(router2).query,
2166
+ queryAll: () => scopedRoute(router2).queryAll,
2037
2167
  hash: () => scopedRoute(router2).hash,
2038
2168
  meta: () => scopedRoute(router2).meta,
2039
2169
  isNavigating: () => router2.isNavigating,
@@ -2319,7 +2449,7 @@ function hydrateRouter(routes, options) {
2319
2449
  const liveUrl = `${window.location.pathname}${window.location.search}${window.location.hash}`;
2320
2450
  const resolved = resolveServerRoute(liveUrl, routes);
2321
2451
  const bootstrapEpoch = __getNavigationEpoch();
2322
- import("./ssr-5OWAH3U2.js").then(async ({ hydrate }) => {
2452
+ import("./ssr-VBM6J5SJ.js").then(async ({ hydrate }) => {
2323
2453
  const { replaceChildrenSafely } = await import("./dispose-GEIG2KOF.js");
2324
2454
  if (__getNavigationEpoch() !== bootstrapEpoch) return;
2325
2455
  if (resolved.component) {
@@ -1,10 +1,13 @@
1
1
  /**
2
- * Converts an HTMLElement tree to an HTML string for server-side rendering.
2
+ * Converts an element tree to an HTML string for server-side rendering.
3
+ * HTML, SVG and MathML elements are serialized; SVG and MathML keep the case
4
+ * of their tag and attribute names and their `xlink:` / `xml:` prefixes.
3
5
  *
4
6
  * Security: attribute names are validated, `on*` handlers are dropped,
5
- * URL-bearing attributes are routed through `sanitizeUrl`, and attribute
6
- * values are escaped against both `"` and `'`. `<script>` and `<style>`
7
- * tags are stripped from the serialized output.
7
+ * URL-bearing attributes are routed through `sanitizeUrl`, attribute
8
+ * values are escaped against both `"` and `'`, and an SVG animation may not
9
+ * target a URL or handler attribute. `<script>` and `<style>` tags are
10
+ * stripped from the serialized output.
8
11
  */
9
12
  declare function renderToString(element: HTMLElement | DocumentFragment | Node): string;
10
13
  interface HydrateOptions {
@@ -1,10 +1,13 @@
1
1
  /**
2
- * Converts an HTMLElement tree to an HTML string for server-side rendering.
2
+ * Converts an element tree to an HTML string for server-side rendering.
3
+ * HTML, SVG and MathML elements are serialized; SVG and MathML keep the case
4
+ * of their tag and attribute names and their `xlink:` / `xml:` prefixes.
3
5
  *
4
6
  * Security: attribute names are validated, `on*` handlers are dropped,
5
- * URL-bearing attributes are routed through `sanitizeUrl`, and attribute
6
- * values are escaped against both `"` and `'`. `<script>` and `<style>`
7
- * tags are stripped from the serialized output.
7
+ * URL-bearing attributes are routed through `sanitizeUrl`, attribute
8
+ * values are escaped against both `"` and `'`, and an SVG animation may not
9
+ * target a URL or handler attribute. `<script>` and `<style>` tags are
10
+ * stripped from the serialized output.
8
11
  */
9
12
  declare function renderToString(element: HTMLElement | DocumentFragment | Node): string;
10
13
  interface HydrateOptions {
@@ -17,9 +17,11 @@ import {
17
17
  ssrSuspense,
18
18
  suspenseSwapScript,
19
19
  trustHTML
20
- } from "./chunk-FC6KCJSA.js";
20
+ } from "./chunk-2F4PSJ5Z.js";
21
+ import "./chunk-AM6DZLBM.js";
21
22
  import "./chunk-62BDYGAG.js";
22
- import "./chunk-3ACAAQIN.js";
23
+ import "./chunk-F2UWOZ6J.js";
24
+ import "./chunk-7ZHH77QA.js";
23
25
  import "./chunk-EXXSN3BW.js";
24
26
  import "./chunk-7XHATCIH.js";
25
27
  import "./chunk-NYNYSPK7.js";