@tanstack/react-router 1.4.8 → 1.4.9

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,7 +1,7 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
3
  "author": "Tanner Linsley",
4
- "version": "1.4.8",
4
+ "version": "1.4.9",
5
5
  "license": "MIT",
6
6
  "repository": "tanstack/router",
7
7
  "homepage": "https://tanstack.com/router",
@@ -44,7 +44,7 @@
44
44
  "@tanstack/store": "^0.1.3",
45
45
  "tiny-invariant": "^1.3.1",
46
46
  "tiny-warning": "^1.0.3",
47
- "@tanstack/history": "1.4.8"
47
+ "@tanstack/history": "1.4.9"
48
48
  },
49
49
  "scripts": {
50
50
  "build": "rollup --config rollup.config.js"
package/src/Matches.tsx CHANGED
@@ -4,9 +4,8 @@ import warning from 'tiny-warning'
4
4
  import { CatchBoundary, ErrorComponent } from './CatchBoundary'
5
5
  import { useRouter, useRouterState } from './RouterProvider'
6
6
  import { ResolveRelativePath, ToOptions } from './link'
7
- import { AnyRoute, ReactNode, rootRouteId } from './route'
7
+ import { AnyRoute, ReactNode } from './route'
8
8
  import {
9
- FullSearchSchema,
10
9
  ParseRoute,
11
10
  RouteById,
12
11
  RouteByPath,
@@ -14,7 +13,7 @@ import {
14
13
  RoutePaths,
15
14
  } from './routeInfo'
16
15
  import { RegisteredRouter, RouterState } from './router'
17
- import { NoInfer, StrictOrFrom, pick } from './utils'
16
+ import { GetTFrom, NoInfer, StrictOrFrom, pick } from './utils'
18
17
 
19
18
  export const matchContext = React.createContext<string | undefined>(undefined)
20
19
 
@@ -37,8 +36,7 @@ export interface RouteMatch<
37
36
  loaderData?: RouteById<TRouteTree, TRouteId>['types']['loaderData']
38
37
  routeContext: RouteById<TRouteTree, TRouteId>['types']['routeContext']
39
38
  context: RouteById<TRouteTree, TRouteId>['types']['allContext']
40
- search: FullSearchSchema<TRouteTree> &
41
- RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema']
39
+ search: RouteById<TRouteTree, TRouteId>['types']['fullSearchSchema']
42
40
  fetchCount: number
43
41
  abortController: AbortController
44
42
  cause: 'preload' | 'enter' | 'stay'
@@ -293,16 +291,17 @@ export function getRenderedMatches(state: RouterState) {
293
291
  }
294
292
 
295
293
  export function useMatch<
294
+ TOpts extends StrictOrFrom<TFrom>,
296
295
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
297
296
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
298
- TStrict extends boolean = true,
299
- TRouteMatchState = RouteMatch<TRouteTree, TFrom>,
297
+ TFromInferred extends RouteIds<TRouteTree> = GetTFrom<TOpts, TRouteTree>,
298
+ TRouteMatchState = RouteMatch<TRouteTree, TFromInferred>,
300
299
  TSelected = TRouteMatchState,
301
300
  >(
302
- opts: StrictOrFrom<TFrom> & {
301
+ opts: TOpts & {
303
302
  select?: (match: TRouteMatchState) => TSelected
304
303
  },
305
- ): TStrict extends true ? TSelected : TSelected | undefined {
304
+ ): TSelected {
306
305
  const router = useRouter()
307
306
  const nearestMatchId = React.useContext(matchContext)
308
307
 
@@ -378,19 +377,20 @@ export function useParentMatches<T = RouteMatch[]>(opts?: {
378
377
  }
379
378
 
380
379
  export function useLoaderDeps<
380
+ TOpts extends StrictOrFrom<TFrom>,
381
381
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
382
382
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
383
- TStrict extends boolean = true,
384
- TRouteMatch extends RouteMatch<TRouteTree, TFrom> = RouteMatch<
383
+ TFromInferred extends RouteIds<TRouteTree> = GetTFrom<TOpts, TRouteTree>,
384
+ TRouteMatch extends RouteMatch<TRouteTree, TFromInferred> = RouteMatch<
385
385
  TRouteTree,
386
- TFrom
386
+ TFromInferred
387
387
  >,
388
388
  TSelected = Required<TRouteMatch>['loaderDeps'],
389
389
  >(
390
- opts: StrictOrFrom<TFrom> & {
390
+ opts: TOpts & {
391
391
  select?: (match: TRouteMatch) => TSelected
392
392
  },
393
- ): TStrict extends true ? TSelected : TSelected | undefined {
393
+ ): TSelected {
394
394
  return useMatch({
395
395
  ...opts,
396
396
  select: (s) => {
@@ -398,23 +398,24 @@ export function useLoaderDeps<
398
398
  ? opts.select(s?.loaderDeps)
399
399
  : s?.loaderDeps
400
400
  },
401
- })!
401
+ })
402
402
  }
403
403
 
404
404
  export function useLoaderData<
405
+ TOpts extends StrictOrFrom<TFrom>,
405
406
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
406
407
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
407
- TStrict extends boolean = true,
408
- TRouteMatch extends RouteMatch<TRouteTree, TFrom> = RouteMatch<
408
+ TFromInferred extends RouteIds<TRouteTree> = GetTFrom<TOpts, TRouteTree>,
409
+ TRouteMatch extends RouteMatch<TRouteTree, TFromInferred> = RouteMatch<
409
410
  TRouteTree,
410
- TFrom
411
+ TFromInferred
411
412
  >,
412
413
  TSelected = Required<TRouteMatch>['loaderData'],
413
414
  >(
414
- opts: StrictOrFrom<TFrom> & {
415
+ opts: TOpts & {
415
416
  select?: (match: TRouteMatch) => TSelected
416
417
  },
417
- ): TStrict extends true ? TSelected : TSelected | undefined {
418
+ ): TSelected {
418
419
  return useMatch({
419
420
  ...opts,
420
421
  select: (s) => {
@@ -422,5 +423,5 @@ export function useLoaderData<
422
423
  ? opts.select(s?.loaderData)
423
424
  : s?.loaderData
424
425
  },
425
- })!
426
+ })
426
427
  }
package/src/link.tsx CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  NoInfer,
16
16
  NonNullableUpdater,
17
17
  PickRequired,
18
+ StringLiteral,
18
19
  Updater,
19
20
  WithoutEmpty,
20
21
  deepEqual,
@@ -114,7 +115,7 @@ export type RelativeToPathAutoComplete<
114
115
 
115
116
  export type NavigateOptions<
116
117
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
117
- TFrom extends RoutePaths<TRouteTree> | string = string,
118
+ TFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
118
119
  TTo extends string = '',
119
120
  TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
120
121
  TMaskTo extends string = '',
@@ -128,7 +129,7 @@ export type NavigateOptions<
128
129
 
129
130
  export type ToOptions<
130
131
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
131
- TFrom extends RoutePaths<TRouteTree> | string = string,
132
+ TFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
132
133
  TTo extends string = '',
133
134
  TMaskFrom extends RoutePaths<TRouteTree> | string = TFrom,
134
135
  TMaskTo extends string = '',
@@ -138,7 +139,7 @@ export type ToOptions<
138
139
 
139
140
  export type ToMaskOptions<
140
141
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
141
- TMaskFrom extends RoutePaths<TRouteTree> | string = string,
142
+ TMaskFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
142
143
  TMaskTo extends string = '',
143
144
  > = ToSubOptions<TRouteTree, TMaskFrom, TMaskTo> & {
144
145
  unmaskOnReload?: boolean
@@ -146,7 +147,7 @@ export type ToMaskOptions<
146
147
 
147
148
  export type ToSubOptions<
148
149
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
149
- TFrom extends RoutePaths<TRouteTree> | string = string,
150
+ TFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
150
151
  TTo extends string = '',
151
152
  TResolved = ResolveRelativePath<TFrom, NoInfer<TTo>>,
152
153
  > = {
@@ -156,7 +157,7 @@ export type ToSubOptions<
156
157
  // State to pass to the history stack
157
158
  state?: true | NonNullableUpdater<HistoryState>
158
159
  // 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
159
- from?: TFrom
160
+ from?: StringLiteral<TFrom>
160
161
  // // When using relative route paths, this option forces resolution from the current path, instead of the route API's path or `from` path
161
162
  } & CheckPath<TRouteTree, NoInfer<TResolved>, {}> &
162
163
  SearchParamOptions<TRouteTree, TFrom, TTo, TResolved> &
package/src/route.ts CHANGED
@@ -485,41 +485,40 @@ export class RouteApi<
485
485
  useMatch = <TSelected = TAllContext>(opts?: {
486
486
  select?: (s: TAllContext) => TSelected
487
487
  }): TSelected => {
488
- return useMatch({ ...opts, from: this.id }) as any
488
+ return useMatch({ select: opts?.select, from: this.id })
489
489
  }
490
490
 
491
491
  useRouteContext = <TSelected = TAllContext>(opts?: {
492
492
  select?: (s: TAllContext) => TSelected
493
493
  }): TSelected => {
494
494
  return useMatch({
495
- ...opts,
496
495
  from: this.id,
497
496
  select: (d: any) => (opts?.select ? opts.select(d.context) : d.context),
498
- } as any)
497
+ })
499
498
  }
500
499
 
501
500
  useSearch = <TSelected = TFullSearchSchema>(opts?: {
502
501
  select?: (s: TFullSearchSchema) => TSelected
503
502
  }): TSelected => {
504
- return useSearch({ ...opts, from: this.id } as any)
503
+ return useSearch({ ...opts, from: this.id })
505
504
  }
506
505
 
507
506
  useParams = <TSelected = TAllParams>(opts?: {
508
507
  select?: (s: TAllParams) => TSelected
509
508
  }): TSelected => {
510
- return useParams({ ...opts, from: this.id } as any)
509
+ return useParams({ ...opts, from: this.id })
511
510
  }
512
511
 
513
512
  useLoaderDeps = <TSelected = TLoaderDeps>(opts?: {
514
513
  select?: (s: TLoaderDeps) => TSelected
515
514
  }): TSelected => {
516
- return useLoaderDeps({ ...opts, from: this.id } as any) as any
515
+ return useLoaderDeps({ ...opts, from: this.id } as any)
517
516
  }
518
517
 
519
518
  useLoaderData = <TSelected = TLoaderData>(opts?: {
520
519
  select?: (s: TLoaderData) => TSelected
521
520
  }): TSelected => {
522
- return useLoaderData({ ...opts, from: this.id } as any) as any
521
+ return useLoaderData({ ...opts, from: this.id } as any)
523
522
  }
524
523
  }
525
524
 
@@ -810,7 +809,7 @@ export class Route<
810
809
  useMatch = <TSelected = TAllContext>(opts?: {
811
810
  select?: (search: TAllContext) => TSelected
812
811
  }): TSelected => {
813
- return useMatch({ ...opts, from: this.id }) as any
812
+ return useMatch({ ...opts, from: this.id })
814
813
  }
815
814
 
816
815
  useRouteContext = <TSelected = TAllContext>(opts?: {
@@ -820,31 +819,31 @@ export class Route<
820
819
  ...opts,
821
820
  from: this.id,
822
821
  select: (d: any) => (opts?.select ? opts.select(d.context) : d.context),
823
- } as any)
822
+ })
824
823
  }
825
824
 
826
825
  useSearch = <TSelected = TFullSearchSchema>(opts?: {
827
826
  select?: (search: TFullSearchSchema) => TSelected
828
827
  }): TSelected => {
829
- return useSearch({ ...opts, from: this.id } as any)
828
+ return useSearch({ ...opts, from: this.id })
830
829
  }
831
830
 
832
831
  useParams = <TSelected = TAllParams>(opts?: {
833
832
  select?: (search: TAllParams) => TSelected
834
833
  }): TSelected => {
835
- return useParams({ ...opts, from: this.id } as any)
834
+ return useParams({ ...opts, from: this.id })
836
835
  }
837
836
 
838
837
  useLoaderDeps = <TSelected = TLoaderDeps>(opts?: {
839
838
  select?: (s: TLoaderDeps) => TSelected
840
839
  }): TSelected => {
841
- return useLoaderDeps({ ...opts, from: this.id } as any) as any
840
+ return useLoaderDeps({ ...opts, from: this.id } as any)
842
841
  }
843
842
 
844
843
  useLoaderData = <TSelected = TLoaderData>(opts?: {
845
844
  select?: (search: TLoaderData) => TSelected
846
845
  }): TSelected => {
847
- return useLoaderData({ ...opts, from: this.id } as any) as any
846
+ return useLoaderData({ ...opts, from: this.id } as any)
848
847
  }
849
848
  }
850
849
 
@@ -5,12 +5,13 @@ import { LinkOptions, NavigateOptions } from './link'
5
5
  import { AnyRoute } from './route'
6
6
  import { RoutePaths } from './routeInfo'
7
7
  import { RegisteredRouter } from './router'
8
+ import { StringLiteral } from './utils'
8
9
 
9
10
  export function useNavigate<
10
11
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
11
- TDefaultFrom extends RoutePaths<TRouteTree> | string = string,
12
- >(_defaultOpts?: { from?: TDefaultFrom }) {
13
- const { navigate, buildLocation } = useRouter()
12
+ TDefaultFrom extends RoutePaths<TRouteTree> | string = RoutePaths<TRouteTree>,
13
+ >(_defaultOpts?: { from?: StringLiteral<TDefaultFrom> }) {
14
+ const { navigate } = useRouter()
14
15
 
15
16
  const matchPathname = useMatch({
16
17
  strict: false,
package/src/useParams.tsx CHANGED
@@ -3,18 +3,19 @@ import { RouteIds, RouteById, AllParams } from './routeInfo'
3
3
  import { RegisteredRouter } from './router'
4
4
  import { last } from './utils'
5
5
  import { useRouterState } from './RouterProvider'
6
- import { StrictOrFrom } from './utils'
6
+ import { StrictOrFrom, GetTFrom } from './utils'
7
7
  import { getRenderedMatches } from './Matches'
8
8
 
9
9
  export function useParams<
10
+ TOpts extends StrictOrFrom<TFrom>,
10
11
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
11
12
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
12
- TDefaultSelected = AllParams<TRouteTree> &
13
- RouteById<TRouteTree, TFrom>['types']['allParams'],
14
- TSelected = TDefaultSelected,
13
+ TFromInferred = GetTFrom<TOpts, TRouteTree>,
14
+ TParams = RouteById<TRouteTree, TFromInferred>['types']['allParams'],
15
+ TSelected = TParams,
15
16
  >(
16
- opts: StrictOrFrom<TFrom> & {
17
- select?: (search: TDefaultSelected) => TSelected
17
+ opts: TOpts & {
18
+ select?: (params: TParams) => TSelected
18
19
  },
19
20
  ): TSelected {
20
21
  return useRouterState({
package/src/useSearch.tsx CHANGED
@@ -3,21 +3,22 @@ import { RouteIds, RouteById } from './routeInfo'
3
3
  import { RegisteredRouter } from './router'
4
4
  import { RouteMatch } from './Matches'
5
5
  import { useMatch } from './Matches'
6
- import { StrictOrFrom } from './utils'
6
+ import { StrictOrFrom, GetTFrom } from './utils'
7
7
 
8
8
  export function useSearch<
9
+ TOpts extends StrictOrFrom<TFrom>,
9
10
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
10
11
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
11
- TStrict extends boolean = true,
12
- TSearch = RouteById<TRouteTree, TFrom>['types']['fullSearchSchema'],
12
+ TFromInferred = GetTFrom<TOpts, TRouteTree>,
13
+ TSearch = RouteById<TRouteTree, TFromInferred>['types']['fullSearchSchema'],
13
14
  TSelected = TSearch,
14
15
  >(
15
- opts: StrictOrFrom<TFrom> & {
16
+ opts: TOpts & {
16
17
  select?: (search: TSearch) => TSelected
17
18
  },
18
- ): TStrict extends true ? TSelected : TSelected | undefined {
19
+ ) : TSelected {
19
20
  return useMatch({
20
- ...(opts as any),
21
+ ...opts,
21
22
  select: (match: RouteMatch) => {
22
23
  return opts?.select ? opts.select(match.search as TSearch) : match.search
23
24
  },
package/src/utils.ts CHANGED
@@ -290,9 +290,15 @@ export function shallow<T>(objA: T, objB: T) {
290
290
  return true
291
291
  }
292
292
 
293
+ export type StringLiteral<T> = T extends string
294
+ ? string extends T
295
+ ? string
296
+ : T
297
+ : never
298
+
293
299
  export type StrictOrFrom<TFrom> =
294
300
  | {
295
- from: TFrom
301
+ from: StringLiteral<TFrom> | TFrom
296
302
  strict?: true
297
303
  }
298
304
  | {
@@ -300,17 +306,22 @@ export type StrictOrFrom<TFrom> =
300
306
  strict: false
301
307
  }
302
308
 
309
+ export type GetTFrom<T, TRouteTree extends AnyRoute> = T extends StrictOrFrom<
310
+ infer TFrom extends RouteIds<TRouteTree>
311
+ >
312
+ ? TFrom
313
+ : never
314
+
303
315
  export function useRouteContext<
304
316
  TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
305
317
  TFrom extends RouteIds<TRouteTree> = RouteIds<TRouteTree>,
306
- TStrict extends boolean = true,
307
318
  TRouteContext = RouteById<TRouteTree, TFrom>['types']['allContext'],
308
319
  TSelected = TRouteContext,
309
320
  >(
310
321
  opts: StrictOrFrom<TFrom> & {
311
322
  select?: (search: TRouteContext) => TSelected
312
323
  },
313
- ): TStrict extends true ? TSelected : TSelected | undefined {
324
+ ): TSelected {
314
325
  return useMatch({
315
326
  ...(opts as any),
316
327
  select: (match: RouteMatch) =>