@tanstack/react-router 1.120.7 → 1.121.0-alpha.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 (61) hide show
  1. package/dist/cjs/HeadContent.cjs +23 -6
  2. package/dist/cjs/HeadContent.cjs.map +1 -1
  3. package/dist/cjs/Match.cjs +6 -1
  4. package/dist/cjs/Match.cjs.map +1 -1
  5. package/dist/cjs/Matches.cjs.map +1 -1
  6. package/dist/cjs/Matches.d.cts +2 -2
  7. package/dist/cjs/RouterProvider.cjs +10 -8
  8. package/dist/cjs/RouterProvider.cjs.map +1 -1
  9. package/dist/cjs/Scripts.cjs +2 -1
  10. package/dist/cjs/Scripts.cjs.map +1 -1
  11. package/dist/cjs/fileRoute.cjs +8 -0
  12. package/dist/cjs/fileRoute.cjs.map +1 -1
  13. package/dist/cjs/fileRoute.d.cts +16 -5
  14. package/dist/cjs/index.d.cts +2 -2
  15. package/dist/cjs/link.cjs +20 -17
  16. package/dist/cjs/link.cjs.map +1 -1
  17. package/dist/cjs/route.cjs.map +1 -1
  18. package/dist/cjs/route.d.cts +3 -3
  19. package/dist/cjs/router.cjs +8 -0
  20. package/dist/cjs/router.cjs.map +1 -1
  21. package/dist/cjs/useBlocker.cjs +4 -1
  22. package/dist/cjs/useBlocker.cjs.map +1 -1
  23. package/dist/cjs/useNavigate.cjs +13 -7
  24. package/dist/cjs/useNavigate.cjs.map +1 -1
  25. package/dist/esm/HeadContent.js +23 -6
  26. package/dist/esm/HeadContent.js.map +1 -1
  27. package/dist/esm/Match.js +6 -1
  28. package/dist/esm/Match.js.map +1 -1
  29. package/dist/esm/Matches.d.ts +2 -2
  30. package/dist/esm/Matches.js.map +1 -1
  31. package/dist/esm/RouterProvider.js +10 -8
  32. package/dist/esm/RouterProvider.js.map +1 -1
  33. package/dist/esm/Scripts.js +2 -1
  34. package/dist/esm/Scripts.js.map +1 -1
  35. package/dist/esm/fileRoute.d.ts +16 -5
  36. package/dist/esm/fileRoute.js +8 -0
  37. package/dist/esm/fileRoute.js.map +1 -1
  38. package/dist/esm/index.d.ts +2 -2
  39. package/dist/esm/link.js +20 -17
  40. package/dist/esm/link.js.map +1 -1
  41. package/dist/esm/route.d.ts +3 -3
  42. package/dist/esm/route.js.map +1 -1
  43. package/dist/esm/router.js +8 -0
  44. package/dist/esm/router.js.map +1 -1
  45. package/dist/esm/useBlocker.js +4 -1
  46. package/dist/esm/useBlocker.js.map +1 -1
  47. package/dist/esm/useNavigate.js +13 -7
  48. package/dist/esm/useNavigate.js.map +1 -1
  49. package/package.json +3 -3
  50. package/src/HeadContent.tsx +26 -3
  51. package/src/Match.tsx +15 -4
  52. package/src/Matches.tsx +4 -1
  53. package/src/RouterProvider.tsx +11 -9
  54. package/src/Scripts.tsx +1 -0
  55. package/src/fileRoute.ts +26 -4
  56. package/src/index.tsx +4 -3
  57. package/src/link.tsx +23 -17
  58. package/src/route.tsx +53 -87
  59. package/src/router.ts +9 -0
  60. package/src/useBlocker.tsx +4 -1
  61. package/src/useNavigate.tsx +19 -6
package/src/link.tsx CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  useLayoutEffect,
17
17
  } from './utils'
18
18
 
19
- import { useMatches } from './Matches'
19
+ import { useMatch } from './useMatch'
20
20
  import type {
21
21
  AnyRouter,
22
22
  Constrain,
@@ -105,26 +105,28 @@ export function useLinkProps<
105
105
  structuralSharing: true as any,
106
106
  })
107
107
 
108
- // when `from` is not supplied, use the leaf route of the current matches as the `from` location
109
- // so relative routing works as expected
110
- const from = useMatches({
111
- select: (matches) => options.from ?? matches[matches.length - 1]?.fullPath,
108
+ const nearestFrom = useMatch({
109
+ strict: false,
110
+ select: (match) => match.fullPath,
112
111
  })
112
+
113
+ const from = options.from ?? nearestFrom
114
+
113
115
  // Use it as the default `from` location
114
- const _options = React.useMemo(() => ({ ...options, from }), [options, from])
116
+ options = { ...options, from }
115
117
 
116
118
  const next = React.useMemo(
117
- () => router.buildLocation(_options as any),
119
+ () => router.buildLocation(options as any),
118
120
  // eslint-disable-next-line react-hooks/exhaustive-deps
119
- [router, _options, currentSearch],
121
+ [router, options, currentSearch],
120
122
  )
121
123
 
122
124
  const preload = React.useMemo(() => {
123
- if (_options.reloadDocument) {
125
+ if (options.reloadDocument) {
124
126
  return false
125
127
  }
126
128
  return userPreload ?? router.options.defaultPreload
127
- }, [router.options.defaultPreload, userPreload, _options.reloadDocument])
129
+ }, [router.options.defaultPreload, userPreload, options.reloadDocument])
128
130
  const preloadDelay =
129
131
  userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0
130
132
 
@@ -175,11 +177,11 @@ export function useLinkProps<
175
177
  })
176
178
 
177
179
  const doPreload = React.useCallback(() => {
178
- router.preloadRoute(_options as any).catch((err) => {
180
+ router.preloadRoute(options as any).catch((err) => {
179
181
  console.warn(err)
180
182
  console.warn(preloadWarning)
181
183
  })
182
- }, [_options, router])
184
+ }, [options, router])
183
185
 
184
186
  const preloadViewportIoCallback = React.useCallback(
185
187
  (entry: IntersectionObserverEntry | undefined) => {
@@ -249,14 +251,14 @@ export function useLinkProps<
249
251
  // All is well? Navigate!
250
252
  // N.B. we don't call `router.commitLocation(next) here because we want to run `validateSearch` before committing
251
253
  return router.navigate({
252
- ..._options,
254
+ ...options,
253
255
  replace,
254
256
  resetScroll,
255
257
  hashScrollIntoView,
256
258
  startTransition,
257
259
  viewTransition,
258
260
  ignoreBlocker,
259
- } as any)
261
+ })
260
262
  }
261
263
  }
262
264
 
@@ -279,10 +281,14 @@ export function useLinkProps<
279
281
  return
280
282
  }
281
283
 
282
- eventTarget.preloadTimeout = setTimeout(() => {
283
- eventTarget.preloadTimeout = null
284
+ if (!preloadDelay) {
284
285
  doPreload()
285
- }, preloadDelay)
286
+ } else {
287
+ eventTarget.preloadTimeout = setTimeout(() => {
288
+ eventTarget.preloadTimeout = null
289
+ doPreload()
290
+ }, preloadDelay)
291
+ }
286
292
  }
287
293
  }
288
294
 
package/src/route.tsx CHANGED
@@ -25,11 +25,9 @@ import type {
25
25
  ResolveFullPath,
26
26
  ResolveId,
27
27
  ResolveParams,
28
- RootRoute as RootRouteCore,
29
28
  RootRouteId,
30
29
  RootRouteOptions,
31
30
  RouteConstraints,
32
- Route as RouteCore,
33
31
  RouteIds,
34
32
  RouteMask,
35
33
  RouteOptions,
@@ -150,62 +148,43 @@ export class RouteApi<
150
148
  }
151
149
 
152
150
  export class Route<
153
- in out TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute,
154
- in out TPath extends RouteConstraints['TPath'] = '/',
155
- in out TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<
156
- TParentRoute,
157
- TPath
158
- >,
159
- in out TCustomId extends RouteConstraints['TCustomId'] = string,
160
- in out TId extends RouteConstraints['TId'] = ResolveId<
161
- TParentRoute,
162
- TCustomId,
163
- TPath
164
- >,
165
- in out TSearchValidator = undefined,
166
- in out TParams = ResolveParams<TPath>,
167
- in out TRouterContext = AnyContext,
168
- in out TRouteContextFn = AnyContext,
169
- in out TBeforeLoadFn = AnyContext,
170
- in out TLoaderDeps extends Record<string, any> = {},
171
- in out TLoaderFn = undefined,
172
- in out TChildren = unknown,
173
- in out TFileRouteTypes = unknown,
174
- >
175
- extends BaseRoute<
151
+ in out TParentRoute extends RouteConstraints['TParentRoute'] = AnyRoute,
152
+ in out TPath extends RouteConstraints['TPath'] = '/',
153
+ in out TFullPath extends RouteConstraints['TFullPath'] = ResolveFullPath<
154
+ TParentRoute,
155
+ TPath
156
+ >,
157
+ in out TCustomId extends RouteConstraints['TCustomId'] = string,
158
+ in out TId extends RouteConstraints['TId'] = ResolveId<
176
159
  TParentRoute,
177
- TPath,
178
- TFullPath,
179
160
  TCustomId,
180
- TId,
181
- TSearchValidator,
182
- TParams,
183
- TRouterContext,
184
- TRouteContextFn,
185
- TBeforeLoadFn,
186
- TLoaderDeps,
187
- TLoaderFn,
188
- TChildren,
189
- TFileRouteTypes
190
- >
191
- implements
192
- RouteCore<
193
- TParentRoute,
194
- TPath,
195
- TFullPath,
196
- TCustomId,
197
- TId,
198
- TSearchValidator,
199
- TParams,
200
- TRouterContext,
201
- TRouteContextFn,
202
- TBeforeLoadFn,
203
- TLoaderDeps,
204
- TLoaderFn,
205
- TChildren,
206
- TFileRouteTypes
207
- >
208
- {
161
+ TPath
162
+ >,
163
+ in out TSearchValidator = undefined,
164
+ in out TParams = ResolveParams<TPath>,
165
+ in out TRouterContext = AnyContext,
166
+ in out TRouteContextFn = AnyContext,
167
+ in out TBeforeLoadFn = AnyContext,
168
+ in out TLoaderDeps extends Record<string, any> = {},
169
+ in out TLoaderFn = undefined,
170
+ in out TChildren = unknown,
171
+ in out TFileRouteTypes = unknown,
172
+ > extends BaseRoute<
173
+ TParentRoute,
174
+ TPath,
175
+ TFullPath,
176
+ TCustomId,
177
+ TId,
178
+ TSearchValidator,
179
+ TParams,
180
+ TRouterContext,
181
+ TRouteContextFn,
182
+ TBeforeLoadFn,
183
+ TLoaderDeps,
184
+ TLoaderFn,
185
+ TChildren,
186
+ TFileRouteTypes
187
+ > {
209
188
  /**
210
189
  * @deprecated Use the `createRoute` function instead.
211
190
  */
@@ -385,37 +364,24 @@ export function createRootRouteWithContext<TRouterContext extends {}>() {
385
364
  export const rootRouteWithContext = createRootRouteWithContext
386
365
 
387
366
  export class RootRoute<
388
- in out TSearchValidator = undefined,
389
- in out TRouterContext = {},
390
- in out TRouteContextFn = AnyContext,
391
- in out TBeforeLoadFn = AnyContext,
392
- in out TLoaderDeps extends Record<string, any> = {},
393
- in out TLoaderFn = undefined,
394
- in out TChildren = unknown,
395
- in out TFileRouteTypes = unknown,
396
- >
397
- extends BaseRootRoute<
398
- TSearchValidator,
399
- TRouterContext,
400
- TRouteContextFn,
401
- TBeforeLoadFn,
402
- TLoaderDeps,
403
- TLoaderFn,
404
- TChildren,
405
- TFileRouteTypes
406
- >
407
- implements
408
- RootRouteCore<
409
- TSearchValidator,
410
- TRouterContext,
411
- TRouteContextFn,
412
- TBeforeLoadFn,
413
- TLoaderDeps,
414
- TLoaderFn,
415
- TChildren,
416
- TFileRouteTypes
417
- >
418
- {
367
+ in out TSearchValidator = undefined,
368
+ in out TRouterContext = {},
369
+ in out TRouteContextFn = AnyContext,
370
+ in out TBeforeLoadFn = AnyContext,
371
+ in out TLoaderDeps extends Record<string, any> = {},
372
+ in out TLoaderFn = undefined,
373
+ in out TChildren = unknown,
374
+ in out TFileRouteTypes = unknown,
375
+ > extends BaseRootRoute<
376
+ TSearchValidator,
377
+ TRouterContext,
378
+ TRouteContextFn,
379
+ TBeforeLoadFn,
380
+ TLoaderDeps,
381
+ TLoaderFn,
382
+ TChildren,
383
+ TFileRouteTypes
384
+ > {
419
385
  /**
420
386
  * @deprecated `RootRoute` is now an internal implementation detail. Use `createRootRoute()` instead.
421
387
  */
package/src/router.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { RouterCore } from '@tanstack/router-core'
2
+ import { createFileRoute, createLazyFileRoute } from './fileRoute'
2
3
  import type { RouterHistory } from '@tanstack/history'
3
4
  import type {
4
5
  AnyRoute,
@@ -105,3 +106,11 @@ export class Router<
105
106
  super(options)
106
107
  }
107
108
  }
109
+
110
+ if (typeof globalThis !== 'undefined') {
111
+ ;(globalThis as any).createFileRoute = createFileRoute
112
+ ;(globalThis as any).createLazyFileRoute = createLazyFileRoute
113
+ } else if (typeof window !== 'undefined') {
114
+ ;(window as any).createFileRoute = createFileRoute
115
+ ;(window as any).createFileRoute = createLazyFileRoute
116
+ }
@@ -177,7 +177,10 @@ export function useBlocker(
177
177
  location: HistoryLocation,
178
178
  ): AnyShouldBlockFnLocation {
179
179
  const parsedLocation = router.parseLocation(undefined, location)
180
- const matchedRoutes = router.getMatchedRoutes(parsedLocation)
180
+ const matchedRoutes = router.getMatchedRoutes(
181
+ parsedLocation.pathname,
182
+ undefined,
183
+ )
181
184
  if (matchedRoutes.foundRoute === undefined) {
182
185
  throw new Error(`No route found for location ${location.href}`)
183
186
  }
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react'
2
2
  import { useRouter } from './useRouter'
3
+ import { useMatch } from './useMatch'
3
4
  import type {
4
5
  AnyRouter,
5
6
  FromPathOption,
@@ -14,15 +15,28 @@ export function useNavigate<
14
15
  >(_defaultOpts?: {
15
16
  from?: FromPathOption<TRouter, TDefaultFrom>
16
17
  }): UseNavigateResult<TDefaultFrom> {
17
- const { navigate } = useRouter()
18
+ const { navigate, state } = useRouter()
19
+
20
+ // Just get the index of the current match to avoid rerenders
21
+ // as much as possible
22
+ const matchIndex = useMatch({
23
+ strict: false,
24
+ select: (match) => match.index,
25
+ })
18
26
 
19
27
  return React.useCallback(
20
28
  (options: NavigateOptions) => {
29
+ const from =
30
+ options.from ??
31
+ _defaultOpts?.from ??
32
+ state.matches[matchIndex]!.fullPath
33
+
21
34
  return navigate({
22
- from: _defaultOpts?.from,
23
35
  ...options,
36
+ from,
24
37
  })
25
38
  },
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
26
40
  [_defaultOpts?.from, navigate],
27
41
  ) as UseNavigateResult<TDefaultFrom>
28
42
  }
@@ -35,6 +49,7 @@ export function Navigate<
35
49
  const TMaskTo extends string = '',
36
50
  >(props: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): null {
37
51
  const router = useRouter()
52
+ const navigate = useNavigate()
38
53
 
39
54
  const previousPropsRef = React.useRef<NavigateOptions<
40
55
  TRouter,
@@ -45,11 +60,9 @@ export function Navigate<
45
60
  > | null>(null)
46
61
  React.useEffect(() => {
47
62
  if (previousPropsRef.current !== props) {
48
- router.navigate({
49
- ...props,
50
- })
63
+ navigate(props)
51
64
  previousPropsRef.current = props
52
65
  }
53
- }, [router, props])
66
+ }, [router, props, navigate])
54
67
  return null
55
68
  }