@tanstack/react-router 0.0.1-beta.211 → 0.0.1-beta.213
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/RouterProvider.js +42 -46
- package/build/cjs/RouterProvider.js.map +1 -1
- package/build/cjs/index.js +3 -0
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/link.js +1 -0
- package/build/cjs/link.js.map +1 -1
- package/build/cjs/router.js.map +1 -1
- package/build/cjs/scroll-restoration.js +186 -0
- package/build/cjs/scroll-restoration.js.map +1 -0
- package/build/esm/index.js +191 -49
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +300 -256
- package/build/types/RouterProvider.d.ts +2 -0
- package/build/types/index.d.ts +1 -0
- package/build/types/router.d.ts +11 -5
- package/build/types/scroll-restoration.d.ts +6 -0
- package/build/umd/index.development.js +197 -51
- 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 +2 -2
- package/src/RouterProvider.tsx +55 -46
- package/src/index.tsx +1 -1
- package/src/link.tsx +1 -0
- package/src/router.ts +11 -5
- package/src/scroll-restoration.tsx +192 -205
|
@@ -1,205 +1,192 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
// useLayoutEffect(() => {
|
|
194
|
-
// return watchScrollPositions(router, state, options)
|
|
195
|
-
// }, [])
|
|
196
|
-
|
|
197
|
-
// useLayoutEffect(() => {
|
|
198
|
-
// restoreScrollPositions(router, state, options)
|
|
199
|
-
// })
|
|
200
|
-
// }
|
|
201
|
-
|
|
202
|
-
// export function ScrollRestoration(props: ScrollRestorationOptions) {
|
|
203
|
-
// useScrollRestoration(props)
|
|
204
|
-
// return null
|
|
205
|
-
// }
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
const useLayoutEffect =
|
|
4
|
+
typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect
|
|
5
|
+
|
|
6
|
+
import { ParsedLocation } from './location'
|
|
7
|
+
import { useRouter } from './RouterProvider'
|
|
8
|
+
import { NonNullableUpdater, functionalUpdate } from './utils'
|
|
9
|
+
|
|
10
|
+
const windowKey = 'window'
|
|
11
|
+
const delimiter = '___'
|
|
12
|
+
|
|
13
|
+
let weakScrolledElements = new WeakSet<any>()
|
|
14
|
+
|
|
15
|
+
type CacheValue = Record<string, { scrollX: number; scrollY: number }>
|
|
16
|
+
type CacheState = {
|
|
17
|
+
cached: CacheValue
|
|
18
|
+
next: CacheValue
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
type Cache = {
|
|
22
|
+
state: CacheState
|
|
23
|
+
set: (updater: NonNullableUpdater<CacheState>) => void
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let cache: Cache
|
|
27
|
+
|
|
28
|
+
const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage
|
|
29
|
+
|
|
30
|
+
export type ScrollRestorationOptions = {
|
|
31
|
+
getKey?: (location: ParsedLocation) => string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const defaultGetKey = (location: ParsedLocation) => location.state.key!
|
|
35
|
+
|
|
36
|
+
export function useScrollRestoration(options?: ScrollRestorationOptions) {
|
|
37
|
+
const { state, subscribe, resetNextScrollRef } = useRouter()
|
|
38
|
+
|
|
39
|
+
useLayoutEffect(() => {
|
|
40
|
+
const getKey = options?.getKey || defaultGetKey
|
|
41
|
+
|
|
42
|
+
if (sessionsStorage) {
|
|
43
|
+
if (!cache) {
|
|
44
|
+
cache = (() => {
|
|
45
|
+
const storageKey = 'tsr-scroll-restoration-v2'
|
|
46
|
+
|
|
47
|
+
const state: CacheState = JSON.parse(
|
|
48
|
+
window.sessionStorage.getItem(storageKey) || 'null',
|
|
49
|
+
) || { cached: {}, next: {} }
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
state,
|
|
53
|
+
set: (updater) => {
|
|
54
|
+
cache.state = functionalUpdate(updater, cache.state)
|
|
55
|
+
window.sessionStorage.setItem(
|
|
56
|
+
storageKey,
|
|
57
|
+
JSON.stringify(cache.state),
|
|
58
|
+
)
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
})()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { history } = window
|
|
66
|
+
if (history.scrollRestoration) {
|
|
67
|
+
history.scrollRestoration = 'manual'
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const onScroll = (event: Event) => {
|
|
71
|
+
if (weakScrolledElements.has(event.target)) return
|
|
72
|
+
weakScrolledElements.add(event.target)
|
|
73
|
+
|
|
74
|
+
const elementSelector =
|
|
75
|
+
event.target === document || event.target === window
|
|
76
|
+
? windowKey
|
|
77
|
+
: getCssSelector(event.target)
|
|
78
|
+
|
|
79
|
+
if (!cache.state.next[elementSelector]) {
|
|
80
|
+
cache.set((c) => ({
|
|
81
|
+
...c,
|
|
82
|
+
next: {
|
|
83
|
+
...c.next,
|
|
84
|
+
[elementSelector]: {
|
|
85
|
+
scrollX: NaN,
|
|
86
|
+
scrollY: NaN,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
}))
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const getCssSelector = (el: any): string => {
|
|
94
|
+
let path = [],
|
|
95
|
+
parent
|
|
96
|
+
while ((parent = el.parentNode)) {
|
|
97
|
+
path.unshift(
|
|
98
|
+
`${el.tagName}:nth-child(${
|
|
99
|
+
([].indexOf as any).call(parent.children, el) + 1
|
|
100
|
+
})`,
|
|
101
|
+
)
|
|
102
|
+
el = parent
|
|
103
|
+
}
|
|
104
|
+
return `${path.join(' > ')}`.toLowerCase()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (typeof document !== 'undefined') {
|
|
108
|
+
document.addEventListener('scroll', onScroll, true)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const unsubOnBeforeLoad = subscribe('onBeforeLoad', (event) => {
|
|
112
|
+
if (event.pathChanged) {
|
|
113
|
+
const restoreKey = getKey(event.fromLocation)
|
|
114
|
+
for (const elementSelector in cache.state.next) {
|
|
115
|
+
const entry = cache.state.next[elementSelector]!
|
|
116
|
+
if (elementSelector === windowKey) {
|
|
117
|
+
entry.scrollX = window.scrollX || 0
|
|
118
|
+
entry.scrollY = window.scrollY || 0
|
|
119
|
+
} else if (elementSelector) {
|
|
120
|
+
const element = document.querySelector(elementSelector)
|
|
121
|
+
entry.scrollX = element?.scrollLeft || 0
|
|
122
|
+
entry.scrollY = element?.scrollTop || 0
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
cache.set((c) => {
|
|
126
|
+
const next = { ...c.next }
|
|
127
|
+
delete next[elementSelector]
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
...c,
|
|
131
|
+
next,
|
|
132
|
+
cached: {
|
|
133
|
+
...c.cached,
|
|
134
|
+
[[restoreKey, elementSelector].join(delimiter)]: entry,
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
const unsubOnResolved = subscribe('onResolved', (event) => {
|
|
143
|
+
if (event.pathChanged) {
|
|
144
|
+
if (!resetNextScrollRef.current) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
resetNextScrollRef.current = true
|
|
149
|
+
|
|
150
|
+
const getKey = options?.getKey || defaultGetKey
|
|
151
|
+
|
|
152
|
+
const restoreKey = getKey(event.toLocation)
|
|
153
|
+
let windowRestored = false
|
|
154
|
+
|
|
155
|
+
for (const cacheKey in cache.state.cached) {
|
|
156
|
+
const entry = cache.state.cached[cacheKey]!
|
|
157
|
+
const [key, elementSelector] = cacheKey.split(delimiter)
|
|
158
|
+
if (key === restoreKey) {
|
|
159
|
+
if (elementSelector === windowKey) {
|
|
160
|
+
windowRestored = true
|
|
161
|
+
window.scrollTo(entry.scrollX, entry.scrollY)
|
|
162
|
+
} else if (elementSelector) {
|
|
163
|
+
const element = document.querySelector(elementSelector)
|
|
164
|
+
if (element) {
|
|
165
|
+
element.scrollLeft = entry.scrollX
|
|
166
|
+
element.scrollTop = entry.scrollY
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (!windowRestored) {
|
|
173
|
+
window.scrollTo(0, 0)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
cache.set((c) => ({ ...c, next: {} }))
|
|
177
|
+
weakScrolledElements = new WeakSet<any>()
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
return () => {
|
|
182
|
+
document.removeEventListener('scroll', onScroll)
|
|
183
|
+
unsubOnBeforeLoad()
|
|
184
|
+
unsubOnResolved()
|
|
185
|
+
}
|
|
186
|
+
}, [])
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function ScrollRestoration(props: ScrollRestorationOptions) {
|
|
190
|
+
useScrollRestoration(props)
|
|
191
|
+
return null
|
|
192
|
+
}
|