@furystack/shades 13.2.2 → 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/CHANGELOG.md +157 -0
  2. package/esm/component-factory.spec.d.ts.map +1 -1
  3. package/esm/component-factory.spec.js +2 -2
  4. package/esm/component-factory.spec.js.map +1 -1
  5. package/esm/components/define-nested-routes.d.ts +27 -0
  6. package/esm/components/define-nested-routes.d.ts.map +1 -0
  7. package/esm/components/define-nested-routes.js +26 -0
  8. package/esm/components/define-nested-routes.js.map +1 -0
  9. package/esm/components/define-nested-routes.spec.d.ts +2 -0
  10. package/esm/components/define-nested-routes.spec.d.ts.map +1 -0
  11. package/esm/components/define-nested-routes.spec.js +81 -0
  12. package/esm/components/define-nested-routes.spec.js.map +1 -0
  13. package/esm/components/index.d.ts +3 -3
  14. package/esm/components/index.d.ts.map +1 -1
  15. package/esm/components/index.js +3 -3
  16. package/esm/components/index.js.map +1 -1
  17. package/esm/components/nested-hooks.d.ts +62 -0
  18. package/esm/components/nested-hooks.d.ts.map +1 -0
  19. package/esm/components/nested-hooks.js +73 -0
  20. package/esm/components/nested-hooks.js.map +1 -0
  21. package/esm/components/nested-hooks.spec.d.ts +2 -0
  22. package/esm/components/nested-hooks.spec.d.ts.map +1 -0
  23. package/esm/components/nested-hooks.spec.js +211 -0
  24. package/esm/components/nested-hooks.spec.js.map +1 -0
  25. package/esm/components/nested-navigate.d.ts +52 -21
  26. package/esm/components/nested-navigate.d.ts.map +1 -1
  27. package/esm/components/nested-navigate.js +32 -17
  28. package/esm/components/nested-navigate.js.map +1 -1
  29. package/esm/components/nested-navigate.spec.js +109 -19
  30. package/esm/components/nested-navigate.spec.js.map +1 -1
  31. package/esm/components/nested-replace.d.ts +36 -0
  32. package/esm/components/nested-replace.d.ts.map +1 -0
  33. package/esm/components/nested-replace.js +38 -0
  34. package/esm/components/nested-replace.js.map +1 -0
  35. package/esm/components/nested-replace.spec.d.ts +2 -0
  36. package/esm/components/nested-replace.spec.d.ts.map +1 -0
  37. package/esm/components/nested-replace.spec.js +59 -0
  38. package/esm/components/nested-replace.spec.js.map +1 -0
  39. package/esm/components/nested-route-link.d.ts +36 -26
  40. package/esm/components/nested-route-link.d.ts.map +1 -1
  41. package/esm/components/nested-route-link.js +18 -20
  42. package/esm/components/nested-route-link.js.map +1 -1
  43. package/esm/components/nested-route-link.spec.js +67 -17
  44. package/esm/components/nested-route-link.spec.js.map +1 -1
  45. package/esm/components/nested-route-types.d.ts +79 -2
  46. package/esm/components/nested-route-types.d.ts.map +1 -1
  47. package/esm/components/nested-router.d.ts +77 -7
  48. package/esm/components/nested-router.d.ts.map +1 -1
  49. package/esm/components/nested-router.js +139 -13
  50. package/esm/components/nested-router.js.map +1 -1
  51. package/esm/components/nested-router.spec.js +283 -52
  52. package/esm/components/nested-router.spec.js.map +1 -1
  53. package/esm/services/location-service.d.ts +39 -42
  54. package/esm/services/location-service.d.ts.map +1 -1
  55. package/esm/services/location-service.js +115 -134
  56. package/esm/services/location-service.js.map +1 -1
  57. package/esm/services/location-service.spec.js +59 -24
  58. package/esm/services/location-service.spec.js.map +1 -1
  59. package/esm/services/route-match-service.d.ts +3 -2
  60. package/esm/services/route-match-service.d.ts.map +1 -1
  61. package/esm/services/route-match-service.js +13 -22
  62. package/esm/services/route-match-service.js.map +1 -1
  63. package/esm/services/route-match-service.spec.js +42 -49
  64. package/esm/services/route-match-service.spec.js.map +1 -1
  65. package/esm/services/route-meta-utils.d.ts +28 -6
  66. package/esm/services/route-meta-utils.d.ts.map +1 -1
  67. package/esm/services/route-meta-utils.js +18 -4
  68. package/esm/services/route-meta-utils.js.map +1 -1
  69. package/esm/services/route-meta-utils.spec.js +60 -5
  70. package/esm/services/route-meta-utils.spec.js.map +1 -1
  71. package/esm/services/screen-service.d.ts +13 -72
  72. package/esm/services/screen-service.d.ts.map +1 -1
  73. package/esm/services/screen-service.js +45 -137
  74. package/esm/services/screen-service.js.map +1 -1
  75. package/esm/services/screen-service.spec.js +19 -18
  76. package/esm/services/screen-service.spec.js.map +1 -1
  77. package/esm/services/spatial-navigation-service.d.ts +17 -39
  78. package/esm/services/spatial-navigation-service.d.ts.map +1 -1
  79. package/esm/services/spatial-navigation-service.js +280 -313
  80. package/esm/services/spatial-navigation-service.js.map +1 -1
  81. package/esm/services/spatial-navigation-service.spec.js +163 -158
  82. package/esm/services/spatial-navigation-service.spec.js.map +1 -1
  83. package/esm/shade.d.ts +1 -1
  84. package/esm/shade.d.ts.map +1 -1
  85. package/esm/shade.js +10 -7
  86. package/esm/shade.js.map +1 -1
  87. package/esm/vnode.d.ts +1 -1
  88. package/esm/vnode.js +1 -1
  89. package/package.json +5 -4
  90. package/src/component-factory.spec.tsx +3 -2
  91. package/src/components/define-nested-routes.spec.ts +91 -0
  92. package/src/components/define-nested-routes.ts +27 -0
  93. package/src/components/index.ts +3 -3
  94. package/src/components/nested-hooks.spec.ts +254 -0
  95. package/src/components/nested-hooks.ts +109 -0
  96. package/src/components/nested-navigate.spec.ts +136 -32
  97. package/src/components/nested-navigate.ts +75 -26
  98. package/src/components/nested-replace.spec.ts +89 -0
  99. package/src/components/nested-replace.ts +46 -0
  100. package/src/components/nested-route-link.spec.tsx +90 -22
  101. package/src/components/nested-route-link.tsx +54 -29
  102. package/src/components/nested-route-types.ts +82 -2
  103. package/src/components/nested-router.spec.tsx +334 -51
  104. package/src/components/nested-router.tsx +184 -24
  105. package/src/services/location-service.spec.ts +68 -25
  106. package/src/services/location-service.tsx +156 -122
  107. package/src/services/route-match-service.spec.ts +41 -28
  108. package/src/services/route-match-service.ts +17 -8
  109. package/src/services/route-meta-utils.spec.ts +78 -10
  110. package/src/services/route-meta-utils.ts +44 -15
  111. package/src/services/screen-service.spec.ts +19 -18
  112. package/src/services/screen-service.ts +65 -110
  113. package/src/services/spatial-navigation-service.spec.ts +165 -160
  114. package/src/services/spatial-navigation-service.ts +299 -287
  115. package/src/shade.ts +11 -8
  116. package/src/vnode.ts +1 -1
  117. package/esm/components/link-to-route.d.ts +0 -10
  118. package/esm/components/link-to-route.d.ts.map +0 -1
  119. package/esm/components/link-to-route.js +0 -16
  120. package/esm/components/link-to-route.js.map +0 -1
  121. package/esm/components/link-to-route.spec.d.ts +0 -2
  122. package/esm/components/link-to-route.spec.d.ts.map +0 -1
  123. package/esm/components/link-to-route.spec.js +0 -30
  124. package/esm/components/link-to-route.spec.js.map +0 -1
  125. package/esm/components/route-link.d.ts +0 -10
  126. package/esm/components/route-link.d.ts.map +0 -1
  127. package/esm/components/route-link.js +0 -25
  128. package/esm/components/route-link.js.map +0 -1
  129. package/esm/components/route-link.spec.d.ts +0 -2
  130. package/esm/components/route-link.spec.d.ts.map +0 -1
  131. package/esm/components/route-link.spec.js +0 -34
  132. package/esm/components/route-link.spec.js.map +0 -1
  133. package/esm/components/router.d.ts +0 -44
  134. package/esm/components/router.d.ts.map +0 -1
  135. package/esm/components/router.js +0 -66
  136. package/esm/components/router.js.map +0 -1
  137. package/esm/components/router.spec.d.ts +0 -2
  138. package/esm/components/router.spec.d.ts.map +0 -1
  139. package/esm/components/router.spec.js +0 -161
  140. package/esm/components/router.spec.js.map +0 -1
  141. package/src/components/link-to-route.spec.tsx +0 -45
  142. package/src/components/link-to-route.tsx +0 -26
  143. package/src/components/route-link.spec.tsx +0 -44
  144. package/src/components/route-link.tsx +0 -29
  145. package/src/components/router.spec.tsx +0 -217
  146. package/src/components/router.tsx +0 -103
@@ -10,9 +10,9 @@ export type ConcatPaths<Parent extends string, Child extends string> = Parent ex
10
10
  * Recursively extracts all valid full URL paths from a nested route tree.
11
11
  * @typeParam T - A record of route patterns to NestedRoute definitions
12
12
  */
13
- export type ExtractRoutePaths<T extends Record<string, NestedRoute<any>>> = {
13
+ export type ExtractRoutePaths<T extends Record<string, NestedRoute<any, any, any>>> = {
14
14
  [K in keyof T & string]: K | (T[K] extends {
15
- children: infer C extends Record<string, NestedRoute<any>>;
15
+ children: infer C extends Record<string, NestedRoute<any, any, any>>;
16
16
  } ? ConcatPaths<K, ExtractRoutePaths<C> & string> : never);
17
17
  }[keyof T & string];
18
18
  /**
@@ -34,4 +34,81 @@ export type ExtractRouteParams<T extends string> = T extends `${string}:${infer
34
34
  export type UrlTree<TPaths extends string> = {
35
35
  [key: string]: TPaths | UrlTree<TPaths>;
36
36
  };
37
+ /**
38
+ * A query string validator function for a nested route. Receives the deserialized
39
+ * query string object and returns either the typed query value or `null` when
40
+ * the URL's query does not match the route's expected shape.
41
+ * @typeParam TQuery - The typed query shape the route expects
42
+ */
43
+ export type QueryValidator<TQuery> = (raw: Record<string, unknown>) => TQuery | null;
44
+ /**
45
+ * A readonly tuple of string literals describing the allowed URL hash values
46
+ * for a nested route.
47
+ */
48
+ export type HashLiterals = readonly string[];
49
+ /**
50
+ * Extracts the typed query shape declared by a {@link NestedRoute}'s `query` validator.
51
+ * Resolves to `never` when the route has no `query` validator.
52
+ * @typeParam R - A NestedRoute value type
53
+ */
54
+ export type ExtractRouteQuery<R> = R extends {
55
+ query: QueryValidator<infer Q>;
56
+ } ? Q : never;
57
+ /**
58
+ * Extracts the typed hash literal union declared by a {@link NestedRoute}'s `hash` tuple.
59
+ * Resolves to `never` when the route has no `hash` declaration.
60
+ * @typeParam R - A NestedRoute value type
61
+ */
62
+ export type ExtractRouteHash<R> = R extends {
63
+ hash: infer H extends HashLiterals;
64
+ } ? H[number] : never;
65
+ /**
66
+ * Walks a nested route tree and resolves the route value at the given composed path.
67
+ * Used to surface per-route `query` / `hash` metadata to call-site helpers.
68
+ * @typeParam TRoutes - The route tree
69
+ * @typeParam TPath - A full composed route path (as produced by {@link ExtractRoutePaths})
70
+ */
71
+ export type RouteAt<TRoutes extends Record<string, NestedRoute<any, any, any>>, TPath extends string> = {
72
+ [K in keyof TRoutes & string]: TPath extends K ? TRoutes[K] : K extends '/' ? TRoutes[K] extends {
73
+ children: infer C extends Record<string, NestedRoute<any, any, any>>;
74
+ } ? RouteAt<C, TPath> : never : TPath extends `${K}${infer Rest}` ? TRoutes[K] extends {
75
+ children: infer C extends Record<string, NestedRoute<any, any, any>>;
76
+ } ? RouteAt<C, Rest> : never : never;
77
+ }[keyof TRoutes & string];
78
+ /**
79
+ * Builds the `params` portion of a typed navigation / link argument.
80
+ * Resolves to `{ params?: Record<string, string> }` when the path has no `:param`
81
+ * segments and `{ params: {...} }` when at least one is required.
82
+ * @typeParam TPath - A URL pattern string
83
+ */
84
+ export type TypedParamsArg<TPath extends string> = string extends keyof ExtractRouteParams<TPath> ? {
85
+ params?: Record<string, string>;
86
+ } : {
87
+ params: ExtractRouteParams<TPath>;
88
+ };
89
+ /**
90
+ * Builds the `query` portion of a typed navigation / link argument.
91
+ * - `never` (route declared no schema) → property is forbidden.
92
+ * - All-optional schema → property itself is optional.
93
+ * - Any required key → property is required.
94
+ * @typeParam TQuery - The route's typed query shape
95
+ */
96
+ export type TypedQueryArg<TQuery> = [TQuery] extends [never] ? {
97
+ query?: never;
98
+ } : {} extends TQuery ? {
99
+ query?: TQuery;
100
+ } : {
101
+ query: TQuery;
102
+ };
103
+ /**
104
+ * Builds the `hash` portion of a typed navigation / link argument.
105
+ * Hash is always optional at the call site (URL fragments are never required
106
+ * for correctness of navigation).
107
+ * @typeParam THash - The route's hash literal union
108
+ */
109
+ export type TypedHashArg<THash> = [THash] extends [never] ? {
110
+ hash?: never;
111
+ } : {
112
+ hash?: THash;
113
+ };
37
114
  //# sourceMappingURL=nested-route-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nested-route-types.d.ts","sourceRoot":"","sources":["../../src/components/nested-route-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;;;GAKG;AACH,MAAM,MAAM,WAAW,CAAC,MAAM,SAAS,MAAM,EAAE,KAAK,SAAS,MAAM,IAAI,MAAM,SAAS,GAAG,GAAG,KAAK,GAAG,GAAG,MAAM,GAAG,KAAK,EAAE,CAAA;AAEvH;;;GAGG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI;KACzE,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,GAClB,CAAC,GACD,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;QAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;KAAE,GACxE,WAAW,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAC7C,KAAK,CAAC;CACf,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAA;AAEnB;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,MAAM,KAAK,IAAI,MAAM,IAAI,EAAE,GACjG;KAAG,CAAC,IAAI,KAAK,GAAG,MAAM,kBAAkB,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,MAAM;CAAE,GAC/D,CAAC,SAAS,GAAG,MAAM,IAAI,MAAM,KAAK,EAAE,GAClC;KAAG,CAAC,IAAI,KAAK,GAAG,MAAM;CAAE,GACxB,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AAE3B;;;;GAIG;AACH,MAAM,MAAM,OAAO,CAAC,MAAM,SAAS,MAAM,IAAI;IAC3C,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACxC,CAAA"}
1
+ {"version":3,"file":"nested-route-types.d.ts","sourceRoot":"","sources":["../../src/components/nested-route-types.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import type { Injector } from '@furystack/inject';
2
2
  import type { MatchOptions, MatchResult } from 'path-to-regexp';
3
3
  import type { RenderOptions } from '../models/render-options.js';
4
4
  import type { ViewTransitionConfig } from '../view-transition.js';
5
+ import type { HashLiterals, QueryValidator } from './nested-route-types.js';
5
6
  /**
6
7
  * Options passed to a dynamic title resolver function.
7
8
  * @typeParam TMatchResult - The type of matched URL parameters
@@ -37,13 +38,27 @@ export interface NestedRouteMeta<TMatchResult = unknown> {
37
38
  * A single route entry in a NestedRouter configuration.
38
39
  * Unlike flat `Route`, the URL is the Record key (not a field), and the
39
40
  * `component` receives an `outlet` for rendering matched child content.
41
+ *
42
+ * Routes may additionally declare:
43
+ * - `query`: a validator that parses the deserialized query string into a
44
+ * typed shape; `component` receives the parsed value (or `null` when
45
+ * validation fails). The route still matches on path alone — an invalid
46
+ * query never prevents navigation.
47
+ * - `hash`: a readonly tuple of allowed URL hash literals; `component`
48
+ * receives the current hash when it matches one of the listed literals,
49
+ * or `undefined` otherwise.
50
+ *
40
51
  * @typeParam TMatchResult - The type of matched URL parameters
52
+ * @typeParam TQuery - The typed query shape parsed from the URL search string (defaults to `never`)
53
+ * @typeParam THash - The readonly tuple of allowed hash literals (defaults to `never`)
41
54
  */
42
- export type NestedRoute<TMatchResult = unknown> = {
55
+ export type NestedRoute<TMatchResult = unknown, TQuery = any, THash extends HashLiterals = readonly any[]> = {
43
56
  meta?: NestedRouteMeta<TMatchResult>;
44
57
  component: (options: {
45
58
  currentUrl: string;
46
59
  match: MatchResult<TMatchResult extends object ? TMatchResult : object>;
60
+ query: TQuery | null;
61
+ hash: THash[number] | undefined;
47
62
  outlet?: JSX.Element;
48
63
  }) => JSX.Element;
49
64
  routingOptions?: MatchOptions;
@@ -64,24 +79,41 @@ export type NestedRoute<TMatchResult = unknown> = {
64
79
  onLeave?: (options: RenderOptions<unknown> & {
65
80
  element: JSX.Element;
66
81
  }) => Promise<void>;
67
- children?: Record<string, NestedRoute<any>>;
82
+ children?: Record<string, NestedRoute<any, any, any>>;
68
83
  viewTransition?: boolean | ViewTransitionConfig;
84
+ /**
85
+ * Optional validator that narrows the deserialized URL query string into a
86
+ * typed shape. Return `null` when the URL's query does not satisfy the route's
87
+ * contract — the route still matches on path, but `component` receives `null`.
88
+ */
89
+ query?: QueryValidator<TQuery>;
90
+ /**
91
+ * Optional readonly tuple of URL hash literals the route understands. Declare
92
+ * with `as const` to preserve literal types, e.g. `hash: ['tab1', 'tab2'] as const`.
93
+ * The router forwards the current hash to `component` only when it matches one
94
+ * of the listed literals; otherwise `component.hash` is `undefined`.
95
+ */
96
+ hash?: THash;
69
97
  };
70
98
  /**
71
99
  * Props for the NestedRouter component.
72
100
  * Routes are defined as a Record where keys are URL patterns.
73
101
  */
74
102
  export type NestedRouterProps = {
75
- routes: Record<string, NestedRoute<any>>;
103
+ routes: Record<string, NestedRoute<any, any, any>>;
76
104
  notFound?: JSX.Element;
77
105
  viewTransition?: boolean | ViewTransitionConfig;
78
106
  };
79
107
  /**
80
- * A single entry in a match chain, pairing a matched route with its match result.
108
+ * A single entry in a match chain, pairing a matched route with its match
109
+ * result and the typed `query` / `hash` values derived from the URL for that
110
+ * route's declared schema.
81
111
  */
82
112
  export type MatchChainEntry = {
83
- route: NestedRoute<unknown>;
113
+ route: NestedRoute<unknown, any, any>;
84
114
  match: MatchResult<object>;
115
+ query: unknown;
116
+ hash: string | undefined;
85
117
  };
86
118
  /**
87
119
  * Internal state for the NestedRouter component.
@@ -102,16 +134,50 @@ export type NestedRouterState = {
102
134
  *
103
135
  * For leaf routes (no children), only exact matching is used.
104
136
  *
137
+ * The returned entries contain placeholder `query: null` / `hash: undefined`
138
+ * values; callers are expected to populate them via {@link enrichMatchChain}.
139
+ *
105
140
  * @param routes - The route definitions to match against
106
141
  * @param currentUrl - The URL path to match
107
142
  * @returns An array of matched chain entries from outermost to innermost, or null if no match
108
143
  */
109
- export declare const buildMatchChain: (routes: Record<string, NestedRoute<any>>, currentUrl: string) => MatchChainEntry[] | null;
144
+ export declare const buildMatchChain: (routes: Record<string, NestedRoute<any, any, any>>, currentUrl: string) => MatchChainEntry[] | null;
110
145
  /**
111
- * Finds the first index where two match chains diverge.
146
+ * Populates each chain entry's `query` and `hash` fields by running the route's
147
+ * declared validator against the URL's deserialized query string, and matching
148
+ * the current URL hash against the route's declared literal tuple.
149
+ *
150
+ * Entries whose route declares neither `query` nor `hash` are returned with
151
+ * `query: null` / `hash: undefined`.
152
+ *
153
+ * When no entry in the chain declares either `query` or `hash`, the input
154
+ * array is returned unchanged to avoid a per-navigation allocation on the
155
+ * common path-only case.
156
+ *
157
+ * @param chain - The chain produced by {@link buildMatchChain}
158
+ * @param deserializedSearch - The deserialized URL query string
159
+ * @param currentHash - The current URL hash (without the leading `#`)
160
+ */
161
+ export declare const enrichMatchChain: (chain: MatchChainEntry[], deserializedSearch: Record<string, unknown>, currentHash: string) => MatchChainEntry[];
162
+ /**
163
+ * Finds the first index where two match chains diverge, considering route
164
+ * identity and matched path parameters only. Used to scope lifecycle hooks
165
+ * (`onLeave` / `onVisit`) so that a query string or hash change does not
166
+ * fire spurious mount / unmount callbacks.
167
+ *
112
168
  * Returns the length of the shorter chain if one is a prefix of the other.
113
169
  */
114
170
  export declare const findDivergenceIndex: (oldChain: MatchChainEntry[], newChain: MatchChainEntry[]) => number;
171
+ /**
172
+ * Returns true when any chain entry differs in its `query` value or `hash`
173
+ * segment, ignoring path-level fields (route identity and params). Used to
174
+ * force a re-render when the URL's query string or hash changes without the
175
+ * matched route chain itself changing.
176
+ *
177
+ * Query values are compared with a key-order-independent shallow equality —
178
+ * sufficient for the typed shapes a route's `query` validator surfaces.
179
+ */
180
+ export declare const hasQueryOrHashChanged: (oldChain: MatchChainEntry[], newChain: MatchChainEntry[]) => boolean;
115
181
  /**
116
182
  * The result of rendering a match chain, containing both the fully composed
117
183
  * JSX tree and per-entry elements for scoped lifecycle animations.
@@ -147,6 +213,10 @@ export declare const resolveViewTransition: (routerConfig: boolean | ViewTransit
147
213
  * Routes are defined as a Record where keys are URL patterns (following the
148
214
  * RestApi pattern). The matching algorithm builds a chain from outermost to
149
215
  * innermost route, then renders inside-out so each parent wraps its child.
216
+ *
217
+ * The router subscribes to path, query string and hash changes; path-level
218
+ * changes drive `onLeave` / `onVisit` lifecycle hooks while query / hash
219
+ * changes re-render the chain without firing lifecycle callbacks.
150
220
  */
151
221
  export declare const NestedRouter: (props: NestedRouterProps & Omit<Partial<HTMLElement>, "style"> & {
152
222
  style?: Partial<CSSStyleDeclaration>;
@@ -1 +1 @@
1
- {"version":3,"file":"nested-router.d.ts","sourceRoot":"","sources":["../../src/components/nested-router.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nested-router.d.ts","sourceRoot":"","sources":["../../src/components/nested-router.tsx"],"names":[],"mappings":"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"}
@@ -14,6 +14,9 @@ import { maybeViewTransition } from '../view-transition.js';
14
14
  *
15
15
  * For leaf routes (no children), only exact matching is used.
16
16
  *
17
+ * The returned entries contain placeholder `query: null` / `hash: undefined`
18
+ * values; callers are expected to populate them via {@link enrichMatchChain}.
19
+ *
17
20
  * @param routes - The route definitions to match against
18
21
  * @param currentUrl - The URL path to match
19
22
  * @returns An array of matched chain entries from outermost to innermost, or null if no match
@@ -35,27 +38,59 @@ export const buildMatchChain = (routes, currentUrl) => {
35
38
  }
36
39
  const childChain = buildMatchChain(route.children, remainingUrl);
37
40
  if (childChain) {
38
- return [{ route, match: prefixResult }, ...childChain];
41
+ return [{ route, match: prefixResult, query: null, hash: undefined }, ...childChain];
39
42
  }
40
43
  }
41
44
  const exactMatchFn = match(pattern, route.routingOptions);
42
45
  const exactResult = exactMatchFn(currentUrl);
43
46
  if (exactResult) {
44
- return [{ route, match: exactResult }];
47
+ return [{ route, match: exactResult, query: null, hash: undefined }];
45
48
  }
46
49
  }
47
50
  else {
48
51
  const matchFn = match(pattern, route.routingOptions);
49
52
  const matchResult = matchFn(currentUrl);
50
53
  if (matchResult) {
51
- return [{ route, match: matchResult }];
54
+ return [{ route, match: matchResult, query: null, hash: undefined }];
52
55
  }
53
56
  }
54
57
  }
55
58
  return null;
56
59
  };
57
60
  /**
58
- * Finds the first index where two match chains diverge.
61
+ * Populates each chain entry's `query` and `hash` fields by running the route's
62
+ * declared validator against the URL's deserialized query string, and matching
63
+ * the current URL hash against the route's declared literal tuple.
64
+ *
65
+ * Entries whose route declares neither `query` nor `hash` are returned with
66
+ * `query: null` / `hash: undefined`.
67
+ *
68
+ * When no entry in the chain declares either `query` or `hash`, the input
69
+ * array is returned unchanged to avoid a per-navigation allocation on the
70
+ * common path-only case.
71
+ *
72
+ * @param chain - The chain produced by {@link buildMatchChain}
73
+ * @param deserializedSearch - The deserialized URL query string
74
+ * @param currentHash - The current URL hash (without the leading `#`)
75
+ */
76
+ export const enrichMatchChain = (chain, deserializedSearch, currentHash) => {
77
+ const hasAnyDeclaration = chain.some((entry) => entry.route.query || entry.route.hash);
78
+ if (!hasAnyDeclaration)
79
+ return chain;
80
+ return chain.map((entry) => {
81
+ const validator = entry.route.query;
82
+ const query = validator ? validator(deserializedSearch) : null;
83
+ const declaredHash = entry.route.hash;
84
+ const hash = declaredHash?.includes(currentHash) ? currentHash : undefined;
85
+ return { ...entry, query, hash };
86
+ });
87
+ };
88
+ /**
89
+ * Finds the first index where two match chains diverge, considering route
90
+ * identity and matched path parameters only. Used to scope lifecycle hooks
91
+ * (`onLeave` / `onVisit`) so that a query string or hash change does not
92
+ * fire spurious mount / unmount callbacks.
93
+ *
59
94
  * Returns the length of the shorter chain if one is a prefix of the other.
60
95
  */
61
96
  export const findDivergenceIndex = (oldChain, newChain) => {
@@ -68,6 +103,62 @@ export const findDivergenceIndex = (oldChain, newChain) => {
68
103
  }
69
104
  return minLength;
70
105
  };
106
+ /**
107
+ * Shallow structural equality for query values. Handles the shapes produced by
108
+ * route-declared query validators: primitives, plain objects (by own enumerable
109
+ * string keys, recursively shallow-compared), and arrays (by index).
110
+ *
111
+ * Nested objects / arrays are compared shallowly one level deep, then fall back
112
+ * to `Object.is` — sufficient for the typed-query shapes the router surfaces,
113
+ * and order-independent unlike `JSON.stringify`.
114
+ */
115
+ const isShallowEqual = (a, b) => {
116
+ if (Object.is(a, b))
117
+ return true;
118
+ if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object')
119
+ return false;
120
+ if (Array.isArray(a)) {
121
+ if (!Array.isArray(b) || a.length !== b.length)
122
+ return false;
123
+ for (let i = 0; i < a.length; i++) {
124
+ if (!Object.is(a[i], b[i]))
125
+ return false;
126
+ }
127
+ return true;
128
+ }
129
+ if (Array.isArray(b))
130
+ return false;
131
+ const aKeys = Object.keys(a);
132
+ const bKeys = Object.keys(b);
133
+ if (aKeys.length !== bKeys.length)
134
+ return false;
135
+ for (const key of aKeys) {
136
+ if (!Object.prototype.hasOwnProperty.call(b, key))
137
+ return false;
138
+ if (!Object.is(a[key], b[key]))
139
+ return false;
140
+ }
141
+ return true;
142
+ };
143
+ /**
144
+ * Returns true when any chain entry differs in its `query` value or `hash`
145
+ * segment, ignoring path-level fields (route identity and params). Used to
146
+ * force a re-render when the URL's query string or hash changes without the
147
+ * matched route chain itself changing.
148
+ *
149
+ * Query values are compared with a key-order-independent shallow equality —
150
+ * sufficient for the typed shapes a route's `query` validator surfaces.
151
+ */
152
+ export const hasQueryOrHashChanged = (oldChain, newChain) => {
153
+ const minLength = Math.min(oldChain.length, newChain.length);
154
+ for (let i = 0; i < minLength; i++) {
155
+ if (oldChain[i].hash !== newChain[i].hash)
156
+ return true;
157
+ if (!isShallowEqual(oldChain[i].query, newChain[i].query))
158
+ return true;
159
+ }
160
+ return false;
161
+ };
71
162
  /**
72
163
  * Renders a match chain inside-out: starts with the innermost (leaf) route
73
164
  * rendered with `outlet: undefined`, then passes its JSX as `outlet` to
@@ -88,6 +179,8 @@ export const renderMatchChain = (chain, currentUrl) => {
88
179
  outlet = entry.route.component({
89
180
  currentUrl,
90
181
  match: entry.match,
182
+ query: entry.query,
183
+ hash: entry.hash,
91
184
  outlet,
92
185
  });
93
186
  chainElements[i] = outlet;
@@ -120,6 +213,10 @@ export const resolveViewTransition = (routerConfig, newChain) => {
120
213
  * Routes are defined as a Record where keys are URL patterns (following the
121
214
  * RestApi pattern). The matching algorithm builds a chain from outermost to
122
215
  * innermost route, then renders inside-out so each parent wraps its child.
216
+ *
217
+ * The router subscribes to path, query string and hash changes; path-level
218
+ * changes drive `onLeave` / `onVisit` lifecycle hooks while query / hash
219
+ * changes re-render the chain without firing lifecycle callbacks.
123
220
  */
124
221
  export const NestedRouter = Shade({
125
222
  customElementName: 'shade-nested-router',
@@ -131,17 +228,22 @@ export const NestedRouter = Shade({
131
228
  jsx: createComponent("div", null),
132
229
  chainElements: [],
133
230
  });
231
+ const locationService = injector.get(LocationService);
134
232
  const updateUrl = async (currentUrl) => {
135
233
  const [lastState] = useState('routerState', state);
136
234
  const { matchChain: lastChain, chainElements: lastChainElements } = lastState;
137
235
  try {
138
- const newChain = buildMatchChain(options.props.routes, currentUrl);
139
- if (newChain) {
236
+ const rawChain = buildMatchChain(options.props.routes, currentUrl);
237
+ if (rawChain) {
238
+ const deserializedSearch = locationService.onDeserializedLocationSearchChanged.getValue();
239
+ const currentHash = locationService.onLocationHashChanged.getValue();
240
+ const newChain = enrichMatchChain(rawChain, deserializedSearch, currentHash);
140
241
  const lastChainEntries = lastChain ?? [];
141
242
  const divergeIndex = findDivergenceIndex(lastChainEntries, newChain);
142
- const hasChanged = divergeIndex < lastChainEntries.length ||
243
+ const hasPathChanged = divergeIndex < lastChainEntries.length ||
143
244
  divergeIndex < newChain.length ||
144
245
  lastChainEntries.length !== newChain.length;
246
+ const hasChanged = hasPathChanged || hasQueryOrHashChanged(lastChainEntries, newChain);
145
247
  if (hasChanged) {
146
248
  const version = ++versionRef.current;
147
249
  for (let i = lastChainEntries.length - 1; i >= divergeIndex; i--) {
@@ -161,7 +263,7 @@ export const NestedRouter = Shade({
161
263
  return;
162
264
  const applyUpdate = () => {
163
265
  setState({ matchChain: newChain, jsx: newResult.jsx, chainElements: newResult.chainElements });
164
- injector.getInstance(RouteMatchService).currentMatchChain.setValue(newChain);
266
+ injector.get(RouteMatchService).currentMatchChain.setValue(newChain);
165
267
  };
166
268
  const vtConfig = resolveViewTransition(options.props.viewTransition, newChain);
167
269
  await maybeViewTransition(vtConfig === false ? undefined : vtConfig, applyUpdate);
@@ -185,7 +287,7 @@ export const NestedRouter = Shade({
185
287
  jsx: options.props.notFound || createComponent("div", null),
186
288
  chainElements: [],
187
289
  });
188
- injector.getInstance(RouteMatchService).currentMatchChain.setValue([]);
290
+ injector.get(RouteMatchService).currentMatchChain.setValue([]);
189
291
  };
190
292
  await maybeViewTransition(options.props.viewTransition, applyNotFound);
191
293
  }
@@ -196,10 +298,34 @@ export const NestedRouter = Shade({
196
298
  }
197
299
  }
198
300
  };
199
- const [locationPath] = useObservable('locationPathChanged', injector.getInstance(LocationService).onLocationPathChanged, {
200
- onChange: (newValue) => {
201
- void updateUrl(newValue);
202
- },
301
+ /**
302
+ * A single `LocationService.navigate` call synchronously fires three
303
+ * observables (path, search, hash). Without coalescing, each would kick
304
+ * off its own `updateUrl` and rely on `versionRef` to cancel the two
305
+ * that lose the race.
306
+ *
307
+ * We dedupe by the composed URL key: each observer fires after the
308
+ * browser's location has already been updated, so the key read at fire
309
+ * time is the final target URL. The first observer in the burst kicks
310
+ * off `updateUrl`; the remaining two see the same key and short-circuit.
311
+ */
312
+ const getUrlKey = () => `${locationService.onLocationPathChanged.getValue()}?${locationService.onLocationSearchChanged.getValue()}#${locationService.onLocationHashChanged.getValue()}`;
313
+ const [lastKeyRef] = useState('navLastKey', { current: getUrlKey() });
314
+ const scheduleUpdate = () => {
315
+ const key = getUrlKey();
316
+ if (key === lastKeyRef.current)
317
+ return;
318
+ lastKeyRef.current = key;
319
+ void updateUrl(locationService.onLocationPathChanged.getValue());
320
+ };
321
+ const [locationPath] = useObservable('locationPathChanged', locationService.onLocationPathChanged, {
322
+ onChange: scheduleUpdate,
323
+ });
324
+ useObservable('locationSearchChanged', locationService.onDeserializedLocationSearchChanged, {
325
+ onChange: scheduleUpdate,
326
+ });
327
+ useObservable('locationHashChanged', locationService.onLocationHashChanged, {
328
+ onChange: scheduleUpdate,
203
329
  });
204
330
  void updateUrl(locationPath);
205
331
  return state.jsx;
@@ -1 +1 @@
1
- {"version":3,"file":"nested-router.js","sourceRoot":"","sources":["../../src/components/nested-router.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nested-router.js","sourceRoot":"","sources":["../../src/components/nested-router.tsx"],"names":[],"mappings":"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"}