@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,298 @@
1
+ import * as Solid from 'solid-js'
2
+ import { useRouter } from './useRouter'
3
+ import type {
4
+ BlockerFnArgs,
5
+ HistoryAction,
6
+ HistoryLocation,
7
+ } from '@tanstack/history'
8
+ import type { AnyRoute, SolidNode } from './route'
9
+ import type { ParseRoute } from './routeInfo'
10
+ import type { AnyRouter, RegisteredRouter } from './router'
11
+
12
+ interface ShouldBlockFnLocation<
13
+ out TRouteId,
14
+ out TFullPath,
15
+ out TAllParams,
16
+ out TFullSearchSchema,
17
+ > {
18
+ routeId: TRouteId
19
+ fullPath: TFullPath
20
+ pathname: string
21
+ params: TAllParams
22
+ search: TFullSearchSchema
23
+ }
24
+
25
+ type AnyShouldBlockFnLocation = ShouldBlockFnLocation<any, any, any, any>
26
+ type MakeShouldBlockFnLocationUnion<
27
+ TRouter extends AnyRouter = RegisteredRouter,
28
+ TRoute extends AnyRoute = ParseRoute<TRouter['routeTree']>,
29
+ > = TRoute extends any
30
+ ? ShouldBlockFnLocation<
31
+ TRoute['id'],
32
+ TRoute['fullPath'],
33
+ TRoute['types']['allParams'],
34
+ TRoute['types']['fullSearchSchema']
35
+ >
36
+ : never
37
+
38
+ type BlockerResolver<TRouter extends AnyRouter = RegisteredRouter> =
39
+ | {
40
+ status: 'blocked'
41
+ current: MakeShouldBlockFnLocationUnion<TRouter>
42
+ next: MakeShouldBlockFnLocationUnion<TRouter>
43
+ action: HistoryAction
44
+ proceed: () => void
45
+ reset: () => void
46
+ }
47
+ | {
48
+ status: 'idle'
49
+ current: undefined
50
+ next: undefined
51
+ action: undefined
52
+ proceed: undefined
53
+ reset: undefined
54
+ }
55
+
56
+ type ShouldBlockFnArgs<TRouter extends AnyRouter = RegisteredRouter> = {
57
+ current: MakeShouldBlockFnLocationUnion<TRouter>
58
+ next: MakeShouldBlockFnLocationUnion<TRouter>
59
+ action: HistoryAction
60
+ }
61
+
62
+ export type ShouldBlockFn<TRouter extends AnyRouter = RegisteredRouter> = (
63
+ args: ShouldBlockFnArgs<TRouter>,
64
+ ) => boolean | Promise<boolean>
65
+ export type UseBlockerOpts<
66
+ TRouter extends AnyRouter = RegisteredRouter,
67
+ TWithResolver extends boolean = boolean,
68
+ > = {
69
+ shouldBlockFn: ShouldBlockFn<TRouter>
70
+ enableBeforeUnload?: boolean | (() => boolean)
71
+ disabled?: boolean
72
+ withResolver?: TWithResolver
73
+ }
74
+
75
+ type LegacyBlockerFn = () => Promise<any> | any
76
+ type LegacyBlockerOpts = {
77
+ blockerFn?: LegacyBlockerFn
78
+ condition?: boolean | any
79
+ }
80
+
81
+ function _resolveBlockerOpts(
82
+ opts?: UseBlockerOpts | LegacyBlockerOpts | LegacyBlockerFn,
83
+ condition?: boolean | any,
84
+ ): UseBlockerOpts {
85
+ if (opts === undefined) {
86
+ return {
87
+ shouldBlockFn: () => true,
88
+ withResolver: false,
89
+ }
90
+ }
91
+
92
+ if ('shouldBlockFn' in opts) {
93
+ return opts
94
+ }
95
+
96
+ if (typeof opts === 'function') {
97
+ const shouldBlock = Boolean(condition ?? true)
98
+
99
+ const _customBlockerFn = async () => {
100
+ if (shouldBlock) return await opts()
101
+ return false
102
+ }
103
+
104
+ return {
105
+ shouldBlockFn: _customBlockerFn,
106
+ enableBeforeUnload: shouldBlock,
107
+ withResolver: false,
108
+ }
109
+ }
110
+
111
+ const shouldBlock = Boolean(opts.condition ?? true)
112
+ const fn = opts.blockerFn
113
+
114
+ const _customBlockerFn = async () => {
115
+ if (shouldBlock && fn !== undefined) {
116
+ return await fn()
117
+ }
118
+ return shouldBlock
119
+ }
120
+
121
+ return {
122
+ shouldBlockFn: _customBlockerFn,
123
+ enableBeforeUnload: shouldBlock,
124
+ withResolver: fn === undefined,
125
+ }
126
+ }
127
+
128
+ export function useBlocker<
129
+ TRouter extends AnyRouter = RegisteredRouter,
130
+ TWithResolver extends boolean = false,
131
+ >(
132
+ opts: UseBlockerOpts<TRouter, TWithResolver>,
133
+ ): TWithResolver extends true ? Solid.Accessor<BlockerResolver<TRouter>> : void
134
+
135
+ /**
136
+ * @deprecated Use the shouldBlockFn property instead
137
+ */
138
+ export function useBlocker(
139
+ blockerFnOrOpts?: LegacyBlockerOpts,
140
+ ): Solid.Accessor<BlockerResolver>
141
+
142
+ /**
143
+ * @deprecated Use the UseBlockerOpts object syntax instead
144
+ */
145
+ export function useBlocker(
146
+ blockerFn?: LegacyBlockerFn,
147
+ condition?: boolean | any,
148
+ ): Solid.Accessor<BlockerResolver>
149
+
150
+ export function useBlocker(
151
+ opts?: UseBlockerOpts | LegacyBlockerOpts | LegacyBlockerFn,
152
+ condition?: boolean | any,
153
+ ): Solid.Accessor<BlockerResolver> | void {
154
+ const {
155
+ shouldBlockFn,
156
+ enableBeforeUnload = true,
157
+ disabled = false,
158
+ withResolver = false,
159
+ } = _resolveBlockerOpts(opts, condition)
160
+
161
+ const router = useRouter()
162
+ const { history } = router
163
+
164
+ const [resolver, setResolver] = Solid.createSignal<BlockerResolver>({
165
+ status: 'idle',
166
+ current: undefined,
167
+ next: undefined,
168
+ action: undefined,
169
+ proceed: undefined,
170
+ reset: undefined,
171
+ })
172
+
173
+ Solid.createEffect(() => {
174
+ const blockerFnComposed = async (blockerFnArgs: BlockerFnArgs) => {
175
+ function getLocation(
176
+ location: HistoryLocation,
177
+ ): AnyShouldBlockFnLocation {
178
+ const parsedLocation = router.parseLocation(undefined, location)
179
+ const matchedRoutes = router.getMatchedRoutes(parsedLocation)
180
+ if (matchedRoutes.foundRoute === undefined) {
181
+ throw new Error(`No route found for location ${location.href}`)
182
+ }
183
+ return {
184
+ routeId: matchedRoutes.foundRoute.id,
185
+ fullPath: matchedRoutes.foundRoute.fullPath,
186
+ pathname: parsedLocation.pathname,
187
+ params: matchedRoutes.routeParams,
188
+ search: parsedLocation.search,
189
+ }
190
+ }
191
+
192
+ const current = getLocation(blockerFnArgs.currentLocation)
193
+ const next = getLocation(blockerFnArgs.nextLocation)
194
+
195
+ const shouldBlock = await shouldBlockFn({
196
+ action: blockerFnArgs.action,
197
+ current,
198
+ next,
199
+ })
200
+ if (!withResolver) {
201
+ return shouldBlock
202
+ }
203
+
204
+ if (!shouldBlock) {
205
+ return false
206
+ }
207
+
208
+ const promise = new Promise<boolean>((resolve) => {
209
+ setResolver({
210
+ status: 'blocked',
211
+ current,
212
+ next,
213
+ action: blockerFnArgs.action,
214
+ proceed: () => resolve(false),
215
+ reset: () => resolve(true),
216
+ })
217
+ })
218
+
219
+ const canNavigateAsync = await promise
220
+ setResolver({
221
+ status: 'idle',
222
+ current: undefined,
223
+ next: undefined,
224
+ action: undefined,
225
+ proceed: undefined,
226
+ reset: undefined,
227
+ })
228
+
229
+ return canNavigateAsync
230
+ }
231
+
232
+ return disabled
233
+ ? undefined
234
+ : history.block({ blockerFn: blockerFnComposed, enableBeforeUnload })
235
+ })
236
+
237
+ return resolver
238
+ }
239
+
240
+ const _resolvePromptBlockerArgs = (
241
+ props: PromptProps | LegacyPromptProps,
242
+ ): UseBlockerOpts => {
243
+ if ('shouldBlockFn' in props) {
244
+ return { ...props }
245
+ }
246
+
247
+ const shouldBlock = Boolean(props.condition ?? true)
248
+ const fn = props.blockerFn
249
+
250
+ const _customBlockerFn = async () => {
251
+ if (shouldBlock && fn !== undefined) {
252
+ return await fn()
253
+ }
254
+ return shouldBlock
255
+ }
256
+
257
+ return {
258
+ shouldBlockFn: _customBlockerFn,
259
+ enableBeforeUnload: shouldBlock,
260
+ withResolver: fn === undefined,
261
+ }
262
+ }
263
+
264
+ export function Block<
265
+ TRouter extends AnyRouter = RegisteredRouter,
266
+ TWithResolver extends boolean = boolean,
267
+ >(opts: PromptProps<TRouter, TWithResolver>): SolidNode
268
+
269
+ /**
270
+ * @deprecated Use the UseBlockerOpts property instead
271
+ */
272
+ export function Block(opts: LegacyPromptProps): SolidNode
273
+
274
+ export function Block(opts: PromptProps | LegacyPromptProps): SolidNode {
275
+ const { children, ...rest } = opts
276
+ const args = _resolvePromptBlockerArgs(rest)
277
+
278
+ const resolver = useBlocker(args)
279
+ return children
280
+ ? typeof children === 'function'
281
+ ? children(resolver as any)
282
+ : children
283
+ : null
284
+ }
285
+
286
+ type LegacyPromptProps = {
287
+ blockerFn?: LegacyBlockerFn
288
+ condition?: boolean | any
289
+ children?: SolidNode | ((params: BlockerResolver) => SolidNode)
290
+ }
291
+
292
+ type PromptProps<
293
+ TRouter extends AnyRouter = RegisteredRouter,
294
+ TWithResolver extends boolean = boolean,
295
+ TParams = TWithResolver extends true ? BlockerResolver<TRouter> : void,
296
+ > = UseBlockerOpts<TRouter, TWithResolver> & {
297
+ children?: SolidNode | ((params: TParams) => SolidNode)
298
+ }
@@ -0,0 +1,5 @@
1
+ import { useRouterState } from './useRouterState'
2
+
3
+ export function useCanGoBack() {
4
+ return useRouterState({ select: (s) => s.location.state.__TSR_index !== 0 })
5
+ }
@@ -0,0 +1,64 @@
1
+ import { useMatch } from './useMatch'
2
+ import type { Accessor } from 'solid-js'
3
+ import type { AnyRouter, RegisteredRouter } from './router'
4
+ import type { AllLoaderData, RouteById } from './routeInfo'
5
+ import type { StrictOrFrom } from './utils'
6
+ import type { Expand } from '@tanstack/router-core'
7
+
8
+ export interface UseLoaderDataBaseOptions<
9
+ TRouter extends AnyRouter,
10
+ TFrom,
11
+ TStrict extends boolean,
12
+ TSelected,
13
+ > {
14
+ select?: (match: ResolveLoaderData<TRouter, TFrom, TStrict>) => TSelected
15
+ }
16
+
17
+ export type UseLoaderDataOptions<
18
+ TRouter extends AnyRouter,
19
+ TFrom extends string | undefined,
20
+ TStrict extends boolean,
21
+ TSelected,
22
+ > = StrictOrFrom<TRouter, TFrom, TStrict> &
23
+ UseLoaderDataBaseOptions<TRouter, TFrom, TStrict, TSelected>
24
+
25
+ export type ResolveLoaderData<
26
+ TRouter extends AnyRouter,
27
+ TFrom,
28
+ TStrict extends boolean,
29
+ > = TStrict extends false
30
+ ? AllLoaderData<TRouter['routeTree']>
31
+ : Expand<RouteById<TRouter['routeTree'], TFrom>['types']['loaderData']>
32
+
33
+ export type UseLoaderDataResult<
34
+ TRouter extends AnyRouter,
35
+ TFrom,
36
+ TStrict extends boolean,
37
+ TSelected,
38
+ > = unknown extends TSelected
39
+ ? ResolveLoaderData<TRouter, TFrom, TStrict>
40
+ : TSelected
41
+
42
+ export type UseLoaderDataRoute<out TId> = <
43
+ TRouter extends AnyRouter = RegisteredRouter,
44
+ TSelected = unknown,
45
+ >(
46
+ opts?: UseLoaderDataBaseOptions<TRouter, TId, true, TSelected>,
47
+ ) => Accessor<UseLoaderDataResult<TRouter, TId, true, TSelected>>
48
+
49
+ export function useLoaderData<
50
+ TRouter extends AnyRouter = RegisteredRouter,
51
+ const TFrom extends string | undefined = undefined,
52
+ TStrict extends boolean = true,
53
+ TSelected = unknown,
54
+ >(
55
+ opts: UseLoaderDataOptions<TRouter, TFrom, TStrict, TSelected>,
56
+ ): Accessor<UseLoaderDataResult<TRouter, TFrom, TStrict, TSelected>> {
57
+ return useMatch({
58
+ from: opts.from!,
59
+ strict: opts.strict,
60
+ select: (s: any) => {
61
+ return opts.select ? opts.select(s.loaderData) : s.loaderData
62
+ },
63
+ } as any) as any
64
+ }
@@ -0,0 +1,52 @@
1
+ import { useMatch } from './useMatch'
2
+ import type { AnyRouter, RegisteredRouter } from './router'
3
+ import type { RouteById } from './routeInfo'
4
+ import type { StrictOrFrom } from './utils'
5
+ import type { Expand } from '@tanstack/router-core'
6
+
7
+ export interface UseLoaderDepsBaseOptions<
8
+ TRouter extends AnyRouter,
9
+ TFrom,
10
+ TSelected,
11
+ > {
12
+ select?: (deps: ResolveLoaderDeps<TRouter, TFrom>) => TSelected
13
+ }
14
+
15
+ export type UseLoaderDepsOptions<
16
+ TRouter extends AnyRouter,
17
+ TFrom extends string | undefined,
18
+ TSelected,
19
+ > = StrictOrFrom<TRouter, TFrom> &
20
+ UseLoaderDepsBaseOptions<TRouter, TFrom, TSelected>
21
+ export type ResolveLoaderDeps<TRouter extends AnyRouter, TFrom> = Expand<
22
+ RouteById<TRouter['routeTree'], TFrom>['types']['loaderDeps']
23
+ >
24
+
25
+ export type UseLoaderDepsResult<
26
+ TRouter extends AnyRouter,
27
+ TFrom,
28
+ TSelected,
29
+ > = unknown extends TSelected ? ResolveLoaderDeps<TRouter, TFrom> : TSelected
30
+
31
+ export type UseLoaderDepsRoute<out TId> = <
32
+ TRouter extends AnyRouter = RegisteredRouter,
33
+ TSelected = unknown,
34
+ >(
35
+ opts?: UseLoaderDepsBaseOptions<TRouter, TId, TSelected>,
36
+ ) => UseLoaderDepsResult<TRouter, TId, TSelected>
37
+
38
+ export function useLoaderDeps<
39
+ TRouter extends AnyRouter = RegisteredRouter,
40
+ const TFrom extends string | undefined = undefined,
41
+ TSelected = unknown,
42
+ >(
43
+ opts: UseLoaderDepsOptions<TRouter, TFrom, TSelected>,
44
+ ): UseLoaderDepsResult<TRouter, TFrom, TSelected> {
45
+ const { select, ...rest } = opts
46
+ return useMatch({
47
+ ...rest,
48
+ select: (s) => {
49
+ return select ? select(s.loaderDeps) : s.loaderDeps
50
+ },
51
+ }) as UseLoaderDepsResult<TRouter, TFrom, TSelected>
52
+ }
@@ -0,0 +1,26 @@
1
+ import { useRouterState } from './useRouterState'
2
+ import type { Accessor } from 'solid-js'
3
+ import type { AnyRouter, RegisteredRouter, RouterState } from './router'
4
+
5
+ export interface UseLocationBaseOptions<TRouter extends AnyRouter, TSelected> {
6
+ select?: (state: RouterState<TRouter['routeTree']>['location']) => TSelected
7
+ }
8
+
9
+ export type UseLocationResult<
10
+ TRouter extends AnyRouter,
11
+ TSelected,
12
+ > = unknown extends TSelected
13
+ ? RouterState<TRouter['routeTree']>['location']
14
+ : TSelected
15
+
16
+ export function useLocation<
17
+ TRouter extends AnyRouter = RegisteredRouter,
18
+ TSelected = unknown,
19
+ >(
20
+ opts?: UseLocationBaseOptions<TRouter, TSelected>,
21
+ ): Accessor<UseLocationResult<TRouter, TSelected>> {
22
+ return useRouterState({
23
+ select: (state: any) =>
24
+ opts?.select ? opts.select(state.location) : state.location,
25
+ } as any) as Accessor<UseLocationResult<TRouter, TSelected>>
26
+ }
@@ -0,0 +1,96 @@
1
+ import * as Solid from 'solid-js'
2
+ import invariant from 'tiny-invariant'
3
+ import { useRouterState } from './useRouterState'
4
+ import { dummyMatchContext, matchContext } from './matchContext'
5
+ import type { AnyRouter, RegisteredRouter } from './router'
6
+ import type { MakeRouteMatch, MakeRouteMatchUnion } from './Matches'
7
+ import type { StrictOrFrom } from './utils'
8
+ import type { ThrowOrOptional } from '@tanstack/router-core'
9
+
10
+ export interface UseMatchBaseOptions<
11
+ TRouter extends AnyRouter,
12
+ TFrom,
13
+ TStrict extends boolean,
14
+ TThrow extends boolean,
15
+ TSelected,
16
+ > {
17
+ select?: (
18
+ match: MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>,
19
+ ) => TSelected
20
+ shouldThrow?: TThrow
21
+ }
22
+
23
+ export type UseMatchRoute<out TFrom> = <
24
+ TRouter extends AnyRouter = RegisteredRouter,
25
+ TSelected = unknown,
26
+ >(
27
+ opts?: UseMatchBaseOptions<TRouter, TFrom, true, true, TSelected>,
28
+ ) => Solid.Accessor<UseMatchResult<TRouter, TFrom, true, TSelected>>
29
+
30
+ export type UseMatchOptions<
31
+ TRouter extends AnyRouter,
32
+ TFrom extends string | undefined,
33
+ TStrict extends boolean,
34
+ TThrow extends boolean,
35
+ TSelected,
36
+ > = StrictOrFrom<TRouter, TFrom, TStrict> &
37
+ UseMatchBaseOptions<TRouter, TFrom, TStrict, TThrow, TSelected>
38
+
39
+ export type UseMatchResult<
40
+ TRouter extends AnyRouter,
41
+ TFrom,
42
+ TStrict extends boolean,
43
+ TSelected,
44
+ > = unknown extends TSelected
45
+ ? TStrict extends true
46
+ ? MakeRouteMatch<TRouter['routeTree'], TFrom, TStrict>
47
+ : MakeRouteMatchUnion<TRouter>
48
+ : TSelected
49
+
50
+ export type ThrowConstraint<
51
+ TStrict extends boolean,
52
+ TThrow extends boolean,
53
+ > = TStrict extends false ? (TThrow extends true ? never : TThrow) : TThrow
54
+
55
+ export function useMatch<
56
+ TRouter extends AnyRouter = RegisteredRouter,
57
+ const TFrom extends string | undefined = undefined,
58
+ TStrict extends boolean = true,
59
+ TThrow extends boolean = true,
60
+ TSelected = unknown,
61
+ >(
62
+ opts: UseMatchOptions<
63
+ TRouter,
64
+ TFrom,
65
+ TStrict,
66
+ ThrowConstraint<TStrict, TThrow>,
67
+ TSelected
68
+ >,
69
+ ): Solid.Accessor<
70
+ ThrowOrOptional<UseMatchResult<TRouter, TFrom, TStrict, TSelected>, TThrow>
71
+ > {
72
+ const nearestMatchId = Solid.useContext(
73
+ opts.from ? dummyMatchContext : matchContext,
74
+ )
75
+
76
+ const matchSelection = useRouterState({
77
+ select: (state: any) => {
78
+ const match = state.matches.find((d: any) =>
79
+ opts.from ? opts.from === d.routeId : d.id === nearestMatchId(),
80
+ )
81
+
82
+ invariant(
83
+ !((opts.shouldThrow ?? true) && !match),
84
+ `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
85
+ )
86
+
87
+ if (match === undefined) {
88
+ return undefined
89
+ }
90
+
91
+ return opts.select ? opts.select(match) : match
92
+ },
93
+ } as any)
94
+
95
+ return matchSelection as any
96
+ }
@@ -0,0 +1,61 @@
1
+ import * as Solid from 'solid-js'
2
+ import { useRouter } from './useRouter'
3
+ import type { FromPathOption, NavigateOptions } from './link'
4
+ import type { AnyRouter, RegisteredRouter } from './router'
5
+
6
+ export type UseNavigateResult<TDefaultFrom extends string> = <
7
+ TRouter extends RegisteredRouter,
8
+ TTo extends string | undefined,
9
+ TFrom extends string = TDefaultFrom,
10
+ TMaskFrom extends string = TFrom,
11
+ TMaskTo extends string = '',
12
+ >({
13
+ from,
14
+ ...rest
15
+ }: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>) => Promise<void>
16
+
17
+ export function useNavigate<
18
+ TRouter extends AnyRouter = RegisteredRouter,
19
+ TDefaultFrom extends string = string,
20
+ >(_defaultOpts?: {
21
+ from?: FromPathOption<TRouter, TDefaultFrom>
22
+ }): UseNavigateResult<TDefaultFrom> {
23
+ const { navigate } = useRouter()
24
+
25
+ return ((options: NavigateOptions) => {
26
+ return navigate({ ...options })
27
+ }) as UseNavigateResult<TDefaultFrom>
28
+ }
29
+
30
+ // NOTE: I don't know of anyone using this. It's undocumented, so let's wait until someone needs it
31
+ // export function typedNavigate<
32
+ // TRouteTree extends AnyRoute = RegisteredRouter['routeTree'],
33
+ // TDefaultFrom extends RoutePaths<TRouteTree> = '/',
34
+ // >(navigate: (opts: NavigateOptions<any>) => Promise<void>) {
35
+ // return navigate as <
36
+ // TFrom extends RoutePaths<TRouteTree> = TDefaultFrom,
37
+ // TTo extends string = '',
38
+ // TMaskFrom extends RoutePaths<TRouteTree> = '/',
39
+ // TMaskTo extends string = '',
40
+ // >(
41
+ // opts?: NavigateOptions<TRouteTree, TFrom, TTo, TMaskFrom, TMaskTo>,
42
+ // ) => Promise<void>
43
+ // } //
44
+
45
+ export function Navigate<
46
+ TRouter extends AnyRouter = RegisteredRouter,
47
+ const TFrom extends string = string,
48
+ const TTo extends string | undefined = undefined,
49
+ const TMaskFrom extends string = TFrom,
50
+ const TMaskTo extends string = '',
51
+ >(props: NavigateOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): null {
52
+ const { navigate } = useRouter()
53
+
54
+ Solid.onMount(() => {
55
+ navigate({
56
+ ...props,
57
+ })
58
+ })
59
+
60
+ return null
61
+ }
@@ -0,0 +1,83 @@
1
+ import { useMatch } from './useMatch'
2
+ import type { ThrowConstraint } from './useMatch'
3
+ import type { Accessor } from 'solid-js'
4
+ import type { AllParams, RouteById } from './routeInfo'
5
+ import type { AnyRouter, RegisteredRouter } from './router'
6
+ import type { StrictOrFrom } from './utils'
7
+ import type { Expand, ThrowOrOptional } from '@tanstack/router-core'
8
+
9
+ export interface UseParamsBaseOptions<
10
+ TRouter extends AnyRouter,
11
+ TFrom,
12
+ TStrict extends boolean,
13
+ TThrow extends boolean,
14
+ TSelected,
15
+ > {
16
+ select?: (params: ResolveParams<TRouter, TFrom, TStrict>) => TSelected
17
+ shouldThrow?: TThrow
18
+ }
19
+
20
+ export type UseParamsOptions<
21
+ TRouter extends AnyRouter,
22
+ TFrom extends string | undefined,
23
+ TStrict extends boolean,
24
+ TThrow extends boolean,
25
+ TSelected,
26
+ > = StrictOrFrom<TRouter, TFrom, TStrict> &
27
+ UseParamsBaseOptions<TRouter, TFrom, TStrict, TThrow, TSelected>
28
+ export type ResolveParams<
29
+ TRouter extends AnyRouter,
30
+ TFrom,
31
+ TStrict extends boolean,
32
+ > = TStrict extends false
33
+ ? AllParams<TRouter['routeTree']>
34
+ : Expand<RouteById<TRouter['routeTree'], TFrom>['types']['allParams']>
35
+
36
+ export type UseParamsResult<
37
+ TRouter extends AnyRouter,
38
+ TFrom,
39
+ TStrict extends boolean,
40
+ TSelected,
41
+ > = unknown extends TSelected
42
+ ? ResolveParams<TRouter, TFrom, TStrict>
43
+ : TSelected
44
+
45
+ export type UseParamsRoute<out TFrom> = <
46
+ TRouter extends AnyRouter = RegisteredRouter,
47
+ TSelected = unknown,
48
+ >(
49
+ opts?: UseParamsBaseOptions<
50
+ TRouter,
51
+ TFrom,
52
+ /* TStrict */ true,
53
+ /* TThrow */ true,
54
+ TSelected
55
+ >,
56
+ ) => Accessor<UseParamsResult<TRouter, TFrom, true, TSelected>>
57
+
58
+ export function useParams<
59
+ TRouter extends AnyRouter = RegisteredRouter,
60
+ const TFrom extends string | undefined = undefined,
61
+ TStrict extends boolean = true,
62
+ TThrow extends boolean = true,
63
+ TSelected = unknown,
64
+ >(
65
+ opts: UseParamsOptions<
66
+ TRouter,
67
+ TFrom,
68
+ TStrict,
69
+ ThrowConstraint<TStrict, TThrow>,
70
+ TSelected
71
+ >,
72
+ ): Accessor<
73
+ ThrowOrOptional<UseParamsResult<TRouter, TFrom, TStrict, TSelected>, TThrow>
74
+ > {
75
+ return useMatch({
76
+ from: opts.from!,
77
+ strict: opts.strict,
78
+ shouldThrow: opts.shouldThrow,
79
+ select: (match: any) => {
80
+ return opts.select ? opts.select(match.params) : match.params
81
+ },
82
+ } as any) as any
83
+ }