@tanstack/react-router 1.49.8 → 1.50.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.49.8",
3
+ "version": "1.50.1",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
package/src/Matches.tsx CHANGED
@@ -25,10 +25,109 @@ import type {
25
25
  RouteIds,
26
26
  RoutePaths,
27
27
  } from './routeInfo'
28
- import type { ControlledPromise, DeepPartial, NoInfer } from './utils'
28
+ import type {
29
+ Constrain,
30
+ ControlledPromise,
31
+ DeepPartial,
32
+ NoInfer,
33
+ } from './utils'
34
+
35
+ export type AnyMatchAndValue = { match: any; value: any }
36
+
37
+ export type FindValueByIndex<
38
+ TKey,
39
+ TValue extends ReadonlyArray<any>,
40
+ > = TKey extends `${infer TIndex extends number}` ? TValue[TIndex] : never
41
+
42
+ export type FindValueByKey<TKey, TValue> =
43
+ TValue extends ReadonlyArray<any>
44
+ ? FindValueByIndex<TKey, TValue>
45
+ : TValue[TKey & keyof TValue]
46
+
47
+ export type CreateMatchAndValue<TMatch, TValue> = TValue extends any
48
+ ? {
49
+ match: TMatch
50
+ value: TValue
51
+ }
52
+ : never
53
+
54
+ export type NextMatchAndValue<
55
+ TKey,
56
+ TMatchAndValue extends AnyMatchAndValue,
57
+ > = TMatchAndValue extends any
58
+ ? CreateMatchAndValue<
59
+ TMatchAndValue['match'],
60
+ FindValueByKey<TKey, TMatchAndValue['value']>
61
+ >
62
+ : never
63
+
64
+ export type IsMatchKeyOf<TValue> =
65
+ TValue extends ReadonlyArray<any>
66
+ ? number extends TValue['length']
67
+ ? `${number}`
68
+ : keyof TValue & `${number}`
69
+ : TValue extends object
70
+ ? keyof TValue & string
71
+ : never
72
+
73
+ export type IsMatchPath<
74
+ TParentPath extends string,
75
+ TMatchAndValue extends AnyMatchAndValue,
76
+ > = `${TParentPath}${IsMatchKeyOf<TMatchAndValue['value']>}`
77
+
78
+ export type IsMatchResult<
79
+ TKey,
80
+ TMatchAndValue extends AnyMatchAndValue,
81
+ > = TMatchAndValue extends any
82
+ ? TKey extends keyof TMatchAndValue['value']
83
+ ? TMatchAndValue['match']
84
+ : never
85
+ : never
86
+
87
+ export type IsMatchParse<
88
+ TPath,
89
+ TMatchAndValue extends AnyMatchAndValue,
90
+ TParentPath extends string = '',
91
+ > = TPath extends `${string}.${string}`
92
+ ? TPath extends `${infer TFirst}.${infer TRest}`
93
+ ? IsMatchParse<
94
+ TRest,
95
+ NextMatchAndValue<TFirst, TMatchAndValue>,
96
+ `${TParentPath}${TFirst}.`
97
+ >
98
+ : never
99
+ : {
100
+ path: IsMatchPath<TParentPath, TMatchAndValue>
101
+ result: IsMatchResult<TPath, TMatchAndValue>
102
+ }
103
+
104
+ export type IsMatch<TMatch, TPath> = IsMatchParse<
105
+ TPath,
106
+ TMatch extends any ? { match: TMatch; value: TMatch } : never
107
+ >
108
+
109
+ /**
110
+ * Narrows matches based on a path
111
+ * @experimental
112
+ */
113
+ export const isMatch = <TMatch, TPath extends string>(
114
+ match: TMatch,
115
+ path: Constrain<TPath, IsMatch<TMatch, TPath>['path']>,
116
+ ): match is IsMatch<TMatch, TPath>['result'] => {
117
+ const parts = (path as string).split('.')
118
+ let part
119
+ let value: any = match
120
+
121
+ while ((part = parts.shift()) != null && value != null) {
122
+ value = value[part]
123
+ }
124
+
125
+ return value != null
126
+ }
29
127
 
30
128
  export interface RouteMatch<
31
129
  TRouteId,
130
+ TFullPath,
32
131
  TAllParams,
33
132
  TFullSearchSchema,
34
133
  TLoaderData,
@@ -37,6 +136,7 @@ export interface RouteMatch<
37
136
  > {
38
137
  id: string
39
138
  routeId: TRouteId
139
+ fullPath: TFullPath
40
140
  index: number
41
141
  pathname: string
42
142
  params: TAllParams
@@ -76,6 +176,7 @@ export type MakeRouteMatch<
76
176
  TRouteId = ParseRoute<TRouteTree>['id'],
77
177
  TStrict extends boolean = true,
78
178
  TTypes extends AnyRoute['types'] = RouteById<TRouteTree, TRouteId>['types'],
179
+ TFullPath = TTypes['fullPath'],
79
180
  TAllParams = TStrict extends false
80
181
  ? AllParams<TRouteTree>
81
182
  : TTypes['allParams'],
@@ -91,6 +192,7 @@ export type MakeRouteMatch<
91
192
  TLoaderDeps = TTypes['loaderDeps'],
92
193
  > = RouteMatch<
93
194
  TRouteId,
195
+ TFullPath,
94
196
  TAllParams,
95
197
  TFullSearchSchema,
96
198
  TLoaderData,
@@ -98,7 +200,7 @@ export type MakeRouteMatch<
98
200
  TLoaderDeps
99
201
  >
100
202
 
101
- export type AnyRouteMatch = RouteMatch<any, any, any, any, any, any>
203
+ export type AnyRouteMatch = RouteMatch<any, any, any, any, any, any, any>
102
204
 
103
205
  export function Matches() {
104
206
  const router = useRouter()
@@ -254,10 +356,24 @@ export function MatchRoute<
254
356
  return params ? props.children : null
255
357
  }
256
358
 
359
+ export type MakeRouteMatches<
360
+ TRouter extends AnyRouter = AnyRouter,
361
+ TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>,
362
+ > = TRoute extends any
363
+ ? RouteMatch<
364
+ TRoute['id'],
365
+ TRoute['fullPath'],
366
+ TRoute['types']['allParams'],
367
+ TRoute['types']['fullSearchSchema'],
368
+ TRoute['types']['loaderData'],
369
+ TRoute['types']['allContext'],
370
+ TRoute['types']['loaderDeps']
371
+ >
372
+ : never
373
+
257
374
  export function useMatches<
258
- TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
259
- TRouteId extends RouteIds<TRouteTree> = ParseRoute<TRouteTree>['id'],
260
- TRouteMatch = MakeRouteMatch<TRouteTree, TRouteId>,
375
+ TRouter extends AnyRouter = RegisteredRouter,
376
+ TRouteMatch = MakeRouteMatches<TRouter>,
261
377
  T = Array<TRouteMatch>,
262
378
  >(opts?: { select?: (matches: Array<TRouteMatch>) => T }): T {
263
379
  return useRouterState({
package/src/fileRoute.ts CHANGED
@@ -88,6 +88,7 @@ export class FileRoute<
88
88
  UpdatableRouteOptions<
89
89
  TParentRoute,
90
90
  TId,
91
+ TFullPath,
91
92
  TParams,
92
93
  TSearchValidator,
93
94
  TLoaderFn,
@@ -155,6 +156,7 @@ export type LazyRouteOptions = Pick<
155
156
  UpdatableRouteOptions<
156
157
  AnyRoute,
157
158
  string,
159
+ string,
158
160
  AnyPathParams,
159
161
  AnySearchValidator,
160
162
  {},
package/src/index.tsx CHANGED
@@ -80,6 +80,7 @@ export {
80
80
  useMatches,
81
81
  useParentMatches,
82
82
  useChildMatches,
83
+ isMatch,
83
84
  } from './Matches'
84
85
  export type {
85
86
  RouteMatch,
package/src/link.tsx CHANGED
@@ -16,12 +16,15 @@ import type { HistoryState } from '@tanstack/history'
16
16
  import type {
17
17
  AllParams,
18
18
  CatchAllPaths,
19
+ CurrentPath,
19
20
  FullSearchSchema,
20
21
  FullSearchSchemaInput,
22
+ ParentPath,
21
23
  RouteByPath,
22
24
  RouteByToPath,
23
25
  RoutePaths,
24
26
  RouteToPath,
27
+ TrailingSlashOptionByRouter,
25
28
  } from './routeInfo'
26
29
  import type { RegisteredRouter } from './router'
27
30
  import type {
@@ -121,7 +124,7 @@ export type SearchRelativePathAutoComplete<
121
124
  TRouter extends AnyRouter,
122
125
  TTo extends string,
123
126
  TSearchPath extends string,
124
- > = `${TTo}/${RemoveLeadingSlashes<SearchPaths<TRouter, TSearchPath>>}`
127
+ > = `${TTo}${SearchPaths<TRouter, TSearchPath>}`
125
128
 
126
129
  export type RelativeToParentPathAutoComplete<
127
130
  TRouter extends AnyRouter,
@@ -132,15 +135,15 @@ export type RelativeToParentPathAutoComplete<
132
135
  >,
133
136
  > =
134
137
  | SearchRelativePathAutoComplete<TRouter, TTo, TResolvedPath>
135
- | (TResolvedPath extends '' ? never : `${TTo}/../`)
138
+ | (TResolvedPath extends ''
139
+ ? never
140
+ : `${TTo}/${ParentPath<TrailingSlashOptionByRouter<TRouter>>}`)
136
141
 
137
142
  export type RelativeToCurrentPathAutoComplete<
138
143
  TRouter extends AnyRouter,
139
144
  TFrom extends string,
140
145
  TTo extends string,
141
- TRestTo extends string,
142
- TResolvedPath extends
143
- string = RemoveTrailingSlashes<`${RemoveTrailingSlashes<TFrom>}/${RemoveLeadingSlashes<TRestTo>}`>,
146
+ TResolvedPath extends string = ResolveRelativePath<TFrom, TTo>,
144
147
  > = SearchRelativePathAutoComplete<TRouter, TTo, TResolvedPath>
145
148
 
146
149
  export type AbsolutePathAutoComplete<
@@ -148,13 +151,17 @@ export type AbsolutePathAutoComplete<
148
151
  TFrom extends string,
149
152
  > =
150
153
  | (string extends TFrom
151
- ? './'
154
+ ? CurrentPath<TrailingSlashOptionByRouter<TRouter>>
152
155
  : TFrom extends `/`
153
156
  ? never
154
157
  : SearchPaths<TRouter, TFrom> extends ''
155
158
  ? never
156
- : './')
157
- | (string extends TFrom ? '../' : TFrom extends `/` ? never : '../')
159
+ : CurrentPath<TrailingSlashOptionByRouter<TRouter>>)
160
+ | (string extends TFrom
161
+ ? ParentPath<TrailingSlashOptionByRouter<TRouter>>
162
+ : TFrom extends `/`
163
+ ? never
164
+ : ParentPath<TrailingSlashOptionByRouter<TRouter>>)
158
165
  | RouteToPath<TRouter, TRouter['routeTree']>
159
166
  | (TFrom extends '/'
160
167
  ? never
@@ -168,12 +175,11 @@ export type RelativeToPathAutoComplete<
168
175
  TTo extends string,
169
176
  > = TTo extends `..${string}`
170
177
  ? RelativeToParentPathAutoComplete<TRouter, TFrom, RemoveTrailingSlashes<TTo>>
171
- : TTo extends `./${infer TRestTTo}`
178
+ : TTo extends `.${string}`
172
179
  ? RelativeToCurrentPathAutoComplete<
173
180
  TRouter,
174
181
  TFrom,
175
- RemoveTrailingSlashes<TTo>,
176
- TRestTTo
182
+ RemoveTrailingSlashes<TTo>
177
183
  >
178
184
  : AbsolutePathAutoComplete<TRouter, TFrom>
179
185
 
@@ -312,7 +318,7 @@ export type ResolveToParams<
312
318
  ResolveRelativePath<TFrom, TTo> extends infer TPath
313
319
  ? string extends TPath
314
320
  ? ResolveAllToParams<TRouter, TParamVariant>
315
- : TPath extends CatchAllPaths
321
+ : TPath extends CatchAllPaths<TrailingSlashOptionByRouter<TRouter>>
316
322
  ? ResolveAllToParams<TRouter, TParamVariant>
317
323
  : ResolveRoute<
318
324
  TRouter,
@@ -397,7 +403,7 @@ export type IsRequired<
397
403
  ResolveRelativePath<TFrom, TTo> extends infer TPath
398
404
  ? string extends TPath
399
405
  ? never
400
- : TPath extends CatchAllPaths
406
+ : TPath extends CatchAllPaths<TrailingSlashOptionByRouter<TRouter>>
401
407
  ? never
402
408
  : IsRequiredParams<
403
409
  ResolveRelativeToParams<TRouter, TParamVariant, TFrom, TTo>
@@ -501,7 +507,9 @@ export interface LinkOptionsProps {
501
507
  export type CheckPath<TRouter extends AnyRouter, TPass, TFail, TFrom, TTo> =
502
508
  string extends ResolveRelativePath<TFrom, TTo>
503
509
  ? TPass
504
- : ResolveRelativePath<TFrom, TTo> extends CatchAllPaths
510
+ : ResolveRelativePath<TFrom, TTo> extends CatchAllPaths<
511
+ TrailingSlashOptionByRouter<TRouter>
512
+ >
505
513
  ? TPass
506
514
  : ResolveRoute<TRouter, TFrom, TTo> extends never
507
515
  ? TFail
package/src/route.ts CHANGED
@@ -53,6 +53,7 @@ export type RoutePathOptionsIntersection<TCustomId, TPath> = {
53
53
  export type RouteOptions<
54
54
  TParentRoute extends AnyRoute = AnyRoute,
55
55
  TCustomId extends string = string,
56
+ TFullPath extends string = string,
56
57
  TPath extends string = string,
57
58
  TSearchValidator = undefined,
58
59
  TParams = AnyPathParams,
@@ -76,6 +77,7 @@ export type RouteOptions<
76
77
  UpdatableRouteOptions<
77
78
  NoInfer<TParentRoute>,
78
79
  NoInfer<TCustomId>,
80
+ NoInfer<TFullPath>,
79
81
  NoInfer<TParams>,
80
82
  NoInfer<TSearchValidator>,
81
83
  NoInfer<TLoaderFn>,
@@ -309,6 +311,7 @@ export interface BeforeLoadContextOptions<
309
311
  export interface UpdatableRouteOptions<
310
312
  in out TParentRoute extends AnyRoute,
311
313
  in out TRouteId,
314
+ in out TFullPath,
312
315
  in out TParams,
313
316
  in out TSearchValidator,
314
317
  in out TLoaderFn,
@@ -351,6 +354,7 @@ export interface UpdatableRouteOptions<
351
354
  onEnter?: (
352
355
  match: RouteMatch<
353
356
  TRouteId,
357
+ TFullPath,
354
358
  ResolveAllParamsFromParent<TParentRoute, TParams>,
355
359
  ResolveFullSearchSchema<TParentRoute, TSearchValidator>,
356
360
  ResolveLoaderData<TLoaderFn>,
@@ -366,6 +370,7 @@ export interface UpdatableRouteOptions<
366
370
  onStay?: (
367
371
  match: RouteMatch<
368
372
  TRouteId,
373
+ TFullPath,
369
374
  ResolveAllParamsFromParent<TParentRoute, TParams>,
370
375
  ResolveFullSearchSchema<TParentRoute, TSearchValidator>,
371
376
  ResolveLoaderData<TLoaderFn>,
@@ -381,6 +386,7 @@ export interface UpdatableRouteOptions<
381
386
  onLeave?: (
382
387
  match: RouteMatch<
383
388
  TRouteId,
389
+ TFullPath,
384
390
  ResolveAllParamsFromParent<TParentRoute, TParams>,
385
391
  ResolveFullSearchSchema<TParentRoute, TSearchValidator>,
386
392
  ResolveLoaderData<TLoaderFn>,
@@ -397,6 +403,7 @@ export interface UpdatableRouteOptions<
397
403
  matches: Array<
398
404
  RouteMatch<
399
405
  TRouteId,
406
+ TFullPath,
400
407
  ResolveAllParamsFromParent<TParentRoute, TParams>,
401
408
  ResolveFullSearchSchema<TParentRoute, TSearchValidator>,
402
409
  ResolveLoaderData<TLoaderFn>,
@@ -411,6 +418,7 @@ export interface UpdatableRouteOptions<
411
418
  >
412
419
  match: RouteMatch<
413
420
  TRouteId,
421
+ TFullPath,
414
422
  ResolveAllParamsFromParent<TParentRoute, TParams>,
415
423
  ResolveFullSearchSchema<TParentRoute, TSearchValidator>,
416
424
  ResolveLoaderData<TLoaderFn>,
@@ -860,6 +868,7 @@ export class Route<
860
868
  options: RouteOptions<
861
869
  TParentRoute,
862
870
  TCustomId,
871
+ TFullPath,
863
872
  TPath,
864
873
  TSearchValidator,
865
874
  TParams,
@@ -893,6 +902,7 @@ export class Route<
893
902
  options?: RouteOptions<
894
903
  TParentRoute,
895
904
  TCustomId,
905
+ TFullPath,
896
906
  TPath,
897
907
  TSearchValidator,
898
908
  TParams,
@@ -952,6 +962,7 @@ export class Route<
952
962
  | (RouteOptions<
953
963
  TParentRoute,
954
964
  TCustomId,
965
+ TFullPath,
955
966
  TPath,
956
967
  TSearchValidator,
957
968
  TParams,
@@ -1075,6 +1086,7 @@ export class Route<
1075
1086
  options: UpdatableRouteOptions<
1076
1087
  TParentRoute,
1077
1088
  TCustomId,
1089
+ TFullPath,
1078
1090
  TParams,
1079
1091
  TSearchValidator,
1080
1092
  TLoaderFn,
@@ -1193,6 +1205,7 @@ export function createRoute<
1193
1205
  options: RouteOptions<
1194
1206
  TParentRoute,
1195
1207
  TCustomId,
1208
+ TFullPath,
1196
1209
  TPath,
1197
1210
  TSearchValidator,
1198
1211
  TParams,
@@ -1232,7 +1245,8 @@ export type RootRouteOptions<
1232
1245
  > = Omit<
1233
1246
  RouteOptions<
1234
1247
  any, // TParentRoute
1235
- RootRouteId, // TCustomId
1248
+ RootRouteId,
1249
+ '', // TCustomId
1236
1250
  '', // TPath
1237
1251
  TSearchValidator,
1238
1252
  {}, // TParams
@@ -1495,6 +1509,7 @@ export class NotFoundRoute<
1495
1509
  TParentRoute,
1496
1510
  string,
1497
1511
  string,
1512
+ string,
1498
1513
  TSearchValidator,
1499
1514
  {},
1500
1515
  TLoaderDeps,
package/src/routeInfo.ts CHANGED
@@ -41,7 +41,22 @@ export type RouteById<TRouteTree extends AnyRoute, TId> = Extract<
41
41
 
42
42
  export type RouteIds<TRouteTree extends AnyRoute> = ParseRoute<TRouteTree>['id']
43
43
 
44
- export type CatchAllPaths = '.' | '..' | ''
44
+ export type ParentPath<TOption> = 'always' extends TOption
45
+ ? '../'
46
+ : 'never' extends TOption
47
+ ? '..'
48
+ : '../' | '..'
49
+
50
+ export type CurrentPath<TOption> = 'always' extends TOption
51
+ ? './'
52
+ : 'never' extends TOption
53
+ ? '.'
54
+ : './' | '.'
55
+
56
+ export type CatchAllPaths<TOption> =
57
+ | CurrentPath<TOption>
58
+ | ParentPath<TOption>
59
+ | ''
45
60
 
46
61
  export type RoutesByPath<TRouteTree extends AnyRoute> = {
47
62
  [K in ParseRoute<TRouteTree> as K['fullPath']]: K
package/src/router.ts CHANGED
@@ -1210,6 +1210,7 @@ export class Router<
1210
1210
  scripts: route.options.scripts?.(),
1211
1211
  staticData: route.options.staticData || {},
1212
1212
  loadPromise: createControlledPromise(),
1213
+ fullPath: route.fullPath,
1213
1214
  }
1214
1215
  }
1215
1216