@tanstack/react-router 1.17.4 → 1.17.5

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/src/link.tsx CHANGED
@@ -4,7 +4,7 @@ import { useRouterState } from './useRouterState'
4
4
  import { useRouter } from './useRouter'
5
5
  import { Trim } from './fileRoute'
6
6
  import { AnyRoute, ReactNode, RootSearchSchema } from './route'
7
- import { RouteByPath, RouteIds, RoutePaths } from './routeInfo'
7
+ import { RouteByPath, RoutePaths, RoutePathsAutoComplete } from './routeInfo'
8
8
  import { RegisteredRouter } from './router'
9
9
  import { LinkProps, UseLinkPropsOptions } from './useNavigate'
10
10
  import {
@@ -14,7 +14,6 @@ import {
14
14
  NoInfer,
15
15
  NonNullableUpdater,
16
16
  PickRequired,
17
- StringLiteral,
18
17
  Updater,
19
18
  WithoutEmpty,
20
19
  deepEqual,
@@ -70,62 +69,81 @@ export type Join<T, Delimiter extends string = '/'> = T extends []
70
69
 
71
70
  export type Last<T extends any[]> = T extends [...infer _, infer L] ? L : never
72
71
 
72
+ export type RemoveTrailingSlashes<T> = T extends `${infer R}/`
73
+ ? RemoveTrailingSlashes<R>
74
+ : T
75
+
76
+ export type RemoveLeadingSlashes<T> = T extends `/${infer R}`
77
+ ? RemoveLeadingSlashes<R>
78
+ : T
79
+
80
+ export type SearchPaths<
81
+ TPaths,
82
+ TSearchPath extends string,
83
+ > = TPaths extends `${TSearchPath}/${infer TRest}` ? TRest : never
84
+
85
+ export type SearchRelativePathAutoComplete<
86
+ TTo extends string,
87
+ TSearchPath extends string,
88
+ TPaths,
89
+ SearchedPaths = SearchPaths<TPaths, TSearchPath>,
90
+ > = SearchedPaths extends string ? `${TTo}/${SearchedPaths}` : never
91
+
92
+ export type RelativeToParentPathAutoComplete<
93
+ TFrom extends string,
94
+ TTo extends string,
95
+ TPaths,
96
+ TResolvedPath extends string = RemoveTrailingSlashes<
97
+ ResolveRelativePath<TFrom, TTo>
98
+ >,
99
+ > =
100
+ | SearchRelativePathAutoComplete<TTo, TResolvedPath, TPaths>
101
+ | (TResolvedPath extends '' ? never : `${TTo}/../`)
102
+
103
+ export type RelativeToCurrentPathAutoComplete<
104
+ TFrom extends string,
105
+ TTo extends string,
106
+ TRestTo extends string,
107
+ TPaths,
108
+ TResolvedPath extends
109
+ string = RemoveTrailingSlashes<`${RemoveTrailingSlashes<TFrom>}/${RemoveLeadingSlashes<TRestTo>}`>,
110
+ > = SearchRelativePathAutoComplete<TTo, TResolvedPath, TPaths>
111
+
112
+ export type AbsolutePathAutoComplete<TFrom extends string, TPaths> =
113
+ | (string extends TFrom
114
+ ? never
115
+ : TFrom extends `/`
116
+ ? never
117
+ : SearchPaths<
118
+ TPaths,
119
+ RemoveTrailingSlashes<TFrom>
120
+ > extends infer SearchedPaths
121
+ ? SearchedPaths extends ''
122
+ ? never
123
+ : './'
124
+ : never)
125
+ | (string extends TFrom ? never : TFrom extends `/` ? never : '../')
126
+ | TPaths
127
+
73
128
  export type RelativeToPathAutoComplete<
74
- AllPaths extends string,
129
+ TRouteTree extends AnyRoute,
75
130
  TFrom extends string,
76
131
  TTo extends string,
77
- > = TTo extends `..${infer _}`
78
- ? Split<AllPaths, false> extends infer SplitPaths
79
- ? SplitPaths extends [
80
- ...Split<ResolveRelativePath<TFrom, TTo>, false>,
81
- ...infer TToRest,
82
- ]
83
- ? `${CleanPath<
84
- Join<
85
- [
86
- ...Split<TTo, false>,
87
- ...(
88
- | TToRest
89
- | (Split<
90
- ResolveRelativePath<TFrom, TTo>,
91
- false
92
- >['length'] extends 1
93
- ? never
94
- : ['../'])
95
- ),
96
- ]
97
- >
98
- >}`
99
- : never
100
- : never
101
- : TTo extends `./${infer RestTTo}`
102
- ? Split<AllPaths, false> extends infer SplitPaths
103
- ? SplitPaths extends [
104
- ...Split<TFrom, false>,
105
- ...Split<RestTTo, false>,
106
- ...infer RestPath,
107
- ]
108
- ? `${TTo}${Join<RestPath>}`
109
- : never
110
- : never
111
- :
112
- | (string extends TFrom
113
- ? '/'
114
- : TFrom extends `/`
115
- ? never
116
- : Split<AllPaths, false> extends infer SplitPaths
117
- ? SplitPaths extends [...Split<TFrom, false>, ...infer RestPath]
118
- ? Join<RestPath> extends { length: 0 }
119
- ? never
120
- : './'
121
- : never
122
- : never)
123
- | (string extends TFrom ? '../' : TFrom extends `/` ? never : '../')
124
- | AllPaths
132
+ TPaths = RoutePaths<TRouteTree>,
133
+ > = TTo extends `..${string}`
134
+ ? RelativeToParentPathAutoComplete<TFrom, RemoveTrailingSlashes<TTo>, TPaths>
135
+ : TTo extends `./${infer TRestTTo}`
136
+ ? RelativeToCurrentPathAutoComplete<
137
+ TFrom,
138
+ RemoveTrailingSlashes<TTo>,
139
+ TRestTTo,
140
+ TPaths
141
+ >
142
+ : AbsolutePathAutoComplete<TFrom, TPaths>
125
143
 
126
144
  export type NavigateOptions<
127
145
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
128
- TFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
146
+ TFrom extends RoutePaths<TRouteTree> | string = string,
129
147
  TTo extends string = '',
130
148
  TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
131
149
  TMaskTo extends string = '',
@@ -139,7 +157,7 @@ export type NavigateOptions<
139
157
 
140
158
  export type ToOptions<
141
159
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
142
- TFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
160
+ TFrom extends RoutePaths<TRouteTree> | string = string,
143
161
  TTo extends string = '',
144
162
  TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
145
163
  TMaskTo extends string = '',
@@ -149,7 +167,7 @@ export type ToOptions<
149
167
 
150
168
  export type ToMaskOptions<
151
169
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
152
- TMaskFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
170
+ TMaskFrom extends RoutePaths<TRouteTree> | string = string,
153
171
  TMaskTo extends string = '',
154
172
  > = ToSubOptions<TRouteTree, TMaskFrom, TMaskTo> & {
155
173
  unmaskOnReload?: boolean
@@ -157,9 +175,8 @@ export type ToMaskOptions<
157
175
 
158
176
  export type ToSubOptions<
159
177
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
160
- TFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
178
+ TFrom extends RoutePaths<TRouteTree> | string = string,
161
179
  TTo extends string = '',
162
- TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>,
163
180
  > = {
164
181
  to?: ToPathOption<TRouteTree, TFrom, TTo>
165
182
  // The new has string or a function to update it
@@ -167,11 +184,11 @@ export type ToSubOptions<
167
184
  // State to pass to the history stack
168
185
  state?: true | NonNullableUpdater<HistoryState>
169
186
  // The source route path. This is automatically set when using route-level APIs, but for type-safe relative routing on the router itself, this is required
170
- from?: StringLiteral<TFrom>
187
+ from?: RoutePathsAutoComplete<TRouteTree, TFrom>
171
188
  // // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
172
- } & CheckPath<TRouteTree, NoInfer<TResolved>, {}> &
173
- SearchParamOptions<TRouteTree, TFrom, TTo, TResolved> &
174
- PathParamOptions<TRouteTree, TFrom, TTo, TResolved>
189
+ } & CheckPath<TRouteTree, {}, TFrom, TTo> &
190
+ SearchParamOptions<TRouteTree, TFrom, TTo> &
191
+ PathParamOptions<TRouteTree, TFrom, TTo>
175
192
 
176
193
  type ParamsReducer<TFrom, TTo> = TTo | ((current: TFrom) => TTo)
177
194
 
@@ -182,6 +199,18 @@ type ExcludeRootSearchSchema<T, Excluded = Exclude<T, RootSearchSchema>> = [
182
199
  ? {}
183
200
  : Excluded
184
201
 
202
+ export type ResolveRoute<
203
+ TRouteTree extends AnyRoute,
204
+ TFrom,
205
+ TTo,
206
+ TPath = RemoveTrailingSlashes<
207
+ string extends TTo ? TFrom : ResolveRelativePath<TFrom, TTo>
208
+ >,
209
+ > =
210
+ RouteByPath<TRouteTree, `${TPath & string}/`> extends never
211
+ ? RouteByPath<TRouteTree, TPath>
212
+ : RouteByPath<TRouteTree, `${TPath & string}/`>
213
+
185
214
  type PostProcessParams<
186
215
  T,
187
216
  TParamVariant extends ParamVariant,
@@ -191,7 +220,6 @@ export type ParamOptions<
191
220
  TRouteTree extends AnyRoute,
192
221
  TFrom,
193
222
  TTo extends string,
194
- TResolved,
195
223
  TParamVariant extends ParamVariant,
196
224
  TFromRouteType extends
197
225
  | 'allParams'
@@ -207,25 +235,10 @@ export type ParamOptions<
207
235
  RouteByPath<TRouteTree, TFrom>['types'][TFromRouteType],
208
236
  TParamVariant
209
237
  >,
210
- TToIndex = TTo extends ''
211
- ? ''
212
- : RouteByPath<TRouteTree, `${TTo}/`> extends never
213
- ? TTo
214
- : `${TTo}/`,
215
- TToParams = TToIndex extends ''
216
- ? PostProcessParams<
217
- RouteByPath<TRouteTree, TFrom>['types'][TToRouteType],
218
- TParamVariant
219
- >
220
- : [TResolved] extends [never]
221
- ? PostProcessParams<
222
- RouteByPath<TRouteTree, TToIndex>['types'][TToRouteType],
223
- TParamVariant
224
- >
225
- : PostProcessParams<
226
- RouteByPath<TRouteTree, TResolved>['types'][TToRouteType],
227
- TParamVariant
228
- >,
238
+ TToParams = PostProcessParams<
239
+ ResolveRoute<TRouteTree, TFrom, TTo>['types'][TToRouteType],
240
+ TParamVariant
241
+ >,
229
242
  TRelativeToParams = TParamVariant extends 'SEARCH'
230
243
  ? TToParams
231
244
  : true extends IsUnion<TFromParams>
@@ -252,15 +265,13 @@ export type SearchParamOptions<
252
265
  TRouteTree extends AnyRoute,
253
266
  TFrom,
254
267
  TTo extends string,
255
- TResolved,
256
- > = ParamOptions<TRouteTree, TFrom, TTo, TResolved, 'SEARCH'>
268
+ > = ParamOptions<TRouteTree, TFrom, TTo, 'SEARCH'>
257
269
 
258
270
  export type PathParamOptions<
259
271
  TRouteTree extends AnyRoute,
260
272
  TFrom,
261
273
  TTo extends string,
262
- TResolved,
263
- > = ParamOptions<TRouteTree, TFrom, TTo, TResolved, 'PATH'>
274
+ > = ParamOptions<TRouteTree, TFrom, TTo, 'PATH'>
264
275
 
265
276
  export type ToPathOption<
266
277
  TRouteTree extends AnyRoute = AnyRoute,
@@ -269,7 +280,7 @@ export type ToPathOption<
269
280
  > =
270
281
  | TTo
271
282
  | RelativeToPathAutoComplete<
272
- RoutePaths<TRouteTree>,
283
+ TRouteTree,
273
284
  NoInfer<TFrom> extends string ? NoInfer<TFrom> : '',
274
285
  NoInfer<TTo> & string
275
286
  >
@@ -299,12 +310,12 @@ export type LinkOptions<
299
310
  disabled?: boolean
300
311
  }
301
312
 
302
- export type CheckPath<TRouteTree extends AnyRoute, TPath, TPass> =
303
- Exclude<TPath, RoutePaths<TRouteTree>> extends never
304
- ? TPass
305
- : CheckPathError<TRouteTree, Exclude<TPath, RoutePaths<TRouteTree>>>
313
+ export type CheckPath<TRouteTree extends AnyRoute, TPass, TFrom, TTo> =
314
+ ResolveRoute<TRouteTree, TFrom, TTo> extends never
315
+ ? CheckPathError<TRouteTree>
316
+ : TPass
306
317
 
307
- export type CheckPathError<TRouteTree extends AnyRoute, TInvalids> = {
318
+ export type CheckPathError<TRouteTree extends AnyRoute> = {
308
319
  to: RoutePaths<TRouteTree>
309
320
  }
310
321
 
@@ -321,7 +332,7 @@ export type ResolveRelativePath<TFrom, TTo = '.'> = TFrom extends string
321
332
  : Split<TTo> extends ['..', ...infer ToRest]
322
333
  ? Split<TFrom> extends [...infer FromRest, infer FromTail]
323
334
  ? ToRest extends ['/']
324
- ? Join<[...FromRest, '/']>
335
+ ? Join<['/', ...FromRest, '/']>
325
336
  : ResolveRelativePath<Join<FromRest>, Join<ToRest>>
326
337
  : never
327
338
  : Split<TTo> extends ['.', ...infer ToRest]
package/src/route.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react'
2
2
  import invariant from 'tiny-invariant'
3
- import { useLoaderData, useLoaderDeps, useMatch } from './Matches'
3
+ import { useLoaderData, useLoaderDeps, useMatch, RouteMatch } from './Matches'
4
4
  import { AnyRouteMatch } from './Matches'
5
5
  import { NavigateOptions, ParsePathParams, ToSubOptions } from './link'
6
6
  import { ParsedLocation } from './location'
@@ -180,7 +180,7 @@ type BeforeLoadFn<
180
180
  params: TAllParams
181
181
  context: TContext
182
182
  location: ParsedLocation
183
- navigate: NavigateFn<AnyRoute>
183
+ navigate: NavigateFn
184
184
  buildLocation: BuildLocationFn<TParentRoute>
185
185
  cause: 'preload' | 'enter' | 'stay'
186
186
  }) => Promise<TRouteContextReturn> | TRouteContextReturn | void
@@ -551,8 +551,12 @@ export class RouteApi<
551
551
  this.id = id as any
552
552
  }
553
553
 
554
- useMatch = <TSelected = TAllContext>(opts?: {
555
- select?: (s: TAllContext) => TSelected
554
+ useMatch = <
555
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
556
+ TRouteMatchState = RouteMatch<TRouteTree, TId>,
557
+ TSelected = TRouteMatchState,
558
+ >(opts?: {
559
+ select?: (match: TRouteMatchState) => TSelected
556
560
  }): TSelected => {
557
561
  return useMatch({ select: opts?.select, from: this.id })
558
562
  }
@@ -600,7 +604,7 @@ export class RouteApi<
600
604
  */
601
605
  export class Route<
602
606
  TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute,
603
- TPath extends RouteConstraints['TPath'] = '/',
607
+ in out TPath extends RouteConstraints['TPath'] = '/',
604
608
  TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<
605
609
  TParentRoute,
606
610
  TPath
@@ -636,12 +640,12 @@ export class Route<
636
640
  TParams
637
641
  >,
638
642
  TRouteContextReturn extends RouteConstraints['TRouteContext'] = RouteContext,
639
- TRouteContext extends RouteConstraints['TRouteContext'] = [
643
+ in out TRouteContext extends RouteConstraints['TRouteContext'] = [
640
644
  TRouteContextReturn,
641
645
  ] extends [never]
642
646
  ? RouteContext
643
647
  : TRouteContextReturn,
644
- TAllContext extends Expand<
648
+ in out TAllContext extends Expand<
645
649
  Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>
646
650
  > = Expand<
647
651
  Assign<IsAny<TParentRoute['types']['allContext'], {}>, TRouteContext>
@@ -886,8 +890,12 @@ export class Route<
886
890
  return this
887
891
  }
888
892
 
889
- useMatch = <TSelected = TAllContext>(opts?: {
890
- select?: (search: TAllContext) => TSelected
893
+ useMatch = <
894
+ TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
895
+ TRouteMatchState = RouteMatch<TRouteTree, TId>,
896
+ TSelected = TRouteMatchState,
897
+ >(opts?: {
898
+ select?: (match: TRouteMatchState) => TSelected
891
899
  }): TSelected => {
892
900
  return useMatch({ ...opts, from: this.id })
893
901
  }
package/src/routeInfo.ts CHANGED
@@ -1,51 +1,21 @@
1
- import { AnyRoute, Route } from './route'
1
+ import { AnyRoute } from './route'
2
2
  import { Expand, UnionToIntersection, UnionToTuple } from './utils'
3
3
 
4
- export type ParseRoute<TRouteTree extends AnyRoute> =
5
- | TRouteTree
6
- | ParseRouteChildren<TRouteTree>
7
-
8
- export type ParseRouteChildren<TRouteTree extends AnyRoute> =
9
- TRouteTree extends Route<
10
- any,
11
- any,
12
- any,
13
- any,
14
- any,
15
- any,
16
- any,
17
- any,
18
- any,
19
- any,
20
- any,
21
- any,
22
- any,
23
- any,
24
- any,
25
- any,
26
- any,
27
- any,
28
- infer TChildren,
29
- any
30
- >
31
- ? unknown extends TChildren
32
- ? never
33
- : TChildren extends AnyRoute[]
34
- ? {
35
- [TId in TChildren[number]['id'] as string]: ParseRoute<
36
- TChildren[number]
37
- >
38
- }[string]
39
- : never
40
- : never
4
+ export type ParseRoute<TRouteTree, TAcc = TRouteTree> = TRouteTree extends {
5
+ types: { children: infer TChildren }
6
+ }
7
+ ? TChildren extends unknown[]
8
+ ? ParseRoute<TChildren[number], TAcc | TChildren[number]>
9
+ : TAcc
10
+ : TAcc
41
11
 
42
12
  export type RoutesById<TRouteTree extends AnyRoute> = {
43
13
  [K in ParseRoute<TRouteTree> as K['id']]: K
44
14
  }
45
15
 
46
16
  export type RouteById<TRouteTree extends AnyRoute, TId> = Extract<
47
- ParseRoute<TRouteTree>,
48
- { id: TId }
17
+ Extract<ParseRoute<TRouteTree>, { id: TId }>,
18
+ AnyRoute
49
19
  >
50
20
 
51
21
  export type RouteIds<TRouteTree extends AnyRoute> = ParseRoute<TRouteTree>['id']
@@ -55,14 +25,18 @@ export type RoutesByPath<TRouteTree extends AnyRoute> = {
55
25
  }
56
26
 
57
27
  export type RouteByPath<TRouteTree extends AnyRoute, TPath> = Extract<
58
- ParseRoute<TRouteTree>,
59
- { fullPath: TPath }
28
+ Extract<ParseRoute<TRouteTree>, { fullPath: TPath }>,
29
+ AnyRoute
60
30
  >
61
-
62
31
  export type RoutePaths<TRouteTree extends AnyRoute> =
63
32
  | ParseRoute<TRouteTree>['fullPath']
64
33
  | '/'
65
34
 
35
+ export type RoutePathsAutoComplete<TRouteTree extends AnyRoute, T> =
36
+ | T
37
+ | RoutePaths<TRouteTree>
38
+ | (string & {})
39
+
66
40
  type UnionizeCollisions<T, U> = {
67
41
  [P in keyof T & keyof U]: T[P] extends U[P] ? T[P] : T[P] | U[P]
68
42
  }
package/src/router.ts CHANGED
@@ -1067,7 +1067,7 @@ export class Router<
1067
1067
  })
1068
1068
  }
1069
1069
 
1070
- navigate: NavigateFn<TRouteTree> = ({ from, to, ...rest }) => {
1070
+ navigate: NavigateFn = ({ from, to, ...rest }) => {
1071
1071
  // If this link simply reloads the current route,
1072
1072
  // make sure it has a new key so it will trigger a data refresh
1073
1073
 
@@ -3,13 +3,13 @@ import { useMatch } from './Matches'
3
3
  import { useRouter } from './useRouter'
4
4
  import { LinkOptions, NavigateOptions } from './link'
5
5
  import { AnyRoute } from './route'
6
- import { RoutePaths } from './routeInfo'
6
+ import { RoutePaths, RoutePathsAutoComplete } from './routeInfo'
7
7
  import { RegisteredRouter } from './router'
8
8
 
9
9
  export type UseNavigateResult<TDefaultFrom extends string> = <
10
+ TTo extends string,
10
11
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
11
12
  TFrom extends RoutePaths<TRouteTree> | string = TDefaultFrom,
12
- TTo extends string = '',
13
13
  TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
14
14
  TMaskTo extends string = '',
15
15
  >({
@@ -20,10 +20,7 @@ export type UseNavigateResult<TDefaultFrom extends string> = <
20
20
  export function useNavigate<
21
21
  TDefaultFrom extends string = string,
22
22
  >(_defaultOpts?: {
23
- from?:
24
- | TDefaultFrom
25
- | RoutePaths<RegisteredRouter['routeTree']>
26
- | (string & {})
23
+ from?: RoutePathsAutoComplete<RegisteredRouter['routeTree'], TDefaultFrom>
27
24
  }) {
28
25
  const { navigate } = useRouter()
29
26