@tanstack/react-router 1.39.8 → 1.41.0

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 (142) hide show
  1. package/dist/cjs/CatchBoundary.d.cts +2 -2
  2. package/dist/cjs/Match.cjs +238 -0
  3. package/dist/cjs/Match.cjs.map +1 -0
  4. package/dist/cjs/Match.d.cts +5 -0
  5. package/dist/cjs/Matches.cjs +8 -253
  6. package/dist/cjs/Matches.cjs.map +1 -1
  7. package/dist/cjs/Matches.d.cts +2 -11
  8. package/dist/cjs/RouterProvider.cjs.map +1 -1
  9. package/dist/cjs/RouterProvider.d.cts +3 -2
  10. package/dist/cjs/SafeFragment.cjs +8 -0
  11. package/dist/cjs/SafeFragment.cjs.map +1 -0
  12. package/dist/cjs/SafeFragment.d.cts +1 -0
  13. package/dist/cjs/ScriptOnce.cjs +28 -0
  14. package/dist/cjs/ScriptOnce.cjs.map +1 -0
  15. package/dist/cjs/ScriptOnce.d.cts +5 -0
  16. package/dist/cjs/Transitioner.cjs +2 -1
  17. package/dist/cjs/Transitioner.cjs.map +1 -1
  18. package/dist/cjs/awaited.cjs +14 -71
  19. package/dist/cjs/awaited.cjs.map +1 -1
  20. package/dist/cjs/awaited.d.cts +3 -6
  21. package/dist/cjs/defer.cjs +7 -13
  22. package/dist/cjs/defer.cjs.map +1 -1
  23. package/dist/cjs/defer.d.cts +2 -6
  24. package/dist/cjs/index.cjs +11 -7
  25. package/dist/cjs/index.cjs.map +1 -1
  26. package/dist/cjs/index.d.cts +8 -3
  27. package/dist/cjs/isServerSideError.cjs +22 -0
  28. package/dist/cjs/isServerSideError.cjs.map +1 -0
  29. package/dist/cjs/isServerSideError.d.cts +5 -0
  30. package/dist/cjs/link.cjs +8 -9
  31. package/dist/cjs/link.cjs.map +1 -1
  32. package/dist/cjs/link.d.cts +1 -0
  33. package/dist/cjs/matchContext.cjs +23 -0
  34. package/dist/cjs/matchContext.cjs.map +1 -0
  35. package/dist/cjs/matchContext.d.cts +2 -0
  36. package/dist/cjs/not-found.cjs +1 -2
  37. package/dist/cjs/not-found.cjs.map +1 -1
  38. package/dist/cjs/not-found.d.cts +2 -2
  39. package/dist/cjs/path.cjs +3 -6
  40. package/dist/cjs/path.cjs.map +1 -1
  41. package/dist/cjs/qss.cjs +3 -6
  42. package/dist/cjs/qss.cjs.map +1 -1
  43. package/dist/cjs/qss.d.cts +1 -1
  44. package/dist/cjs/redirects.cjs.map +1 -1
  45. package/dist/cjs/renderRouteNotFound.cjs +22 -0
  46. package/dist/cjs/renderRouteNotFound.cjs.map +1 -0
  47. package/dist/cjs/renderRouteNotFound.d.cts +4 -0
  48. package/dist/cjs/root.cjs.map +1 -1
  49. package/dist/cjs/root.d.cts +1 -1
  50. package/dist/cjs/route.cjs.map +1 -1
  51. package/dist/cjs/router.cjs +33 -26
  52. package/dist/cjs/router.cjs.map +1 -1
  53. package/dist/cjs/router.d.cts +16 -11
  54. package/dist/cjs/scroll-restoration.cjs +1 -2
  55. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  56. package/dist/cjs/useMatch.cjs +2 -2
  57. package/dist/cjs/useMatch.cjs.map +1 -1
  58. package/dist/cjs/utils.cjs +4 -3
  59. package/dist/cjs/utils.cjs.map +1 -1
  60. package/dist/cjs/utils.d.cts +3 -2
  61. package/dist/esm/CatchBoundary.d.ts +2 -2
  62. package/dist/esm/Match.d.ts +5 -0
  63. package/dist/esm/Match.js +221 -0
  64. package/dist/esm/Match.js.map +1 -0
  65. package/dist/esm/Matches.d.ts +2 -11
  66. package/dist/esm/Matches.js +5 -250
  67. package/dist/esm/Matches.js.map +1 -1
  68. package/dist/esm/RouterProvider.d.ts +3 -2
  69. package/dist/esm/RouterProvider.js.map +1 -1
  70. package/dist/esm/SafeFragment.d.ts +1 -0
  71. package/dist/esm/SafeFragment.js +8 -0
  72. package/dist/esm/SafeFragment.js.map +1 -0
  73. package/dist/esm/ScriptOnce.d.ts +5 -0
  74. package/dist/esm/ScriptOnce.js +28 -0
  75. package/dist/esm/ScriptOnce.js.map +1 -0
  76. package/dist/esm/Transitioner.js +2 -1
  77. package/dist/esm/Transitioner.js.map +1 -1
  78. package/dist/esm/awaited.d.ts +3 -6
  79. package/dist/esm/awaited.js +16 -73
  80. package/dist/esm/awaited.js.map +1 -1
  81. package/dist/esm/defer.d.ts +2 -6
  82. package/dist/esm/defer.js +8 -14
  83. package/dist/esm/defer.js.map +1 -1
  84. package/dist/esm/index.d.ts +8 -3
  85. package/dist/esm/index.js +9 -5
  86. package/dist/esm/index.js.map +1 -1
  87. package/dist/esm/isServerSideError.d.ts +5 -0
  88. package/dist/esm/isServerSideError.js +22 -0
  89. package/dist/esm/isServerSideError.js.map +1 -0
  90. package/dist/esm/link.d.ts +1 -0
  91. package/dist/esm/link.js +8 -9
  92. package/dist/esm/link.js.map +1 -1
  93. package/dist/esm/matchContext.d.ts +2 -0
  94. package/dist/esm/matchContext.js +6 -0
  95. package/dist/esm/matchContext.js.map +1 -0
  96. package/dist/esm/not-found.d.ts +2 -2
  97. package/dist/esm/not-found.js +1 -2
  98. package/dist/esm/not-found.js.map +1 -1
  99. package/dist/esm/path.js +3 -6
  100. package/dist/esm/path.js.map +1 -1
  101. package/dist/esm/qss.d.ts +1 -1
  102. package/dist/esm/qss.js +3 -6
  103. package/dist/esm/qss.js.map +1 -1
  104. package/dist/esm/redirects.js.map +1 -1
  105. package/dist/esm/renderRouteNotFound.d.ts +4 -0
  106. package/dist/esm/renderRouteNotFound.js +22 -0
  107. package/dist/esm/renderRouteNotFound.js.map +1 -0
  108. package/dist/esm/root.d.ts +1 -1
  109. package/dist/esm/root.js.map +1 -1
  110. package/dist/esm/route.js.map +1 -1
  111. package/dist/esm/router.d.ts +16 -11
  112. package/dist/esm/router.js +33 -26
  113. package/dist/esm/router.js.map +1 -1
  114. package/dist/esm/scroll-restoration.js +1 -2
  115. package/dist/esm/scroll-restoration.js.map +1 -1
  116. package/dist/esm/useMatch.js +1 -1
  117. package/dist/esm/useMatch.js.map +1 -1
  118. package/dist/esm/utils.d.ts +3 -2
  119. package/dist/esm/utils.js +4 -3
  120. package/dist/esm/utils.js.map +1 -1
  121. package/package.json +6 -5
  122. package/src/Match.tsx +296 -0
  123. package/src/Matches.tsx +4 -333
  124. package/src/RouterProvider.tsx +2 -1
  125. package/src/SafeFragment.tsx +5 -0
  126. package/src/ScriptOnce.tsx +27 -0
  127. package/src/Transitioner.tsx +1 -1
  128. package/src/awaited.tsx +17 -89
  129. package/src/defer.ts +9 -26
  130. package/src/index.tsx +7 -13
  131. package/src/isServerSideError.tsx +23 -0
  132. package/src/link.tsx +5 -0
  133. package/src/matchContext.tsx +3 -0
  134. package/src/not-found.tsx +1 -1
  135. package/src/qss.ts +5 -6
  136. package/src/redirects.ts +0 -1
  137. package/src/renderRouteNotFound.tsx +28 -0
  138. package/src/root.ts +1 -1
  139. package/src/route.ts +1 -1
  140. package/src/router.ts +54 -39
  141. package/src/useMatch.tsx +1 -1
  142. package/src/utils.ts +11 -9
@@ -0,0 +1,23 @@
1
+ export function isServerSideError(error: unknown): error is {
2
+ __isServerError: true
3
+ data: Record<string, any>
4
+ } {
5
+ if (!(typeof error === 'object' && error && 'data' in error)) return false
6
+ if (!('__isServerError' in error && error.__isServerError)) return false
7
+ if (!(typeof error.data === 'object' && error.data)) return false
8
+
9
+ return error.__isServerError === true
10
+ }
11
+
12
+ export function defaultDeserializeError(serializedData: Record<string, any>) {
13
+ if ('name' in serializedData && 'message' in serializedData) {
14
+ const error = new Error(serializedData.message)
15
+ error.name = serializedData.name
16
+ if (process.env.NODE_ENV === 'development') {
17
+ error.stack = serializedData.stack
18
+ }
19
+ return error
20
+ }
21
+
22
+ return serializedData.data
23
+ }
package/src/link.tsx CHANGED
@@ -1,3 +1,5 @@
1
+ 'use client'
2
+
1
3
  import * as React from 'react'
2
4
  import { flushSync } from 'react-dom'
3
5
  import { useMatch } from './useMatch'
@@ -183,6 +185,7 @@ export interface NavigateOptionProps {
183
185
  startTransition?: boolean
184
186
  // if set to `true`, the router will wrap the resulting navigation in a document.startViewTransition() call.
185
187
  viewTransition?: boolean
188
+ ignoreBlocker?: boolean
186
189
  }
187
190
 
188
191
  export type ToOptions<
@@ -572,6 +575,7 @@ export function useLinkProps<
572
575
  onMouseEnter,
573
576
  onMouseLeave,
574
577
  onTouchStart,
578
+ ignoreBlocker,
575
579
  ...rest
576
580
  } = options
577
581
 
@@ -669,6 +673,7 @@ export function useLinkProps<
669
673
  resetScroll,
670
674
  startTransition,
671
675
  viewTransition,
676
+ ignoreBlocker,
672
677
  })
673
678
  }
674
679
  }
@@ -0,0 +1,3 @@
1
+ import * as React from 'react'
2
+
3
+ export const matchContext = React.createContext<string | undefined>(undefined)
package/src/not-found.tsx CHANGED
@@ -1,4 +1,4 @@
1
- // eslint-disable-next-line @typescript-eslint/consistent-type-imports
1
+ // eslint-disable-next-line ts/consistent-type-imports
2
2
  import * as React from 'react'
3
3
  import { CatchBoundary } from './CatchBoundary'
4
4
  import { useRouterState } from './useRouterState'
package/src/qss.ts CHANGED
@@ -1,5 +1,3 @@
1
- // @ts-nocheck
2
-
3
1
  // qss has been slightly modified and inlined here for our use cases (and compression's sake). We've included it as a hard dependency for MIT license attribution.
4
2
 
5
3
  /**
@@ -13,7 +11,7 @@
13
11
  * // Expected output: "token=foo&key=value"
14
12
  * ```
15
13
  */
16
- export function encode(obj, pfx?: string) {
14
+ export function encode(obj: any, pfx?: string) {
17
15
  let k,
18
16
  i,
19
17
  tmp,
@@ -44,7 +42,7 @@ export function encode(obj, pfx?: string) {
44
42
  * // Example input: toValue("123")
45
43
  * // Expected output: 123
46
44
  */
47
- function toValue(mix) {
45
+ function toValue(mix: any) {
48
46
  if (!mix) return ''
49
47
  const str = decodeURIComponent(mix)
50
48
  if (str === 'false') return false
@@ -61,9 +59,9 @@ function toValue(mix) {
61
59
  * // Example input: decode("token=foo&key=value")
62
60
  * // Expected output: { "token": "foo", "key": "value" }
63
61
  */
64
- export function decode(str, pfx?: string) {
62
+ export function decode(str: any, pfx?: string) {
65
63
  let tmp, k
66
- const out = {},
64
+ const out: any = {},
67
65
  arr = (pfx ? str.substr(pfx.length) : str).split('&')
68
66
 
69
67
  while ((tmp = arr.shift())) {
@@ -72,6 +70,7 @@ export function decode(str, pfx?: string) {
72
70
  k = tmp.slice(0, equalIndex)
73
71
  const value = tmp.slice(equalIndex + 1)
74
72
  if (out[k] !== void 0) {
73
+ // @ts-expect-error
75
74
  out[k] = [].concat(out[k], toValue(value))
76
75
  } else {
77
76
  out[k] = toValue(value)
package/src/redirects.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { NavigateOptions } from './link'
2
- import type { AnyRoute } from './route'
3
2
  import type { RoutePaths } from './routeInfo'
4
3
  import type { AnyRouter, RegisteredRouter } from './router'
5
4
  import type { PickAsRequired } from './utils'
@@ -0,0 +1,28 @@
1
+ import * as React from 'react'
2
+ import warning from 'tiny-warning'
3
+ import { DefaultGlobalNotFound } from './not-found'
4
+ import { type AnyRouter } from './router'
5
+ import { type AnyRoute } from './route'
6
+
7
+ export function renderRouteNotFound(
8
+ router: AnyRouter,
9
+ route: AnyRoute,
10
+ data: any,
11
+ ) {
12
+ if (!route.options.notFoundComponent) {
13
+ if (router.options.defaultNotFoundComponent) {
14
+ return <router.options.defaultNotFoundComponent data={data} />
15
+ }
16
+
17
+ if (process.env.NODE_ENV === 'development') {
18
+ warning(
19
+ route.options.notFoundComponent,
20
+ `A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (<div>Not Found<div>)`,
21
+ )
22
+ }
23
+
24
+ return <DefaultGlobalNotFound />
25
+ }
26
+
27
+ return <route.options.notFoundComponent data={data} />
28
+ }
package/src/root.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const rootRouteId = '__root__' as const
1
+ export const rootRouteId = '__root__'
2
2
  export type RootRouteId = typeof rootRouteId
package/src/route.ts CHANGED
@@ -706,7 +706,7 @@ export class Route<
706
706
 
707
707
  const isRoot = !options?.path && !options?.id
708
708
 
709
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
709
+ // eslint-disable-next-line ts/no-unnecessary-condition
710
710
  this.parentRoute = this.options?.getParentRoute?.()
711
711
 
712
712
  if (isRoot) {
package/src/router.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { createBrowserHistory, createMemoryHistory } from '@tanstack/history'
2
2
  import { Store } from '@tanstack/react-store'
3
3
  import invariant from 'tiny-invariant'
4
- import warning from 'tiny-warning'
5
4
  import { rootRouteId } from './root'
6
5
  import { defaultParseSearch, defaultStringifySearch } from './searchParams'
7
6
  import {
@@ -44,6 +43,7 @@ import type {
44
43
  LoaderFnContext,
45
44
  NotFoundRouteComponent,
46
45
  RootRoute,
46
+ RouteComponent,
47
47
  RouteMask,
48
48
  } from './route'
49
49
  import type {
@@ -57,22 +57,18 @@ import type {
57
57
  ControlledPromise,
58
58
  NonNullableUpdater,
59
59
  PickAsRequired,
60
- Timeout,
61
60
  Updater,
62
61
  } from './utils'
63
- import type { RouteComponent } from './route'
64
62
  import type {
65
63
  AnyRouteMatch,
66
64
  MakeRouteMatch,
67
65
  MatchRouteOptions,
68
- RouteMatch,
69
66
  } from './Matches'
70
67
  import type { ParsedLocation } from './location'
71
68
  import type { SearchParser, SearchSerializer } from './searchParams'
72
69
  import type {
73
70
  BuildLocationFn,
74
71
  CommitLocationOptions,
75
- InjectedHtmlEntry,
76
72
  NavigateFn,
77
73
  } from './RouterProvider'
78
74
 
@@ -82,13 +78,16 @@ import type { NotFoundError } from './not-found'
82
78
  import type { NavigateOptions, ResolveRelativePath, ToOptions } from './link'
83
79
  import type { NoInfer } from '@tanstack/react-store'
84
80
  import type { DeferredPromiseState } from './defer'
85
- import type { ErrorInfo } from 'react'
86
81
 
87
82
  //
88
83
 
89
84
  declare global {
90
85
  interface Window {
91
- __TSR_DEHYDRATED__?: { data: string }
86
+ __TSR__?: {
87
+ matches: Array<any>
88
+ cleanScripts: () => void
89
+ dehydrated?: any
90
+ }
92
91
  __TSR_ROUTER_CONTEXT__?: React.Context<Router<any, any>>
93
92
  }
94
93
  }
@@ -237,7 +236,7 @@ export interface RouterOptions<
237
236
  * @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#defaultoncatch-property)
238
237
  * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#handling-errors-with-routeoptionsoncatch)
239
238
  */
240
- defaultOnCatch?: (error: Error, errorInfo: ErrorInfo) => void
239
+ defaultOnCatch?: (error: Error, errorInfo: React.ErrorInfo) => void
241
240
  defaultViewTransition?: boolean
242
241
  /**
243
242
  * @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/not-found-errors#the-notfoundmode-option)
@@ -508,6 +507,20 @@ export class Router<
508
507
  dehydratedData?: TDehydrated
509
508
  viewTransitionPromise?: ControlledPromise<true>
510
509
  manifest?: Manifest
510
+ AfterEachMatch?: (props: {
511
+ match: Pick<
512
+ AnyRouteMatch,
513
+ 'id' | 'status' | 'error' | 'loadPromise' | 'minPendingPromise'
514
+ >
515
+ matchIndex: number
516
+ }) => any
517
+ serializeLoaderData?: (
518
+ data: any,
519
+ ctx: {
520
+ router: AnyRouter
521
+ match: AnyRouteMatch
522
+ },
523
+ ) => any
511
524
 
512
525
  // Must build in constructor
513
526
  __store!: Store<RouterState<TRouteTree>>
@@ -603,7 +616,7 @@ export class Router<
603
616
  }
604
617
 
605
618
  if (
606
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
619
+ // eslint-disable-next-line ts/no-unnecessary-condition
607
620
  !this.history ||
608
621
  (this.options.history && this.options.history !== this.history)
609
622
  ) {
@@ -622,7 +635,7 @@ export class Router<
622
635
  this.buildRouteTree()
623
636
  }
624
637
 
625
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
638
+ // eslint-disable-next-line ts/no-unnecessary-condition
626
639
  if (!this.__store) {
627
640
  this.__store = new Store(getInitialRouterState(this.latestLocation), {
628
641
  onUpdate: () => {
@@ -1042,6 +1055,7 @@ export class Router<
1042
1055
 
1043
1056
  match = {
1044
1057
  id: matchId,
1058
+ index,
1045
1059
  routeId: route.id,
1046
1060
  params: routeParams,
1047
1061
  pathname: joinPaths([this.basepath, interpolatedPath]),
@@ -1332,6 +1346,7 @@ export class Router<
1332
1346
  commitLocation = async ({
1333
1347
  startTransition,
1334
1348
  viewTransition,
1349
+ ignoreBlocker,
1335
1350
  ...next
1336
1351
  }: ParsedLocation & CommitLocationOptions) => {
1337
1352
  const isSameState = () => {
@@ -1387,6 +1402,7 @@ export class Router<
1387
1402
  this.history[next.replace ? 'replace' : 'push'](
1388
1403
  nextHistory.href,
1389
1404
  nextHistory.state,
1405
+ { ignoreBlocker },
1390
1406
  )
1391
1407
  }
1392
1408
 
@@ -1400,6 +1416,7 @@ export class Router<
1400
1416
  resetScroll,
1401
1417
  startTransition,
1402
1418
  viewTransition,
1419
+ ignoreBlocker,
1403
1420
  ...rest
1404
1421
  }: BuildNextOptions & CommitLocationOptions = {}) => {
1405
1422
  const location = this.buildLocation(rest as any)
@@ -1409,6 +1426,7 @@ export class Router<
1409
1426
  viewTransition,
1410
1427
  replace,
1411
1428
  resetScroll,
1429
+ ignoreBlocker,
1412
1430
  })
1413
1431
  }
1414
1432
 
@@ -1954,7 +1972,13 @@ export class Router<
1954
1972
  )
1955
1973
  }
1956
1974
 
1957
- const loaderData = await loaderPromise
1975
+ let loaderData = await loaderPromise
1976
+ if (this.serializeLoaderData) {
1977
+ loaderData = this.serializeLoaderData(loaderData, {
1978
+ router: this,
1979
+ match,
1980
+ })
1981
+ }
1958
1982
  checkLatest()
1959
1983
 
1960
1984
  handleRedirectAndNotFound(match, loaderData)
@@ -2284,38 +2308,29 @@ export class Router<
2284
2308
  return match
2285
2309
  }
2286
2310
 
2287
- // We use a token -> weak map to keep track of deferred promises
2288
- // that are registered on the server and need to be resolved
2289
- registeredDeferredsIds = new Map<string, {}>()
2290
- registeredDeferreds = new WeakMap<{}, DeferredPromiseState<any>>()
2291
-
2292
- getDeferred = (uid: string) => {
2293
- const token = this.registeredDeferredsIds.get(uid)
2294
-
2295
- if (!token) {
2296
- return undefined
2297
- }
2298
-
2299
- return this.registeredDeferreds.get(token)
2300
- }
2301
-
2302
2311
  dehydrate = (): DehydratedRouter => {
2303
2312
  const pickError =
2304
2313
  this.options.errorSerializer?.serialize ?? defaultSerializeError
2305
2314
 
2306
2315
  return {
2307
2316
  state: {
2308
- dehydratedMatches: this.state.matches.map((d) => ({
2309
- ...pick(d, ['id', 'status', 'updatedAt', 'loaderData']),
2310
- // If an error occurs server-side during SSRing,
2311
- // send a small subset of the error to the client
2312
- error: d.error
2313
- ? {
2314
- data: pickError(d.error),
2315
- __isServerError: true,
2316
- }
2317
- : undefined,
2318
- })),
2317
+ dehydratedMatches: this.state.matches.map((d) => {
2318
+ return {
2319
+ ...pick(d, ['id', 'status', 'updatedAt']),
2320
+ // If an error occurs server-side during SSRing,
2321
+ // send a small subset of the error to the client
2322
+ error: d.error
2323
+ ? {
2324
+ data: pickError(d.error),
2325
+ __isServerError: true,
2326
+ }
2327
+ : undefined,
2328
+ // NOTE: We don't send the loader data here, because
2329
+ // there is a potential that it needs to be streamed.
2330
+ // Instead, we render it next to the route match in the HTML
2331
+ // which gives us the potential to stream it via suspense.
2332
+ }
2333
+ }),
2319
2334
  },
2320
2335
  manifest: this.manifest,
2321
2336
  }
@@ -2325,12 +2340,12 @@ export class Router<
2325
2340
  let _ctx = __do_not_use_server_ctx
2326
2341
  // Client hydrates from window
2327
2342
  if (typeof document !== 'undefined') {
2328
- _ctx = window.__TSR_DEHYDRATED__?.data
2343
+ _ctx = window.__TSR__?.dehydrated
2329
2344
  }
2330
2345
 
2331
2346
  invariant(
2332
2347
  _ctx,
2333
- 'Expected to find a __TSR_DEHYDRATED__ property on window... but we did not. Please file an issue!',
2348
+ 'Expected to find a dehydrated data on window.__TSR__.dehydrated... but we did not. Please file an issue!',
2334
2349
  )
2335
2350
 
2336
2351
  const ctx = this.options.transformer.parse(_ctx) as HydrationCtx
package/src/useMatch.tsx CHANGED
@@ -3,7 +3,7 @@ import invariant from 'tiny-invariant'
3
3
  import { useRouterState } from './useRouterState'
4
4
  import { type RegisteredRouter } from './router'
5
5
  import { type AnyRoute } from './route'
6
- import { matchContext } from './Matches'
6
+ import { matchContext } from './matchContext'
7
7
  import type { MakeRouteMatch } from './Matches'
8
8
  import type { RouteIds } from './routeInfo'
9
9
  import type { StrictOrFrom } from './utils'
package/src/utils.ts CHANGED
@@ -40,7 +40,7 @@ export type MakeDifferenceOptional<TLeft, TRight> = Omit<
40
40
  }
41
41
 
42
42
  // from https://stackoverflow.com/a/53955431
43
- // eslint-disable-next-line @typescript-eslint/naming-convention
43
+ // eslint-disable-next-line ts/naming-convention
44
44
  export type IsUnion<T, U extends T = T> = (
45
45
  T extends any ? (U extends T ? false : true) : never
46
46
  ) extends false
@@ -152,7 +152,7 @@ export function replaceEqualDeep<T>(prev: any, _next: T): T {
152
152
  let equalItems = 0
153
153
 
154
154
  for (let i = 0; i < nextSize; i++) {
155
- const key = array ? i : nextItems[i]
155
+ const key = array ? i : (nextItems[i] as any)
156
156
  if (
157
157
  ((!array && prevItems.includes(key)) || array) &&
158
158
  prev[key] === undefined &&
@@ -205,7 +205,7 @@ function hasObjectPrototype(o: any) {
205
205
  return Object.prototype.toString.call(o) === '[object Object]'
206
206
  }
207
207
 
208
- export function isPlainArray(value: unknown) {
208
+ export function isPlainArray(value: unknown): value is Array<unknown> {
209
209
  return Array.isArray(value) && value.length === Object.keys(value).length
210
210
  }
211
211
 
@@ -315,23 +315,25 @@ export type ControlledPromise<T> = Promise<T> & {
315
315
  resolve: (value: T) => void
316
316
  reject: (value: any) => void
317
317
  status: 'pending' | 'resolved' | 'rejected'
318
+ value?: T
318
319
  }
319
320
 
320
- export function createControlledPromise<T>(onResolve?: () => void) {
321
- let resolveLoadPromise!: () => void
321
+ export function createControlledPromise<T>(onResolve?: (value: T) => void) {
322
+ let resolveLoadPromise!: (value: T) => void
322
323
  let rejectLoadPromise!: (value: any) => void
323
324
 
324
- const controlledPromise = new Promise<void>((resolve, reject) => {
325
+ const controlledPromise = new Promise<T>((resolve, reject) => {
325
326
  resolveLoadPromise = resolve
326
327
  rejectLoadPromise = reject
327
328
  }) as ControlledPromise<T>
328
329
 
329
330
  controlledPromise.status = 'pending'
330
331
 
331
- controlledPromise.resolve = () => {
332
+ controlledPromise.resolve = (value: T) => {
332
333
  controlledPromise.status = 'resolved'
333
- resolveLoadPromise()
334
- onResolve?.()
334
+ controlledPromise.value = value
335
+ resolveLoadPromise(value)
336
+ onResolve?.(value)
335
337
  }
336
338
 
337
339
  controlledPromise.reject = (e) => {