@tanstack/react-router 0.0.1-beta.163 → 0.0.1-beta.164
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/build/cjs/index.js +1 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/scroll-restoration.js +8 -116
- package/build/cjs/scroll-restoration.js.map +1 -1
- package/build/esm/index.js +8 -118
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +80 -74
- package/build/types/index.d.ts +4 -3
- package/build/umd/index.development.js +103 -91
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +3 -3
- package/src/scroll-restoration.tsx +12 -148
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-router",
|
|
3
3
|
"author": "Tanner Linsley",
|
|
4
|
-
"version": "0.0.1-beta.
|
|
4
|
+
"version": "0.0.1-beta.164",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "tanstack/router",
|
|
7
7
|
"homepage": "https://tanstack.com/router",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"tiny-invariant": "^1.3.1",
|
|
44
44
|
"tiny-warning": "^1.0.3",
|
|
45
45
|
"@gisatcz/cross-package-react-context": "^0.2.0",
|
|
46
|
-
"@tanstack/router-core": "0.0.1-beta.
|
|
47
|
-
"@tanstack/react-store": "0.0.1-beta.
|
|
46
|
+
"@tanstack/router-core": "0.0.1-beta.164",
|
|
47
|
+
"@tanstack/react-store": "0.0.1-beta.164"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "rollup --config rollup.config.js"
|
|
@@ -1,163 +1,27 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ScrollRestorationOptions,
|
|
4
|
+
restoreScrollPositions,
|
|
5
|
+
watchScrollPositions,
|
|
6
|
+
} from '@tanstack/router-core'
|
|
7
|
+
import { useRouter } from '.'
|
|
3
8
|
|
|
4
9
|
const useLayoutEffect =
|
|
5
10
|
typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
const delimiter = '___'
|
|
9
|
-
|
|
10
|
-
let weakScrolledElementsByRestoreKey: Record<string, WeakSet<any>> = {}
|
|
11
|
-
|
|
12
|
-
const cache = (() => {
|
|
13
|
-
if (typeof window === 'undefined') {
|
|
14
|
-
return {
|
|
15
|
-
set: () => {},
|
|
16
|
-
get: () => {},
|
|
17
|
-
} as never
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const storageKey = 'tsr-scroll-restoration-v1'
|
|
21
|
-
|
|
22
|
-
let cache = JSON.parse(window.sessionStorage.getItem(storageKey) || '{}')
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
current: cache,
|
|
26
|
-
set: (key: string, value: any) => {
|
|
27
|
-
cache[key] = value
|
|
28
|
-
window.sessionStorage.setItem(storageKey, JSON.stringify(cache))
|
|
29
|
-
},
|
|
30
|
-
}
|
|
31
|
-
})()
|
|
32
|
-
|
|
33
|
-
export function ScrollRestoration() {
|
|
12
|
+
export function useScrollRestoration(options?: ScrollRestorationOptions) {
|
|
34
13
|
const router = useRouter()
|
|
35
|
-
const getKey = (location: ParsedLocation) => location.key as string
|
|
36
|
-
|
|
37
|
-
const pathDidChangeRef = React.useRef(false)
|
|
38
|
-
|
|
39
|
-
const restoreScrollPositions = () => {
|
|
40
|
-
const restoreKey = getKey(router.state.location)
|
|
41
|
-
let windowRestored = false
|
|
42
|
-
|
|
43
|
-
for (const cacheKey in cache.current) {
|
|
44
|
-
const entry = cache.current[cacheKey]!
|
|
45
|
-
const [key, elementSelector] = cacheKey.split(delimiter)
|
|
46
|
-
if (key === restoreKey) {
|
|
47
|
-
if (elementSelector === windowKey) {
|
|
48
|
-
windowRestored = true
|
|
49
|
-
window.scrollTo(entry.scrollX, entry.scrollY)
|
|
50
|
-
} else if (elementSelector) {
|
|
51
|
-
const element = document.querySelector(elementSelector)
|
|
52
|
-
if (element) {
|
|
53
|
-
element.scrollLeft = entry.scrollX
|
|
54
|
-
element.scrollTop = entry.scrollY
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (!windowRestored) {
|
|
61
|
-
window.scrollTo(0, 0)
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
14
|
|
|
65
15
|
useLayoutEffect(() => {
|
|
66
|
-
|
|
67
|
-
if (history.scrollRestoration) {
|
|
68
|
-
history.scrollRestoration = 'manual'
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const onScroll = (event: Event) => {
|
|
72
|
-
const restoreKey = getKey(router.state.resolvedLocation)
|
|
73
|
-
|
|
74
|
-
if (!weakScrolledElementsByRestoreKey[restoreKey]) {
|
|
75
|
-
weakScrolledElementsByRestoreKey[restoreKey] = new WeakSet()
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const set = weakScrolledElementsByRestoreKey[restoreKey]!
|
|
79
|
-
|
|
80
|
-
if (set.has(event.target)) return
|
|
81
|
-
set.add(event.target)
|
|
82
|
-
|
|
83
|
-
const cacheKey = [
|
|
84
|
-
restoreKey,
|
|
85
|
-
event.target === document || event.target === window
|
|
86
|
-
? windowKey
|
|
87
|
-
: getCssSelector(event.target),
|
|
88
|
-
].join(delimiter)
|
|
89
|
-
|
|
90
|
-
if (!cache.current[cacheKey]) {
|
|
91
|
-
cache.set(cacheKey, {
|
|
92
|
-
scrollX: NaN,
|
|
93
|
-
scrollY: NaN,
|
|
94
|
-
})
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const getCssSelector = (el: any): string => {
|
|
99
|
-
let path = [],
|
|
100
|
-
parent
|
|
101
|
-
while ((parent = el.parentNode)) {
|
|
102
|
-
path.unshift(
|
|
103
|
-
`${el.tagName}:nth-child(${
|
|
104
|
-
([].indexOf as any).call(parent.children, el) + 1
|
|
105
|
-
})`,
|
|
106
|
-
)
|
|
107
|
-
el = parent
|
|
108
|
-
}
|
|
109
|
-
return `${path.join(' > ')}`.toLowerCase()
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const onPathWillChange = (from: ParsedLocation) => {
|
|
113
|
-
const restoreKey = getKey(from)
|
|
114
|
-
for (const cacheKey in cache.current) {
|
|
115
|
-
const entry = cache.current[cacheKey]!
|
|
116
|
-
const [key, elementSelector] = cacheKey.split(delimiter)
|
|
117
|
-
if (restoreKey === key) {
|
|
118
|
-
if (elementSelector === windowKey) {
|
|
119
|
-
entry.scrollX = window.scrollX || 0
|
|
120
|
-
entry.scrollY = window.scrollY || 0
|
|
121
|
-
} else if (elementSelector) {
|
|
122
|
-
const element = document.querySelector(elementSelector)
|
|
123
|
-
entry.scrollX = element?.scrollLeft || 0
|
|
124
|
-
entry.scrollY = element?.scrollTop || 0
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
cache.set(cacheKey, entry)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const onPathChange = () => {
|
|
133
|
-
pathDidChangeRef.current = true
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (typeof document !== 'undefined') {
|
|
137
|
-
document.addEventListener('scroll', onScroll, true)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const unsubOnBeforeLoad = router.subscribe('onBeforeLoad', (event) => {
|
|
141
|
-
if (event.pathChanged) onPathWillChange(event.from)
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
const unsubOnLoad = router.subscribe('onLoad', (event) => {
|
|
145
|
-
if (event.pathChanged) onPathChange()
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
return () => {
|
|
149
|
-
document.removeEventListener('scroll', onScroll)
|
|
150
|
-
unsubOnBeforeLoad()
|
|
151
|
-
unsubOnLoad()
|
|
152
|
-
}
|
|
16
|
+
return watchScrollPositions(router, options)
|
|
153
17
|
}, [])
|
|
154
18
|
|
|
155
19
|
useLayoutEffect(() => {
|
|
156
|
-
|
|
157
|
-
pathDidChangeRef.current = false
|
|
158
|
-
restoreScrollPositions()
|
|
159
|
-
}
|
|
20
|
+
restoreScrollPositions(router, options)
|
|
160
21
|
})
|
|
22
|
+
}
|
|
161
23
|
|
|
24
|
+
export function ScrollRestoration(props: ScrollRestorationOptions) {
|
|
25
|
+
useScrollRestoration(props)
|
|
162
26
|
return null
|
|
163
27
|
}
|