@tanstack/react-router 1.97.26 → 1.98.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/dist/cjs/Match.cjs +78 -28
- package/dist/cjs/Match.cjs.map +1 -1
- package/dist/cjs/Matches.cjs +4 -1
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +2 -0
- package/dist/cjs/ScriptOnce.cjs +1 -1
- package/dist/cjs/ScriptOnce.cjs.map +1 -1
- package/dist/cjs/ScrollRestoration.cjs +39 -0
- package/dist/cjs/ScrollRestoration.cjs.map +1 -0
- package/dist/cjs/ScrollRestoration.d.cts +15 -0
- package/dist/cjs/Transitioner.cjs +3 -33
- package/dist/cjs/Transitioner.cjs.map +1 -1
- package/dist/cjs/index.cjs +3 -4
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +2 -3
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +10 -2
- package/dist/cjs/router.cjs +37 -23
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +28 -27
- package/dist/cjs/scroll-restoration.cjs +168 -165
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.d.cts +25 -15
- package/dist/esm/Match.js +80 -30
- package/dist/esm/Match.js.map +1 -1
- package/dist/esm/Matches.d.ts +2 -0
- package/dist/esm/Matches.js +4 -1
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/ScriptOnce.js +1 -1
- package/dist/esm/ScriptOnce.js.map +1 -1
- package/dist/esm/ScrollRestoration.d.ts +15 -0
- package/dist/esm/ScrollRestoration.js +39 -0
- package/dist/esm/ScrollRestoration.js.map +1 -0
- package/dist/esm/Transitioner.js +4 -34
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/index.d.ts +2 -3
- package/dist/esm/index.js +1 -2
- package/dist/esm/route.d.ts +10 -2
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +28 -27
- package/dist/esm/router.js +38 -24
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +25 -15
- package/dist/esm/scroll-restoration.js +168 -148
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/package.json +3 -3
- package/src/Match.tsx +101 -54
- package/src/Matches.tsx +3 -1
- package/src/ScriptOnce.tsx +1 -1
- package/src/ScrollRestoration.tsx +65 -0
- package/src/Transitioner.tsx +4 -40
- package/src/index.tsx +3 -3
- package/src/route.ts +38 -1
- package/src/router.ts +75 -49
- package/src/scroll-restoration.tsx +271 -183
package/src/Match.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import invariant from 'tiny-invariant'
|
|
|
5
5
|
import warning from 'tiny-warning'
|
|
6
6
|
import {
|
|
7
7
|
createControlledPromise,
|
|
8
|
+
getLocationChangeInfo,
|
|
8
9
|
pick,
|
|
9
10
|
rootRouteId,
|
|
10
11
|
} from '@tanstack/router-core'
|
|
@@ -16,6 +17,8 @@ import { isRedirect } from './redirects'
|
|
|
16
17
|
import { matchContext } from './matchContext'
|
|
17
18
|
import { SafeFragment } from './SafeFragment'
|
|
18
19
|
import { renderRouteNotFound } from './renderRouteNotFound'
|
|
20
|
+
import { ScrollRestoration } from './scroll-restoration'
|
|
21
|
+
import type { ParsedLocation } from '@tanstack/router-core'
|
|
19
22
|
import type { AnyRoute } from './route'
|
|
20
23
|
|
|
21
24
|
export const Match = React.memo(function MatchImpl({
|
|
@@ -72,41 +75,88 @@ export const Match = React.memo(function MatchImpl({
|
|
|
72
75
|
select: (s) => s.loadedAt,
|
|
73
76
|
})
|
|
74
77
|
|
|
78
|
+
const parentRouteId = useRouterState({
|
|
79
|
+
select: (s) => {
|
|
80
|
+
const index = s.matches.findIndex((d) => d.id === matchId)
|
|
81
|
+
return s.matches[index - 1]?.routeId as string
|
|
82
|
+
},
|
|
83
|
+
})
|
|
84
|
+
|
|
75
85
|
return (
|
|
76
|
-
|
|
77
|
-
<
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
>
|
|
88
|
-
<ResolvedNotFoundBoundary
|
|
89
|
-
fallback={(error) => {
|
|
90
|
-
// If the current not found handler doesn't exist or it has a
|
|
91
|
-
// route ID which doesn't match the current route, rethrow the error
|
|
92
|
-
if (
|
|
93
|
-
!routeNotFoundComponent ||
|
|
94
|
-
(error.routeId && error.routeId !== routeId) ||
|
|
95
|
-
(!error.routeId && !route.isRoot)
|
|
96
|
-
)
|
|
97
|
-
throw error
|
|
98
|
-
|
|
99
|
-
return React.createElement(routeNotFoundComponent, error as any)
|
|
86
|
+
<>
|
|
87
|
+
<matchContext.Provider value={matchId}>
|
|
88
|
+
<ResolvedSuspenseBoundary fallback={pendingElement}>
|
|
89
|
+
<ResolvedCatchBoundary
|
|
90
|
+
getResetKey={() => resetKey}
|
|
91
|
+
errorComponent={routeErrorComponent || ErrorComponent}
|
|
92
|
+
onCatch={(error, errorInfo) => {
|
|
93
|
+
// Forward not found errors (we don't want to show the error component for these)
|
|
94
|
+
if (isNotFound(error)) throw error
|
|
95
|
+
warning(false, `Error in route match: ${matchId}`)
|
|
96
|
+
routeOnCatch?.(error, errorInfo)
|
|
100
97
|
}}
|
|
101
98
|
>
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
99
|
+
<ResolvedNotFoundBoundary
|
|
100
|
+
fallback={(error) => {
|
|
101
|
+
// If the current not found handler doesn't exist or it has a
|
|
102
|
+
// route ID which doesn't match the current route, rethrow the error
|
|
103
|
+
if (
|
|
104
|
+
!routeNotFoundComponent ||
|
|
105
|
+
(error.routeId && error.routeId !== routeId) ||
|
|
106
|
+
(!error.routeId && !route.isRoot)
|
|
107
|
+
)
|
|
108
|
+
throw error
|
|
109
|
+
|
|
110
|
+
return React.createElement(routeNotFoundComponent, error as any)
|
|
111
|
+
}}
|
|
112
|
+
>
|
|
113
|
+
<MatchInner matchId={matchId} />
|
|
114
|
+
</ResolvedNotFoundBoundary>
|
|
115
|
+
</ResolvedCatchBoundary>
|
|
116
|
+
</ResolvedSuspenseBoundary>
|
|
117
|
+
</matchContext.Provider>
|
|
118
|
+
{parentRouteId === rootRouteId ? (
|
|
119
|
+
<>
|
|
120
|
+
<OnRendered />
|
|
121
|
+
<ScrollRestoration />
|
|
122
|
+
</>
|
|
123
|
+
) : null}
|
|
124
|
+
</>
|
|
107
125
|
)
|
|
108
126
|
})
|
|
109
127
|
|
|
128
|
+
// On Rendered can't happen above the root layout because it actually
|
|
129
|
+
// renders a dummy dom element to track the rendered state of the app.
|
|
130
|
+
// We render a script tag with a key that changes based on the current
|
|
131
|
+
// location state.key. Also, because it's below the root layout, it
|
|
132
|
+
// allows us to fire onRendered events even after a hydration mismatch
|
|
133
|
+
// error that occurred above the root layout (like bad head/link tags,
|
|
134
|
+
// which is common).
|
|
135
|
+
function OnRendered() {
|
|
136
|
+
const router = useRouter()
|
|
137
|
+
|
|
138
|
+
const prevLocationRef = React.useRef<undefined | ParsedLocation<{}>>(
|
|
139
|
+
undefined,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<script
|
|
144
|
+
key={router.state.resolvedLocation?.state.key}
|
|
145
|
+
suppressHydrationWarning
|
|
146
|
+
ref={(el) => {
|
|
147
|
+
if (el) {
|
|
148
|
+
router.emit({
|
|
149
|
+
type: 'onRendered',
|
|
150
|
+
...getLocationChangeInfo(router.state),
|
|
151
|
+
})
|
|
152
|
+
} else {
|
|
153
|
+
prevLocationRef.current = router.state.resolvedLocation
|
|
154
|
+
}
|
|
155
|
+
}}
|
|
156
|
+
/>
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
110
160
|
export const MatchInner = React.memo(function MatchInnerImpl({
|
|
111
161
|
matchId,
|
|
112
162
|
}: {
|
|
@@ -114,45 +164,41 @@ export const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
114
164
|
}): any {
|
|
115
165
|
const router = useRouter()
|
|
116
166
|
|
|
117
|
-
const { match,
|
|
167
|
+
const { match, key, routeId } = useRouterState({
|
|
118
168
|
select: (s) => {
|
|
119
169
|
const matchIndex = s.matches.findIndex((d) => d.id === matchId)
|
|
120
170
|
const match = s.matches[matchIndex]!
|
|
121
171
|
const routeId = match.routeId as string
|
|
172
|
+
|
|
173
|
+
const remountFn =
|
|
174
|
+
(router.routesById[routeId] as AnyRoute).options.remountDeps ??
|
|
175
|
+
router.options.defaultRemountDeps
|
|
176
|
+
const remountDeps = remountFn?.({
|
|
177
|
+
routeId,
|
|
178
|
+
loaderDeps: match.loaderDeps,
|
|
179
|
+
params: match._strictParams,
|
|
180
|
+
search: match._strictSearch,
|
|
181
|
+
})
|
|
182
|
+
const key = remountDeps ? JSON.stringify(remountDeps) : undefined
|
|
183
|
+
|
|
122
184
|
return {
|
|
185
|
+
key,
|
|
123
186
|
routeId,
|
|
124
|
-
matchIndex,
|
|
125
187
|
match: pick(match, ['id', 'status', 'error']),
|
|
126
188
|
}
|
|
127
189
|
},
|
|
128
190
|
structuralSharing: true as any,
|
|
129
191
|
})
|
|
130
192
|
|
|
131
|
-
const route = router.routesById[routeId]
|
|
193
|
+
const route = router.routesById[routeId] as AnyRoute
|
|
132
194
|
|
|
133
195
|
const out = React.useMemo(() => {
|
|
134
196
|
const Comp = route.options.component ?? router.options.defaultComponent
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// const changed = ref.current !== value
|
|
141
|
-
// if (changed) {
|
|
142
|
-
// console.log(
|
|
143
|
-
// 'Changed:',
|
|
144
|
-
// value,
|
|
145
|
-
// Object.fromEntries(
|
|
146
|
-
// Object.entries(value).filter(
|
|
147
|
-
// ([key, val]) => val !== ref.current[key],
|
|
148
|
-
// ),
|
|
149
|
-
// ),
|
|
150
|
-
// )
|
|
151
|
-
// }
|
|
152
|
-
// ref.current = value
|
|
153
|
-
// }
|
|
154
|
-
|
|
155
|
-
// useChangedDiff(match)
|
|
197
|
+
if (Comp) {
|
|
198
|
+
return <Comp key={key} />
|
|
199
|
+
}
|
|
200
|
+
return <Outlet />
|
|
201
|
+
}, [key, route.options.component, router.options.defaultComponent])
|
|
156
202
|
|
|
157
203
|
const RouteErrorComponent =
|
|
158
204
|
(route.options.errorComponent ?? router.options.defaultErrorComponent) ||
|
|
@@ -184,7 +230,8 @@ export const MatchInner = React.memo(function MatchInnerImpl({
|
|
|
184
230
|
if (router.isServer) {
|
|
185
231
|
return (
|
|
186
232
|
<RouteErrorComponent
|
|
187
|
-
error={match.error}
|
|
233
|
+
error={match.error as any}
|
|
234
|
+
reset={undefined as any}
|
|
188
235
|
info={{
|
|
189
236
|
componentStack: '',
|
|
190
237
|
}}
|
package/src/Matches.tsx
CHANGED
|
@@ -63,6 +63,7 @@ export interface RouteMatch<
|
|
|
63
63
|
index: number
|
|
64
64
|
pathname: string
|
|
65
65
|
params: TAllParams
|
|
66
|
+
_strictParams: TAllParams
|
|
66
67
|
status: 'pending' | 'success' | 'error' | 'redirected' | 'notFound'
|
|
67
68
|
isFetching: false | 'beforeLoad' | 'loader'
|
|
68
69
|
error: unknown
|
|
@@ -77,6 +78,7 @@ export interface RouteMatch<
|
|
|
77
78
|
__beforeLoadContext: Record<string, unknown>
|
|
78
79
|
context: TAllContext
|
|
79
80
|
search: TFullSearchSchema
|
|
81
|
+
_strictSearch: TFullSearchSchema
|
|
80
82
|
fetchCount: number
|
|
81
83
|
abortController: AbortController
|
|
82
84
|
cause: 'preload' | 'enter' | 'stay'
|
|
@@ -197,7 +199,7 @@ export function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>() {
|
|
|
197
199
|
const router = useRouter()
|
|
198
200
|
|
|
199
201
|
useRouterState({
|
|
200
|
-
select: (s) => [s.location.href, s.resolvedLocation
|
|
202
|
+
select: (s) => [s.location.href, s.resolvedLocation?.href, s.status],
|
|
201
203
|
structuralSharing: true as any,
|
|
202
204
|
})
|
|
203
205
|
|
package/src/ScriptOnce.tsx
CHANGED
|
@@ -22,7 +22,7 @@ export function ScriptOnce({
|
|
|
22
22
|
? `console.info(\`Injected From Server:
|
|
23
23
|
${jsesc(children.toString(), { quotes: 'backtick' })}\`)`
|
|
24
24
|
: '',
|
|
25
|
-
'if (typeof
|
|
25
|
+
'if (typeof __TSR_SSR__ !== "undefined") __TSR_SSR__.cleanScripts()',
|
|
26
26
|
]
|
|
27
27
|
.filter(Boolean)
|
|
28
28
|
.join('\n'),
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useRouter } from './useRouter'
|
|
2
|
+
import {
|
|
3
|
+
defaultGetScrollRestorationKey,
|
|
4
|
+
getCssSelector,
|
|
5
|
+
scrollRestorationCache,
|
|
6
|
+
setupScrollRestoration,
|
|
7
|
+
} from './scroll-restoration'
|
|
8
|
+
import type { ScrollRestorationOptions } from './scroll-restoration'
|
|
9
|
+
import type { ParsedLocation } from '@tanstack/router-core'
|
|
10
|
+
|
|
11
|
+
function useScrollRestoration() {
|
|
12
|
+
const router = useRouter()
|
|
13
|
+
setupScrollRestoration(router, true)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @deprecated use createRouter's `scrollRestoration` option instead
|
|
18
|
+
*/
|
|
19
|
+
export function ScrollRestoration(_props: ScrollRestorationOptions) {
|
|
20
|
+
useScrollRestoration()
|
|
21
|
+
|
|
22
|
+
if (process.env.NODE_ENV === 'development') {
|
|
23
|
+
console.warn(
|
|
24
|
+
"The ScrollRestoration component is deprecated. Use createRouter's `scrollRestoration` option instead.",
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function useElementScrollRestoration(
|
|
32
|
+
options: (
|
|
33
|
+
| {
|
|
34
|
+
id: string
|
|
35
|
+
getElement?: () => Element | undefined | null
|
|
36
|
+
}
|
|
37
|
+
| {
|
|
38
|
+
id?: string
|
|
39
|
+
getElement: () => Element | undefined | null
|
|
40
|
+
}
|
|
41
|
+
) & {
|
|
42
|
+
getKey?: (location: ParsedLocation) => string
|
|
43
|
+
},
|
|
44
|
+
) {
|
|
45
|
+
useScrollRestoration()
|
|
46
|
+
|
|
47
|
+
const router = useRouter()
|
|
48
|
+
const getKey = options.getKey || defaultGetScrollRestorationKey
|
|
49
|
+
|
|
50
|
+
let elementSelector = ''
|
|
51
|
+
|
|
52
|
+
if (options.id) {
|
|
53
|
+
elementSelector = `[data-scroll-restoration-id="${options.id}"]`
|
|
54
|
+
} else {
|
|
55
|
+
const element = options.getElement?.()
|
|
56
|
+
if (!element) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
elementSelector = getCssSelector(element)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const restoreKey = getKey(router.latestLocation)
|
|
63
|
+
const byKey = scrollRestorationCache.state[restoreKey]
|
|
64
|
+
return byKey?.[elementSelector]
|
|
65
|
+
}
|
package/src/Transitioner.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import { trimPathRight } from '@tanstack/router-core'
|
|
2
|
+
import { getLocationChangeInfo, trimPathRight } from '@tanstack/router-core'
|
|
3
3
|
import { useLayoutEffect, usePrevious } from './utils'
|
|
4
4
|
import { useRouter } from './useRouter'
|
|
5
5
|
import { useRouterState } from './useRouterState'
|
|
@@ -87,17 +87,9 @@ export function Transitioner() {
|
|
|
87
87
|
useLayoutEffect(() => {
|
|
88
88
|
// The router was loading and now it's not
|
|
89
89
|
if (previousIsLoading && !isLoading) {
|
|
90
|
-
const toLocation = router.state.location
|
|
91
|
-
const fromLocation = router.state.resolvedLocation
|
|
92
|
-
const pathChanged = fromLocation.pathname !== toLocation.pathname
|
|
93
|
-
const hrefChanged = fromLocation.href !== toLocation.href
|
|
94
|
-
|
|
95
90
|
router.emit({
|
|
96
91
|
type: 'onLoad', // When the new URL has committed, when the new matches have been loaded into state.matches
|
|
97
|
-
|
|
98
|
-
toLocation,
|
|
99
|
-
pathChanged,
|
|
100
|
-
hrefChanged,
|
|
92
|
+
...getLocationChangeInfo(router.state),
|
|
101
93
|
})
|
|
102
94
|
}
|
|
103
95
|
}, [previousIsLoading, router, isLoading])
|
|
@@ -105,17 +97,9 @@ export function Transitioner() {
|
|
|
105
97
|
useLayoutEffect(() => {
|
|
106
98
|
// emit onBeforeRouteMount
|
|
107
99
|
if (previousIsPagePending && !isPagePending) {
|
|
108
|
-
const toLocation = router.state.location
|
|
109
|
-
const fromLocation = router.state.resolvedLocation
|
|
110
|
-
const pathChanged = fromLocation.pathname !== toLocation.pathname
|
|
111
|
-
const hrefChanged = fromLocation.href !== toLocation.href
|
|
112
|
-
|
|
113
100
|
router.emit({
|
|
114
101
|
type: 'onBeforeRouteMount',
|
|
115
|
-
|
|
116
|
-
toLocation,
|
|
117
|
-
pathChanged,
|
|
118
|
-
hrefChanged,
|
|
102
|
+
...getLocationChangeInfo(router.state),
|
|
119
103
|
})
|
|
120
104
|
}
|
|
121
105
|
}, [isPagePending, previousIsPagePending, router])
|
|
@@ -123,17 +107,9 @@ export function Transitioner() {
|
|
|
123
107
|
useLayoutEffect(() => {
|
|
124
108
|
// The router was pending and now it's not
|
|
125
109
|
if (previousIsAnyPending && !isAnyPending) {
|
|
126
|
-
const toLocation = router.state.location
|
|
127
|
-
const fromLocation = router.state.resolvedLocation
|
|
128
|
-
const pathChanged = fromLocation.pathname !== toLocation.pathname
|
|
129
|
-
const hrefChanged = fromLocation.href !== toLocation.href
|
|
130
|
-
|
|
131
110
|
router.emit({
|
|
132
111
|
type: 'onResolved',
|
|
133
|
-
|
|
134
|
-
toLocation,
|
|
135
|
-
pathChanged,
|
|
136
|
-
hrefChanged,
|
|
112
|
+
...getLocationChangeInfo(router.state),
|
|
137
113
|
})
|
|
138
114
|
|
|
139
115
|
router.__store.setState((s) => ({
|
|
@@ -141,18 +117,6 @@ export function Transitioner() {
|
|
|
141
117
|
status: 'idle',
|
|
142
118
|
resolvedLocation: s.location,
|
|
143
119
|
}))
|
|
144
|
-
|
|
145
|
-
if (typeof document !== 'undefined' && (document as any).querySelector) {
|
|
146
|
-
const hashScrollIntoViewOptions =
|
|
147
|
-
router.state.location.state.__hashScrollIntoViewOptions ?? true
|
|
148
|
-
|
|
149
|
-
if (hashScrollIntoViewOptions && router.state.location.hash !== '') {
|
|
150
|
-
const el = document.getElementById(router.state.location.hash)
|
|
151
|
-
if (el) {
|
|
152
|
-
el.scrollIntoView(hashScrollIntoViewOptions)
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
120
|
}
|
|
157
121
|
}, [isAnyPending, previousIsAnyPending, router])
|
|
158
122
|
|
package/src/index.tsx
CHANGED
|
@@ -259,6 +259,8 @@ export type {
|
|
|
259
259
|
BeforeLoadContextParameter,
|
|
260
260
|
ResolveAllContext,
|
|
261
261
|
ResolveAllParamsFromParent,
|
|
262
|
+
MakeRemountDepsOptionsUnion,
|
|
263
|
+
RemountDepsOptions,
|
|
262
264
|
} from './route'
|
|
263
265
|
|
|
264
266
|
export type {
|
|
@@ -315,11 +317,9 @@ export type {
|
|
|
315
317
|
} from './RouterProvider'
|
|
316
318
|
|
|
317
319
|
export {
|
|
318
|
-
useScrollRestoration,
|
|
319
320
|
useElementScrollRestoration,
|
|
320
321
|
ScrollRestoration,
|
|
321
|
-
} from './
|
|
322
|
-
export type { ScrollRestorationOptions } from './scroll-restoration'
|
|
322
|
+
} from './ScrollRestoration'
|
|
323
323
|
|
|
324
324
|
export type { UseBlockerOpts, ShouldBlockFn } from './useBlocker'
|
|
325
325
|
export { useBlocker, Block } from './useBlocker'
|
package/src/route.ts
CHANGED
|
@@ -59,7 +59,7 @@ import type {
|
|
|
59
59
|
RouteMatch,
|
|
60
60
|
} from './Matches'
|
|
61
61
|
import type { NavigateOptions, ToMaskOptions } from './link'
|
|
62
|
-
import type { RouteById, RouteIds, RoutePaths } from './routeInfo'
|
|
62
|
+
import type { ParseRoute, RouteById, RouteIds, RoutePaths } from './routeInfo'
|
|
63
63
|
import type { AnyRouter, RegisteredRouter, Router } from './router'
|
|
64
64
|
import type { BuildLocationFn, NavigateFn } from './RouterProvider'
|
|
65
65
|
import type { NotFoundError } from './not-found'
|
|
@@ -154,6 +154,7 @@ export type FileBaseRouteOptions<
|
|
|
154
154
|
TRouterContext = {},
|
|
155
155
|
TRouteContextFn = AnyContext,
|
|
156
156
|
TBeforeLoadFn = AnyContext,
|
|
157
|
+
TRemountDepsFn = AnyContext,
|
|
157
158
|
> = ParamsOptions<TPath, TParams> & {
|
|
158
159
|
validateSearch?: Constrain<TSearchValidator, AnyValidator, DefaultValidator>
|
|
159
160
|
|
|
@@ -204,6 +205,18 @@ export type FileBaseRouteOptions<
|
|
|
204
205
|
opts: FullSearchSchemaOption<TParentRoute, TSearchValidator>,
|
|
205
206
|
) => TLoaderDeps
|
|
206
207
|
|
|
208
|
+
remountDeps?: Constrain<
|
|
209
|
+
TRemountDepsFn,
|
|
210
|
+
(
|
|
211
|
+
opt: RemountDepsOptions<
|
|
212
|
+
TId,
|
|
213
|
+
FullSearchSchemaOption<TParentRoute, TSearchValidator>,
|
|
214
|
+
Expand<ResolveAllParamsFromParent<TParentRoute, TParams>>,
|
|
215
|
+
TLoaderDeps
|
|
216
|
+
>,
|
|
217
|
+
) => any
|
|
218
|
+
>
|
|
219
|
+
|
|
207
220
|
loader?: Constrain<
|
|
208
221
|
TLoaderFn,
|
|
209
222
|
(
|
|
@@ -275,6 +288,30 @@ export interface RouteContextOptions<
|
|
|
275
288
|
context: Expand<RouteContextParameter<TParentRoute, TRouterContext>>
|
|
276
289
|
}
|
|
277
290
|
|
|
291
|
+
export interface RemountDepsOptions<
|
|
292
|
+
in out TRouteId,
|
|
293
|
+
in out TFullSearchSchema,
|
|
294
|
+
in out TAllParams,
|
|
295
|
+
in out TLoaderDeps,
|
|
296
|
+
> {
|
|
297
|
+
routeId: TRouteId
|
|
298
|
+
search: TFullSearchSchema
|
|
299
|
+
params: TAllParams
|
|
300
|
+
loaderDeps: TLoaderDeps
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export type MakeRemountDepsOptionsUnion<
|
|
304
|
+
TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
|
|
305
|
+
TRoute extends AnyRoute = ParseRoute<TRouteTree>,
|
|
306
|
+
> = TRoute extends any
|
|
307
|
+
? RemountDepsOptions<
|
|
308
|
+
TRoute['id'],
|
|
309
|
+
TRoute['types']['fullSearchSchema'],
|
|
310
|
+
TRoute['types']['allParams'],
|
|
311
|
+
TRoute['types']['loaderDeps']
|
|
312
|
+
>
|
|
313
|
+
: never
|
|
314
|
+
|
|
278
315
|
export interface BeforeLoadContextOptions<
|
|
279
316
|
in out TParentRoute extends AnyRoute,
|
|
280
317
|
in out TSearchValidator,
|