@tanstack/solid-router 1.108.0

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.
Files changed (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +29 -0
  3. package/dist/cjs/Asset.cjs +59 -0
  4. package/dist/cjs/Asset.cjs.map +1 -0
  5. package/dist/cjs/Asset.d.cts +2 -0
  6. package/dist/cjs/CatchBoundary.cjs +92 -0
  7. package/dist/cjs/CatchBoundary.cjs.map +1 -0
  8. package/dist/cjs/CatchBoundary.d.cts +11 -0
  9. package/dist/cjs/HeadContent.cjs +129 -0
  10. package/dist/cjs/HeadContent.cjs.map +1 -0
  11. package/dist/cjs/HeadContent.d.cts +8 -0
  12. package/dist/cjs/Match.cjs +340 -0
  13. package/dist/cjs/Match.cjs.map +1 -0
  14. package/dist/cjs/Match.d.cts +8 -0
  15. package/dist/cjs/Matches.cjs +151 -0
  16. package/dist/cjs/Matches.cjs.map +1 -0
  17. package/dist/cjs/Matches.d.cts +69 -0
  18. package/dist/cjs/RouterProvider.cjs +45 -0
  19. package/dist/cjs/RouterProvider.cjs.map +1 -0
  20. package/dist/cjs/RouterProvider.d.cts +35 -0
  21. package/dist/cjs/SafeFragment.cjs +8 -0
  22. package/dist/cjs/SafeFragment.cjs.map +1 -0
  23. package/dist/cjs/SafeFragment.d.cts +1 -0
  24. package/dist/cjs/ScriptOnce.cjs +23 -0
  25. package/dist/cjs/ScriptOnce.cjs.map +1 -0
  26. package/dist/cjs/ScriptOnce.d.cts +5 -0
  27. package/dist/cjs/Scripts.cjs +48 -0
  28. package/dist/cjs/Scripts.cjs.map +1 -0
  29. package/dist/cjs/Scripts.d.cts +1 -0
  30. package/dist/cjs/ScrollRestoration.cjs +37 -0
  31. package/dist/cjs/ScrollRestoration.cjs.map +1 -0
  32. package/dist/cjs/ScrollRestoration.d.cts +15 -0
  33. package/dist/cjs/Transitioner.cjs +132 -0
  34. package/dist/cjs/Transitioner.cjs.map +1 -0
  35. package/dist/cjs/Transitioner.d.cts +1 -0
  36. package/dist/cjs/awaited.cjs +53 -0
  37. package/dist/cjs/awaited.cjs.map +1 -0
  38. package/dist/cjs/awaited.d.cts +11 -0
  39. package/dist/cjs/fileRoute.cjs +90 -0
  40. package/dist/cjs/fileRoute.cjs.map +1 -0
  41. package/dist/cjs/fileRoute.d.cts +58 -0
  42. package/dist/cjs/history.d.cts +8 -0
  43. package/dist/cjs/index.cjs +260 -0
  44. package/dist/cjs/index.cjs.map +1 -0
  45. package/dist/cjs/index.d.cts +53 -0
  46. package/dist/cjs/lazyRouteComponent.cjs +74 -0
  47. package/dist/cjs/lazyRouteComponent.cjs.map +1 -0
  48. package/dist/cjs/lazyRouteComponent.d.cts +7 -0
  49. package/dist/cjs/link.cjs +279 -0
  50. package/dist/cjs/link.cjs.map +1 -0
  51. package/dist/cjs/link.d.cts +113 -0
  52. package/dist/cjs/matchContext.cjs +25 -0
  53. package/dist/cjs/matchContext.cjs.map +1 -0
  54. package/dist/cjs/matchContext.d.cts +3 -0
  55. package/dist/cjs/not-found.cjs +51 -0
  56. package/dist/cjs/not-found.cjs.map +1 -0
  57. package/dist/cjs/not-found.d.cts +27 -0
  58. package/dist/cjs/redirects.cjs +29 -0
  59. package/dist/cjs/redirects.cjs.map +1 -0
  60. package/dist/cjs/redirects.d.cts +21 -0
  61. package/dist/cjs/renderRouteNotFound.cjs +23 -0
  62. package/dist/cjs/renderRouteNotFound.cjs.map +1 -0
  63. package/dist/cjs/renderRouteNotFound.d.cts +3 -0
  64. package/dist/cjs/route.cjs +233 -0
  65. package/dist/cjs/route.cjs.map +1 -0
  66. package/dist/cjs/route.d.cts +297 -0
  67. package/dist/cjs/routeInfo.d.cts +53 -0
  68. package/dist/cjs/router.cjs +1687 -0
  69. package/dist/cjs/router.cjs.map +1 -0
  70. package/dist/cjs/router.d.cts +555 -0
  71. package/dist/cjs/routerContext.cjs +33 -0
  72. package/dist/cjs/routerContext.cjs.map +1 -0
  73. package/dist/cjs/routerContext.d.cts +8 -0
  74. package/dist/cjs/scroll-restoration.cjs +183 -0
  75. package/dist/cjs/scroll-restoration.cjs.map +1 -0
  76. package/dist/cjs/scroll-restoration.d.cts +29 -0
  77. package/dist/cjs/typePrimitives.d.cts +66 -0
  78. package/dist/cjs/useBlocker.cjs +165 -0
  79. package/dist/cjs/useBlocker.cjs.map +1 -0
  80. package/dist/cjs/useBlocker.d.cts +68 -0
  81. package/dist/cjs/useCanGoBack.cjs +8 -0
  82. package/dist/cjs/useCanGoBack.cjs.map +1 -0
  83. package/dist/cjs/useCanGoBack.d.cts +1 -0
  84. package/dist/cjs/useLoaderData.cjs +14 -0
  85. package/dist/cjs/useLoaderData.cjs.map +1 -0
  86. package/dist/cjs/useLoaderData.d.cts +13 -0
  87. package/dist/cjs/useLoaderDeps.cjs +17 -0
  88. package/dist/cjs/useLoaderDeps.cjs.map +1 -0
  89. package/dist/cjs/useLoaderDeps.d.cts +12 -0
  90. package/dist/cjs/useLocation.cjs +10 -0
  91. package/dist/cjs/useLocation.cjs.map +1 -0
  92. package/dist/cjs/useLocation.d.cts +7 -0
  93. package/dist/cjs/useMatch.cjs +39 -0
  94. package/dist/cjs/useMatch.cjs.map +1 -0
  95. package/dist/cjs/useMatch.d.cts +14 -0
  96. package/dist/cjs/useNavigate.cjs +45 -0
  97. package/dist/cjs/useNavigate.cjs.map +1 -0
  98. package/dist/cjs/useNavigate.d.cts +7 -0
  99. package/dist/cjs/useParams.cjs +15 -0
  100. package/dist/cjs/useParams.cjs.map +1 -0
  101. package/dist/cjs/useParams.d.cts +15 -0
  102. package/dist/cjs/useRouteContext.cjs +11 -0
  103. package/dist/cjs/useRouteContext.cjs.map +1 -0
  104. package/dist/cjs/useRouteContext.d.cts +13 -0
  105. package/dist/cjs/useRouter.cjs +29 -0
  106. package/dist/cjs/useRouter.cjs.map +1 -0
  107. package/dist/cjs/useRouter.d.cts +4 -0
  108. package/dist/cjs/useRouterState.cjs +16 -0
  109. package/dist/cjs/useRouterState.cjs.map +1 -0
  110. package/dist/cjs/useRouterState.d.cts +8 -0
  111. package/dist/cjs/useSearch.cjs +15 -0
  112. package/dist/cjs/useSearch.cjs.map +1 -0
  113. package/dist/cjs/useSearch.d.cts +15 -0
  114. package/dist/cjs/utils.cjs +58 -0
  115. package/dist/cjs/utils.cjs.map +1 -0
  116. package/dist/cjs/utils.d.cts +44 -0
  117. package/dist/esm/Asset.d.ts +2 -0
  118. package/dist/esm/Asset.js +59 -0
  119. package/dist/esm/Asset.js.map +1 -0
  120. package/dist/esm/CatchBoundary.d.ts +11 -0
  121. package/dist/esm/CatchBoundary.js +75 -0
  122. package/dist/esm/CatchBoundary.js.map +1 -0
  123. package/dist/esm/HeadContent.d.ts +8 -0
  124. package/dist/esm/HeadContent.js +112 -0
  125. package/dist/esm/HeadContent.js.map +1 -0
  126. package/dist/esm/Match.d.ts +8 -0
  127. package/dist/esm/Match.js +323 -0
  128. package/dist/esm/Match.js.map +1 -0
  129. package/dist/esm/Matches.d.ts +69 -0
  130. package/dist/esm/Matches.js +134 -0
  131. package/dist/esm/Matches.js.map +1 -0
  132. package/dist/esm/RouterProvider.d.ts +35 -0
  133. package/dist/esm/RouterProvider.js +45 -0
  134. package/dist/esm/RouterProvider.js.map +1 -0
  135. package/dist/esm/SafeFragment.d.ts +1 -0
  136. package/dist/esm/SafeFragment.js +8 -0
  137. package/dist/esm/SafeFragment.js.map +1 -0
  138. package/dist/esm/ScriptOnce.d.ts +5 -0
  139. package/dist/esm/ScriptOnce.js +23 -0
  140. package/dist/esm/ScriptOnce.js.map +1 -0
  141. package/dist/esm/Scripts.d.ts +1 -0
  142. package/dist/esm/Scripts.js +48 -0
  143. package/dist/esm/Scripts.js.map +1 -0
  144. package/dist/esm/ScrollRestoration.d.ts +15 -0
  145. package/dist/esm/ScrollRestoration.js +37 -0
  146. package/dist/esm/ScrollRestoration.js.map +1 -0
  147. package/dist/esm/Transitioner.d.ts +1 -0
  148. package/dist/esm/Transitioner.js +115 -0
  149. package/dist/esm/Transitioner.js.map +1 -0
  150. package/dist/esm/awaited.d.ts +11 -0
  151. package/dist/esm/awaited.js +36 -0
  152. package/dist/esm/awaited.js.map +1 -0
  153. package/dist/esm/fileRoute.d.ts +58 -0
  154. package/dist/esm/fileRoute.js +90 -0
  155. package/dist/esm/fileRoute.js.map +1 -0
  156. package/dist/esm/history.d.ts +8 -0
  157. package/dist/esm/index.d.ts +53 -0
  158. package/dist/esm/index.js +149 -0
  159. package/dist/esm/index.js.map +1 -0
  160. package/dist/esm/lazyRouteComponent.d.ts +7 -0
  161. package/dist/esm/lazyRouteComponent.js +74 -0
  162. package/dist/esm/lazyRouteComponent.js.map +1 -0
  163. package/dist/esm/link.d.ts +113 -0
  164. package/dist/esm/link.js +262 -0
  165. package/dist/esm/link.js.map +1 -0
  166. package/dist/esm/matchContext.d.ts +3 -0
  167. package/dist/esm/matchContext.js +8 -0
  168. package/dist/esm/matchContext.js.map +1 -0
  169. package/dist/esm/not-found.d.ts +27 -0
  170. package/dist/esm/not-found.js +51 -0
  171. package/dist/esm/not-found.js.map +1 -0
  172. package/dist/esm/redirects.d.ts +21 -0
  173. package/dist/esm/redirects.js +29 -0
  174. package/dist/esm/redirects.js.map +1 -0
  175. package/dist/esm/renderRouteNotFound.d.ts +3 -0
  176. package/dist/esm/renderRouteNotFound.js +23 -0
  177. package/dist/esm/renderRouteNotFound.js.map +1 -0
  178. package/dist/esm/route.d.ts +297 -0
  179. package/dist/esm/route.js +233 -0
  180. package/dist/esm/route.js.map +1 -0
  181. package/dist/esm/routeInfo.d.ts +53 -0
  182. package/dist/esm/router.d.ts +555 -0
  183. package/dist/esm/router.js +1687 -0
  184. package/dist/esm/router.js.map +1 -0
  185. package/dist/esm/routerContext.d.ts +8 -0
  186. package/dist/esm/routerContext.js +16 -0
  187. package/dist/esm/routerContext.js.map +1 -0
  188. package/dist/esm/scroll-restoration.d.ts +29 -0
  189. package/dist/esm/scroll-restoration.js +183 -0
  190. package/dist/esm/scroll-restoration.js.map +1 -0
  191. package/dist/esm/typePrimitives.d.ts +66 -0
  192. package/dist/esm/useBlocker.d.ts +68 -0
  193. package/dist/esm/useBlocker.js +148 -0
  194. package/dist/esm/useBlocker.js.map +1 -0
  195. package/dist/esm/useCanGoBack.d.ts +1 -0
  196. package/dist/esm/useCanGoBack.js +8 -0
  197. package/dist/esm/useCanGoBack.js.map +1 -0
  198. package/dist/esm/useLoaderData.d.ts +13 -0
  199. package/dist/esm/useLoaderData.js +14 -0
  200. package/dist/esm/useLoaderData.js.map +1 -0
  201. package/dist/esm/useLoaderDeps.d.ts +12 -0
  202. package/dist/esm/useLoaderDeps.js +17 -0
  203. package/dist/esm/useLoaderDeps.js.map +1 -0
  204. package/dist/esm/useLocation.d.ts +7 -0
  205. package/dist/esm/useLocation.js +10 -0
  206. package/dist/esm/useLocation.js.map +1 -0
  207. package/dist/esm/useMatch.d.ts +14 -0
  208. package/dist/esm/useMatch.js +22 -0
  209. package/dist/esm/useMatch.js.map +1 -0
  210. package/dist/esm/useNavigate.d.ts +7 -0
  211. package/dist/esm/useNavigate.js +28 -0
  212. package/dist/esm/useNavigate.js.map +1 -0
  213. package/dist/esm/useParams.d.ts +15 -0
  214. package/dist/esm/useParams.js +15 -0
  215. package/dist/esm/useParams.js.map +1 -0
  216. package/dist/esm/useRouteContext.d.ts +13 -0
  217. package/dist/esm/useRouteContext.js +11 -0
  218. package/dist/esm/useRouteContext.js.map +1 -0
  219. package/dist/esm/useRouter.d.ts +4 -0
  220. package/dist/esm/useRouter.js +12 -0
  221. package/dist/esm/useRouter.js.map +1 -0
  222. package/dist/esm/useRouterState.d.ts +8 -0
  223. package/dist/esm/useRouterState.js +16 -0
  224. package/dist/esm/useRouterState.js.map +1 -0
  225. package/dist/esm/useSearch.d.ts +15 -0
  226. package/dist/esm/useSearch.js +15 -0
  227. package/dist/esm/useSearch.js.map +1 -0
  228. package/dist/esm/utils.d.ts +44 -0
  229. package/dist/esm/utils.js +41 -0
  230. package/dist/esm/utils.js.map +1 -0
  231. package/package.json +75 -0
  232. package/src/Asset.tsx +23 -0
  233. package/src/CatchBoundary.tsx +78 -0
  234. package/src/HeadContent.tsx +146 -0
  235. package/src/Match.tsx +356 -0
  236. package/src/Matches.tsx +348 -0
  237. package/src/RouterProvider.tsx +130 -0
  238. package/src/SafeFragment.tsx +3 -0
  239. package/src/ScriptOnce.tsx +30 -0
  240. package/src/Scripts.tsx +65 -0
  241. package/src/ScrollRestoration.tsx +65 -0
  242. package/src/Transitioner.tsx +152 -0
  243. package/src/awaited.tsx +49 -0
  244. package/src/fileRoute.ts +274 -0
  245. package/src/history.ts +9 -0
  246. package/src/index.tsx +359 -0
  247. package/src/lazyRouteComponent.tsx +114 -0
  248. package/src/link.tsx +1002 -0
  249. package/src/matchContext.tsx +10 -0
  250. package/src/not-found.tsx +69 -0
  251. package/src/redirects.ts +71 -0
  252. package/src/renderRouteNotFound.tsx +27 -0
  253. package/src/route.ts +1477 -0
  254. package/src/routeInfo.ts +239 -0
  255. package/src/router.ts +3066 -0
  256. package/src/routerContext.tsx +26 -0
  257. package/src/scroll-restoration.tsx +337 -0
  258. package/src/typePrimitives.ts +195 -0
  259. package/src/useBlocker.tsx +298 -0
  260. package/src/useCanGoBack.ts +5 -0
  261. package/src/useLoaderData.tsx +64 -0
  262. package/src/useLoaderDeps.tsx +52 -0
  263. package/src/useLocation.tsx +26 -0
  264. package/src/useMatch.tsx +96 -0
  265. package/src/useNavigate.tsx +61 -0
  266. package/src/useParams.tsx +83 -0
  267. package/src/useRouteContext.ts +62 -0
  268. package/src/useRouter.tsx +15 -0
  269. package/src/useRouterState.tsx +32 -0
  270. package/src/useSearch.tsx +84 -0
  271. package/src/utils.ts +96 -0
@@ -0,0 +1,26 @@
1
+ import * as Solid from 'solid-js'
2
+ import type { AnyRouter, Router } from './router'
3
+
4
+ declare global {
5
+ interface Window {
6
+ __TSR_ROUTER_CONTEXT__?: Solid.Context<AnyRouter>
7
+ }
8
+ }
9
+
10
+ const routerContext = Solid.createContext<Router<any, any, any>>(
11
+ null as unknown as Router<any, any, any>,
12
+ )
13
+
14
+ export function getRouterContext() {
15
+ if (typeof document === 'undefined') {
16
+ return routerContext
17
+ }
18
+
19
+ if (window.__TSR_ROUTER_CONTEXT__) {
20
+ return window.__TSR_ROUTER_CONTEXT__
21
+ }
22
+
23
+ window.__TSR_ROUTER_CONTEXT__ = routerContext as any
24
+
25
+ return routerContext
26
+ }
@@ -0,0 +1,337 @@
1
+ import { functionalUpdate } from '@tanstack/router-core'
2
+ import { useRouter } from './useRouter'
3
+ import { ScriptOnce } from './ScriptOnce'
4
+ import type { AnyRouter } from './router'
5
+ import type { NonNullableUpdater, ParsedLocation } from '@tanstack/router-core'
6
+
7
+ export type ScrollRestorationEntry = { scrollX: number; scrollY: number }
8
+
9
+ export type ScrollRestorationByElement = Record<string, ScrollRestorationEntry>
10
+
11
+ export type ScrollRestorationByKey = Record<string, ScrollRestorationByElement>
12
+
13
+ export type ScrollRestorationCache = {
14
+ state: ScrollRestorationByKey
15
+ set: (updater: NonNullableUpdater<ScrollRestorationByKey>) => void
16
+ }
17
+ export type ScrollRestorationOptions = {
18
+ getKey?: (location: ParsedLocation) => string
19
+ scrollBehavior?: ScrollToOptions['behavior']
20
+ }
21
+
22
+ export const storageKey = 'tsr-scroll-restoration-v1_3'
23
+ const sessionsStorage = typeof window !== 'undefined' && window.sessionStorage
24
+ const throttle = (fn: (...args: Array<any>) => void, wait: number) => {
25
+ let timeout: any
26
+ return (...args: Array<any>) => {
27
+ if (!timeout) {
28
+ timeout = setTimeout(() => {
29
+ fn(...args)
30
+ timeout = null
31
+ }, wait)
32
+ }
33
+ }
34
+ }
35
+ export const scrollRestorationCache: ScrollRestorationCache = sessionsStorage
36
+ ? (() => {
37
+ const state: ScrollRestorationByKey =
38
+ JSON.parse(window.sessionStorage.getItem(storageKey) || 'null') || {}
39
+
40
+ return {
41
+ state,
42
+ // This setter is simply to make sure that we set the sessionStorage right
43
+ // after the state is updated. It doesn't necessarily need to be a functional
44
+ // update.
45
+ set: (updater) => (
46
+ (scrollRestorationCache.state =
47
+ functionalUpdate(updater, scrollRestorationCache.state) ||
48
+ scrollRestorationCache.state),
49
+ window.sessionStorage.setItem(
50
+ storageKey,
51
+ JSON.stringify(scrollRestorationCache.state),
52
+ )
53
+ ),
54
+ }
55
+ })()
56
+ : (undefined as any)
57
+ /**
58
+ * The default `getKey` function for `useScrollRestoration`.
59
+ * It returns the `key` from the location state or the `href` of the location.
60
+ *
61
+ * The `location.href` is used as a fallback to support the use case where the location state is not available like the initial render.
62
+ */
63
+
64
+ export const defaultGetScrollRestorationKey = (location: ParsedLocation) => {
65
+ return location.state.key! || location.href
66
+ }
67
+
68
+ export function getCssSelector(el: any): string {
69
+ const path = []
70
+ let parent
71
+ while ((parent = el.parentNode)) {
72
+ path.unshift(
73
+ `${el.tagName}:nth-child(${([].indexOf as any).call(parent.children, el) + 1})`,
74
+ )
75
+ el = parent
76
+ }
77
+ return `${path.join(' > ')}`.toLowerCase()
78
+ }
79
+
80
+ let ignoreScroll = false
81
+
82
+ // NOTE: This function must remain pure and not use any outside variables
83
+ // unless they are passed in as arguments. Why? Because we need to be able to
84
+ // toString() it into a script tag to execute as early as possible in the browser
85
+ // during SSR. Additionally, we also call it from within the router lifecycle
86
+ export function restoreScroll(
87
+ storageKey: string,
88
+ key?: string,
89
+ behavior?: ScrollToOptions['behavior'],
90
+ shouldScrollRestoration?: boolean,
91
+ scrollToTopSelectors?: Array<string>,
92
+ ) {
93
+ let byKey: ScrollRestorationByKey
94
+
95
+ try {
96
+ byKey = JSON.parse(sessionStorage.getItem(storageKey) || '{}')
97
+ } catch (error: any) {
98
+ console.error(error)
99
+ return
100
+ }
101
+
102
+ const resolvedKey = key || window.history.state?.key
103
+ const elementEntries = byKey[resolvedKey]
104
+
105
+ //
106
+ ignoreScroll = true
107
+
108
+ //
109
+ ;(() => {
110
+ // If we have a cached entry for this location state,
111
+ // we always need to prefer that over the hash scroll.
112
+ if (shouldScrollRestoration && elementEntries) {
113
+ for (const elementSelector in elementEntries) {
114
+ const entry = elementEntries[elementSelector]!
115
+ if (elementSelector === 'window') {
116
+ window.scrollTo({
117
+ top: entry.scrollY,
118
+ left: entry.scrollX,
119
+ behavior,
120
+ })
121
+ } else if (elementSelector) {
122
+ const element = document.querySelector(elementSelector)
123
+ if (element) {
124
+ element.scrollLeft = entry.scrollX
125
+ element.scrollTop = entry.scrollY
126
+ }
127
+ }
128
+ }
129
+
130
+ return
131
+ }
132
+
133
+ // If we don't have a cached entry for the hash,
134
+ // Which means we've never seen this location before,
135
+ // we need to check if there is a hash in the URL.
136
+ // If there is, we need to scroll it's ID into view.
137
+ const hash = window.location.hash.split('#')[1]
138
+
139
+ if (hash) {
140
+ const hashScrollIntoViewOptions =
141
+ (window.history.state || {}).__hashScrollIntoViewOptions ?? true
142
+
143
+ if (hashScrollIntoViewOptions) {
144
+ const el = document.getElementById(hash)
145
+ if (el) {
146
+ el.scrollIntoView(hashScrollIntoViewOptions)
147
+ }
148
+ }
149
+
150
+ return
151
+ }
152
+
153
+ // If there is no cached entry for the hash and there is no hash in the URL,
154
+ // we need to scroll to the top of the page for every scrollToTop element
155
+ ;[
156
+ 'window',
157
+ ...(scrollToTopSelectors?.filter((d) => d !== 'window') ?? []),
158
+ ].forEach((selector) => {
159
+ const element =
160
+ selector === 'window' ? window : document.querySelector(selector)
161
+ if (element) {
162
+ element.scrollTo({
163
+ top: 0,
164
+ left: 0,
165
+ behavior,
166
+ })
167
+ }
168
+ })
169
+ })()
170
+
171
+ //
172
+ ignoreScroll = false
173
+ }
174
+
175
+ export function setupScrollRestoration(router: AnyRouter, force?: boolean) {
176
+ const shouldScrollRestoration =
177
+ force ?? router.options.scrollRestoration ?? false
178
+
179
+ if (shouldScrollRestoration) {
180
+ router.isScrollRestoring = true
181
+ }
182
+
183
+ if (typeof document === 'undefined' || router.isScrollRestorationSetup) {
184
+ return
185
+ }
186
+
187
+ router.isScrollRestorationSetup = true
188
+
189
+ //
190
+ ignoreScroll = false
191
+
192
+ const getKey =
193
+ router.options.getScrollRestorationKey || defaultGetScrollRestorationKey
194
+
195
+ window.history.scrollRestoration = 'manual'
196
+
197
+ // // Create a MutationObserver to monitor DOM changes
198
+ // const mutationObserver = new MutationObserver(() => {
199
+ // ;ignoreScroll = true
200
+ // requestAnimationFrame(() => {
201
+ // ;ignoreScroll = false
202
+
203
+ // // Attempt to restore scroll position on each dom
204
+ // // mutation until the user scrolls. We do this
205
+ // // because dynamic content may come in at different
206
+ // // ticks after the initial render and we want to
207
+ // // keep up with that content as much as possible.
208
+ // // As soon as the user scrolls, we no longer need
209
+ // // to attempt router.
210
+ // // console.log('mutation observer restoreScroll')
211
+ // restoreScroll(
212
+ // storageKey,
213
+ // getKey(router.state.location),
214
+ // router.options.scrollRestorationBehavior,
215
+ // )
216
+ // })
217
+ // })
218
+
219
+ // const observeDom = () => {
220
+ // // Observe changes to the entire document
221
+ // mutationObserver.observe(document, {
222
+ // childList: true, // Detect added or removed child nodes
223
+ // subtree: true, // Monitor all descendants
224
+ // characterData: true, // Detect text content changes
225
+ // })
226
+ // }
227
+
228
+ // const unobserveDom = () => {
229
+ // mutationObserver.disconnect()
230
+ // }
231
+
232
+ // observeDom()
233
+
234
+ const onScroll = (event: Event) => {
235
+ // unobserveDom()
236
+
237
+ if (ignoreScroll || !router.isScrollRestoring) {
238
+ return
239
+ }
240
+
241
+ let elementSelector = ''
242
+
243
+ if (event.target === document || event.target === window) {
244
+ elementSelector = 'window'
245
+ } else {
246
+ const attrId = (event.target as Element).getAttribute(
247
+ 'data-scroll-restoration-id',
248
+ )
249
+
250
+ if (attrId) {
251
+ elementSelector = `[data-scroll-restoration-id="${attrId}"]`
252
+ } else {
253
+ elementSelector = getCssSelector(event.target)
254
+ }
255
+ }
256
+
257
+ const restoreKey = getKey(router.state.location)
258
+
259
+ scrollRestorationCache.set((state) => {
260
+ const keyEntry = (state[restoreKey] =
261
+ state[restoreKey] || ({} as ScrollRestorationByElement))
262
+
263
+ const elementEntry = (keyEntry[elementSelector] =
264
+ keyEntry[elementSelector] || ({} as ScrollRestorationEntry))
265
+
266
+ if (elementSelector === 'window') {
267
+ elementEntry.scrollX = window.scrollX || 0
268
+ elementEntry.scrollY = window.scrollY || 0
269
+ } else if (elementSelector) {
270
+ const element = document.querySelector(elementSelector)
271
+ if (element) {
272
+ elementEntry.scrollX = element.scrollLeft || 0
273
+ elementEntry.scrollY = element.scrollTop || 0
274
+ }
275
+ }
276
+
277
+ return state
278
+ })
279
+ }
280
+
281
+ // Throttle the scroll event to avoid excessive updates
282
+ if (typeof document !== 'undefined') {
283
+ document.addEventListener('scroll', throttle(onScroll, 100), true)
284
+ }
285
+
286
+ router.subscribe('onRendered', (event) => {
287
+ // unobserveDom()
288
+
289
+ const cacheKey = getKey(event.toLocation)
290
+
291
+ // If the user doesn't want to restore the scroll position,
292
+ // we don't need to do anything.
293
+ if (!router.resetNextScroll) {
294
+ router.resetNextScroll = true
295
+ return
296
+ }
297
+
298
+ restoreScroll(
299
+ storageKey,
300
+ cacheKey,
301
+ router.options.scrollRestorationBehavior,
302
+ router.isScrollRestoring,
303
+ router.options.scrollToTopSelectors,
304
+ )
305
+
306
+ if (router.isScrollRestoring) {
307
+ // Mark the location as having been seen
308
+ scrollRestorationCache.set((state) => {
309
+ state[cacheKey] = state[cacheKey] || ({} as ScrollRestorationByElement)
310
+
311
+ return state
312
+ })
313
+ }
314
+ })
315
+ }
316
+
317
+ export function ScrollRestoration() {
318
+ const router = useRouter()
319
+ const getKey =
320
+ router.options.getScrollRestorationKey || defaultGetScrollRestorationKey
321
+ const userKey = getKey(router.latestLocation)
322
+ const resolvedKey =
323
+ userKey !== defaultGetScrollRestorationKey(router.latestLocation)
324
+ ? userKey
325
+ : null
326
+
327
+ if (!router.isScrollRestoring || !router.isServer) {
328
+ return null
329
+ }
330
+
331
+ return (
332
+ <ScriptOnce
333
+ children={`(${restoreScroll.toString()})(${JSON.stringify(storageKey)},${JSON.stringify(resolvedKey)}, undefined, true)`}
334
+ log={false}
335
+ />
336
+ )
337
+ }
@@ -0,0 +1,195 @@
1
+ import type {
2
+ FromPathOption,
3
+ LinkComponentProps,
4
+ NavigateOptions,
5
+ PathParamOptions,
6
+ SearchParamOptions,
7
+ ToPathOption,
8
+ } from './link'
9
+ import type { RouteIds } from './routeInfo'
10
+ import type { AnyRouter, RegisteredRouter } from './router'
11
+ import type { UseParamsOptions, UseParamsResult } from './useParams'
12
+ import type { UseSearchOptions, UseSearchResult } from './useSearch'
13
+ import type { Constrain, ConstrainLiteral } from '@tanstack/router-core'
14
+
15
+ export type ValidateFromPath<
16
+ TFrom,
17
+ TRouter extends AnyRouter = RegisteredRouter,
18
+ > = FromPathOption<TRouter, TFrom>
19
+
20
+ export type ValidateToPath<
21
+ TTo extends string | undefined,
22
+ TFrom extends string = string,
23
+ TRouter extends AnyRouter = RegisteredRouter,
24
+ > = ToPathOption<TRouter, TFrom, TTo>
25
+
26
+ export type ValidateSearch<
27
+ TTo extends string | undefined,
28
+ TFrom extends string = string,
29
+ TRouter extends AnyRouter = RegisteredRouter,
30
+ > = SearchParamOptions<TRouter, TFrom, TTo>
31
+
32
+ export type ValidateParams<
33
+ TTo extends string | undefined,
34
+ TFrom extends string = string,
35
+ TRouter extends AnyRouter = RegisteredRouter,
36
+ > = PathParamOptions<TRouter, TFrom, TTo>
37
+
38
+ /**
39
+ * @internal
40
+ */
41
+ export type InferFrom<TOptions> = TOptions extends {
42
+ from: infer TFrom extends string
43
+ }
44
+ ? TFrom
45
+ : string
46
+
47
+ /**
48
+ * @internal
49
+ */
50
+ export type InferTo<TOptions> = TOptions extends {
51
+ to: infer TTo extends string
52
+ }
53
+ ? TTo
54
+ : undefined
55
+
56
+ /**
57
+ * @internal
58
+ */
59
+ export type InferMaskTo<TOptions> = TOptions extends {
60
+ mask: { to: infer TTo extends string }
61
+ }
62
+ ? TTo
63
+ : ''
64
+
65
+ export type InferMaskFrom<TOptions> = TOptions extends {
66
+ mask: { from: infer TFrom extends string }
67
+ }
68
+ ? TFrom
69
+ : string
70
+
71
+ export type ValidateNavigateOptions<
72
+ TOptions,
73
+ TRouter extends AnyRouter = RegisteredRouter,
74
+ > = Constrain<
75
+ TOptions,
76
+ NavigateOptions<
77
+ TRouter,
78
+ InferFrom<TOptions>,
79
+ InferTo<TOptions>,
80
+ InferMaskFrom<TOptions>,
81
+ InferMaskTo<TOptions>
82
+ >
83
+ >
84
+
85
+ export type ValidateNavigateOptionsArray<
86
+ TOptions extends ReadonlyArray<any>,
87
+ TRouter extends AnyRouter = RegisteredRouter,
88
+ > = { [K in keyof TOptions]: ValidateNavigateOptions<TOptions[K], TRouter> }
89
+
90
+ export type ValidateLinkOptions<
91
+ TOptions,
92
+ TComp = 'a',
93
+ TRouter extends AnyRouter = RegisteredRouter,
94
+ > = Constrain<
95
+ TOptions,
96
+ LinkComponentProps<
97
+ TComp,
98
+ TRouter,
99
+ InferFrom<TOptions>,
100
+ InferTo<TOptions>,
101
+ InferMaskFrom<TOptions>,
102
+ InferMaskTo<TOptions>
103
+ >
104
+ >
105
+
106
+ export type ValidateLinkOptionsArray<
107
+ TOptions extends ReadonlyArray<any>,
108
+ TComp = 'a',
109
+ TRouter extends AnyRouter = RegisteredRouter,
110
+ > = {
111
+ [K in keyof TOptions]: ValidateLinkOptions<TOptions[K], TComp, TRouter>
112
+ }
113
+
114
+ export type ValidateId<
115
+ TId extends string,
116
+ TRouter extends AnyRouter = RegisteredRouter,
117
+ > = ConstrainLiteral<TId, RouteIds<TRouter['routeTree']>>
118
+
119
+ /**
120
+ * @internal
121
+ */
122
+ export type InferStrict<TOptions> = TOptions extends {
123
+ strict: infer TStrict extends boolean
124
+ }
125
+ ? TStrict
126
+ : true
127
+
128
+ /**
129
+ * @internal
130
+ */
131
+ export type InferShouldThrow<TOptions> = TOptions extends {
132
+ shouldThrow: infer TShouldThrow extends boolean
133
+ }
134
+ ? TShouldThrow
135
+ : true
136
+
137
+ /**
138
+ * @internal
139
+ */
140
+ export type InferSelected<TOptions> = TOptions extends {
141
+ select: (...args: Array<any>) => infer TSelected
142
+ }
143
+ ? TSelected
144
+ : unknown
145
+
146
+ export type ValidateUseSearchOptions<
147
+ TOptions,
148
+ TRouter extends AnyRouter = RegisteredRouter,
149
+ > = Constrain<
150
+ TOptions,
151
+ UseSearchOptions<
152
+ TRouter,
153
+ InferFrom<TOptions>,
154
+ InferStrict<TOptions>,
155
+ InferShouldThrow<TOptions>,
156
+ InferSelected<TOptions>
157
+ >
158
+ >
159
+
160
+ export type ValidateUseSearchResult<
161
+ TOptions,
162
+ TRouter extends AnyRouter = RegisteredRouter,
163
+ > = UseSearchResult<
164
+ TRouter,
165
+ InferFrom<TOptions>,
166
+ InferStrict<TOptions>,
167
+ InferSelected<TOptions>
168
+ >
169
+
170
+ export type ValidateUseParamsOptions<
171
+ TOptions,
172
+ TRouter extends AnyRouter = RegisteredRouter,
173
+ > = Constrain<
174
+ TOptions,
175
+ UseParamsOptions<
176
+ TRouter,
177
+ InferFrom<TOptions>,
178
+ InferStrict<TOptions>,
179
+ InferShouldThrow<TOptions>,
180
+ InferSelected<TOptions>
181
+ >
182
+ >
183
+
184
+ export type ValidateUseParamsResult<
185
+ TOptions,
186
+ TRouter extends AnyRouter = RegisteredRouter,
187
+ > = Constrain<
188
+ TOptions,
189
+ UseParamsResult<
190
+ TRouter,
191
+ InferFrom<TOptions>,
192
+ InferStrict<TOptions>,
193
+ InferSelected<TOptions>
194
+ >
195
+ >