@tanstack/react-router 1.98.0 → 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 +60 -22
- 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/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 +1 -2
- package/dist/cjs/router.cjs +14 -12
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +26 -26
- 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 +62 -24
- package/dist/esm/Match.js.map +1 -1
- 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 +1 -2
- package/dist/esm/index.js +1 -2
- package/dist/esm/router.d.ts +26 -26
- package/dist/esm/router.js +15 -13
- 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 +79 -48
- package/src/Matches.tsx +1 -1
- package/src/ScriptOnce.tsx +1 -1
- package/src/ScrollRestoration.tsx +65 -0
- package/src/Transitioner.tsx +4 -40
- package/src/index.tsx +1 -3
- package/src/router.ts +43 -38
- package/src/scroll-restoration.tsx +271 -183
|
@@ -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
|
@@ -317,11 +317,9 @@ export type {
|
|
|
317
317
|
} from './RouterProvider'
|
|
318
318
|
|
|
319
319
|
export {
|
|
320
|
-
useScrollRestoration,
|
|
321
320
|
useElementScrollRestoration,
|
|
322
321
|
ScrollRestoration,
|
|
323
|
-
} from './
|
|
324
|
-
export type { ScrollRestorationOptions } from './scroll-restoration'
|
|
322
|
+
} from './ScrollRestoration'
|
|
325
323
|
|
|
326
324
|
export type { UseBlockerOpts, ShouldBlockFn } from './useBlocker'
|
|
327
325
|
export { useBlocker, Block } from './useBlocker'
|
package/src/router.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
defaultParseSearch,
|
|
13
13
|
defaultStringifySearch,
|
|
14
14
|
functionalUpdate,
|
|
15
|
+
getLocationChangeInfo,
|
|
15
16
|
interpolatePath,
|
|
16
17
|
joinPaths,
|
|
17
18
|
last,
|
|
@@ -27,6 +28,8 @@ import {
|
|
|
27
28
|
} from '@tanstack/router-core'
|
|
28
29
|
import { isRedirect, isResolvedRedirect } from './redirects'
|
|
29
30
|
import { isNotFound } from './not-found'
|
|
31
|
+
|
|
32
|
+
import { setupScrollRestoration } from './scroll-restoration'
|
|
30
33
|
import type * as React from 'react'
|
|
31
34
|
import type {
|
|
32
35
|
HistoryLocation,
|
|
@@ -454,6 +457,15 @@ export interface RouterOptions<
|
|
|
454
457
|
>
|
|
455
458
|
|
|
456
459
|
defaultRemountDeps?: (opts: MakeRemountDepsOptionsUnion<TRouteTree>) => any
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* If `false`, scroll restoration will be disabled
|
|
463
|
+
*
|
|
464
|
+
* @default true
|
|
465
|
+
*/
|
|
466
|
+
scrollRestoration?: boolean
|
|
467
|
+
getScrollRestorationKey?: (location: ParsedLocation) => string
|
|
468
|
+
scrollRestorationBehavior?: ScrollBehavior
|
|
457
469
|
}
|
|
458
470
|
|
|
459
471
|
export interface RouterErrorSerializer<TSerializedError> {
|
|
@@ -473,7 +485,7 @@ export interface RouterState<
|
|
|
473
485
|
pendingMatches?: Array<TRouteMatch>
|
|
474
486
|
cachedMatches: Array<TRouteMatch>
|
|
475
487
|
location: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
476
|
-
resolvedLocation
|
|
488
|
+
resolvedLocation?: ParsedLocation<FullSearchSchema<TRouteTree>>
|
|
477
489
|
statusCode: number
|
|
478
490
|
redirect?: ResolvedRedirect
|
|
479
491
|
}
|
|
@@ -566,46 +578,37 @@ function validateSearch(validateSearch: AnyValidator, input: unknown): unknown {
|
|
|
566
578
|
return {}
|
|
567
579
|
}
|
|
568
580
|
|
|
581
|
+
type NavigationEventInfo = {
|
|
582
|
+
fromLocation?: ParsedLocation
|
|
583
|
+
toLocation: ParsedLocation
|
|
584
|
+
pathChanged: boolean
|
|
585
|
+
hrefChanged: boolean
|
|
586
|
+
hashChanged: boolean
|
|
587
|
+
}
|
|
588
|
+
|
|
569
589
|
export type RouterEvents = {
|
|
570
590
|
onBeforeNavigate: {
|
|
571
591
|
type: 'onBeforeNavigate'
|
|
572
|
-
|
|
573
|
-
toLocation: ParsedLocation
|
|
574
|
-
pathChanged: boolean
|
|
575
|
-
hrefChanged: boolean
|
|
576
|
-
}
|
|
592
|
+
} & NavigationEventInfo
|
|
577
593
|
onBeforeLoad: {
|
|
578
594
|
type: 'onBeforeLoad'
|
|
579
|
-
|
|
580
|
-
toLocation: ParsedLocation
|
|
581
|
-
pathChanged: boolean
|
|
582
|
-
hrefChanged: boolean
|
|
583
|
-
}
|
|
595
|
+
} & NavigationEventInfo
|
|
584
596
|
onLoad: {
|
|
585
597
|
type: 'onLoad'
|
|
586
|
-
|
|
587
|
-
toLocation: ParsedLocation
|
|
588
|
-
pathChanged: boolean
|
|
589
|
-
hrefChanged: boolean
|
|
590
|
-
}
|
|
598
|
+
} & NavigationEventInfo
|
|
591
599
|
onResolved: {
|
|
592
600
|
type: 'onResolved'
|
|
593
|
-
|
|
594
|
-
toLocation: ParsedLocation
|
|
595
|
-
pathChanged: boolean
|
|
596
|
-
hrefChanged: boolean
|
|
597
|
-
}
|
|
601
|
+
} & NavigationEventInfo
|
|
598
602
|
onBeforeRouteMount: {
|
|
599
603
|
type: 'onBeforeRouteMount'
|
|
600
|
-
|
|
601
|
-
toLocation: ParsedLocation
|
|
602
|
-
pathChanged: boolean
|
|
603
|
-
hrefChanged: boolean
|
|
604
|
-
}
|
|
604
|
+
} & NavigationEventInfo
|
|
605
605
|
onInjectedHtml: {
|
|
606
606
|
type: 'onInjectedHtml'
|
|
607
607
|
promise: Promise<string>
|
|
608
608
|
}
|
|
609
|
+
onRendered: {
|
|
610
|
+
type: 'onRendered'
|
|
611
|
+
} & NavigationEventInfo
|
|
609
612
|
}
|
|
610
613
|
|
|
611
614
|
export type RouterEvent = RouterEvents[keyof RouterEvents]
|
|
@@ -667,6 +670,8 @@ export class Router<
|
|
|
667
670
|
isViewTransitionTypesSupported?: boolean = undefined
|
|
668
671
|
subscribers = new Set<RouterListener<RouterEvent>>()
|
|
669
672
|
viewTransitionPromise?: ControlledPromise<true>
|
|
673
|
+
isScrollRestoring = false
|
|
674
|
+
isScrollRestorationSetup = false
|
|
670
675
|
|
|
671
676
|
// Must build in constructor
|
|
672
677
|
__store!: Store<RouterState<TRouteTree>>
|
|
@@ -803,6 +808,8 @@ export class Router<
|
|
|
803
808
|
}
|
|
804
809
|
},
|
|
805
810
|
})
|
|
811
|
+
|
|
812
|
+
setupScrollRestoration(this)
|
|
806
813
|
}
|
|
807
814
|
|
|
808
815
|
if (
|
|
@@ -1881,8 +1888,6 @@ export class Router<
|
|
|
1881
1888
|
try {
|
|
1882
1889
|
const next = this.latestLocation
|
|
1883
1890
|
const prevLocation = this.state.resolvedLocation
|
|
1884
|
-
const hrefChanged = prevLocation.href !== next.href
|
|
1885
|
-
const pathChanged = prevLocation.pathname !== next.pathname
|
|
1886
1891
|
|
|
1887
1892
|
// Cancel any pending matches
|
|
1888
1893
|
this.cancelMatches()
|
|
@@ -1914,19 +1919,19 @@ export class Router<
|
|
|
1914
1919
|
if (!this.state.redirect) {
|
|
1915
1920
|
this.emit({
|
|
1916
1921
|
type: 'onBeforeNavigate',
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1922
|
+
...getLocationChangeInfo({
|
|
1923
|
+
resolvedLocation: prevLocation,
|
|
1924
|
+
location: next,
|
|
1925
|
+
}),
|
|
1921
1926
|
})
|
|
1922
1927
|
}
|
|
1923
1928
|
|
|
1924
1929
|
this.emit({
|
|
1925
1930
|
type: 'onBeforeLoad',
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1931
|
+
...getLocationChangeInfo({
|
|
1932
|
+
resolvedLocation: prevLocation,
|
|
1933
|
+
location: next,
|
|
1934
|
+
}),
|
|
1930
1935
|
})
|
|
1931
1936
|
|
|
1932
1937
|
await this.loadMatches({
|
|
@@ -2903,7 +2908,7 @@ export class Router<
|
|
|
2903
2908
|
|
|
2904
2909
|
const baseLocation = pending
|
|
2905
2910
|
? this.latestLocation
|
|
2906
|
-
: this.state.resolvedLocation
|
|
2911
|
+
: this.state.resolvedLocation || this.state.location
|
|
2907
2912
|
|
|
2908
2913
|
const match = matchPathname(this.basepath, baseLocation.pathname, {
|
|
2909
2914
|
...opts,
|
|
@@ -3041,7 +3046,7 @@ export function getInitialRouterState(
|
|
|
3041
3046
|
isLoading: false,
|
|
3042
3047
|
isTransitioning: false,
|
|
3043
3048
|
status: 'idle',
|
|
3044
|
-
resolvedLocation:
|
|
3049
|
+
resolvedLocation: undefined,
|
|
3045
3050
|
location,
|
|
3046
3051
|
matches: [],
|
|
3047
3052
|
pendingMatches: [],
|