@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/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.163",
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.163",
47
- "@tanstack/react-store": "0.0.1-beta.163"
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 { ParsedLocation, useRouter } from '.'
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
- const windowKey = 'window'
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
- const { history } = window
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
- if (pathDidChangeRef.current) {
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
  }