@benjavicente/angular-router-experimental 1.142.11

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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/dist/fesm2022/tanstack-angular-router-experimental-experimental.mjs +920 -0
  4. package/dist/fesm2022/tanstack-angular-router-experimental.mjs +4131 -0
  5. package/dist/types/tanstack-angular-router-experimental-experimental.d.ts +110 -0
  6. package/dist/types/tanstack-angular-router-experimental.d.ts +733 -0
  7. package/experimental/injectRouteErrorHandler.ts +51 -0
  8. package/experimental/public_api.ts +8 -0
  9. package/package.json +98 -0
  10. package/src/DefaultNotFound.ts +9 -0
  11. package/src/Link.ts +352 -0
  12. package/src/Match.ts +338 -0
  13. package/src/Matches.ts +37 -0
  14. package/src/RouterProvider.ts +162 -0
  15. package/src/document/build-match-managed-document.ts +308 -0
  16. package/src/document/document-dehydration.ts +27 -0
  17. package/src/document/document-equality.ts +29 -0
  18. package/src/document/document-router-token.ts +6 -0
  19. package/src/document/index.ts +33 -0
  20. package/src/document/install-unified-document-sync.ts +108 -0
  21. package/src/document/managed-document-types.ts +36 -0
  22. package/src/document/managed-dom.ts +307 -0
  23. package/src/document/provide-tanstack-body-managed-tags.ts +78 -0
  24. package/src/document/provide-tanstack-document-title.ts +59 -0
  25. package/src/document/provide-tanstack-document.ts +62 -0
  26. package/src/document/provide-tanstack-head-managed-tags.ts +63 -0
  27. package/src/fileRoute.ts +232 -0
  28. package/src/index.ts +173 -0
  29. package/src/injectBlocker.ts +196 -0
  30. package/src/injectCanGoBack.ts +11 -0
  31. package/src/injectErrorState.ts +21 -0
  32. package/src/injectIntersectionObserver.ts +28 -0
  33. package/src/injectLoaderData.ts +49 -0
  34. package/src/injectLoaderDeps.ts +45 -0
  35. package/src/injectLocation.ts +38 -0
  36. package/src/injectMatch.ts +122 -0
  37. package/src/injectMatchRoute.ts +58 -0
  38. package/src/injectMatches.ts +79 -0
  39. package/src/injectNavigate.ts +24 -0
  40. package/src/injectParams.ts +71 -0
  41. package/src/injectRouteContext.ts +31 -0
  42. package/src/injectRouter.ts +17 -0
  43. package/src/injectRouterState.ts +53 -0
  44. package/src/injectSearch.ts +71 -0
  45. package/src/injectStore.ts +87 -0
  46. package/src/matchInjectorToken.ts +23 -0
  47. package/src/renderer/injectIsCatchingError.ts +40 -0
  48. package/src/renderer/injectRender.ts +69 -0
  49. package/src/route.ts +641 -0
  50. package/src/router.ts +141 -0
  51. package/src/routerInjectionToken.ts +24 -0
  52. package/src/routerStores.ts +107 -0
  53. package/src/ssr-scroll-restoration.ts +48 -0
  54. package/src/transitioner.ts +255 -0
@@ -0,0 +1,45 @@
1
+ import { injectMatch } from './injectMatch'
2
+ import type * as Angular from '@angular/core'
3
+ import type {
4
+ AnyRouter,
5
+ RegisteredRouter,
6
+ ResolveUseLoaderDeps,
7
+ StrictOrFrom,
8
+ UseLoaderDepsResult,
9
+ } from '@benjavicente/router-core'
10
+
11
+ export interface InjectLoaderDepsBaseOptions<
12
+ TRouter extends AnyRouter,
13
+ TFrom,
14
+ TSelected,
15
+ > {
16
+ select?: (deps: ResolveUseLoaderDeps<TRouter, TFrom>) => TSelected
17
+ }
18
+
19
+ export type InjectLoaderDepsOptions<
20
+ TRouter extends AnyRouter,
21
+ TFrom extends string | undefined,
22
+ TSelected,
23
+ > = StrictOrFrom<TRouter, TFrom> &
24
+ InjectLoaderDepsBaseOptions<TRouter, TFrom, TSelected>
25
+
26
+ export type InjectLoaderDepsRoute<out TFrom> = <
27
+ TRouter extends AnyRouter = RegisteredRouter,
28
+ TSelected = unknown,
29
+ >(
30
+ opts?: InjectLoaderDepsBaseOptions<TRouter, TFrom, TSelected>,
31
+ ) => Angular.Signal<UseLoaderDepsResult<TRouter, TFrom, TSelected>>
32
+
33
+ export function injectLoaderDeps<
34
+ TRouter extends AnyRouter = RegisteredRouter,
35
+ const TFrom extends string | undefined = undefined,
36
+ TSelected = unknown,
37
+ >(
38
+ opts: InjectLoaderDepsOptions<TRouter, TFrom, TSelected>,
39
+ ): Angular.Signal<UseLoaderDepsResult<TRouter, TFrom, TSelected>> {
40
+ const { select, ...rest } = opts
41
+ return injectMatch({
42
+ ...rest,
43
+ select: (s) => (select ? select(s.loaderDeps) : s.loaderDeps),
44
+ }) as any
45
+ }
@@ -0,0 +1,38 @@
1
+ import { deepEqual } from '@benjavicente/router-core'
2
+ import { injectRouter } from './injectRouter'
3
+ import { injectStore } from './injectStore'
4
+ import type {
5
+ AnyRouter,
6
+ RegisteredRouter,
7
+ RouterState,
8
+ } from '@benjavicente/router-core'
9
+ import type * as Angular from '@angular/core'
10
+
11
+ export interface InjectLocationOptions<TRouter extends AnyRouter, TSelected> {
12
+ select?: (
13
+ location: RouterState<TRouter['routeTree']>['location'],
14
+ ) => TSelected
15
+ }
16
+
17
+ export type InjectLocationResult<
18
+ TRouter extends AnyRouter,
19
+ TSelected,
20
+ > = unknown extends TSelected
21
+ ? RouterState<TRouter['routeTree']>['location']
22
+ : TSelected
23
+
24
+ export function injectLocation<
25
+ TRouter extends AnyRouter = RegisteredRouter,
26
+ TSelected = unknown,
27
+ >(
28
+ opts?: InjectLocationOptions<TRouter, TSelected>,
29
+ ): Angular.Signal<InjectLocationResult<TRouter, TSelected>> {
30
+ const router = injectRouter<TRouter>()
31
+
32
+ return injectStore(
33
+ router.stores.location,
34
+ (location) =>
35
+ (opts?.select ? opts.select(location as any) : location) as any,
36
+ { equal: deepEqual }
37
+ ) as Angular.Signal<InjectLocationResult<TRouter, TSelected>>
38
+ }
@@ -0,0 +1,122 @@
1
+ import * as Angular from '@angular/core'
2
+ import { deepEqual, invariant } from '@benjavicente/router-core'
3
+ import { MATCH_CONTEXT_INJECTOR_TOKEN } from './matchInjectorToken'
4
+ import { injectRouter } from './injectRouter'
5
+ import { injectStore } from './injectStore'
6
+ import type {
7
+ AnyRouter,
8
+ MakeRouteMatch,
9
+ MakeRouteMatchUnion,
10
+ RegisteredRouter,
11
+ StrictOrFrom,
12
+ ThrowConstraint,
13
+ ThrowOrOptional,
14
+ } from '@benjavicente/router-core'
15
+
16
+ export interface InjectMatchBaseOptions<
17
+ TRouter extends AnyRouter,
18
+ TFrom,
19
+ TStrict extends boolean,
20
+ TThrow extends boolean,
21
+ TSelected,
22
+ > {
23
+ select?: (
24
+ match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>,
25
+ ) => TSelected
26
+ shouldThrow?: TThrow
27
+ }
28
+
29
+ export type InjectMatchRoute<out TFrom> = <
30
+ TRouter extends AnyRouter = RegisteredRouter,
31
+ TSelected = unknown,
32
+ >(
33
+ opts?: InjectMatchBaseOptions<TRouter, TFrom, true, true, TSelected>,
34
+ ) => Angular.Signal<InjectMatchResult<TRouter, TFrom, true, TSelected>>
35
+
36
+ export type InjectMatchOptions<
37
+ TRouter extends AnyRouter,
38
+ TFrom,
39
+ TStrict extends boolean,
40
+ TThrow extends boolean,
41
+ TSelected,
42
+ > = StrictOrFrom<TRouter, TFrom, TStrict> &
43
+ InjectMatchBaseOptions<TRouter, TFrom, TStrict, TThrow, TSelected>
44
+
45
+ export type InjectMatchResult<
46
+ TRouter extends AnyRouter,
47
+ TFrom,
48
+ TStrict extends boolean,
49
+ TSelected,
50
+ > = unknown extends TSelected
51
+ ? TStrict extends true
52
+ ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>
53
+ : MakeRouteMatchUnion<TRouter>
54
+ : TSelected
55
+
56
+ export function injectMatch<
57
+ TRouter extends AnyRouter = RegisteredRouter,
58
+ const TFrom extends string | undefined = undefined,
59
+ TStrict extends boolean = true,
60
+ TThrow extends boolean = true,
61
+ TSelected = unknown,
62
+ >(
63
+ opts: InjectMatchOptions<
64
+ TRouter,
65
+ TFrom,
66
+ TStrict,
67
+ ThrowConstraint<TStrict, TThrow>,
68
+ TSelected
69
+ >,
70
+ ): Angular.Signal<
71
+ ThrowOrOptional<InjectMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow>
72
+ > {
73
+ const router = injectRouter<TRouter>()
74
+ const nearestMatch = opts.from
75
+ ? undefined
76
+ : Angular.inject(MATCH_CONTEXT_INJECTOR_TOKEN)
77
+
78
+ const pendingRouteIds = injectStore(
79
+ router.stores.pendingRouteIds,
80
+ (s) => s,
81
+ )
82
+ const isTransitioning = injectStore(
83
+ router.stores.isTransitioning,
84
+ (s) => s,
85
+ )
86
+
87
+ const match = () => {
88
+ if (opts.from) {
89
+ return router.stores.getMatchStoreByRouteId(opts.from).state
90
+ }
91
+
92
+ return nearestMatch?.match()
93
+ }
94
+
95
+ return Angular.computed(() => {
96
+ const selectedMatch = match()
97
+
98
+ if (selectedMatch !== undefined) {
99
+ return opts.select ? opts.select(selectedMatch as any) : selectedMatch
100
+ }
101
+
102
+ const hasPendingMatch = opts.from
103
+ ? Boolean(pendingRouteIds()[opts.from])
104
+ : nearestMatch?.hasPending() ?? false
105
+
106
+ if (
107
+ !hasPendingMatch &&
108
+ !isTransitioning() &&
109
+ (opts.shouldThrow ?? true)
110
+ ) {
111
+ if (process.env.NODE_ENV !== 'production') {
112
+ throw new Error(
113
+ `Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
114
+ )
115
+ }
116
+
117
+ invariant()
118
+ }
119
+
120
+ return undefined
121
+ }, { equal: deepEqual }) as any
122
+ }
@@ -0,0 +1,58 @@
1
+ import * as Angular from '@angular/core'
2
+ import { injectRouter } from './injectRouter'
3
+ import { injectStore } from './injectStore'
4
+ import type {
5
+ AnyRouter,
6
+ DeepPartial,
7
+ Expand,
8
+ MakeOptionalPathParams,
9
+ MakeOptionalSearchParams,
10
+ MaskOptions,
11
+ MatchRouteOptions,
12
+ NoInfer,
13
+ RegisteredRouter,
14
+ ResolveRoute,
15
+ ToSubOptionsProps,
16
+ } from '@benjavicente/router-core'
17
+
18
+ export type InjectMatchRouteOptions<
19
+ TRouter extends AnyRouter = RegisteredRouter,
20
+ TFrom extends string = string,
21
+ TTo extends string | undefined = undefined,
22
+ TMaskFrom extends string = TFrom,
23
+ TMaskTo extends string = '',
24
+ > = ToSubOptionsProps<TRouter, TFrom, TTo> &
25
+ DeepPartial<MakeOptionalSearchParams<TRouter, TFrom, TTo>> &
26
+ DeepPartial<MakeOptionalPathParams<TRouter, TFrom, TTo>> &
27
+ MaskOptions<TRouter, TMaskFrom, TMaskTo> &
28
+ MatchRouteOptions
29
+
30
+ export function injectMatchRoute<
31
+ TRouter extends AnyRouter = RegisteredRouter,
32
+ >() {
33
+ const router = injectRouter<TRouter>()
34
+ const reactivity = injectStore(router.stores.matchRouteReactivity, (d) => d)
35
+
36
+ return <
37
+ const TFrom extends string = string,
38
+ const TTo extends string | undefined = undefined,
39
+ const TMaskFrom extends string = TFrom,
40
+ const TMaskTo extends string = '',
41
+ >(
42
+ opts: InjectMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,
43
+ ): Angular.Signal<
44
+ false | Expand<ResolveRoute<TRouter, TFrom, NoInfer<TTo>>['types']['allParams']>
45
+ > => {
46
+ return Angular.computed(() => {
47
+ reactivity()
48
+ const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts
49
+
50
+ return router.matchRoute(rest as any, {
51
+ pending,
52
+ caseSensitive,
53
+ fuzzy,
54
+ includeSearch,
55
+ })
56
+ })
57
+ }
58
+ }
@@ -0,0 +1,79 @@
1
+ import * as Angular from '@angular/core'
2
+ import { deepEqual } from '@benjavicente/router-core'
3
+ import { injectRouter } from './injectRouter'
4
+ import { injectStore } from './injectStore'
5
+ import { MATCH_CONTEXT_INJECTOR_TOKEN } from './matchInjectorToken'
6
+ import type {
7
+ AnyRouter,
8
+ MakeRouteMatchUnion,
9
+ RegisteredRouter,
10
+ } from '@benjavicente/router-core'
11
+
12
+ export interface InjectMatchesBaseOptions<
13
+ TRouter extends AnyRouter,
14
+ TSelected,
15
+ > {
16
+ select?: (matches: Array<MakeRouteMatchUnion<TRouter>>) => TSelected
17
+ }
18
+
19
+ export type InjectMatchesResult<
20
+ TRouter extends AnyRouter,
21
+ TSelected,
22
+ > = unknown extends TSelected ? Array<MakeRouteMatchUnion<TRouter>> : TSelected
23
+
24
+ export function injectMatches<
25
+ TRouter extends AnyRouter = RegisteredRouter,
26
+ TSelected = unknown,
27
+ >(
28
+ opts?: InjectMatchesBaseOptions<TRouter, TSelected>,
29
+ ): Angular.Signal<InjectMatchesResult<TRouter, TSelected>> {
30
+ const router = injectRouter<TRouter>()
31
+ const matches = injectStore(router.stores.activeMatchesSnapshot, (value) => {
32
+ return value as Array<MakeRouteMatchUnion<TRouter>>
33
+ })
34
+
35
+ return Angular.computed(() => {
36
+ const currentMatches = matches()
37
+ const result = opts?.select ? opts.select(currentMatches) : currentMatches
38
+ return result as InjectMatchesResult<TRouter, TSelected>
39
+ }, { equal: deepEqual }) as any
40
+ }
41
+
42
+ export function injectParentMatches<
43
+ TRouter extends AnyRouter = RegisteredRouter,
44
+ TSelected = unknown,
45
+ >(
46
+ opts?: InjectMatchesBaseOptions<TRouter, TSelected>,
47
+ ): Angular.Signal<InjectMatchesResult<TRouter, TSelected>> {
48
+ const nearestMatch = Angular.inject(MATCH_CONTEXT_INJECTOR_TOKEN)
49
+
50
+ return injectMatches({
51
+ select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {
52
+ const sliced = matches.slice(
53
+ 0,
54
+ matches.findIndex((d) => d.id === nearestMatch.matchId()),
55
+ )
56
+
57
+ return opts?.select ? opts.select(sliced) : sliced
58
+ },
59
+ } as any)
60
+ }
61
+
62
+ export function injectChildMatches<
63
+ TRouter extends AnyRouter = RegisteredRouter,
64
+ TSelected = unknown,
65
+ >(
66
+ opts?: InjectMatchesBaseOptions<TRouter, TSelected>,
67
+ ): Angular.Signal<InjectMatchesResult<TRouter, TSelected>> {
68
+ const nearestMatch = Angular.inject(MATCH_CONTEXT_INJECTOR_TOKEN)
69
+
70
+ return injectMatches({
71
+ select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {
72
+ const sliced = matches.slice(
73
+ matches.findIndex((d) => d.id === nearestMatch.matchId()) + 1,
74
+ )
75
+
76
+ return opts?.select ? opts.select(sliced) : sliced
77
+ },
78
+ } as any)
79
+ }
@@ -0,0 +1,24 @@
1
+ import { injectRouter } from './injectRouter'
2
+ import type {
3
+ AnyRouter,
4
+ FromPathOption,
5
+ NavigateOptions,
6
+ RegisteredRouter,
7
+ UseNavigateResult,
8
+ } from '@benjavicente/router-core'
9
+
10
+ export function injectNavigate<
11
+ TRouter extends AnyRouter = RegisteredRouter,
12
+ TDefaultFrom extends string = string,
13
+ >(_defaultOpts?: {
14
+ from?: FromPathOption<TRouter, TDefaultFrom>
15
+ }): UseNavigateResult<TDefaultFrom> {
16
+ const router = injectRouter()
17
+
18
+ return ((options: NavigateOptions) => {
19
+ return router.navigate({
20
+ ...options,
21
+ from: options.from ?? _defaultOpts?.from,
22
+ })
23
+ }) as UseNavigateResult<TDefaultFrom>
24
+ }
@@ -0,0 +1,71 @@
1
+ import { injectMatch } from './injectMatch'
2
+ import type * as Angular from '@angular/core'
3
+ import type {
4
+ AnyRouter,
5
+ RegisteredRouter,
6
+ ResolveUseParams,
7
+ StrictOrFrom,
8
+ ThrowConstraint,
9
+ ThrowOrOptional,
10
+ UseParamsResult,
11
+ } from '@benjavicente/router-core'
12
+
13
+ export interface InjectParamsBaseOptions<
14
+ TRouter extends AnyRouter,
15
+ TFrom,
16
+ TStrict extends boolean,
17
+ TThrow extends boolean,
18
+ TSelected,
19
+ > {
20
+ select?: (params: ResolveUseParams<TRouter, TFrom, TStrict>) => TSelected
21
+ shouldThrow?: TThrow
22
+ }
23
+
24
+ export type InjectParamsOptions<
25
+ TRouter extends AnyRouter,
26
+ TFrom extends string | undefined,
27
+ TStrict extends boolean,
28
+ TThrow extends boolean,
29
+ TSelected,
30
+ > = StrictOrFrom<TRouter, TFrom, TStrict> &
31
+ InjectParamsBaseOptions<TRouter, TFrom, TStrict, TThrow, TSelected>
32
+
33
+ export type InjectParamsRoute<out TFrom> = <
34
+ TRouter extends AnyRouter = RegisteredRouter,
35
+ TSelected = unknown,
36
+ >(
37
+ opts?: InjectParamsBaseOptions<
38
+ TRouter,
39
+ TFrom,
40
+ /* TStrict */ true,
41
+ /* TThrow */ true,
42
+ TSelected
43
+ >,
44
+ ) => Angular.Signal<UseParamsResult<TRouter, TFrom, true, TSelected>>
45
+
46
+ export function injectParams<
47
+ TRouter extends AnyRouter = RegisteredRouter,
48
+ const TFrom extends string | undefined = undefined,
49
+ TStrict extends boolean = true,
50
+ TThrow extends boolean = true,
51
+ TSelected = unknown,
52
+ >(
53
+ opts: InjectParamsOptions<
54
+ TRouter,
55
+ TFrom,
56
+ TStrict,
57
+ ThrowConstraint<TStrict, TThrow>,
58
+ TSelected
59
+ >,
60
+ ): Angular.Signal<
61
+ ThrowOrOptional<UseParamsResult<TRouter, TFrom, true, TSelected>, TThrow>
62
+ > {
63
+ return injectMatch({
64
+ from: opts.from!,
65
+ strict: opts.strict,
66
+ shouldThrow: opts.shouldThrow,
67
+ select: (match: any) => {
68
+ return opts.select ? opts.select(match.params) : match.params
69
+ },
70
+ } as any) as Angular.Signal<any>
71
+ }
@@ -0,0 +1,31 @@
1
+ import { injectMatch } from './injectMatch'
2
+ import type * as Angular from '@angular/core'
3
+ import type {
4
+ AnyRouter,
5
+ RegisteredRouter,
6
+ UseRouteContextBaseOptions,
7
+ UseRouteContextOptions,
8
+ UseRouteContextResult,
9
+ } from '@benjavicente/router-core'
10
+
11
+ export type InjectRouteContextRoute<out TFrom> = <
12
+ TRouter extends AnyRouter = RegisteredRouter,
13
+ TSelected = unknown,
14
+ >(
15
+ opts?: UseRouteContextBaseOptions<TRouter, TFrom, true, TSelected>,
16
+ ) => Angular.Signal<UseRouteContextResult<TRouter, TFrom, true, TSelected>>
17
+
18
+ export function injectRouteContext<
19
+ TRouter extends AnyRouter = RegisteredRouter,
20
+ const TFrom extends string | undefined = undefined,
21
+ TStrict extends boolean = true,
22
+ TSelected = unknown,
23
+ >(
24
+ opts: UseRouteContextOptions<TRouter, TFrom, TStrict, TSelected>,
25
+ ): Angular.Signal<UseRouteContextResult<TRouter, TFrom, TStrict, TSelected>> {
26
+ return injectMatch({
27
+ ...(opts as any),
28
+ select: (match) =>
29
+ opts.select ? opts.select(match.context) : match.context,
30
+ }) as any
31
+ }
@@ -0,0 +1,17 @@
1
+ import * as Angular from '@angular/core'
2
+ import { getRouterInjectionKey } from './routerInjectionToken'
3
+ import type { AnyRouter, RegisteredRouter } from '@benjavicente/router-core'
4
+
5
+ export function injectRouter<
6
+ TRouter extends AnyRouter = RegisteredRouter,
7
+ >(opts?: { warn?: boolean }): TRouter {
8
+ const router = Angular.inject(getRouterInjectionKey(), { optional: true })
9
+ if (process.env.NODE_ENV !== 'production') {
10
+ if ((opts?.warn ?? true) && !router) {
11
+ console.warn(
12
+ 'Warning: injectRouter must be used inside a <router-provider> component!',
13
+ )
14
+ }
15
+ }
16
+ return router as any
17
+ }
@@ -0,0 +1,53 @@
1
+ import { isServer } from '@benjavicente/router-core/isServer'
2
+ import * as Angular from '@angular/core'
3
+ import { deepEqual } from '@benjavicente/router-core'
4
+ import { injectRouter } from './injectRouter'
5
+ import { injectStore } from './injectStore'
6
+ import type {
7
+ AnyRouter,
8
+ RegisteredRouter,
9
+ RouterState,
10
+ } from '@benjavicente/router-core'
11
+
12
+ export type InjectRouterStateOptions<TRouter extends AnyRouter, TSelected> = {
13
+ router?: TRouter
14
+ select?: (state: RouterState<TRouter['routeTree']>) => TSelected
15
+ }
16
+
17
+ export type InjectRouterStateResult<
18
+ TRouter extends AnyRouter,
19
+ TSelected,
20
+ > = unknown extends TSelected ? RouterState<TRouter['routeTree']> : TSelected
21
+
22
+ export function injectRouterState<
23
+ TRouter extends AnyRouter = RegisteredRouter,
24
+ TSelected = unknown,
25
+ >(
26
+ opts?: InjectRouterStateOptions<TRouter, TSelected>,
27
+ ): Angular.Signal<InjectRouterStateResult<TRouter, TSelected>> {
28
+ const contextRouter = injectRouter({
29
+ warn: opts?.router === undefined,
30
+ })
31
+ const router = opts?.router ?? contextRouter
32
+ const state = injectStore(router.stores.__store, (state) => state)
33
+
34
+ // During SSR we render exactly once and do not need reactivity.
35
+ // Avoid subscribing to the store on the server since the server store
36
+ // implementation does not provide subscribe() semantics.
37
+ const _isServer =
38
+ typeof isServer === 'boolean' ? isServer : router.isServer
39
+ if (_isServer) {
40
+ const state = router.stores.__store.state as RouterState<
41
+ TRouter['routeTree']
42
+ >
43
+ const selected = (
44
+ opts?.select ? opts.select(state) : state
45
+ ) as InjectRouterStateResult<TRouter, TSelected>
46
+ return (() => selected) as Angular.Signal<InjectRouterStateResult<TRouter, TSelected>>
47
+ }
48
+
49
+ return Angular.computed(() => {
50
+ const result = opts?.select ? opts.select(state()) : state()
51
+ return result as InjectRouterStateResult<TRouter, TSelected>
52
+ }, { equal: deepEqual }) as any;
53
+ }
@@ -0,0 +1,71 @@
1
+ import { injectMatch } from './injectMatch'
2
+ import type * as Angular from '@angular/core'
3
+ import type {
4
+ AnyRouter,
5
+ RegisteredRouter,
6
+ ResolveUseSearch,
7
+ StrictOrFrom,
8
+ ThrowConstraint,
9
+ ThrowOrOptional,
10
+ UseSearchResult,
11
+ } from '@benjavicente/router-core'
12
+
13
+ export interface InjectSearchBaseOptions<
14
+ TRouter extends AnyRouter,
15
+ TFrom,
16
+ TStrict extends boolean,
17
+ TThrow extends boolean,
18
+ TSelected,
19
+ > {
20
+ select?: (state: ResolveUseSearch<TRouter, TFrom, TStrict>) => TSelected
21
+ shouldThrow?: TThrow
22
+ }
23
+
24
+ export type InjectSearchOptions<
25
+ TRouter extends AnyRouter,
26
+ TFrom,
27
+ TStrict extends boolean,
28
+ TThrow extends boolean,
29
+ TSelected,
30
+ > = StrictOrFrom<TRouter, TFrom, TStrict> &
31
+ InjectSearchBaseOptions<TRouter, TFrom, TStrict, TThrow, TSelected>
32
+
33
+ export type InjectSearchRoute<out TFrom> = <
34
+ TRouter extends AnyRouter = RegisteredRouter,
35
+ TSelected = unknown,
36
+ >(
37
+ opts?: InjectSearchBaseOptions<
38
+ TRouter,
39
+ TFrom,
40
+ /* TStrict */ true,
41
+ /* TThrow */ true,
42
+ TSelected
43
+ >,
44
+ ) => Angular.Signal<UseSearchResult<TRouter, TFrom, true, TSelected>>
45
+
46
+ export function injectSearch<
47
+ TRouter extends AnyRouter = RegisteredRouter,
48
+ const TFrom extends string | undefined = undefined,
49
+ TStrict extends boolean = true,
50
+ TThrow extends boolean = true,
51
+ TSelected = unknown,
52
+ >(
53
+ opts: InjectSearchOptions<
54
+ TRouter,
55
+ TFrom,
56
+ TStrict,
57
+ ThrowConstraint<TStrict, TThrow>,
58
+ TSelected
59
+ >,
60
+ ): Angular.Signal<
61
+ ThrowOrOptional<UseSearchResult<TRouter, TFrom, TStrict, TSelected>, TThrow>
62
+ > {
63
+ return injectMatch({
64
+ from: opts.from!,
65
+ strict: opts.strict,
66
+ shouldThrow: opts.shouldThrow,
67
+ select: (match: any) => {
68
+ return opts.select ? opts.select(match.search) : match.search
69
+ },
70
+ } as any) as any
71
+ }