@furystack/shades 13.1.2 โ 13.2.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.
- package/CHANGELOG.md +29 -0
- package/esm/components/index.d.ts +1 -0
- package/esm/components/index.d.ts.map +1 -1
- package/esm/components/index.js +1 -0
- package/esm/components/index.js.map +1 -1
- package/esm/components/nested-navigate.d.ts +46 -0
- package/esm/components/nested-navigate.d.ts.map +1 -0
- package/esm/components/nested-navigate.js +44 -0
- package/esm/components/nested-navigate.js.map +1 -0
- package/esm/components/nested-navigate.spec.d.ts +2 -0
- package/esm/components/nested-navigate.spec.d.ts.map +1 -0
- package/esm/components/nested-navigate.spec.js +76 -0
- package/esm/components/nested-navigate.spec.js.map +1 -0
- package/esm/components/nested-route-link.d.ts +1 -1
- package/esm/components/nested-route-link.d.ts.map +1 -1
- package/esm/components/nested-route-link.js.map +1 -1
- package/esm/components/nested-route-link.spec.js +38 -0
- package/esm/components/nested-route-link.spec.js.map +1 -1
- package/esm/components/nested-route-types.d.ts +2 -2
- package/esm/components/nested-route-types.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/components/index.ts +1 -0
- package/src/components/nested-navigate.spec.ts +143 -0
- package/src/components/nested-navigate.ts +60 -0
- package/src/components/nested-route-link.spec.tsx +52 -0
- package/src/components/nested-route-link.tsx +1 -1
- package/src/components/nested-route-types.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [13.2.0] - 2026-03-27
|
|
4
|
+
|
|
5
|
+
### โจ Features
|
|
6
|
+
|
|
7
|
+
### Type-safe programmatic navigation for NestedRouter
|
|
8
|
+
|
|
9
|
+
Added `nestedNavigate()` and `createNestedNavigate()` for programmatic SPA navigation within the nested router system.
|
|
10
|
+
|
|
11
|
+
- `nestedNavigate(injector, path, params?)` navigates to a route path using `LocationService`, with optional route parameter compilation (e.g. `/users/:id`)
|
|
12
|
+
- `createNestedNavigate<typeof routes>()` returns a type-safe wrapper that restricts `path` to valid route paths and requires `params` when the route is parameterized
|
|
13
|
+
|
|
14
|
+
**Usage:**
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
const appNavigate = createNestedNavigate<typeof appRoutes>()
|
|
18
|
+
|
|
19
|
+
appNavigate(injector, '/buttons')
|
|
20
|
+
appNavigate(injector, '/users/:id', { id: '123' })
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### ๐ Bug Fixes
|
|
24
|
+
|
|
25
|
+
- Fixed `ExtractRoutePaths` and `createNestedRouteLink` generic constraints from `NestedRoute<unknown>` to `NestedRoute<any>`, resolving type inference failures when routes use concrete component prop types
|
|
26
|
+
|
|
27
|
+
### ๐งช Tests
|
|
28
|
+
|
|
29
|
+
- Added tests for `nestedNavigate()` and `createNestedNavigate()`
|
|
30
|
+
- Added tests for `NestedRouteLink` and `createNestedRouteLink` with parameterized routes
|
|
31
|
+
|
|
3
32
|
## [13.1.2] - 2026-03-25
|
|
4
33
|
|
|
5
34
|
### ๐ฆ Build
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,wBAAwB,CAAA;AACtC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA"}
|
package/esm/components/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,wBAAwB,CAAA;AACtC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA;AAClC,cAAc,sBAAsB,CAAA;AACpC,cAAc,wBAAwB,CAAA;AACtC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Injector } from '@furystack/inject';
|
|
2
|
+
import type { ExtractRouteParams, ExtractRoutePaths } from './nested-route-types.js';
|
|
3
|
+
import type { NestedRoute } from './nested-router.js';
|
|
4
|
+
/**
|
|
5
|
+
* Arguments for a type-safe nested navigate call.
|
|
6
|
+
* When the path contains parameters (e.g. `:id`), the `params` argument becomes required.
|
|
7
|
+
* @typeParam TPath - A specific route path string
|
|
8
|
+
*/
|
|
9
|
+
export type TypedNavigateArgs<TPath extends string> = string extends keyof ExtractRouteParams<TPath> ? [path: TPath, params?: Record<string, string>] : [path: TPath, params: ExtractRouteParams<TPath>];
|
|
10
|
+
/**
|
|
11
|
+
* Navigates to a route path using the LocationService from the given injector.
|
|
12
|
+
* Compiles parameterized routes (e.g. `/users/:id`) when `params` is provided.
|
|
13
|
+
*
|
|
14
|
+
* @param injector - The injector instance to resolve LocationService from
|
|
15
|
+
* @param path - The route path to navigate to
|
|
16
|
+
* @param params - Optional route parameters to compile into the path
|
|
17
|
+
*/
|
|
18
|
+
export declare const nestedNavigate: (injector: Injector, path: string, params?: Record<string, string>) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Creates a type-safe navigate function constrained to a specific route tree.
|
|
21
|
+
* The returned function has the same runtime behavior as {@link nestedNavigate}
|
|
22
|
+
* but narrows `path` to only accept valid route paths, and requires `params`
|
|
23
|
+
* when the route has parameters.
|
|
24
|
+
*
|
|
25
|
+
* Unlike {@link createNestedRouteLink}, the injector is passed at call time,
|
|
26
|
+
* not at creation time.
|
|
27
|
+
*
|
|
28
|
+
* @typeParam TRoutes - The route tree type (use `typeof yourRoutes`)
|
|
29
|
+
* @returns A type-safe navigate function
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const appNavigate = createNestedNavigate<typeof appRoutes>()
|
|
34
|
+
*
|
|
35
|
+
* // Type-safe: only valid paths accepted
|
|
36
|
+
* appNavigate(injector, '/buttons')
|
|
37
|
+
*
|
|
38
|
+
* // TypeScript error: invalid path
|
|
39
|
+
* appNavigate(injector, '/nonexistent')
|
|
40
|
+
*
|
|
41
|
+
* // Params required for parameterized routes
|
|
42
|
+
* appNavigate(injector, '/users/:id', { id: '123' })
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare const createNestedNavigate: <TRoutes extends Record<string, NestedRoute<any>>>() => <TPath extends ExtractRoutePaths<TRoutes>>(injector: Injector, ...args: TypedNavigateArgs<TPath>) => void;
|
|
46
|
+
//# sourceMappingURL=nested-navigate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nested-navigate.d.ts","sourceRoot":"","sources":["../../src/components/nested-navigate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAGjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,MAAM,IAAI,MAAM,SAAS,MAAM,kBAAkB,CAAC,KAAK,CAAC,GAChG,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAC9C,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAA;AAEpD;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,GAAI,UAAU,QAAQ,EAAE,MAAM,MAAM,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,IAGlG,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,OAC1D,CAAC,KAAK,SAAS,iBAAiB,CAAC,OAAO,CAAC,EAChE,QAAQ,EAAE,QAAQ,EAClB,GAAG,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAC9B,IACN,CAAA"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { compileRoute } from '../compile-route.js';
|
|
2
|
+
import { LocationService } from '../services/location-service.js';
|
|
3
|
+
/**
|
|
4
|
+
* Navigates to a route path using the LocationService from the given injector.
|
|
5
|
+
* Compiles parameterized routes (e.g. `/users/:id`) when `params` is provided.
|
|
6
|
+
*
|
|
7
|
+
* @param injector - The injector instance to resolve LocationService from
|
|
8
|
+
* @param path - The route path to navigate to
|
|
9
|
+
* @param params - Optional route parameters to compile into the path
|
|
10
|
+
*/
|
|
11
|
+
export const nestedNavigate = (injector, path, params) => {
|
|
12
|
+
const resolvedUrl = params ? compileRoute(path, params) : path;
|
|
13
|
+
injector.getInstance(LocationService).navigate(resolvedUrl);
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Creates a type-safe navigate function constrained to a specific route tree.
|
|
17
|
+
* The returned function has the same runtime behavior as {@link nestedNavigate}
|
|
18
|
+
* but narrows `path` to only accept valid route paths, and requires `params`
|
|
19
|
+
* when the route has parameters.
|
|
20
|
+
*
|
|
21
|
+
* Unlike {@link createNestedRouteLink}, the injector is passed at call time,
|
|
22
|
+
* not at creation time.
|
|
23
|
+
*
|
|
24
|
+
* @typeParam TRoutes - The route tree type (use `typeof yourRoutes`)
|
|
25
|
+
* @returns A type-safe navigate function
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const appNavigate = createNestedNavigate<typeof appRoutes>()
|
|
30
|
+
*
|
|
31
|
+
* // Type-safe: only valid paths accepted
|
|
32
|
+
* appNavigate(injector, '/buttons')
|
|
33
|
+
*
|
|
34
|
+
* // TypeScript error: invalid path
|
|
35
|
+
* appNavigate(injector, '/nonexistent')
|
|
36
|
+
*
|
|
37
|
+
* // Params required for parameterized routes
|
|
38
|
+
* appNavigate(injector, '/users/:id', { id: '123' })
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export const createNestedNavigate = () => {
|
|
42
|
+
return nestedNavigate;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=nested-navigate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nested-navigate.js","sourceRoot":"","sources":["../../src/components/nested-navigate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AAajE;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,QAAkB,EAAE,IAAY,EAAE,MAA+B,EAAQ,EAAE;IACxG,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9D,QAAQ,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;AAC7D,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAqD,EAAE;IACzF,OAAO,cAGE,CAAA;AACX,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nested-navigate.spec.d.ts","sourceRoot":"","sources":["../../src/components/nested-navigate.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Injector } 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 { createNestedNavigate, nestedNavigate } from './nested-navigate.js';
|
|
6
|
+
describe('nestedNavigate', () => {
|
|
7
|
+
it('Should navigate to a simple path', async () => {
|
|
8
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
9
|
+
const locationService = injector.getInstance(LocationService);
|
|
10
|
+
const spy = vi.spyOn(locationService, 'navigate');
|
|
11
|
+
nestedNavigate(injector, '/buttons');
|
|
12
|
+
expect(spy).toHaveBeenCalledWith('/buttons');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
it('Should compile params into the path', async () => {
|
|
16
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
17
|
+
const locationService = injector.getInstance(LocationService);
|
|
18
|
+
const spy = vi.spyOn(locationService, 'navigate');
|
|
19
|
+
nestedNavigate(injector, '/users/:id', { id: '42' });
|
|
20
|
+
expect(spy).toHaveBeenCalledWith('/users/42');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
it('Should compile multiple params into the path', async () => {
|
|
24
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
25
|
+
const locationService = injector.getInstance(LocationService);
|
|
26
|
+
const spy = vi.spyOn(locationService, 'navigate');
|
|
27
|
+
nestedNavigate(injector, '/users/:userId/posts/:postId', { userId: '1', postId: '99' });
|
|
28
|
+
expect(spy).toHaveBeenCalledWith('/users/1/posts/99');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('Type utilities', () => {
|
|
33
|
+
describe('TypedNavigateArgs', () => {
|
|
34
|
+
it('Should make params optional for paths without parameters', () => {
|
|
35
|
+
expectTypeOf().toEqualTypeOf();
|
|
36
|
+
});
|
|
37
|
+
it('Should require params for parameterized paths', () => {
|
|
38
|
+
expectTypeOf().toEqualTypeOf();
|
|
39
|
+
});
|
|
40
|
+
it('Should require all params for multi-param paths', () => {
|
|
41
|
+
expectTypeOf().toEqualTypeOf();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe('createNestedNavigate', () => {
|
|
45
|
+
it('Should constrain path to valid route paths', () => {
|
|
46
|
+
const appNavigate = createNestedNavigate();
|
|
47
|
+
expectTypeOf((appNavigate))
|
|
48
|
+
.parameter(0)
|
|
49
|
+
.toEqualTypeOf();
|
|
50
|
+
});
|
|
51
|
+
it('Should require params for parameterized routes in the tree', () => {
|
|
52
|
+
const appNavigate = createNestedNavigate();
|
|
53
|
+
expectTypeOf((appNavigate)).parameters.toEqualTypeOf();
|
|
54
|
+
});
|
|
55
|
+
it('Should make params optional for non-parameterized routes', () => {
|
|
56
|
+
const appNavigate = createNestedNavigate();
|
|
57
|
+
expectTypeOf((appNavigate)).parameters.toEqualTypeOf();
|
|
58
|
+
});
|
|
59
|
+
it('Should reject invalid paths', () => {
|
|
60
|
+
const appNavigate = createNestedNavigate();
|
|
61
|
+
// @ts-expect-error -- '/nonexistent' is not a valid route path
|
|
62
|
+
appNavigate(new Injector(), '/nonexistent');
|
|
63
|
+
});
|
|
64
|
+
it('Should accept routes with typed match parameters (NestedRoute<T>)', () => {
|
|
65
|
+
const typedRoute = {
|
|
66
|
+
component: ({ match }) => match.params.stackName,
|
|
67
|
+
};
|
|
68
|
+
const routes = {
|
|
69
|
+
'/stacks/:stackName': typedRoute,
|
|
70
|
+
};
|
|
71
|
+
const appNavigate = createNestedNavigate();
|
|
72
|
+
expectTypeOf((appNavigate)).parameters.toEqualTypeOf();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=nested-navigate.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nested-navigate.spec.js","sourceRoot":"","sources":["../../src/components/nested-navigate.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -58,5 +58,5 @@ export declare const NestedRouteLink: <TPath extends string = string>(props: Typ
|
|
|
58
58
|
* <AppLink href="/users/:id" params={{ id: '123' }}>User</AppLink>
|
|
59
59
|
* ```
|
|
60
60
|
*/
|
|
61
|
-
export declare const createNestedRouteLink: <TRoutes extends Record<string, NestedRoute<
|
|
61
|
+
export declare const createNestedRouteLink: <TRoutes extends Record<string, NestedRoute<any>>>() => <TPath extends ExtractRoutePaths<TRoutes>>(props: TypedNestedRouteLinkProps<TPath>, children?: ChildrenList) => JSX.Element;
|
|
62
62
|
//# 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,
|
|
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 +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,
|
|
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"}
|
|
@@ -162,6 +162,11 @@ describe('Type utilities', () => {
|
|
|
162
162
|
const AppLink = createNestedRouteLink();
|
|
163
163
|
expectTypeOf(AppLink).parameter(0).toHaveProperty('href');
|
|
164
164
|
});
|
|
165
|
+
it('Should reject invalid paths', () => {
|
|
166
|
+
const AppLink = createNestedRouteLink();
|
|
167
|
+
// @ts-expect-error -- '/nonexistent' is not a valid route path
|
|
168
|
+
AppLink({ href: '/nonexistent' });
|
|
169
|
+
});
|
|
165
170
|
it('Should require params for parameterized routes in the tree', () => {
|
|
166
171
|
const AppLink = createNestedRouteLink();
|
|
167
172
|
expectTypeOf((AppLink))
|
|
@@ -174,6 +179,39 @@ describe('Type utilities', () => {
|
|
|
174
179
|
.parameter(0)
|
|
175
180
|
.toExtend();
|
|
176
181
|
});
|
|
182
|
+
it('Should accept routes with typed match parameters (NestedRoute<T>)', () => {
|
|
183
|
+
const routes = {
|
|
184
|
+
'/stacks/:stackName': {
|
|
185
|
+
component: ({ match }) => createComponent("div", null, match.params.stackName),
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
const AppLink = createNestedRouteLink();
|
|
189
|
+
expectTypeOf((AppLink))
|
|
190
|
+
.parameter(0)
|
|
191
|
+
.toExtend();
|
|
192
|
+
});
|
|
193
|
+
it('Should accept a mixed route tree with typed and untyped match parameters', () => {
|
|
194
|
+
const usersRoute = {
|
|
195
|
+
component: ({ match }) => createComponent("div", null, match.params.userId),
|
|
196
|
+
};
|
|
197
|
+
const buttonsRoute = {
|
|
198
|
+
component: () => createComponent("div", null),
|
|
199
|
+
};
|
|
200
|
+
const routes = {
|
|
201
|
+
'/': {
|
|
202
|
+
component: ({ outlet }) => outlet ?? createComponent("div", null),
|
|
203
|
+
children: {
|
|
204
|
+
'/buttons': buttonsRoute,
|
|
205
|
+
'/users/:userId': usersRoute,
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
const AppLink = createNestedRouteLink();
|
|
210
|
+
expectTypeOf(AppLink).parameter(0).toHaveProperty('href');
|
|
211
|
+
expectTypeOf((AppLink))
|
|
212
|
+
.parameter(0)
|
|
213
|
+
.toExtend();
|
|
214
|
+
});
|
|
177
215
|
});
|
|
178
216
|
});
|
|
179
217
|
//# sourceMappingURL=nested-route-link.spec.js.map
|
|
@@ -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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"}
|
|
@@ -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<
|
|
13
|
+
export type ExtractRoutePaths<T extends Record<string, NestedRoute<any>>> = {
|
|
14
14
|
[K in keyof T & string]: K | (T[K] extends {
|
|
15
|
-
children: infer C extends Record<string, NestedRoute<
|
|
15
|
+
children: infer C extends Record<string, NestedRoute<any>>;
|
|
16
16
|
} ? ConcatPaths<K, ExtractRoutePaths<C> & string> : never);
|
|
17
17
|
}[keyof T & string];
|
|
18
18
|
/**
|
|
@@ -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,
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@furystack/shades",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.2.0",
|
|
4
4
|
"description": "A lightweight UI framework for FuryStack with JSX support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
"@types/node": "^25.5.0",
|
|
44
44
|
"jsdom": "^29.0.1",
|
|
45
45
|
"typescript": "^6.0.2",
|
|
46
|
-
"vitest": "^4.1.
|
|
46
|
+
"vitest": "^4.1.2"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@furystack/inject": "^12.0.
|
|
50
|
-
"@furystack/rest": "^8.1.
|
|
51
|
-
"@furystack/utils": "^8.2.
|
|
52
|
-
"path-to-regexp": "^8.
|
|
49
|
+
"@furystack/inject": "^12.0.35",
|
|
50
|
+
"@furystack/rest": "^8.1.4",
|
|
51
|
+
"@furystack/utils": "^8.2.4",
|
|
52
|
+
"path-to-regexp": "^8.4.0"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
55
|
"node": ">=22.0.0"
|
package/src/components/index.ts
CHANGED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Injector } 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 type { TypedNavigateArgs } from './nested-navigate.js'
|
|
6
|
+
import { createNestedNavigate, nestedNavigate } from './nested-navigate.js'
|
|
7
|
+
import type { NestedRoute } from './nested-router.js'
|
|
8
|
+
|
|
9
|
+
type TestRoute = Pick<NestedRoute<unknown>, 'component'>
|
|
10
|
+
|
|
11
|
+
describe('nestedNavigate', () => {
|
|
12
|
+
it('Should navigate to a simple path', async () => {
|
|
13
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
14
|
+
const locationService = injector.getInstance(LocationService)
|
|
15
|
+
const spy = vi.spyOn(locationService, 'navigate')
|
|
16
|
+
|
|
17
|
+
nestedNavigate(injector, '/buttons')
|
|
18
|
+
|
|
19
|
+
expect(spy).toHaveBeenCalledWith('/buttons')
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('Should compile params into the path', async () => {
|
|
24
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
25
|
+
const locationService = injector.getInstance(LocationService)
|
|
26
|
+
const spy = vi.spyOn(locationService, 'navigate')
|
|
27
|
+
|
|
28
|
+
nestedNavigate(injector, '/users/:id', { id: '42' })
|
|
29
|
+
|
|
30
|
+
expect(spy).toHaveBeenCalledWith('/users/42')
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('Should compile multiple params into the path', async () => {
|
|
35
|
+
await usingAsync(new Injector(), async (injector) => {
|
|
36
|
+
const locationService = injector.getInstance(LocationService)
|
|
37
|
+
const spy = vi.spyOn(locationService, 'navigate')
|
|
38
|
+
|
|
39
|
+
nestedNavigate(injector, '/users/:userId/posts/:postId', { userId: '1', postId: '99' })
|
|
40
|
+
|
|
41
|
+
expect(spy).toHaveBeenCalledWith('/users/1/posts/99')
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('Type utilities', () => {
|
|
47
|
+
describe('TypedNavigateArgs', () => {
|
|
48
|
+
it('Should make params optional for paths without parameters', () => {
|
|
49
|
+
type Args = TypedNavigateArgs<'/buttons'>
|
|
50
|
+
expectTypeOf<Args>().toEqualTypeOf<[path: '/buttons', params?: Record<string, string>]>()
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('Should require params for parameterized paths', () => {
|
|
54
|
+
type Args = TypedNavigateArgs<'/users/:id'>
|
|
55
|
+
expectTypeOf<Args>().toEqualTypeOf<[path: '/users/:id', params: { id: string }]>()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('Should require all params for multi-param paths', () => {
|
|
59
|
+
type Args = TypedNavigateArgs<'/users/:userId/posts/:postId'>
|
|
60
|
+
expectTypeOf<Args>().toEqualTypeOf<
|
|
61
|
+
[path: '/users/:userId/posts/:postId', params: { userId: string; postId: string }]
|
|
62
|
+
>()
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
describe('createNestedNavigate', () => {
|
|
67
|
+
it('Should constrain path to valid route paths', () => {
|
|
68
|
+
type Routes = {
|
|
69
|
+
'/': TestRoute & {
|
|
70
|
+
children: {
|
|
71
|
+
'/buttons': TestRoute
|
|
72
|
+
'/inputs': TestRoute
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const appNavigate = createNestedNavigate<Routes>()
|
|
78
|
+
expectTypeOf(appNavigate<'/buttons'>)
|
|
79
|
+
.parameter(0)
|
|
80
|
+
.toEqualTypeOf<Injector>()
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('Should require params for parameterized routes in the tree', () => {
|
|
84
|
+
type Routes = {
|
|
85
|
+
'/': TestRoute & {
|
|
86
|
+
children: {
|
|
87
|
+
'/users/:userId': TestRoute
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const appNavigate = createNestedNavigate<Routes>()
|
|
93
|
+
expectTypeOf(appNavigate<'/users/:userId'>).parameters.toEqualTypeOf<
|
|
94
|
+
[injector: Injector, path: '/users/:userId', params: { userId: string }]
|
|
95
|
+
>()
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('Should make params optional for non-parameterized routes', () => {
|
|
99
|
+
type Routes = {
|
|
100
|
+
'/': TestRoute & {
|
|
101
|
+
children: {
|
|
102
|
+
'/buttons': TestRoute
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const appNavigate = createNestedNavigate<Routes>()
|
|
108
|
+
expectTypeOf(appNavigate<'/buttons'>).parameters.toEqualTypeOf<
|
|
109
|
+
[injector: Injector, path: '/buttons', params?: Record<string, string>]
|
|
110
|
+
>()
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('Should reject invalid paths', () => {
|
|
114
|
+
type Routes = {
|
|
115
|
+
'/': TestRoute & {
|
|
116
|
+
children: {
|
|
117
|
+
'/buttons': TestRoute
|
|
118
|
+
'/inputs': TestRoute
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const appNavigate = createNestedNavigate<Routes>()
|
|
124
|
+
// @ts-expect-error -- '/nonexistent' is not a valid route path
|
|
125
|
+
appNavigate(new Injector(), '/nonexistent')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('Should accept routes with typed match parameters (NestedRoute<T>)', () => {
|
|
129
|
+
const typedRoute: NestedRoute<{ stackName: string }> = {
|
|
130
|
+
component: ({ match }) => match.params.stackName as unknown as JSX.Element,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const routes = {
|
|
134
|
+
'/stacks/:stackName': typedRoute,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const appNavigate = createNestedNavigate<typeof routes>()
|
|
138
|
+
expectTypeOf(appNavigate<'/stacks/:stackName'>).parameters.toEqualTypeOf<
|
|
139
|
+
[injector: Injector, path: '/stacks/:stackName', params: { stackName: string }]
|
|
140
|
+
>()
|
|
141
|
+
})
|
|
142
|
+
})
|
|
143
|
+
})
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Injector } from '@furystack/inject'
|
|
2
|
+
import { compileRoute } from '../compile-route.js'
|
|
3
|
+
import { LocationService } from '../services/location-service.js'
|
|
4
|
+
import type { ExtractRouteParams, ExtractRoutePaths } from './nested-route-types.js'
|
|
5
|
+
import type { NestedRoute } from './nested-router.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Arguments for a type-safe nested navigate call.
|
|
9
|
+
* When the path contains parameters (e.g. `:id`), the `params` argument becomes required.
|
|
10
|
+
* @typeParam TPath - A specific route path string
|
|
11
|
+
*/
|
|
12
|
+
export type TypedNavigateArgs<TPath extends string> = string extends keyof ExtractRouteParams<TPath>
|
|
13
|
+
? [path: TPath, params?: Record<string, string>]
|
|
14
|
+
: [path: TPath, params: ExtractRouteParams<TPath>]
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Navigates to a route path using the LocationService from the given injector.
|
|
18
|
+
* Compiles parameterized routes (e.g. `/users/:id`) when `params` is provided.
|
|
19
|
+
*
|
|
20
|
+
* @param injector - The injector instance to resolve LocationService from
|
|
21
|
+
* @param path - The route path to navigate to
|
|
22
|
+
* @param params - Optional route parameters to compile into the path
|
|
23
|
+
*/
|
|
24
|
+
export const nestedNavigate = (injector: Injector, path: string, params?: Record<string, string>): void => {
|
|
25
|
+
const resolvedUrl = params ? compileRoute(path, params) : path
|
|
26
|
+
injector.getInstance(LocationService).navigate(resolvedUrl)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creates a type-safe navigate function constrained to a specific route tree.
|
|
31
|
+
* The returned function has the same runtime behavior as {@link nestedNavigate}
|
|
32
|
+
* but narrows `path` to only accept valid route paths, and requires `params`
|
|
33
|
+
* when the route has parameters.
|
|
34
|
+
*
|
|
35
|
+
* Unlike {@link createNestedRouteLink}, the injector is passed at call time,
|
|
36
|
+
* not at creation time.
|
|
37
|
+
*
|
|
38
|
+
* @typeParam TRoutes - The route tree type (use `typeof yourRoutes`)
|
|
39
|
+
* @returns A type-safe navigate function
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const appNavigate = createNestedNavigate<typeof appRoutes>()
|
|
44
|
+
*
|
|
45
|
+
* // Type-safe: only valid paths accepted
|
|
46
|
+
* appNavigate(injector, '/buttons')
|
|
47
|
+
*
|
|
48
|
+
* // TypeScript error: invalid path
|
|
49
|
+
* appNavigate(injector, '/nonexistent')
|
|
50
|
+
*
|
|
51
|
+
* // Params required for parameterized routes
|
|
52
|
+
* appNavigate(injector, '/users/:id', { id: '123' })
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export const createNestedNavigate = <TRoutes extends Record<string, NestedRoute<any>>>() => {
|
|
56
|
+
return nestedNavigate as <TPath extends ExtractRoutePaths<TRoutes>>(
|
|
57
|
+
injector: Injector,
|
|
58
|
+
...args: TypedNavigateArgs<TPath>
|
|
59
|
+
) => void
|
|
60
|
+
}
|
|
@@ -270,6 +270,20 @@ describe('Type utilities', () => {
|
|
|
270
270
|
expectTypeOf(AppLink).parameter(0).toHaveProperty('href')
|
|
271
271
|
})
|
|
272
272
|
|
|
273
|
+
it('Should reject invalid paths', () => {
|
|
274
|
+
type Routes = {
|
|
275
|
+
'/': TestRoute & {
|
|
276
|
+
children: {
|
|
277
|
+
'/buttons': TestRoute
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const AppLink = createNestedRouteLink<Routes>()
|
|
283
|
+
// @ts-expect-error -- '/nonexistent' is not a valid route path
|
|
284
|
+
AppLink({ href: '/nonexistent' })
|
|
285
|
+
})
|
|
286
|
+
|
|
273
287
|
it('Should require params for parameterized routes in the tree', () => {
|
|
274
288
|
type Routes = {
|
|
275
289
|
'/': TestRoute & {
|
|
@@ -299,5 +313,43 @@ describe('Type utilities', () => {
|
|
|
299
313
|
.parameter(0)
|
|
300
314
|
.toExtend<{ params: { userId: string; postId: string } }>()
|
|
301
315
|
})
|
|
316
|
+
|
|
317
|
+
it('Should accept routes with typed match parameters (NestedRoute<T>)', () => {
|
|
318
|
+
const routes = {
|
|
319
|
+
'/stacks/:stackName': {
|
|
320
|
+
component: ({ match }) => <div>{match.params.stackName}</div>,
|
|
321
|
+
},
|
|
322
|
+
} satisfies Record<string, NestedRoute<{ stackName: string }>>
|
|
323
|
+
|
|
324
|
+
const AppLink = createNestedRouteLink<typeof routes>()
|
|
325
|
+
expectTypeOf(AppLink<'/stacks/:stackName'>)
|
|
326
|
+
.parameter(0)
|
|
327
|
+
.toExtend<{ params: { stackName: string } }>()
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
it('Should accept a mixed route tree with typed and untyped match parameters', () => {
|
|
331
|
+
const usersRoute: NestedRoute<{ userId: string }> = {
|
|
332
|
+
component: ({ match }) => <div>{match.params.userId}</div>,
|
|
333
|
+
}
|
|
334
|
+
const buttonsRoute: NestedRoute = {
|
|
335
|
+
component: () => <div />,
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const routes = {
|
|
339
|
+
'/': {
|
|
340
|
+
component: ({ outlet }) => outlet ?? <div />,
|
|
341
|
+
children: {
|
|
342
|
+
'/buttons': buttonsRoute,
|
|
343
|
+
'/users/:userId': usersRoute,
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
} satisfies Record<string, NestedRoute<any>>
|
|
347
|
+
|
|
348
|
+
const AppLink = createNestedRouteLink<typeof routes>()
|
|
349
|
+
expectTypeOf(AppLink).parameter(0).toHaveProperty('href')
|
|
350
|
+
expectTypeOf(AppLink<'/users/:userId'>)
|
|
351
|
+
.parameter(0)
|
|
352
|
+
.toExtend<{ params: { userId: string } }>()
|
|
353
|
+
})
|
|
302
354
|
})
|
|
303
355
|
})
|
|
@@ -93,7 +93,7 @@ export const NestedRouteLink = _NestedRouteLink as unknown as <TPath extends str
|
|
|
93
93
|
* <AppLink href="/users/:id" params={{ id: '123' }}>User</AppLink>
|
|
94
94
|
* ```
|
|
95
95
|
*/
|
|
96
|
-
export const createNestedRouteLink = <TRoutes extends Record<string, NestedRoute<
|
|
96
|
+
export const createNestedRouteLink = <TRoutes extends Record<string, NestedRoute<any>>>() => {
|
|
97
97
|
return _NestedRouteLink as unknown as <TPath extends ExtractRoutePaths<TRoutes>>(
|
|
98
98
|
props: TypedNestedRouteLinkProps<TPath>,
|
|
99
99
|
children?: ChildrenList,
|
|
@@ -12,10 +12,10 @@ export type ConcatPaths<Parent extends string, Child extends string> = Parent ex
|
|
|
12
12
|
* Recursively extracts all valid full URL paths from a nested route tree.
|
|
13
13
|
* @typeParam T - A record of route patterns to NestedRoute definitions
|
|
14
14
|
*/
|
|
15
|
-
export type ExtractRoutePaths<T extends Record<string, NestedRoute<
|
|
15
|
+
export type ExtractRoutePaths<T extends Record<string, NestedRoute<any>>> = {
|
|
16
16
|
[K in keyof T & string]:
|
|
17
17
|
| K
|
|
18
|
-
| (T[K] extends { children: infer C extends Record<string, NestedRoute<
|
|
18
|
+
| (T[K] extends { children: infer C extends Record<string, NestedRoute<any>> }
|
|
19
19
|
? ConcatPaths<K, ExtractRoutePaths<C> & string>
|
|
20
20
|
: never)
|
|
21
21
|
}[keyof T & string]
|