@benjavicente/angular-router-experimental 1.142.11 → 1.142.13
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/dist/fesm2022/tanstack-angular-router-experimental-experimental.mjs +242 -204
- package/dist/fesm2022/tanstack-angular-router-experimental.mjs +1228 -1204
- package/dist/types/tanstack-angular-router-experimental-experimental.d.ts +38 -37
- package/dist/types/tanstack-angular-router-experimental.d.ts +59 -46
- package/package.json +4 -3
- package/src/Match.ts +90 -33
- package/src/Matches.ts +5 -2
- package/src/RouterProvider.ts +3 -0
- package/src/document/build-match-managed-document.ts +1 -1
- package/src/document/install-unified-document-sync.ts +6 -3
- package/src/document/provide-tanstack-body-managed-tags.ts +2 -2
- package/src/document/provide-tanstack-document-title.ts +4 -5
- package/src/document/provide-tanstack-head-managed-tags.ts +2 -2
- package/src/index.ts +6 -2
- package/src/injectCanGoBack.ts +2 -2
- package/src/injectIsShell.ts +7 -0
- package/src/injectLocation.ts +11 -8
- package/src/injectMatch.ts +45 -34
- package/src/injectMatchRoute.ts +4 -5
- package/src/injectMatches.ts +9 -9
- package/src/injectRouterState.ts +15 -10
- package/src/renderer/injectIsCatchingError.ts +20 -8
- package/src/renderer/injectRender.ts +4 -2
- package/src/route.ts +0 -3
- package/src/routerStores.ts +25 -52
- package/src/store/injectSelector.ts +62 -0
- package/src/store/injectStore.ts +33 -0
- package/src/transitioner.ts +12 -25
- package/src/injectStore.ts +0 -87
|
@@ -22,43 +22,6 @@ export declare function injectRouteErrorHandler<TRouter extends AnyRouter = Regi
|
|
|
22
22
|
export { }
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
declare module '@benjavicente/router-core' {
|
|
26
|
-
interface UpdatableRouteOptionsExtensions {
|
|
27
|
-
component?: RouteComponent;
|
|
28
|
-
errorComponent?: false | null | undefined | ErrorRouteComponent;
|
|
29
|
-
notFoundComponent?: NotFoundRouteComponent;
|
|
30
|
-
pendingComponent?: RouteComponent;
|
|
31
|
-
}
|
|
32
|
-
interface RootRouteOptionsExtensions {
|
|
33
|
-
shellComponent?: Angular.Type<{
|
|
34
|
-
children: any;
|
|
35
|
-
}>;
|
|
36
|
-
}
|
|
37
|
-
interface RouteExtensions<in out TId extends string, in out TFullPath extends string> {
|
|
38
|
-
injectMatch: InjectMatchRoute<TId>;
|
|
39
|
-
injectRouteContext: InjectRouteContextRoute<TId>;
|
|
40
|
-
injectSearch: InjectSearchRoute<TId>;
|
|
41
|
-
injectParams: InjectParamsRoute<TId>;
|
|
42
|
-
injectLoaderDeps: InjectLoaderDepsRoute<TId>;
|
|
43
|
-
injectLoaderData: InjectLoaderDataRoute<TId>;
|
|
44
|
-
injectNavigate: () => UseNavigateResult<TFullPath>;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
declare module '@benjavicente/router-core' {
|
|
50
|
-
interface LazyRoute<in out TRoute extends AnyRoute> {
|
|
51
|
-
injectMatch: InjectMatchRoute<TRoute['id']>;
|
|
52
|
-
injectRouteContext: InjectRouteContextRoute<TRoute['id']>;
|
|
53
|
-
injectSearch: InjectSearchRoute<TRoute['id']>;
|
|
54
|
-
injectParams: InjectParamsRoute<TRoute['id']>;
|
|
55
|
-
injectLoaderDeps: InjectLoaderDepsRoute<TRoute['id']>;
|
|
56
|
-
injectLoaderData: InjectLoaderDataRoute<TRoute['id']>;
|
|
57
|
-
injectNavigate: () => UseNavigateResult<TRoute['fullPath']>;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
25
|
declare module '@benjavicente/router-core' {
|
|
63
26
|
interface RouterOptionsExtensions {
|
|
64
27
|
/**
|
|
@@ -96,8 +59,46 @@ declare module '@benjavicente/router-core' {
|
|
|
96
59
|
|
|
97
60
|
|
|
98
61
|
declare module '@benjavicente/router-core' {
|
|
62
|
+
interface UpdatableRouteOptionsExtensions {
|
|
63
|
+
component?: RouteComponent;
|
|
64
|
+
errorComponent?: false | null | undefined | ErrorRouteComponent;
|
|
65
|
+
notFoundComponent?: NotFoundRouteComponent;
|
|
66
|
+
pendingComponent?: RouteComponent;
|
|
67
|
+
}
|
|
68
|
+
interface RootRouteOptionsExtensions {
|
|
69
|
+
}
|
|
70
|
+
interface RouteExtensions<in out TId extends string, in out TFullPath extends string> {
|
|
71
|
+
injectMatch: InjectMatchRoute<TId>;
|
|
72
|
+
injectRouteContext: InjectRouteContextRoute<TId>;
|
|
73
|
+
injectSearch: InjectSearchRoute<TId>;
|
|
74
|
+
injectParams: InjectParamsRoute<TId>;
|
|
75
|
+
injectLoaderDeps: InjectLoaderDepsRoute<TId>;
|
|
76
|
+
injectLoaderData: InjectLoaderDataRoute<TId>;
|
|
77
|
+
injectNavigate: () => UseNavigateResult<TFullPath>;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
declare module '@benjavicente/router-core' {
|
|
83
|
+
interface LazyRoute<in out TRoute extends AnyRoute> {
|
|
84
|
+
injectMatch: InjectMatchRoute<TRoute['id']>;
|
|
85
|
+
injectRouteContext: InjectRouteContextRoute<TRoute['id']>;
|
|
86
|
+
injectSearch: InjectSearchRoute<TRoute['id']>;
|
|
87
|
+
injectParams: InjectParamsRoute<TRoute['id']>;
|
|
88
|
+
injectLoaderDeps: InjectLoaderDepsRoute<TRoute['id']>;
|
|
89
|
+
injectLoaderData: InjectLoaderDataRoute<TRoute['id']>;
|
|
90
|
+
injectNavigate: () => UseNavigateResult<TRoute['fullPath']>;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
declare module '@benjavicente/router-core' {
|
|
96
|
+
interface RouterReadableStore<TValue> extends Readable<TValue> {
|
|
97
|
+
}
|
|
99
98
|
interface RouterStores<in out TRouteTree extends AnyRoute> {
|
|
99
|
+
/** Maps each active routeId to the matchId of its child in the match tree. */
|
|
100
100
|
childMatchIdByRouteId: RouterReadableStore<Record<string, string>>;
|
|
101
|
+
/** Maps each pending routeId to true for quick lookup. */
|
|
101
102
|
pendingRouteIds: RouterReadableStore<Record<string, boolean>>;
|
|
102
103
|
}
|
|
103
104
|
}
|
|
@@ -28,6 +28,7 @@ import { HistoryAction } from '@benjavicente/history';
|
|
|
28
28
|
import { HistoryLocation } from '@benjavicente/history';
|
|
29
29
|
import { HistoryState } from '@benjavicente/history';
|
|
30
30
|
import { InjectionToken } from '@angular/core';
|
|
31
|
+
import { Injector } from '@angular/core';
|
|
31
32
|
import { InputSignal } from '@angular/core';
|
|
32
33
|
import { isRedirect } from '@benjavicente/router-core';
|
|
33
34
|
import { lazyFn } from '@benjavicente/router-core';
|
|
@@ -40,7 +41,6 @@ import { MakeRouteMatchUnion } from '@benjavicente/router-core';
|
|
|
40
41
|
import { MaskOptions } from '@benjavicente/router-core';
|
|
41
42
|
import { MatchRouteOptions } from '@benjavicente/router-core';
|
|
42
43
|
import { NavigateOptions } from '@benjavicente/router-core';
|
|
43
|
-
import { NoInfer as NoInfer_2 } from '@benjavicente/router-core';
|
|
44
44
|
import { notFound } from '@benjavicente/router-core';
|
|
45
45
|
import { NotFoundError } from '@benjavicente/router-core';
|
|
46
46
|
import { ParsedLocation } from '@benjavicente/router-core';
|
|
@@ -158,6 +158,10 @@ export declare function buildManagedDocumentContent(router: AnyRouter): ManagedD
|
|
|
158
158
|
*/
|
|
159
159
|
export declare function buildMatchManagedDocumentContent(router: AnyRouter): ManagedDocumentContent;
|
|
160
160
|
|
|
161
|
+
declare type CompatibilityInjectStoreOptions<TSelected> = CreateSignalOptions<TSelected> & {
|
|
162
|
+
injector?: Injector;
|
|
163
|
+
};
|
|
164
|
+
|
|
161
165
|
export { createBrowserHistory }
|
|
162
166
|
|
|
163
167
|
export { CreateFileRoute }
|
|
@@ -228,6 +232,8 @@ export declare function injectErrorState(): {
|
|
|
228
232
|
};
|
|
229
233
|
};
|
|
230
234
|
|
|
235
|
+
export declare function injectIsShell(): Signal<boolean>;
|
|
236
|
+
|
|
231
237
|
export declare function injectLoaderData<TRouter extends AnyRouter = RegisteredRouter, const TFrom extends string | undefined = undefined, TStrict extends boolean = true, TSelected = unknown>(opts: InjectLoaderDataOptions<TRouter, TFrom, TStrict, TSelected>): Angular.Signal<UseLoaderDataResult<TRouter, TFrom, TStrict, TSelected>>;
|
|
232
238
|
|
|
233
239
|
export declare interface InjectLoaderDataBaseOptions<TRouter extends AnyRouter, TFrom, TStrict extends boolean, TSelected> {
|
|
@@ -277,7 +283,7 @@ export declare type InjectMatchResult<TRouter extends AnyRouter, TFrom, TStrict
|
|
|
277
283
|
|
|
278
284
|
export declare type InjectMatchRoute<out TFrom> = <TRouter extends AnyRouter = RegisteredRouter, TSelected = unknown>(opts?: InjectMatchBaseOptions<TRouter, TFrom, true, true, TSelected>) => Angular.Signal<InjectMatchResult<TRouter, TFrom, true, TSelected>>;
|
|
279
285
|
|
|
280
|
-
export declare function injectMatchRoute<TRouter extends AnyRouter = RegisteredRouter>(): <const TFrom extends string = string, const TTo extends string | undefined = undefined, const TMaskFrom extends string = TFrom, const TMaskTo extends string = "">(opts: InjectMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>) => Angular.Signal<false | Expand<ResolveRoute<TRouter, TFrom,
|
|
286
|
+
export declare function injectMatchRoute<TRouter extends AnyRouter = RegisteredRouter>(): <const TFrom extends string = string, const TTo extends string | undefined = undefined, const TMaskFrom extends string = TFrom, const TMaskTo extends string = "">(opts: InjectMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>) => Angular.Signal<false | Expand<ResolveRoute<TRouter, TFrom, TTo>["types"]["allParams"]>>;
|
|
281
287
|
|
|
282
288
|
export declare type InjectMatchRouteOptions<TRouter extends AnyRouter = RegisteredRouter, TFrom extends string = string, TTo extends string | undefined = undefined, TMaskFrom extends string = TFrom, TMaskTo extends string = ''> = ToSubOptionsProps<TRouter, TFrom, TTo> & DeepPartial<MakeOptionalSearchParams<TRouter, TFrom, TTo>> & DeepPartial<MakeOptionalPathParams<TRouter, TFrom, TTo>> & MaskOptions<TRouter, TMaskFrom, TMaskTo> & MatchRouteOptions;
|
|
283
289
|
|
|
@@ -335,7 +341,9 @@ export declare type InjectSearchRoute<out TFrom> = <TRouter extends AnyRouter =
|
|
|
335
341
|
*/
|
|
336
342
|
export declare function injectSsrScrollRestorationScript(): void;
|
|
337
343
|
|
|
338
|
-
export declare function injectStore<TState, TSelected = NoInfer<TState>>(
|
|
344
|
+
export declare function injectStore<TState, TSelected = NoInfer<TState>>(store: SelectionSource<TState>, selector?: (state: NoInfer<TState>) => TSelected, options?: CompatibilityInjectStoreOptions<TSelected>): Signal<TSelected>;
|
|
345
|
+
|
|
346
|
+
export declare function injectStore<TState, TSelected = NoInfer<TState>>(store: SelectionSource<TState> | (() => SelectionSource<TState>), selector?: (state: NoInfer<TState>) => TSelected, options?: CompatibilityInjectStoreOptions<TSelected>): Signal<TSelected>;
|
|
339
347
|
|
|
340
348
|
declare class InternalFileRouteFactory<TFilePath extends keyof FileRoutesByPath, TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'], TId extends RouteConstraints['TId'] = FileRoutesByPath[TFilePath]['id'], TPath extends RouteConstraints['TPath'] = FileRoutesByPath[TFilePath]['path'], TFullPath extends RouteConstraints['TFullPath'] = FileRoutesByPath[TFilePath]['fullPath']> {
|
|
341
349
|
createRoute: <TRegister = Register, TSearchValidator = undefined, TParams = ResolveParams<TPath>, TRouteContextFn = AnyContext, TBeforeLoadFn = AnyContext, TLoaderDeps extends Record<string, any> = {}, TLoaderFn = undefined, TChildren = unknown, TSSR = unknown, TMiddlewares = unknown, THandlers = undefined>(options?: FileBaseRouteOptions<TRegister, TParentRoute, TId, TPath, TSearchValidator, TParams, TLoaderDeps, TLoaderFn, AnyContext, TRouteContextFn, TBeforeLoadFn, AnyContext, TSSR, TMiddlewares, THandlers> & UpdatableRouteOptions<TParentRoute, TId, TFullPath, TParams, TSearchValidator, TLoaderFn, TLoaderDeps, AnyContext, TRouteContextFn, TBeforeLoadFn>) => Route_2<TRegister, TParentRoute, TPath, TFullPath, TFilePath, TId, TSearchValidator, TParams, AnyContext, TRouteContextFn, TBeforeLoadFn, TLoaderDeps, TLoaderFn, TChildren, unknown, TSSR, TMiddlewares, THandlers>;
|
|
@@ -484,10 +492,6 @@ export declare function provideTanstackRouter({ router, context, options, }: Tan
|
|
|
484
492
|
useFactory?: undefined;
|
|
485
493
|
})[];
|
|
486
494
|
|
|
487
|
-
declare type ReadableStore<TState> = {
|
|
488
|
-
state: TState;
|
|
489
|
-
};
|
|
490
|
-
|
|
491
495
|
export { redirect }
|
|
492
496
|
|
|
493
497
|
export { Register }
|
|
@@ -495,7 +499,7 @@ export { Register }
|
|
|
495
499
|
export { RegisteredRouter }
|
|
496
500
|
|
|
497
501
|
declare type RenderValue = {
|
|
498
|
-
key?:
|
|
502
|
+
key?: unknown;
|
|
499
503
|
component: Type<any> | null | undefined;
|
|
500
504
|
inputs?: Record<string, () => unknown>;
|
|
501
505
|
providers?: Array<Provider>;
|
|
@@ -556,6 +560,7 @@ export declare class RouteMatch {
|
|
|
556
560
|
matchId: InputSignal<string>;
|
|
557
561
|
router: AnyRouter;
|
|
558
562
|
match: Signal<AnyRouteMatch | undefined>;
|
|
563
|
+
private matchSignal;
|
|
559
564
|
matchData: Signal<{
|
|
560
565
|
key: string | undefined;
|
|
561
566
|
route: AnyRoute;
|
|
@@ -570,7 +575,7 @@ export declare class RouteMatch {
|
|
|
570
575
|
hasPendingMatch: Signal<boolean>;
|
|
571
576
|
pendingRouteIds: Signal<Record<string, boolean>>;
|
|
572
577
|
nearestMatchContext: NearestMatchContextValue;
|
|
573
|
-
|
|
578
|
+
catchingErrorMatch: Signal<AnyRouteMatch | undefined>;
|
|
574
579
|
render: void;
|
|
575
580
|
onRendered: void;
|
|
576
581
|
}
|
|
@@ -604,6 +609,13 @@ export declare class RouterProvider<TRouter extends AnyRouter = RegisteredRouter
|
|
|
604
609
|
|
|
605
610
|
export { RouterState }
|
|
606
611
|
|
|
612
|
+
declare type SelectionSource<T> = {
|
|
613
|
+
get: () => T;
|
|
614
|
+
subscribe: (listener: (value: T) => void) => {
|
|
615
|
+
unsubscribe: () => void;
|
|
616
|
+
};
|
|
617
|
+
};
|
|
618
|
+
|
|
607
619
|
export declare type ShouldBlockFn<TRouter extends AnyRouter = RegisteredRouter> = (args: ShouldBlockFnArgs<TRouter>) => boolean | Promise<boolean>;
|
|
608
620
|
|
|
609
621
|
declare type ShouldBlockFnArgs<TRouter extends AnyRouter = RegisteredRouter> = {
|
|
@@ -645,43 +657,6 @@ export declare type UseBlockerOpts<TRouter extends AnyRouter = RegisteredRouter,
|
|
|
645
657
|
export { }
|
|
646
658
|
|
|
647
659
|
|
|
648
|
-
declare module '@benjavicente/router-core' {
|
|
649
|
-
interface UpdatableRouteOptionsExtensions {
|
|
650
|
-
component?: RouteComponent;
|
|
651
|
-
errorComponent?: false | null | undefined | ErrorRouteComponent;
|
|
652
|
-
notFoundComponent?: NotFoundRouteComponent;
|
|
653
|
-
pendingComponent?: RouteComponent;
|
|
654
|
-
}
|
|
655
|
-
interface RootRouteOptionsExtensions {
|
|
656
|
-
shellComponent?: Angular.Type<{
|
|
657
|
-
children: any;
|
|
658
|
-
}>;
|
|
659
|
-
}
|
|
660
|
-
interface RouteExtensions<in out TId extends string, in out TFullPath extends string> {
|
|
661
|
-
injectMatch: InjectMatchRoute<TId>;
|
|
662
|
-
injectRouteContext: InjectRouteContextRoute<TId>;
|
|
663
|
-
injectSearch: InjectSearchRoute<TId>;
|
|
664
|
-
injectParams: InjectParamsRoute<TId>;
|
|
665
|
-
injectLoaderDeps: InjectLoaderDepsRoute<TId>;
|
|
666
|
-
injectLoaderData: InjectLoaderDataRoute<TId>;
|
|
667
|
-
injectNavigate: () => UseNavigateResult<TFullPath>;
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
declare module '@benjavicente/router-core' {
|
|
673
|
-
interface LazyRoute<in out TRoute extends AnyRoute> {
|
|
674
|
-
injectMatch: InjectMatchRoute<TRoute['id']>;
|
|
675
|
-
injectRouteContext: InjectRouteContextRoute<TRoute['id']>;
|
|
676
|
-
injectSearch: InjectSearchRoute<TRoute['id']>;
|
|
677
|
-
injectParams: InjectParamsRoute<TRoute['id']>;
|
|
678
|
-
injectLoaderDeps: InjectLoaderDepsRoute<TRoute['id']>;
|
|
679
|
-
injectLoaderData: InjectLoaderDataRoute<TRoute['id']>;
|
|
680
|
-
injectNavigate: () => UseNavigateResult<TRoute['fullPath']>;
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
|
|
685
660
|
declare module '@benjavicente/router-core' {
|
|
686
661
|
interface RouterOptionsExtensions {
|
|
687
662
|
/**
|
|
@@ -719,8 +694,46 @@ declare module '@benjavicente/router-core' {
|
|
|
719
694
|
|
|
720
695
|
|
|
721
696
|
declare module '@benjavicente/router-core' {
|
|
697
|
+
interface UpdatableRouteOptionsExtensions {
|
|
698
|
+
component?: RouteComponent;
|
|
699
|
+
errorComponent?: false | null | undefined | ErrorRouteComponent;
|
|
700
|
+
notFoundComponent?: NotFoundRouteComponent;
|
|
701
|
+
pendingComponent?: RouteComponent;
|
|
702
|
+
}
|
|
703
|
+
interface RootRouteOptionsExtensions {
|
|
704
|
+
}
|
|
705
|
+
interface RouteExtensions<in out TId extends string, in out TFullPath extends string> {
|
|
706
|
+
injectMatch: InjectMatchRoute<TId>;
|
|
707
|
+
injectRouteContext: InjectRouteContextRoute<TId>;
|
|
708
|
+
injectSearch: InjectSearchRoute<TId>;
|
|
709
|
+
injectParams: InjectParamsRoute<TId>;
|
|
710
|
+
injectLoaderDeps: InjectLoaderDepsRoute<TId>;
|
|
711
|
+
injectLoaderData: InjectLoaderDataRoute<TId>;
|
|
712
|
+
injectNavigate: () => UseNavigateResult<TFullPath>;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
declare module '@benjavicente/router-core' {
|
|
718
|
+
interface LazyRoute<in out TRoute extends AnyRoute> {
|
|
719
|
+
injectMatch: InjectMatchRoute<TRoute['id']>;
|
|
720
|
+
injectRouteContext: InjectRouteContextRoute<TRoute['id']>;
|
|
721
|
+
injectSearch: InjectSearchRoute<TRoute['id']>;
|
|
722
|
+
injectParams: InjectParamsRoute<TRoute['id']>;
|
|
723
|
+
injectLoaderDeps: InjectLoaderDepsRoute<TRoute['id']>;
|
|
724
|
+
injectLoaderData: InjectLoaderDataRoute<TRoute['id']>;
|
|
725
|
+
injectNavigate: () => UseNavigateResult<TRoute['fullPath']>;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
declare module '@benjavicente/router-core' {
|
|
731
|
+
interface RouterReadableStore<TValue> extends Readable<TValue> {
|
|
732
|
+
}
|
|
722
733
|
interface RouterStores<in out TRouteTree extends AnyRoute> {
|
|
734
|
+
/** Maps each active routeId to the matchId of its child in the match tree. */
|
|
723
735
|
childMatchIdByRouteId: RouterReadableStore<Record<string, string>>;
|
|
736
|
+
/** Maps each pending routeId to true for quick lookup. */
|
|
724
737
|
pendingRouteIds: RouterReadableStore<Record<string, boolean>>;
|
|
725
738
|
}
|
|
726
739
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@benjavicente/angular-router-experimental",
|
|
3
|
-
"version": "1.142.
|
|
3
|
+
"version": "1.142.13",
|
|
4
4
|
"description": "Modern and scalable routing for Angular applications",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,10 +50,11 @@
|
|
|
50
50
|
"node": ">=20.19"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
+
"@tanstack/store": "^0.9.3",
|
|
53
54
|
"isbot": "^5.1.22",
|
|
54
55
|
"tslib": "^2.3.0",
|
|
55
|
-
"@benjavicente/
|
|
56
|
-
"@benjavicente/
|
|
56
|
+
"@benjavicente/router-core": "1.169.2",
|
|
57
|
+
"@benjavicente/history": "1.161.6"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@analogjs/vitest-angular": "^2.2.1",
|
package/src/Match.ts
CHANGED
|
@@ -16,14 +16,40 @@ import {
|
|
|
16
16
|
rootRouteId,
|
|
17
17
|
} from '@benjavicente/router-core'
|
|
18
18
|
import { injectRouter } from './injectRouter'
|
|
19
|
-
import { injectStore } from './injectStore'
|
|
19
|
+
import { injectStore } from './store/injectStore'
|
|
20
20
|
import { DefaultNotFoundComponent } from './DefaultNotFound'
|
|
21
21
|
import { MATCH_CONTEXT_INJECTOR_TOKEN } from './matchInjectorToken'
|
|
22
22
|
import { injectRender } from './renderer/injectRender'
|
|
23
23
|
import { ERROR_STATE_INJECTOR_TOKEN } from './injectErrorState'
|
|
24
|
-
import {
|
|
24
|
+
import { injectCatchingErrorMatch } from './renderer/injectIsCatchingError'
|
|
25
25
|
import type { Signal } from '@angular/core'
|
|
26
26
|
import type { NearestMatchContextValue } from './matchInjectorToken'
|
|
27
|
+
import type { AnyRouteMatch } from '@benjavicente/router-core'
|
|
28
|
+
|
|
29
|
+
const dummyMatchStore = {
|
|
30
|
+
get: () => undefined as AnyRouteMatch | undefined,
|
|
31
|
+
subscribe: () => ({ unsubscribe: () => {} }),
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Component({
|
|
35
|
+
selector: 'tanstack-router-default-error',
|
|
36
|
+
template: `
|
|
37
|
+
<div role="alert">
|
|
38
|
+
<p>Something went wrong.</p>
|
|
39
|
+
<pre>{{ message() }}</pre>
|
|
40
|
+
</div>
|
|
41
|
+
`,
|
|
42
|
+
standalone: true,
|
|
43
|
+
})
|
|
44
|
+
export class DefaultErrorComponent {
|
|
45
|
+
state = inject(ERROR_STATE_INJECTOR_TOKEN)
|
|
46
|
+
|
|
47
|
+
message = computed(() => {
|
|
48
|
+
const error = this.state.error
|
|
49
|
+
if (error instanceof Error) return error.stack ?? error.message
|
|
50
|
+
return String(error)
|
|
51
|
+
})
|
|
52
|
+
}
|
|
27
53
|
|
|
28
54
|
function injectOnRendered({
|
|
29
55
|
parentRouteIsRoot,
|
|
@@ -35,7 +61,7 @@ function injectOnRendered({
|
|
|
35
61
|
const destroyRef = inject(DestroyRef)
|
|
36
62
|
const location = injectStore(
|
|
37
63
|
router.stores.resolvedLocation,
|
|
38
|
-
(resolvedLocation) => resolvedLocation?.state
|
|
64
|
+
(resolvedLocation) => resolvedLocation?.state?.__TSR_key,
|
|
39
65
|
)
|
|
40
66
|
const loadedAt = injectStore(router.stores.loadedAt, (value) => value)
|
|
41
67
|
|
|
@@ -68,8 +94,8 @@ function injectOnRendered({
|
|
|
68
94
|
router.emit({
|
|
69
95
|
type: 'onRendered',
|
|
70
96
|
...getLocationChangeInfo(
|
|
71
|
-
router.stores.location.
|
|
72
|
-
router.stores.resolvedLocation.
|
|
97
|
+
router.stores.location.get(),
|
|
98
|
+
router.stores.resolvedLocation.get(),
|
|
73
99
|
),
|
|
74
100
|
})
|
|
75
101
|
},
|
|
@@ -84,6 +110,7 @@ function injectOnRendered({
|
|
|
84
110
|
template: '',
|
|
85
111
|
standalone: true,
|
|
86
112
|
host: {
|
|
113
|
+
hidden: '',
|
|
87
114
|
'[attr.data-matchId]': 'matchId()',
|
|
88
115
|
},
|
|
89
116
|
})
|
|
@@ -93,11 +120,12 @@ export class RouteMatch {
|
|
|
93
120
|
router = injectRouter()
|
|
94
121
|
|
|
95
122
|
match = computed(() => {
|
|
96
|
-
|
|
97
|
-
return matchId
|
|
98
|
-
? this.router.stores.activeMatchStoresById.get(matchId)?.state
|
|
99
|
-
: undefined
|
|
123
|
+
return this.matchSignal()
|
|
100
124
|
})
|
|
125
|
+
private matchSignal = injectStore(
|
|
126
|
+
() => this.router.stores.matchStores.get(this.matchId()) ?? dummyMatchStore,
|
|
127
|
+
(value) => value,
|
|
128
|
+
)
|
|
101
129
|
|
|
102
130
|
matchData = computed(() => {
|
|
103
131
|
const match = this.match()
|
|
@@ -141,16 +169,17 @@ export class RouteMatch {
|
|
|
141
169
|
return this.resolvedNoSsr() || !!match._displayPending
|
|
142
170
|
})
|
|
143
171
|
|
|
144
|
-
parentRouteIdSignal = computed(
|
|
145
|
-
() => this.matchData()?.parentRouteId ?? '',
|
|
146
|
-
)
|
|
172
|
+
parentRouteIdSignal = computed(() => this.matchData()?.parentRouteId ?? '')
|
|
147
173
|
rootRouteIdSignal = computed(() => rootRouteId)
|
|
148
174
|
|
|
149
175
|
hasPendingMatch = computed(() => {
|
|
150
176
|
const routeId = this.matchData()?.route.id
|
|
151
177
|
return routeId ? Boolean(this.pendingRouteIds()[routeId]) : false
|
|
152
178
|
})
|
|
153
|
-
pendingRouteIds = injectStore(
|
|
179
|
+
pendingRouteIds = injectStore(
|
|
180
|
+
this.router.stores.pendingRouteIds,
|
|
181
|
+
(ids) => ids,
|
|
182
|
+
)
|
|
154
183
|
nearestMatchContext: NearestMatchContextValue = {
|
|
155
184
|
matchId: this.matchId,
|
|
156
185
|
routeId: computed(() => this.matchData()?.route.id),
|
|
@@ -158,7 +187,7 @@ export class RouteMatch {
|
|
|
158
187
|
hasPending: this.hasPendingMatch,
|
|
159
188
|
}
|
|
160
189
|
|
|
161
|
-
|
|
190
|
+
catchingErrorMatch = injectCatchingErrorMatch({
|
|
162
191
|
matchId: this.matchId,
|
|
163
192
|
})
|
|
164
193
|
|
|
@@ -166,11 +195,15 @@ export class RouteMatch {
|
|
|
166
195
|
const matchData = this.matchData()
|
|
167
196
|
if (!matchData) return null
|
|
168
197
|
|
|
198
|
+
const { match, route } = matchData
|
|
199
|
+
|
|
169
200
|
if (this.shouldClientOnly() && this.router.isServer) {
|
|
170
|
-
|
|
171
|
-
|
|
201
|
+
const PendingComponent =
|
|
202
|
+
getComponent(route.options.pendingComponent) ??
|
|
203
|
+
getComponent(this.router.options.defaultPendingComponent)
|
|
172
204
|
|
|
173
|
-
|
|
205
|
+
return PendingComponent ? { component: PendingComponent } : null
|
|
206
|
+
}
|
|
174
207
|
|
|
175
208
|
if (match.status === 'notFound') {
|
|
176
209
|
const NotFoundComponent = getNotFoundComponent(this.router, route)
|
|
@@ -178,18 +211,18 @@ export class RouteMatch {
|
|
|
178
211
|
return {
|
|
179
212
|
component: NotFoundComponent,
|
|
180
213
|
}
|
|
181
|
-
} else if (match.status === 'error' || this.
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
getComponent(this.router.options.defaultErrorComponent)
|
|
214
|
+
} else if (match.status === 'error' || this.catchingErrorMatch()) {
|
|
215
|
+
const caughtMatch = this.catchingErrorMatch()
|
|
216
|
+
const RouteErrorComponent = getErrorComponent(this.router, route)
|
|
185
217
|
|
|
186
218
|
return {
|
|
187
|
-
component: RouteErrorComponent
|
|
219
|
+
component: RouteErrorComponent,
|
|
188
220
|
providers: [
|
|
189
221
|
{
|
|
190
222
|
provide: ERROR_STATE_INJECTOR_TOKEN,
|
|
191
223
|
useValue: {
|
|
192
|
-
error:
|
|
224
|
+
error:
|
|
225
|
+
match.status === 'error' ? match.error : caughtMatch?.error,
|
|
193
226
|
reset: () => {
|
|
194
227
|
this.router.invalidate()
|
|
195
228
|
},
|
|
@@ -258,23 +291,27 @@ export class RouteMatch {
|
|
|
258
291
|
selector: 'outlet,[outlet]',
|
|
259
292
|
template: '',
|
|
260
293
|
standalone: true,
|
|
294
|
+
host: {
|
|
295
|
+
hidden: '',
|
|
296
|
+
},
|
|
261
297
|
})
|
|
262
298
|
export class Outlet {
|
|
263
299
|
router = injectRouter()
|
|
264
300
|
nearestMatch = inject(MATCH_CONTEXT_INJECTOR_TOKEN)
|
|
265
301
|
|
|
266
|
-
currentMatch =
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
302
|
+
currentMatch = injectStore(
|
|
303
|
+
() => {
|
|
304
|
+
const matchId = this.nearestMatch.matchId()
|
|
305
|
+
return matchId
|
|
306
|
+
? (this.router.stores.matchStores.get(matchId) ?? dummyMatchStore)
|
|
307
|
+
: dummyMatchStore
|
|
308
|
+
},
|
|
309
|
+
(value) => value,
|
|
310
|
+
)
|
|
272
311
|
|
|
273
312
|
routeId = computed(() => this.currentMatch()?.routeId as string)
|
|
274
313
|
|
|
275
|
-
route = computed(
|
|
276
|
-
() => this.router.routesById[this.routeId()] as AnyRoute,
|
|
277
|
-
)
|
|
314
|
+
route = computed(() => this.router.routesById[this.routeId()] as AnyRoute)
|
|
278
315
|
|
|
279
316
|
parentGlobalNotFound = computed(
|
|
280
317
|
() => this.currentMatch()?.globalNotFound ?? false,
|
|
@@ -310,7 +347,9 @@ export class Outlet {
|
|
|
310
347
|
})
|
|
311
348
|
}
|
|
312
349
|
|
|
313
|
-
type CalledIfFunction<T> = T extends (...args: Array<any>) => any
|
|
350
|
+
type CalledIfFunction<T> = T extends (...args: Array<any>) => any
|
|
351
|
+
? ReturnType<T>
|
|
352
|
+
: T
|
|
314
353
|
|
|
315
354
|
function getComponent<T>(routeComponent: T): CalledIfFunction<T> {
|
|
316
355
|
if (typeof routeComponent === 'function') {
|
|
@@ -336,3 +375,21 @@ function getNotFoundComponent(router: AnyRouter, route: AnyRoute) {
|
|
|
336
375
|
|
|
337
376
|
return DefaultNotFoundComponent
|
|
338
377
|
}
|
|
378
|
+
|
|
379
|
+
function getErrorComponent(router: AnyRouter, route: AnyRoute) {
|
|
380
|
+
const RouteErrorComponent =
|
|
381
|
+
getComponent(route.options.errorComponent) ??
|
|
382
|
+
getComponent(router.options.defaultErrorComponent)
|
|
383
|
+
|
|
384
|
+
if (RouteErrorComponent) {
|
|
385
|
+
return RouteErrorComponent
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (isDevMode() && !route.options.errorComponent) {
|
|
389
|
+
console.warn(
|
|
390
|
+
`An error was encountered on the route with ID "${route.id}", but an errorComponent option was not configured, nor was a router level defaultErrorComponent configured. Consider configuring at least one of these to avoid TanStack Router's generic defaultErrorComponent.`,
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return DefaultErrorComponent
|
|
395
|
+
}
|
package/src/Matches.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component } from '@angular/core'
|
|
2
2
|
import { injectRouter } from './injectRouter'
|
|
3
|
-
import { injectStore } from './injectStore'
|
|
3
|
+
import { injectStore } from './store/injectStore'
|
|
4
4
|
import { injectRender } from './renderer/injectRender'
|
|
5
5
|
import { RouteMatch } from './Match'
|
|
6
6
|
import { injectSsrScrollRestorationScript } from './ssr-scroll-restoration'
|
|
@@ -10,11 +10,14 @@ import { injectTransitionerSetup } from './transitioner'
|
|
|
10
10
|
selector: 'router-matches',
|
|
11
11
|
template: '',
|
|
12
12
|
standalone: true,
|
|
13
|
+
host: {
|
|
14
|
+
hidden: '',
|
|
15
|
+
},
|
|
13
16
|
})
|
|
14
17
|
export class Matches {
|
|
15
18
|
router = injectRouter()
|
|
16
19
|
|
|
17
|
-
private matchId = injectStore(this.router.stores.
|
|
20
|
+
private matchId = injectStore(this.router.stores.firstId, (id) => id)
|
|
18
21
|
|
|
19
22
|
private ssrScrollRestoration = injectSsrScrollRestorationScript()
|
|
20
23
|
|
package/src/RouterProvider.ts
CHANGED
|
@@ -75,6 +75,9 @@ export function provideTanstackRouter({
|
|
|
75
75
|
selector: 'router-provider,[router-provider]',
|
|
76
76
|
template: '',
|
|
77
77
|
standalone: true,
|
|
78
|
+
host: {
|
|
79
|
+
hidden: '',
|
|
80
|
+
},
|
|
78
81
|
})
|
|
79
82
|
export class RouterProvider<TRouter extends AnyRouter = RegisteredRouter> {
|
|
80
83
|
readonly injectedContext: RouterInputs<TRouter>['context'] = inject(
|
|
@@ -16,7 +16,7 @@ export function buildMatchManagedDocumentContent(
|
|
|
16
16
|
router: AnyRouter,
|
|
17
17
|
): ManagedDocumentContent {
|
|
18
18
|
const nonce = router.options.ssr?.nonce
|
|
19
|
-
const matches = router.stores.
|
|
19
|
+
const matches = router.stores.matches.get()
|
|
20
20
|
const title = selectTitle(matches)
|
|
21
21
|
const metaTags = selectMetaTags(matches, nonce)
|
|
22
22
|
const links = selectConstructedLinks(matches, nonce)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DOCUMENT } from '@angular/common'
|
|
2
2
|
import * as Angular from '@angular/core'
|
|
3
|
-
import { injectStore } from '../injectStore'
|
|
3
|
+
import { injectStore } from '../store/injectStore'
|
|
4
4
|
import { buildMatchManagedDocumentContent } from './build-match-managed-document'
|
|
5
5
|
import {
|
|
6
6
|
collectDehydrationScriptManagedTags,
|
|
@@ -9,7 +9,10 @@ import {
|
|
|
9
9
|
import { areManagedDocumentContentsEqual } from './document-equality'
|
|
10
10
|
import { createManagedTagCollection } from './managed-dom'
|
|
11
11
|
import type { AnyRouter } from '@benjavicente/router-core'
|
|
12
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
ManagedDocumentContent,
|
|
14
|
+
ManagedTagCollection,
|
|
15
|
+
} from './managed-document-types'
|
|
13
16
|
|
|
14
17
|
function applyManagedDocumentContent({
|
|
15
18
|
document,
|
|
@@ -45,7 +48,7 @@ export function installUnifiedTanstackDocumentSync(injectedRouter: AnyRouter) {
|
|
|
45
48
|
})
|
|
46
49
|
const destroyRef = Angular.inject(Angular.DestroyRef)
|
|
47
50
|
const activeMatches = injectStore(
|
|
48
|
-
injectedRouter.stores.
|
|
51
|
+
injectedRouter.stores.matches,
|
|
49
52
|
(matches) => matches,
|
|
50
53
|
)
|
|
51
54
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DOCUMENT } from '@angular/common'
|
|
2
2
|
import * as Angular from '@angular/core'
|
|
3
|
-
import { injectStore } from '../injectStore'
|
|
3
|
+
import { injectStore } from '../store/injectStore'
|
|
4
4
|
import { buildMatchManagedDocumentContent } from './build-match-managed-document'
|
|
5
5
|
import { collectDehydrationScriptManagedTags } from './document-dehydration'
|
|
6
6
|
import { areManagedTagArraysEqual } from './document-equality'
|
|
@@ -20,7 +20,7 @@ export function installTanstackBodyManagedTags(injectedRouter: AnyRouter) {
|
|
|
20
20
|
})
|
|
21
21
|
const destroyRef = Angular.inject(Angular.DestroyRef)
|
|
22
22
|
const activeMatches = injectStore(
|
|
23
|
-
injectedRouter.stores.
|
|
23
|
+
injectedRouter.stores.matches,
|
|
24
24
|
(matches) => matches,
|
|
25
25
|
)
|
|
26
26
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DOCUMENT } from '@angular/common'
|
|
2
2
|
import * as Angular from '@angular/core'
|
|
3
|
-
import { injectStore } from '../injectStore'
|
|
3
|
+
import { injectStore } from '../store/injectStore'
|
|
4
4
|
import { buildMatchManagedDocumentContent } from './build-match-managed-document'
|
|
5
5
|
import { TANSTACK_DOCUMENT_ROUTER } from './document-router-token'
|
|
6
6
|
import type { AnyRouter } from '@benjavicente/router-core'
|
|
@@ -10,14 +10,13 @@ export function installTanstackDocumentTitle(injectedRouter: AnyRouter) {
|
|
|
10
10
|
const document = Angular.inject(DOCUMENT)
|
|
11
11
|
const destroyRef = Angular.inject(Angular.DestroyRef)
|
|
12
12
|
const activeMatches = injectStore(
|
|
13
|
-
injectedRouter.stores.
|
|
13
|
+
injectedRouter.stores.matches,
|
|
14
14
|
(matches) => matches,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
const initialTitle = document.title
|
|
18
|
-
let currentTitle: string | undefined =
|
|
19
|
-
injectedRouter
|
|
20
|
-
).title
|
|
18
|
+
let currentTitle: string | undefined =
|
|
19
|
+
buildMatchManagedDocumentContent(injectedRouter).title
|
|
21
20
|
|
|
22
21
|
const applyTitle = (next?: string) => {
|
|
23
22
|
if (next !== undefined) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DOCUMENT } from '@angular/common'
|
|
2
2
|
import * as Angular from '@angular/core'
|
|
3
|
-
import { injectStore } from '../injectStore'
|
|
3
|
+
import { injectStore } from '../store/injectStore'
|
|
4
4
|
import { buildMatchManagedDocumentContent } from './build-match-managed-document'
|
|
5
5
|
import { areManagedTagArraysEqual } from './document-equality'
|
|
6
6
|
import { TANSTACK_DOCUMENT_ROUTER } from './document-router-token'
|
|
@@ -16,7 +16,7 @@ export function installTanstackHeadManagedTags(injectedRouter: AnyRouter) {
|
|
|
16
16
|
})
|
|
17
17
|
const destroyRef = Angular.inject(Angular.DestroyRef)
|
|
18
18
|
const activeMatches = injectStore(
|
|
19
|
-
injectedRouter.stores.
|
|
19
|
+
injectedRouter.stores.matches,
|
|
20
20
|
(matches) => matches,
|
|
21
21
|
)
|
|
22
22
|
|