@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
@@ -0,0 +1,36 @@
1
+ import type { Injector } from '@furystack/inject';
2
+ import type { NestedNavigateArgs, TypedNestedNavigateArgs } from './nested-navigate.js';
3
+ import type { ExtractRoutePaths } from './nested-route-types.js';
4
+ import type { NestedRoute } from './nested-router.js';
5
+ /**
6
+ * Replaces the current history entry with a route using the LocationService
7
+ * resolved from the given injector. Has the same URL-composition semantics as
8
+ * `nestedNavigate`, but calls `history.replaceState` under the hood so the
9
+ * intermediate URL does not appear in the browser's back / forward stack.
10
+ *
11
+ * Use this for SPA redirects (e.g. canonicalization, auth guards) where the
12
+ * caller's URL should not be recoverable with the Back button.
13
+ *
14
+ * @param injector - The injector instance to resolve LocationService from
15
+ * @param args - The navigation arguments
16
+ */
17
+ export declare const nestedReplace: (injector: Injector, args: NestedNavigateArgs) => void;
18
+ /**
19
+ * Creates a type-safe replace function constrained to a specific route tree.
20
+ * The returned function has the same runtime behavior as {@link nestedReplace}
21
+ * but narrows `path` to valid route paths, requires `params` when the route has
22
+ * parameters, and enforces the route's declared `query` and `hash` schemas.
23
+ *
24
+ * @typeParam TRoutes - The route tree type (use `typeof yourRoutes`)
25
+ * @returns A type-safe replace function
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const appReplace = createNestedReplace<typeof appRoutes>()
30
+ *
31
+ * // Redirect an unauthenticated visitor without polluting history
32
+ * appReplace(injector, { path: '/login' })
33
+ * ```
34
+ */
35
+ export declare const createNestedReplace: <TRoutes extends Record<string, NestedRoute<any, any, any>>>() => <TPath extends ExtractRoutePaths<TRoutes>>(injector: Injector, args: TypedNestedNavigateArgs<TRoutes, TPath>) => void;
36
+ //# sourceMappingURL=nested-replace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested-replace.d.ts","sourceRoot":"","sources":["../../src/components/nested-replace.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAEvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,GAAI,UAAU,QAAQ,EAAE,MAAM,kBAAkB,KAAG,IAE5E,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,OACpE,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAC/D,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,KAC1C,IACN,CAAA"}
@@ -0,0 +1,38 @@
1
+ import { LocationService } from '../services/location-service.js';
2
+ import { buildNestedNavigateUrl } from './nested-navigate.js';
3
+ /**
4
+ * Replaces the current history entry with a route using the LocationService
5
+ * resolved from the given injector. Has the same URL-composition semantics as
6
+ * `nestedNavigate`, but calls `history.replaceState` under the hood so the
7
+ * intermediate URL does not appear in the browser's back / forward stack.
8
+ *
9
+ * Use this for SPA redirects (e.g. canonicalization, auth guards) where the
10
+ * caller's URL should not be recoverable with the Back button.
11
+ *
12
+ * @param injector - The injector instance to resolve LocationService from
13
+ * @param args - The navigation arguments
14
+ */
15
+ export const nestedReplace = (injector, args) => {
16
+ injector.get(LocationService).replace(buildNestedNavigateUrl(args));
17
+ };
18
+ /**
19
+ * Creates a type-safe replace function constrained to a specific route tree.
20
+ * The returned function has the same runtime behavior as {@link nestedReplace}
21
+ * but narrows `path` to valid route paths, requires `params` when the route has
22
+ * parameters, and enforces the route's declared `query` and `hash` schemas.
23
+ *
24
+ * @typeParam TRoutes - The route tree type (use `typeof yourRoutes`)
25
+ * @returns A type-safe replace function
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const appReplace = createNestedReplace<typeof appRoutes>()
30
+ *
31
+ * // Redirect an unauthenticated visitor without polluting history
32
+ * appReplace(injector, { path: '/login' })
33
+ * ```
34
+ */
35
+ export const createNestedReplace = () => {
36
+ return nestedReplace;
37
+ };
38
+ //# sourceMappingURL=nested-replace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested-replace.js","sourceRoot":"","sources":["../../src/components/nested-replace.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAEjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAI7D;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,QAAkB,EAAE,IAAwB,EAAQ,EAAE;IAClF,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAA;AACrE,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAA+D,EAAE;IAClG,OAAO,aAGE,CAAA;AACX,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=nested-replace.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested-replace.spec.d.ts","sourceRoot":"","sources":["../../src/components/nested-replace.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ import { createInjector } from '@furystack/inject';
2
+ import { usingAsync } from '@furystack/utils';
3
+ import { describe, expect, expectTypeOf, it, vi } from 'vitest';
4
+ import { LocationService } from '../services/location-service.js';
5
+ import { createNestedReplace, nestedReplace } from './nested-replace.js';
6
+ describe('nestedReplace', () => {
7
+ it('Should replace the current history entry with a simple path', async () => {
8
+ await usingAsync(createInjector(), async (injector) => {
9
+ const locationService = injector.get(LocationService);
10
+ const navigateSpy = vi.spyOn(locationService, 'navigate');
11
+ const replaceSpy = vi.spyOn(locationService, 'replace');
12
+ nestedReplace(injector, { path: '/buttons' });
13
+ expect(replaceSpy).toHaveBeenCalledWith('/buttons');
14
+ expect(navigateSpy).not.toHaveBeenCalled();
15
+ });
16
+ });
17
+ it('Should compile params, query and hash for a replace call', async () => {
18
+ await usingAsync(createInjector(), async (injector) => {
19
+ const locationService = injector.get(LocationService);
20
+ const replaceSpy = vi.spyOn(locationService, 'replace');
21
+ nestedReplace(injector, {
22
+ path: '/users/:id',
23
+ params: { id: '7' },
24
+ query: { tab: 'profile' },
25
+ hash: 'notes',
26
+ });
27
+ expect(replaceSpy).toHaveBeenCalledTimes(1);
28
+ const replacedUrl = replaceSpy.mock.calls[0][0];
29
+ expect(replacedUrl.startsWith('/users/7?')).toBe(true);
30
+ expect(replacedUrl.endsWith('#notes')).toBe(true);
31
+ });
32
+ });
33
+ });
34
+ describe('createNestedReplace', () => {
35
+ it('Should constrain path to valid route paths', () => {
36
+ const appReplace = createNestedReplace();
37
+ expectTypeOf((appReplace))
38
+ .parameter(0)
39
+ .toEqualTypeOf();
40
+ });
41
+ it('Should reject invalid paths', () => {
42
+ const appReplace = createNestedReplace();
43
+ // @ts-expect-error -- '/nonexistent' is not a valid route path
44
+ appReplace(createInjector(), { path: '/nonexistent' });
45
+ });
46
+ it('Should enforce a declared required query shape', () => {
47
+ const routes = {
48
+ '/list': {
49
+ component: () => null,
50
+ query: (raw) => (typeof raw.page === 'number' ? { page: raw.page } : null),
51
+ },
52
+ };
53
+ const appReplace = createNestedReplace();
54
+ expectTypeOf((appReplace))
55
+ .parameter(1)
56
+ .toExtend();
57
+ });
58
+ });
59
+ //# sourceMappingURL=nested-replace.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested-replace.spec.js","sourceRoot":"","sources":["../../src/components/nested-replace.spec.ts"],"names":[],"mappings":"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"}
@@ -1,45 +1,60 @@
1
1
  import type { ChildrenList } from '../models/children-list.js';
2
2
  import type { PartialElement } from '../models/partial-element.js';
3
- import type { ExtractRouteParams, ExtractRoutePaths } from './nested-route-types.js';
3
+ import type { ExtractRouteHash, ExtractRouteQuery, ExtractRoutePaths, RouteAt, TypedHashArg, TypedParamsArg, TypedQueryArg } from './nested-route-types.js';
4
4
  import type { NestedRoute } from './nested-router.js';
5
5
  /**
6
6
  * Props for the NestedRouteLink component.
7
- * Combines SPA navigation from RouteLink with parameter compilation from LinkToRoute.
7
+ * Combines SPA navigation with parameter compilation for nested routes,
8
+ * plus optional query string and hash fragment composition.
8
9
  */
9
10
  export type NestedRouteLinkProps = {
10
- href: string;
11
+ path: string;
11
12
  params?: Record<string, string>;
13
+ query?: Record<string, unknown>;
14
+ hash?: string;
12
15
  } & PartialElement<Omit<HTMLAnchorElement, 'onclick' | 'href'>>;
13
16
  /**
14
17
  * Props for a type-safe nested route link.
15
18
  * When the path contains parameters (e.g. `:id`), the `params` prop becomes required.
19
+ * `query` and `hash` remain loose (untyped) on this variant; use
20
+ * {@link createNestedRouteLink} to narrow them against a specific route tree.
16
21
  * @typeParam TPath - A specific route path string
17
22
  */
18
23
  export type TypedNestedRouteLinkProps<TPath extends string> = {
19
- href: TPath;
20
- } & (string extends keyof ExtractRouteParams<TPath> ? {
21
- params?: Record<string, string>;
22
- } : {
23
- params: ExtractRouteParams<TPath>;
24
- }) & PartialElement<Omit<HTMLAnchorElement, 'onclick' | 'href'>>;
24
+ path: TPath;
25
+ query?: Record<string, unknown>;
26
+ hash?: string;
27
+ } & TypedParamsArg<TPath> & PartialElement<Omit<HTMLAnchorElement, 'onclick' | 'href'>>;
28
+ /**
29
+ * Props for a route-tree-aware nested route link. Narrows `query` and `hash`
30
+ * against the specific route at `TPath` in `TRoutes`.
31
+ * @typeParam TRoutes - The route tree
32
+ * @typeParam TPath - A composed route path within `TRoutes`
33
+ */
34
+ export type TreeAwareNestedRouteLinkProps<TRoutes extends Record<string, NestedRoute<any, any, any>>, TPath extends string> = {
35
+ path: TPath;
36
+ } & TypedParamsArg<TPath> & TypedQueryArg<ExtractRouteQuery<RouteAt<TRoutes, TPath>>> & TypedHashArg<ExtractRouteHash<RouteAt<TRoutes, TPath>>> & PartialElement<Omit<HTMLAnchorElement, 'onclick' | 'href'>>;
25
37
  /**
26
38
  * A link component for NestedRouter that supports SPA navigation with
27
39
  * type-safe route parameter compilation.
28
40
  *
29
41
  * Intercepts click events to use `history.pushState` for client-side navigation,
30
- * and compiles parameterized routes (e.g. `/users/:id`) when `params` is provided.
42
+ * compiles parameterized routes (e.g. `/users/:id`) when `params` is provided,
43
+ * serializes `query` to the URL search string and appends `hash` when set.
31
44
  *
32
- * Route parameters are automatically inferred from the `href` pattern:
33
- * - `href="/buttons"` — `params` is optional
34
- * - `href="/users/:id"` — `params: { id: string }` is required
45
+ * Route parameters are automatically inferred from the `path` pattern:
46
+ * - `path="/buttons"` — `params` is optional
47
+ * - `path="/users/:id"` — `params: { id: string }` is required
35
48
  *
36
- * For additional URL validation against a route tree, use {@link createNestedRouteLink}.
49
+ * For additional URL validation against a route tree (including `query` and
50
+ * `hash` narrowing), use {@link createNestedRouteLink}.
37
51
  */
38
52
  export declare const NestedRouteLink: <TPath extends string = string>(props: TypedNestedRouteLinkProps<TPath>, children?: ChildrenList) => JSX.Element;
39
53
  /**
40
- * Creates a type-safe wrapper around NestedRouteLink constrained to a specific route tree.
41
- * The returned component has the same runtime behavior but narrows `href` to only accept
42
- * valid route paths, and requires `params` when the route has parameters.
54
+ * Creates a type-safe wrapper around NestedRouteLink constrained to a specific
55
+ * route tree. The returned component has the same runtime behavior but narrows
56
+ * `path` to only accept valid route paths, requires `params` when the route
57
+ * has parameters, and enforces the route's declared `query` and `hash` schemas.
43
58
  *
44
59
  * @typeParam TRoutes - The route tree type (use `typeof yourRoutes`)
45
60
  * @returns A narrowed NestedRouteLink component
@@ -48,15 +63,10 @@ export declare const NestedRouteLink: <TPath extends string = string>(props: Typ
48
63
  * ```typescript
49
64
  * const AppLink = createNestedRouteLink<typeof appRoutes>()
50
65
  *
51
- * // Type-safe: only valid paths accepted
52
- * <AppLink href="/buttons">Buttons</AppLink>
53
- *
54
- * // TypeScript error: invalid path
55
- * <AppLink href="/nonexistent">Error!</AppLink>
56
- *
57
- * // Params required for parameterized routes
58
- * <AppLink href="/users/:id" params={{ id: '123' }}>User</AppLink>
66
+ * <AppLink path="/buttons">Buttons</AppLink>
67
+ * <AppLink path="/users/:id" params={{ id: '123' }}>User</AppLink>
68
+ * <AppLink path="/users/:id" params={{ id: '1' }} query={{ tab: 'profile' }} hash="notes">User</AppLink>
59
69
  * ```
60
70
  */
61
- export declare const createNestedRouteLink: <TRoutes extends Record<string, NestedRoute<any>>>() => <TPath extends ExtractRoutePaths<TRoutes>>(props: TypedNestedRouteLinkProps<TPath>, children?: ChildrenList) => JSX.Element;
71
+ export declare const createNestedRouteLink: <TRoutes extends Record<string, NestedRoute<any, any, any>>>() => <TPath extends ExtractRoutePaths<TRoutes>>(props: TreeAwareNestedRouteLinkProps<TRoutes, TPath>, children?: ChildrenList) => JSX.Element;
62
72
  //# sourceMappingURL=nested-route-link.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nested-route-link.d.ts","sourceRoot":"","sources":["../../src/components/nested-route-link.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAIlE,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAChC,GAAG,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,CAAA;AAE/D;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,CAAC,KAAK,SAAS,MAAM,IAAI;IAC5D,IAAI,EAAE,KAAK,CAAA;CACZ,GAAG,CAAC,MAAM,SAAS,MAAM,kBAAkB,CAAC,KAAK,CAAC,GAC/C;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACnC;IAAE,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAA;CAAE,CAAC,GACxC,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,CAAA;AA2B7D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,EAAkC,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAC1F,KAAK,EAAE,yBAAyB,CAAC,KAAK,CAAC,EACvC,QAAQ,CAAC,EAAE,YAAY,KACpB,GAAG,CAAC,OAAO,CAAA;AAEhB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,OAC9C,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAC7E,KAAK,EAAE,yBAAyB,CAAC,KAAK,CAAC,EACvC,QAAQ,CAAC,EAAE,YAAY,KACpB,GAAG,CAAC,OACV,CAAA"}
1
+ {"version":3,"file":"nested-route-link.d.ts","sourceRoot":"","sources":["../../src/components/nested-route-link.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAA;AAKlE,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,OAAO,EACP,YAAY,EACZ,cAAc,EACd,aAAa,EACd,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,CAAA;AAE/D;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,CAAC,KAAK,SAAS,MAAM,IAAI;IAC5D,IAAI,EAAE,KAAK,CAAA;IACX,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,cAAc,CAAC,KAAK,CAAC,GACvB,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,CAAA;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,6BAA6B,CACvC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAC1D,KAAK,SAAS,MAAM,IAClB;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GAAG,cAAc,CAAC,KAAK,CAAC,GACzC,aAAa,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,GACzD,YAAY,CAAC,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,GACvD,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,MAAM,CAAC,CAAC,CAAA;AA2B7D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,eAAe,EAAkC,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAC1F,KAAK,EAAE,yBAAyB,CAAC,KAAK,CAAC,EACvC,QAAQ,CAAC,EAAE,YAAY,KACpB,GAAG,CAAC,OAAO,CAAA;AAEhB;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,OACxD,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAC7E,KAAK,EAAE,6BAA6B,CAAC,OAAO,EAAE,KAAK,CAAC,EACpD,QAAQ,CAAC,EAAE,YAAY,KACpB,GAAG,CAAC,OACV,CAAA"}
@@ -1,7 +1,7 @@
1
- import { compileRoute } from '../compile-route.js';
2
1
  import { LocationService } from '../services/location-service.js';
3
2
  import { createComponent } from '../shade-component.js';
4
3
  import { Shade } from '../shade.js';
4
+ import { buildNestedNavigateUrl } from './nested-navigate.js';
5
5
  const _NestedRouteLink = Shade({
6
6
  customElementName: 'nested-route-link',
7
7
  elementBase: HTMLAnchorElement,
@@ -11,15 +11,15 @@ const _NestedRouteLink = Shade({
11
11
  textDecoration: 'inherit',
12
12
  },
13
13
  render: ({ children, props, injector, useHostProps }) => {
14
- const { href, params } = props;
15
- const resolvedUrl = params ? compileRoute(href, params) : href;
14
+ const { path, params, query, hash } = props;
15
+ const resolvedUrl = buildNestedNavigateUrl({ path, params, query, hash });
16
16
  useHostProps({
17
17
  href: resolvedUrl,
18
18
  onclick: (ev) => {
19
19
  ev.preventDefault();
20
20
  // eslint-disable-next-line furystack/prefer-location-service -- This IS the SPA link component; it must call pushState directly.
21
21
  history.pushState('', props.title || '', resolvedUrl);
22
- injector.getInstance(LocationService).updateState();
22
+ injector.get(LocationService).updateState();
23
23
  },
24
24
  });
25
25
  return createComponent(createComponent, null, children);
@@ -30,19 +30,22 @@ const _NestedRouteLink = Shade({
30
30
  * type-safe route parameter compilation.
31
31
  *
32
32
  * Intercepts click events to use `history.pushState` for client-side navigation,
33
- * and compiles parameterized routes (e.g. `/users/:id`) when `params` is provided.
33
+ * compiles parameterized routes (e.g. `/users/:id`) when `params` is provided,
34
+ * serializes `query` to the URL search string and appends `hash` when set.
34
35
  *
35
- * Route parameters are automatically inferred from the `href` pattern:
36
- * - `href="/buttons"` — `params` is optional
37
- * - `href="/users/:id"` — `params: { id: string }` is required
36
+ * Route parameters are automatically inferred from the `path` pattern:
37
+ * - `path="/buttons"` — `params` is optional
38
+ * - `path="/users/:id"` — `params: { id: string }` is required
38
39
  *
39
- * For additional URL validation against a route tree, use {@link createNestedRouteLink}.
40
+ * For additional URL validation against a route tree (including `query` and
41
+ * `hash` narrowing), use {@link createNestedRouteLink}.
40
42
  */
41
43
  export const NestedRouteLink = _NestedRouteLink;
42
44
  /**
43
- * Creates a type-safe wrapper around NestedRouteLink constrained to a specific route tree.
44
- * The returned component has the same runtime behavior but narrows `href` to only accept
45
- * valid route paths, and requires `params` when the route has parameters.
45
+ * Creates a type-safe wrapper around NestedRouteLink constrained to a specific
46
+ * route tree. The returned component has the same runtime behavior but narrows
47
+ * `path` to only accept valid route paths, requires `params` when the route
48
+ * has parameters, and enforces the route's declared `query` and `hash` schemas.
46
49
  *
47
50
  * @typeParam TRoutes - The route tree type (use `typeof yourRoutes`)
48
51
  * @returns A narrowed NestedRouteLink component
@@ -51,14 +54,9 @@ export const NestedRouteLink = _NestedRouteLink;
51
54
  * ```typescript
52
55
  * const AppLink = createNestedRouteLink<typeof appRoutes>()
53
56
  *
54
- * // Type-safe: only valid paths accepted
55
- * <AppLink href="/buttons">Buttons</AppLink>
56
- *
57
- * // TypeScript error: invalid path
58
- * <AppLink href="/nonexistent">Error!</AppLink>
59
- *
60
- * // Params required for parameterized routes
61
- * <AppLink href="/users/:id" params={{ id: '123' }}>User</AppLink>
57
+ * <AppLink path="/buttons">Buttons</AppLink>
58
+ * <AppLink path="/users/:id" params={{ id: '123' }}>User</AppLink>
59
+ * <AppLink path="/users/:id" params={{ id: '1' }} query={{ tab: 'profile' }} hash="notes">User</AppLink>
62
60
  * ```
63
61
  */
64
62
  export const createNestedRouteLink = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"nested-route-link.js","sourceRoot":"","sources":["../../src/components/nested-route-link.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAyBnC,MAAM,gBAAgB,GAAG,KAAK,CAAuB;IACnD,iBAAiB,EAAE,mBAAmB;IACtC,WAAW,EAAE,iBAAiB;IAC9B,eAAe,EAAE,GAAG;IACpB,GAAG,EAAE;QACH,KAAK,EAAE,SAAS;QAChB,cAAc,EAAE,SAAS;KAC1B;IACD,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE;QACtD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;QAC9B,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAE9D,YAAY,CAAC;YACX,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,CAAC,EAAc,EAAE,EAAE;gBAC1B,EAAE,CAAC,cAAc,EAAE,CAAA;gBACnB,iIAAiI;gBACjI,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,WAAW,CAAC,CAAA;gBACrD,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAA;YACrD,CAAC;SACF,CAAC,CAAA;QACF,OAAO,uCAAG,QAAQ,CAAI,CAAA;IACxB,CAAC;CACF,CAAC,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,gBAGf,CAAA;AAEhB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAqD,EAAE;IAC1F,OAAO,gBAGS,CAAA;AAClB,CAAC,CAAA"}
1
+ {"version":3,"file":"nested-route-link.js","sourceRoot":"","sources":["../../src/components/nested-route-link.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAoD7D,MAAM,gBAAgB,GAAG,KAAK,CAAuB;IACnD,iBAAiB,EAAE,mBAAmB;IACtC,WAAW,EAAE,iBAAiB;IAC9B,eAAe,EAAE,GAAG;IACpB,GAAG,EAAE;QACH,KAAK,EAAE,SAAS;QAChB,cAAc,EAAE,SAAS;KAC1B;IACD,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE;QACtD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,CAAA;QAC3C,MAAM,WAAW,GAAG,sBAAsB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAEzE,YAAY,CAAC;YACX,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,CAAC,EAAc,EAAE,EAAE;gBAC1B,EAAE,CAAC,cAAc,EAAE,CAAA;gBACnB,iIAAiI;gBACjI,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,WAAW,CAAC,CAAA;gBACrD,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAA;YAC7C,CAAC;SACF,CAAC,CAAA;QACF,OAAO,uCAAG,QAAQ,CAAI,CAAA;IACxB,CAAC;CACF,CAAC,CAAA;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,gBAGf,CAAA;AAEhB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAA+D,EAAE;IACpG,OAAO,gBAGS,CAAA;AAClB,CAAC,CAAA"}
@@ -1,4 +1,4 @@
1
- import { Injector } from '@furystack/inject';
1
+ import { createInjector } from '@furystack/inject';
2
2
  import { usingAsync } from '@furystack/utils';
3
3
  import { afterEach, beforeEach, describe, expect, expectTypeOf, it, vi } from 'vitest';
4
4
  import { initializeShadeRoot } from '../initialize.js';
@@ -14,26 +14,26 @@ describe('NestedRouteLink', () => {
14
14
  document.body.innerHTML = '';
15
15
  });
16
16
  it('Should render a link with the correct href', async () => {
17
- await usingAsync(new Injector(), async (injector) => {
17
+ await usingAsync(createInjector(), async (injector) => {
18
18
  const rootElement = document.getElementById('root');
19
19
  initializeShadeRoot({
20
20
  injector,
21
21
  rootElement,
22
- jsxElement: (createComponent(NestedRouteLink, { id: "link", href: "/buttons" }, "Buttons")),
22
+ jsxElement: (createComponent(NestedRouteLink, { id: "link", path: "/buttons" }, "Buttons")),
23
23
  });
24
24
  await flushUpdates();
25
25
  expect(document.body.innerHTML).toBe('<div id="root"><a is="nested-route-link" id="link" href="/buttons">Buttons</a></div>');
26
26
  });
27
27
  });
28
28
  it('Should trigger SPA navigation on click', async () => {
29
- await usingAsync(new Injector(), async (injector) => {
29
+ await usingAsync(createInjector(), async (injector) => {
30
30
  const rootElement = document.getElementById('root');
31
31
  const onRouteChange = vi.fn();
32
- injector.getInstance(LocationService).onLocationPathChanged.subscribe(onRouteChange);
32
+ injector.get(LocationService).onLocationPathChanged.subscribe(onRouteChange);
33
33
  initializeShadeRoot({
34
34
  injector,
35
35
  rootElement,
36
- jsxElement: (createComponent(NestedRouteLink, { id: "link", href: "/buttons" }, "Buttons")),
36
+ jsxElement: (createComponent(NestedRouteLink, { id: "link", path: "/buttons" }, "Buttons")),
37
37
  });
38
38
  await flushUpdates();
39
39
  expect(onRouteChange).not.toBeCalled();
@@ -42,29 +42,55 @@ describe('NestedRouteLink', () => {
42
42
  });
43
43
  });
44
44
  it('Should compile route params in the href', async () => {
45
- await usingAsync(new Injector(), async (injector) => {
45
+ await usingAsync(createInjector(), async (injector) => {
46
46
  const rootElement = document.getElementById('root');
47
47
  initializeShadeRoot({
48
48
  injector,
49
49
  rootElement,
50
- jsxElement: (createComponent(NestedRouteLink, { id: "link", href: "/users/:id", params: { id: '42' } }, "User 42")),
50
+ jsxElement: (createComponent(NestedRouteLink, { id: "link", path: "/users/:id", params: { id: '42' } }, "User 42")),
51
51
  });
52
52
  await flushUpdates();
53
53
  expect(document.body.innerHTML).toBe('<div id="root"><a is="nested-route-link" id="link" href="/users/42">User 42</a></div>');
54
54
  });
55
55
  });
56
56
  it('Should compile route params with multiple segments', async () => {
57
- await usingAsync(new Injector(), async (injector) => {
57
+ await usingAsync(createInjector(), async (injector) => {
58
58
  const rootElement = document.getElementById('root');
59
59
  initializeShadeRoot({
60
60
  injector,
61
61
  rootElement,
62
- jsxElement: (createComponent(NestedRouteLink, { id: "link", href: "/users/:userId/posts/:postId", params: { userId: '1', postId: '99' } }, "Post")),
62
+ jsxElement: (createComponent(NestedRouteLink, { id: "link", path: "/users/:userId/posts/:postId", params: { userId: '1', postId: '99' } }, "Post")),
63
63
  });
64
64
  await flushUpdates();
65
65
  expect(document.body.innerHTML).toBe('<div id="root"><a is="nested-route-link" id="link" href="/users/1/posts/99">Post</a></div>');
66
66
  });
67
67
  });
68
+ it('Should append a serialized query string to the rendered href', async () => {
69
+ await usingAsync(createInjector(), async (injector) => {
70
+ const rootElement = document.getElementById('root');
71
+ initializeShadeRoot({
72
+ injector,
73
+ rootElement,
74
+ jsxElement: (createComponent(NestedRouteLink, { id: "link", path: "/buttons", query: { page: 2 } }, "Buttons")),
75
+ });
76
+ await flushUpdates();
77
+ const link = document.getElementById('link');
78
+ expect(link.getAttribute('href')?.startsWith('/buttons?')).toBe(true);
79
+ });
80
+ });
81
+ it('Should append the hash segment to the rendered href', async () => {
82
+ await usingAsync(createInjector(), async (injector) => {
83
+ const rootElement = document.getElementById('root');
84
+ initializeShadeRoot({
85
+ injector,
86
+ rootElement,
87
+ jsxElement: (createComponent(NestedRouteLink, { id: "link", path: "/buttons", hash: "overview" }, "Buttons")),
88
+ });
89
+ await flushUpdates();
90
+ const link = document.getElementById('link');
91
+ expect(link.getAttribute('href')).toBe('/buttons#overview');
92
+ });
93
+ });
68
94
  });
69
95
  describe('Type utilities', () => {
70
96
  describe('ConcatPaths', () => {
@@ -140,32 +166,32 @@ describe('Type utilities', () => {
140
166
  });
141
167
  });
142
168
  describe('NestedRouteLink param inference', () => {
143
- it('Should infer params as optional when href has no parameters', () => {
169
+ it('Should infer params as optional when path has no parameters', () => {
144
170
  expectTypeOf(NestedRouteLink).parameter(0).toHaveProperty('params');
145
171
  expectTypeOf((NestedRouteLink))
146
172
  .parameter(0)
147
173
  .toExtend();
148
174
  });
149
- it('Should infer params as required when href has a parameter', () => {
175
+ it('Should infer params as required when path has a parameter', () => {
150
176
  expectTypeOf((NestedRouteLink))
151
177
  .parameter(0)
152
178
  .toExtend();
153
179
  });
154
- it('Should infer multiple params from href', () => {
180
+ it('Should infer multiple params from path', () => {
155
181
  expectTypeOf((NestedRouteLink))
156
182
  .parameter(0)
157
183
  .toExtend();
158
184
  });
159
185
  });
160
186
  describe('createNestedRouteLink', () => {
161
- it('Should constrain href to valid route paths', () => {
187
+ it('Should constrain path to valid route paths', () => {
162
188
  const AppLink = createNestedRouteLink();
163
- expectTypeOf(AppLink).parameter(0).toHaveProperty('href');
189
+ expectTypeOf(AppLink).parameter(0).toHaveProperty('path');
164
190
  });
165
191
  it('Should reject invalid paths', () => {
166
192
  const AppLink = createNestedRouteLink();
167
193
  // @ts-expect-error -- '/nonexistent' is not a valid route path
168
- AppLink({ href: '/nonexistent' });
194
+ AppLink({ path: '/nonexistent' });
169
195
  });
170
196
  it('Should require params for parameterized routes in the tree', () => {
171
197
  const AppLink = createNestedRouteLink();
@@ -207,7 +233,31 @@ describe('Type utilities', () => {
207
233
  },
208
234
  };
209
235
  const AppLink = createNestedRouteLink();
210
- expectTypeOf(AppLink).parameter(0).toHaveProperty('href');
236
+ expectTypeOf(AppLink).parameter(0).toHaveProperty('path');
237
+ expectTypeOf((AppLink))
238
+ .parameter(0)
239
+ .toExtend();
240
+ });
241
+ it('Should enforce a declared required query shape on the link', () => {
242
+ const routes = {
243
+ '/list': {
244
+ component: () => null,
245
+ query: (raw) => (typeof raw.page === 'number' ? { page: raw.page } : null),
246
+ },
247
+ };
248
+ const AppLink = createNestedRouteLink();
249
+ expectTypeOf((AppLink))
250
+ .parameter(0)
251
+ .toExtend();
252
+ });
253
+ it('Should narrow hash on the link to the declared literal tuple', () => {
254
+ const routes = {
255
+ '/tabs': {
256
+ component: () => null,
257
+ hash: ['overview', 'details'],
258
+ },
259
+ };
260
+ const AppLink = createNestedRouteLink();
211
261
  expectTypeOf((AppLink))
212
262
  .parameter(0)
213
263
  .toExtend();
@@ -1 +1 @@
1
- {"version":3,"file":"nested-route-link.spec.js","sourceRoot":"","sources":["../../src/components/nested-route-link.spec.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"nested-route-link.spec.js","sourceRoot":"","sources":["../../src/components/nested-route-link.spec.tsx"],"names":[],"mappings":"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"}