@tanstack/solid-router 1.121.0-alpha.27 → 1.121.0-alpha.28

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 (265) hide show
  1. package/dist/cjs/Asset.cjs +65 -21
  2. package/dist/cjs/Asset.cjs.map +1 -1
  3. package/dist/cjs/Asset.d.cts +2 -1
  4. package/dist/cjs/CatchBoundary.cjs +14 -15
  5. package/dist/cjs/CatchBoundary.cjs.map +1 -1
  6. package/dist/cjs/ClientOnly.cjs +12 -14
  7. package/dist/cjs/ClientOnly.cjs.map +1 -1
  8. package/dist/cjs/ClientOnly.d.cts +0 -20
  9. package/dist/cjs/HeadContent.cjs +28 -23
  10. package/dist/cjs/HeadContent.cjs.map +1 -1
  11. package/dist/cjs/Match.cjs +167 -141
  12. package/dist/cjs/Match.cjs.map +1 -1
  13. package/dist/cjs/Matches.cjs +26 -24
  14. package/dist/cjs/Matches.cjs.map +1 -1
  15. package/dist/cjs/Matches.d.cts +1 -0
  16. package/dist/cjs/RouterProvider.cjs +5 -5
  17. package/dist/cjs/RouterProvider.cjs.map +1 -1
  18. package/dist/cjs/SafeFragment.cjs +2 -2
  19. package/dist/cjs/SafeFragment.cjs.map +1 -1
  20. package/dist/cjs/ScriptOnce.cjs +4 -9
  21. package/dist/cjs/ScriptOnce.cjs.map +1 -1
  22. package/dist/cjs/ScriptOnce.d.cts +1 -1
  23. package/dist/cjs/Scripts.cjs +9 -13
  24. package/dist/cjs/Scripts.cjs.map +1 -1
  25. package/dist/cjs/ScrollRestoration.cjs +3 -4
  26. package/dist/cjs/ScrollRestoration.cjs.map +1 -1
  27. package/dist/cjs/Transitioner.cjs +9 -8
  28. package/dist/cjs/Transitioner.cjs.map +1 -1
  29. package/dist/cjs/awaited.cjs +2 -2
  30. package/dist/cjs/awaited.cjs.map +1 -1
  31. package/dist/cjs/fileRoute.cjs +5 -5
  32. package/dist/cjs/fileRoute.cjs.map +1 -1
  33. package/dist/cjs/index.cjs +0 -12
  34. package/dist/cjs/index.cjs.map +1 -1
  35. package/dist/cjs/index.d.cts +3 -6
  36. package/dist/cjs/lazyRouteComponent.cjs +6 -26
  37. package/dist/cjs/lazyRouteComponent.cjs.map +1 -1
  38. package/dist/cjs/lazyRouteComponent.d.cts +1 -1
  39. package/dist/cjs/link.cjs +37 -31
  40. package/dist/cjs/link.cjs.map +1 -1
  41. package/dist/cjs/not-found.cjs +5 -7
  42. package/dist/cjs/not-found.cjs.map +1 -1
  43. package/dist/cjs/renderRouteNotFound.cjs +4 -4
  44. package/dist/cjs/renderRouteNotFound.cjs.map +1 -1
  45. package/dist/cjs/route.cjs +16 -16
  46. package/dist/cjs/route.cjs.map +1 -1
  47. package/dist/cjs/route.d.cts +14 -5
  48. package/dist/cjs/router.cjs.map +1 -1
  49. package/dist/cjs/routerContext.cjs.map +1 -1
  50. package/dist/cjs/scroll-restoration.cjs +12 -6
  51. package/dist/cjs/scroll-restoration.cjs.map +1 -1
  52. package/dist/cjs/ssr/RouterClient.cjs +45 -0
  53. package/dist/cjs/ssr/RouterClient.cjs.map +1 -0
  54. package/dist/cjs/ssr/RouterClient.d.cts +4 -0
  55. package/dist/cjs/ssr/RouterServer.cjs +56 -0
  56. package/dist/cjs/ssr/RouterServer.cjs.map +1 -0
  57. package/dist/cjs/ssr/RouterServer.d.cts +5 -0
  58. package/dist/cjs/ssr/client.cjs +5 -0
  59. package/dist/cjs/ssr/client.cjs.map +1 -0
  60. package/dist/cjs/ssr/client.d.cts +1 -0
  61. package/dist/cjs/ssr/defaultRenderHandler.cjs +18 -0
  62. package/dist/cjs/ssr/defaultRenderHandler.cjs.map +1 -0
  63. package/dist/cjs/ssr/defaultRenderHandler.d.cts +1 -0
  64. package/dist/cjs/ssr/defaultStreamHandler.cjs +20 -0
  65. package/dist/cjs/ssr/defaultStreamHandler.cjs.map +1 -0
  66. package/dist/cjs/ssr/defaultStreamHandler.d.cts +1 -0
  67. package/dist/cjs/ssr/renderRouterToStream.cjs +45 -0
  68. package/dist/cjs/ssr/renderRouterToStream.cjs.map +1 -0
  69. package/dist/cjs/ssr/renderRouterToStream.d.cts +8 -0
  70. package/dist/cjs/ssr/renderRouterToString.cjs +43 -0
  71. package/dist/cjs/ssr/renderRouterToString.cjs.map +1 -0
  72. package/dist/cjs/ssr/renderRouterToString.d.cts +7 -0
  73. package/dist/cjs/ssr/server.cjs +20 -0
  74. package/dist/cjs/ssr/server.cjs.map +1 -0
  75. package/dist/cjs/ssr/server.d.cts +6 -0
  76. package/dist/cjs/useBlocker.cjs +41 -35
  77. package/dist/cjs/useBlocker.cjs.map +1 -1
  78. package/dist/cjs/useCanGoBack.cjs.map +1 -1
  79. package/dist/cjs/useLoaderData.cjs.map +1 -1
  80. package/dist/cjs/useLoaderDeps.cjs.map +1 -1
  81. package/dist/cjs/useLocation.cjs +1 -1
  82. package/dist/cjs/useLocation.cjs.map +1 -1
  83. package/dist/cjs/useMatch.cjs.map +1 -1
  84. package/dist/cjs/useNavigate.cjs +9 -3
  85. package/dist/cjs/useNavigate.cjs.map +1 -1
  86. package/dist/cjs/useParams.cjs.map +1 -1
  87. package/dist/cjs/useRouter.cjs +1 -1
  88. package/dist/cjs/useRouter.cjs.map +1 -1
  89. package/dist/cjs/useRouterState.cjs +3 -3
  90. package/dist/cjs/useRouterState.cjs.map +1 -1
  91. package/dist/cjs/useSearch.cjs.map +1 -1
  92. package/dist/cjs/utils.cjs +1 -1
  93. package/dist/cjs/utils.cjs.map +1 -1
  94. package/dist/esm/Asset.d.ts +2 -1
  95. package/dist/esm/Asset.js +60 -16
  96. package/dist/esm/Asset.js.map +1 -1
  97. package/dist/esm/CatchBoundary.js +1 -2
  98. package/dist/esm/CatchBoundary.js.map +1 -1
  99. package/dist/esm/ClientOnly.d.ts +0 -20
  100. package/dist/esm/ClientOnly.js +11 -13
  101. package/dist/esm/ClientOnly.js.map +1 -1
  102. package/dist/esm/HeadContent.js +23 -18
  103. package/dist/esm/HeadContent.js.map +1 -1
  104. package/dist/esm/Match.js +148 -122
  105. package/dist/esm/Match.js.map +1 -1
  106. package/dist/esm/Matches.d.ts +1 -0
  107. package/dist/esm/Matches.js +18 -16
  108. package/dist/esm/Matches.js.map +1 -1
  109. package/dist/esm/RouterProvider.js.map +1 -1
  110. package/dist/esm/SafeFragment.js.map +1 -1
  111. package/dist/esm/ScriptOnce.d.ts +1 -1
  112. package/dist/esm/ScriptOnce.js +2 -7
  113. package/dist/esm/ScriptOnce.js.map +1 -1
  114. package/dist/esm/Scripts.js +7 -11
  115. package/dist/esm/Scripts.js.map +1 -1
  116. package/dist/esm/ScrollRestoration.js +3 -4
  117. package/dist/esm/ScrollRestoration.js.map +1 -1
  118. package/dist/esm/Transitioner.js +9 -8
  119. package/dist/esm/Transitioner.js.map +1 -1
  120. package/dist/esm/awaited.js.map +1 -1
  121. package/dist/esm/fileRoute.js +5 -5
  122. package/dist/esm/fileRoute.js.map +1 -1
  123. package/dist/esm/index.d.ts +3 -6
  124. package/dist/esm/index.js +2 -8
  125. package/dist/esm/index.js.map +1 -1
  126. package/dist/esm/lazyRouteComponent.d.ts +1 -1
  127. package/dist/esm/lazyRouteComponent.js +2 -22
  128. package/dist/esm/lazyRouteComponent.js.map +1 -1
  129. package/dist/esm/link.js +34 -28
  130. package/dist/esm/link.js.map +1 -1
  131. package/dist/esm/not-found.js +2 -4
  132. package/dist/esm/not-found.js.map +1 -1
  133. package/dist/esm/renderRouteNotFound.js.map +1 -1
  134. package/dist/esm/route.d.ts +14 -5
  135. package/dist/esm/route.js +12 -12
  136. package/dist/esm/route.js.map +1 -1
  137. package/dist/esm/router.js.map +1 -1
  138. package/dist/esm/routerContext.js.map +1 -1
  139. package/dist/esm/scroll-restoration.js +10 -4
  140. package/dist/esm/scroll-restoration.js.map +1 -1
  141. package/dist/esm/ssr/RouterClient.d.ts +4 -0
  142. package/dist/esm/ssr/RouterClient.js +45 -0
  143. package/dist/esm/ssr/RouterClient.js.map +1 -0
  144. package/dist/esm/ssr/RouterServer.d.ts +5 -0
  145. package/dist/esm/ssr/RouterServer.js +56 -0
  146. package/dist/esm/ssr/RouterServer.js.map +1 -0
  147. package/dist/esm/ssr/client.d.ts +1 -0
  148. package/dist/esm/ssr/client.js +5 -0
  149. package/dist/esm/ssr/client.js.map +1 -0
  150. package/dist/esm/ssr/defaultRenderHandler.d.ts +1 -0
  151. package/dist/esm/ssr/defaultRenderHandler.js +18 -0
  152. package/dist/esm/ssr/defaultRenderHandler.js.map +1 -0
  153. package/dist/esm/ssr/defaultStreamHandler.d.ts +1 -0
  154. package/dist/esm/ssr/defaultStreamHandler.js +20 -0
  155. package/dist/esm/ssr/defaultStreamHandler.js.map +1 -0
  156. package/dist/esm/ssr/renderRouterToStream.d.ts +8 -0
  157. package/dist/esm/ssr/renderRouterToStream.js +28 -0
  158. package/dist/esm/ssr/renderRouterToStream.js.map +1 -0
  159. package/dist/esm/ssr/renderRouterToString.d.ts +7 -0
  160. package/dist/esm/ssr/renderRouterToString.js +26 -0
  161. package/dist/esm/ssr/renderRouterToString.js.map +1 -0
  162. package/dist/esm/ssr/server.d.ts +6 -0
  163. package/dist/esm/ssr/server.js +14 -0
  164. package/dist/esm/ssr/server.js.map +1 -0
  165. package/dist/esm/useBlocker.js +41 -35
  166. package/dist/esm/useBlocker.js.map +1 -1
  167. package/dist/esm/useCanGoBack.js.map +1 -1
  168. package/dist/esm/useLoaderData.js.map +1 -1
  169. package/dist/esm/useLoaderDeps.js.map +1 -1
  170. package/dist/esm/useLocation.js +1 -1
  171. package/dist/esm/useLocation.js.map +1 -1
  172. package/dist/esm/useMatch.js.map +1 -1
  173. package/dist/esm/useNavigate.js +9 -3
  174. package/dist/esm/useNavigate.js.map +1 -1
  175. package/dist/esm/useParams.js.map +1 -1
  176. package/dist/esm/useRouter.js +1 -1
  177. package/dist/esm/useRouter.js.map +1 -1
  178. package/dist/esm/useRouterState.js +3 -3
  179. package/dist/esm/useRouterState.js.map +1 -1
  180. package/dist/esm/useSearch.js.map +1 -1
  181. package/dist/esm/utils.js +1 -1
  182. package/dist/esm/utils.js.map +1 -1
  183. package/dist/source/Asset.d.ts +2 -1
  184. package/dist/source/Asset.jsx +45 -7
  185. package/dist/source/Asset.jsx.map +1 -1
  186. package/dist/source/ClientOnly.d.ts +0 -20
  187. package/dist/source/ClientOnly.jsx +3 -29
  188. package/dist/source/ClientOnly.jsx.map +1 -1
  189. package/dist/source/HeadContent.jsx +13 -0
  190. package/dist/source/HeadContent.jsx.map +1 -1
  191. package/dist/source/Match.jsx +74 -61
  192. package/dist/source/Match.jsx.map +1 -1
  193. package/dist/source/Matches.d.ts +1 -0
  194. package/dist/source/Matches.jsx +14 -11
  195. package/dist/source/Matches.jsx.map +1 -1
  196. package/dist/source/ScriptOnce.d.ts +1 -1
  197. package/dist/source/ScriptOnce.jsx +2 -12
  198. package/dist/source/ScriptOnce.jsx.map +1 -1
  199. package/dist/source/Transitioner.jsx +8 -8
  200. package/dist/source/Transitioner.jsx.map +1 -1
  201. package/dist/source/index.d.ts +3 -6
  202. package/dist/source/index.jsx +1 -4
  203. package/dist/source/index.jsx.map +1 -1
  204. package/dist/source/lazyRouteComponent.d.ts +1 -1
  205. package/dist/source/lazyRouteComponent.jsx +7 -21
  206. package/dist/source/lazyRouteComponent.jsx.map +1 -1
  207. package/dist/source/link.jsx +22 -17
  208. package/dist/source/link.jsx.map +1 -1
  209. package/dist/source/not-found.jsx.map +1 -1
  210. package/dist/source/route.d.ts +14 -5
  211. package/dist/source/route.jsx.map +1 -1
  212. package/dist/source/scroll-restoration.jsx +9 -2
  213. package/dist/source/scroll-restoration.jsx.map +1 -1
  214. package/dist/source/ssr/RouterClient.d.ts +4 -0
  215. package/dist/source/ssr/RouterClient.jsx +28 -0
  216. package/dist/source/ssr/RouterClient.jsx.map +1 -0
  217. package/dist/source/ssr/RouterServer.d.ts +5 -0
  218. package/dist/source/ssr/RouterServer.jsx +38 -0
  219. package/dist/source/ssr/RouterServer.jsx.map +1 -0
  220. package/dist/source/ssr/client.d.ts +1 -0
  221. package/dist/source/ssr/client.js +2 -0
  222. package/dist/source/ssr/client.js.map +1 -0
  223. package/dist/source/ssr/defaultRenderHandler.d.ts +1 -0
  224. package/dist/source/ssr/defaultRenderHandler.jsx +9 -0
  225. package/dist/source/ssr/defaultRenderHandler.jsx.map +1 -0
  226. package/dist/source/ssr/defaultStreamHandler.d.ts +1 -0
  227. package/dist/source/ssr/defaultStreamHandler.jsx +10 -0
  228. package/dist/source/ssr/defaultStreamHandler.jsx.map +1 -0
  229. package/dist/source/ssr/renderRouterToStream.d.ts +8 -0
  230. package/dist/source/ssr/renderRouterToStream.jsx +17 -0
  231. package/dist/source/ssr/renderRouterToStream.jsx.map +1 -0
  232. package/dist/source/ssr/renderRouterToString.d.ts +7 -0
  233. package/dist/source/ssr/renderRouterToString.jsx +20 -0
  234. package/dist/source/ssr/renderRouterToString.jsx.map +1 -0
  235. package/dist/source/ssr/server.d.ts +6 -0
  236. package/dist/source/ssr/server.js +7 -0
  237. package/dist/source/ssr/server.js.map +1 -0
  238. package/dist/source/useBlocker.jsx +44 -27
  239. package/dist/source/useBlocker.jsx.map +1 -1
  240. package/dist/source/useNavigate.jsx +12 -2
  241. package/dist/source/useNavigate.jsx.map +1 -1
  242. package/package.json +34 -7
  243. package/src/Asset.tsx +76 -7
  244. package/src/ClientOnly.tsx +5 -32
  245. package/src/HeadContent.tsx +17 -0
  246. package/src/Match.tsx +103 -81
  247. package/src/Matches.tsx +28 -19
  248. package/src/ScriptOnce.tsx +1 -13
  249. package/src/Transitioner.tsx +7 -7
  250. package/src/index.tsx +1 -18
  251. package/src/lazyRouteComponent.tsx +6 -26
  252. package/src/link.tsx +29 -21
  253. package/src/not-found.tsx +1 -1
  254. package/src/route.tsx +16 -5
  255. package/src/scroll-restoration.tsx +10 -3
  256. package/src/ssr/RouterClient.tsx +43 -0
  257. package/src/ssr/RouterServer.tsx +60 -0
  258. package/src/ssr/client.ts +1 -0
  259. package/src/ssr/defaultRenderHandler.tsx +12 -0
  260. package/src/ssr/defaultStreamHandler.tsx +13 -0
  261. package/src/ssr/renderRouterToStream.tsx +36 -0
  262. package/src/ssr/renderRouterToString.tsx +31 -0
  263. package/src/ssr/server.ts +6 -0
  264. package/src/useBlocker.tsx +48 -32
  265. package/src/useNavigate.tsx +14 -2
@@ -116,6 +116,22 @@ export const useTags = () => {
116
116
  },
117
117
  })
118
118
 
119
+ const styles = useRouterState({
120
+ select: (state) =>
121
+ (
122
+ state.matches
123
+ .map((match) => match.styles!)
124
+ .flat(1)
125
+ .filter(Boolean) as Array<RouterManagedTag>
126
+ ).map(({ children, ...style }) => ({
127
+ tag: 'style',
128
+ attrs: {
129
+ ...style,
130
+ },
131
+ children,
132
+ })),
133
+ })
134
+
119
135
  const headScripts = useRouterState({
120
136
  select: (state) =>
121
137
  (
@@ -138,6 +154,7 @@ export const useTags = () => {
138
154
  ...meta(),
139
155
  ...preloadMeta(),
140
156
  ...links(),
157
+ ...styles(),
141
158
  ...headScripts(),
142
159
  ] as Array<RouterManagedTag>,
143
160
  (d) => {
package/src/Match.tsx CHANGED
@@ -18,22 +18,23 @@ import { matchContext } from './matchContext'
18
18
  import { SafeFragment } from './SafeFragment'
19
19
  import { renderRouteNotFound } from './renderRouteNotFound'
20
20
  import { ScrollRestoration } from './scroll-restoration'
21
- import type { AnyRoute } from '@tanstack/router-core'
21
+ import type { AnyRoute, RootRouteOptions } from '@tanstack/router-core'
22
22
 
23
23
  export const Match = (props: { matchId: string }) => {
24
24
  const router = useRouter()
25
- const routeId = useRouterState({
25
+ const matchState = useRouterState({
26
26
  select: (s) => {
27
- return s.matches.find((d) => d.id === props.matchId)?.routeId as string
27
+ const match = s.matches.find((d) => d.id === props.matchId)
28
+
29
+ invariant(
30
+ match,
31
+ `Could not find match for matchId "${props.matchId}". Please file an issue!`,
32
+ )
33
+ return pick(match, ['routeId', 'ssr', '_displayPending'])
28
34
  },
29
35
  })
30
36
 
31
- invariant(
32
- routeId,
33
- `Could not find routeId for matchId "${props.matchId}". Please file an issue!`,
34
- )
35
-
36
- const route: () => AnyRoute = () => router.routesById[routeId()]
37
+ const route: () => AnyRoute = () => router.routesById[matchState().routeId]
37
38
 
38
39
  const PendingComponent = () =>
39
40
  route().options.pendingComponent ?? router.options.defaultPendingComponent
@@ -51,12 +52,18 @@ export const Match = (props: { matchId: string }) => {
51
52
  router.options.notFoundRoute?.options.component)
52
53
  : route().options.notFoundComponent
53
54
 
55
+ const resolvedNoSsr =
56
+ matchState().ssr === false || matchState().ssr === 'data-only'
57
+
54
58
  const ResolvedSuspenseBoundary = () =>
55
59
  // If we're on the root route, allow forcefully wrapping in suspense
56
- (!route().isRoot || route().options.wrapInSuspense) &&
60
+ (!route().isRoot ||
61
+ route().options.wrapInSuspense ||
62
+ resolvedNoSsr ||
63
+ matchState()._displayPending) &&
57
64
  (route().options.wrapInSuspense ??
58
65
  PendingComponent() ??
59
- (route().options.errorComponent as any)?.preload)
66
+ ((route().options.errorComponent as any)?.preload || resolvedNoSsr))
60
67
  ? Solid.Suspense
61
68
  : SafeFragment
62
69
 
@@ -77,8 +84,12 @@ export const Match = (props: { matchId: string }) => {
77
84
  },
78
85
  })
79
86
 
87
+ const ShellComponent = route().isRoot
88
+ ? ((route().options as RootRouteOptions).shellComponent ?? SafeFragment)
89
+ : SafeFragment
90
+
80
91
  return (
81
- <>
92
+ <ShellComponent>
82
93
  <matchContext.Provider value={() => props.matchId}>
83
94
  <Dynamic
84
95
  component={ResolvedSuspenseBoundary()}
@@ -102,7 +113,7 @@ export const Match = (props: { matchId: string }) => {
102
113
  // route ID which doesn't match the current route, rethrow the error
103
114
  if (
104
115
  !routeNotFoundComponent() ||
105
- (error.routeId && error.routeId !== routeId) ||
116
+ (error.routeId && error.routeId !== matchState().routeId) ||
106
117
  (!error.routeId && !route().isRoot)
107
118
  )
108
119
  throw error
@@ -112,7 +123,19 @@ export const Match = (props: { matchId: string }) => {
112
123
  )
113
124
  }}
114
125
  >
115
- <MatchInner matchId={props.matchId} />
126
+ <Solid.Switch>
127
+ <Solid.Match when={resolvedNoSsr}>
128
+ <Solid.Show
129
+ when={!router.isServer}
130
+ fallback={<Dynamic component={PendingComponent()} />}
131
+ >
132
+ <MatchInner matchId={props.matchId} />
133
+ </Solid.Show>
134
+ </Solid.Match>
135
+ <Solid.Match when={!resolvedNoSsr}>
136
+ <MatchInner matchId={props.matchId} />
137
+ </Solid.Match>
138
+ </Solid.Switch>
116
139
  </Dynamic>
117
140
  </Dynamic>
118
141
  </Dynamic>
@@ -124,14 +147,14 @@ export const Match = (props: { matchId: string }) => {
124
147
  <ScrollRestoration />
125
148
  </>
126
149
  ) : null}
127
- </>
150
+ </ShellComponent>
128
151
  )
129
152
  }
130
153
 
131
154
  // On Rendered can't happen above the root layout because it actually
132
155
  // renders a dummy dom element to track the rendered state of the app.
133
156
  // We render a script tag with a key that changes based on the current
134
- // location state.key. Also, because it's below the root layout, it
157
+ // location state.__TSR_key. Also, because it's below the root layout, it
135
158
  // allows us to fire onRendered events even after a hydration mismatch
136
159
  // error that occurred above the root layout (like bad head/link tags,
137
160
  // which is common).
@@ -140,7 +163,7 @@ function OnRendered() {
140
163
 
141
164
  const location = useRouterState({
142
165
  select: (s) => {
143
- return s.resolvedLocation?.state.key
166
+ return s.resolvedLocation?.state.__TSR_key
144
167
  },
145
168
  })
146
169
  Solid.createEffect(
@@ -157,8 +180,7 @@ function OnRendered() {
157
180
  export const MatchInner = (props: { matchId: string }): any => {
158
181
  const router = useRouter()
159
182
 
160
- // { match, key, routeId } =
161
- const matchState: Solid.Accessor<any> = useRouterState({
183
+ const matchState = useRouterState({
162
184
  select: (s) => {
163
185
  const matchIndex = s.matches.findIndex((d) => d.id === props.matchId)
164
186
  const match = s.matches[matchIndex]!
@@ -178,81 +200,51 @@ export const MatchInner = (props: { matchId: string }): any => {
178
200
  return {
179
201
  key,
180
202
  routeId,
181
- match: pick(match, ['id', 'status', 'error']),
203
+ match: pick(match, [
204
+ 'id',
205
+ 'status',
206
+ 'error',
207
+ '_forcePending',
208
+ '_displayPending',
209
+ ]),
182
210
  }
183
211
  },
184
212
  })
185
213
 
186
214
  const route = () => router.routesById[matchState().routeId]!
187
215
 
188
- // function useChangedDiff(value: any) {
189
- // const ref = Solid.useRef(value)
190
- // const changed = ref.current !== value
191
- // if (changed) {
192
- // console.log(
193
- // 'Changed:',
194
- // value,
195
- // Object.fromEntries(
196
- // Object.entries(value).filter(
197
- // ([key, val]) => val !== ref.current[key],
198
- // ),
199
- // ),
200
- // )
201
- // }
202
- // ref.current = value
203
- // }
204
-
205
- // useChangedDiff(match)
206
216
  const match = () => matchState().match
207
217
 
208
218
  const out = () => {
209
219
  const Comp = route().options.component ?? router.options.defaultComponent
210
220
  if (Comp) {
211
- return <Comp />
221
+ return (
222
+ <Solid.Show when={matchState().match.id} keyed>
223
+ <Comp />
224
+ </Solid.Show>
225
+ )
212
226
  }
213
227
  return <Outlet />
214
228
  }
215
229
 
216
230
  return (
217
231
  <Solid.Switch>
218
- <Solid.Match when={match().status === 'notFound'}>
219
- {(_) => {
220
- invariant(isNotFound(match().error), 'Expected a notFound error')
221
-
222
- return renderRouteNotFound(router, route(), match().error)
223
- }}
224
- </Solid.Match>
225
- <Solid.Match when={match().status === 'redirected'}>
232
+ <Solid.Match when={match()._displayPending}>
226
233
  {(_) => {
227
- invariant(isRedirect(match().error), 'Expected a redirect error')
228
-
229
- const [loaderResult] = Solid.createResource(async () => {
230
- await new Promise((r) => setTimeout(r, 0))
231
- return router.getMatch(match().id)?.loadPromise
232
- })
234
+ const [displayPendingResult] = Solid.createResource(
235
+ () => router.getMatch(match().id)?.displayPendingPromise,
236
+ )
233
237
 
234
- return <>{loaderResult()}</>
238
+ return <>{displayPendingResult()}</>
235
239
  }}
236
240
  </Solid.Match>
237
- <Solid.Match when={match().status === 'error'}>
241
+ <Solid.Match when={match()._forcePending}>
238
242
  {(_) => {
239
- if (router.isServer) {
240
- const RouteErrorComponent =
241
- (route().options.errorComponent ??
242
- router.options.defaultErrorComponent) ||
243
- ErrorComponent
244
-
245
- return (
246
- <RouteErrorComponent
247
- error={match().error}
248
- info={{
249
- componentStack: '',
250
- }}
251
- />
252
- )
253
- }
243
+ const [minPendingResult] = Solid.createResource(
244
+ () => router.getMatch(match().id)?.minPendingPromise,
245
+ )
254
246
 
255
- throw match().error
247
+ return <>{minPendingResult()}</>
256
248
  }}
257
249
  </Solid.Match>
258
250
  <Solid.Match when={match().status === 'pending'}>
@@ -292,6 +284,46 @@ export const MatchInner = (props: { matchId: string }): any => {
292
284
  return <>{loaderResult()}</>
293
285
  }}
294
286
  </Solid.Match>
287
+ <Solid.Match when={match().status === 'notFound'}>
288
+ {(_) => {
289
+ invariant(isNotFound(match().error), 'Expected a notFound error')
290
+
291
+ return renderRouteNotFound(router, route(), match().error)
292
+ }}
293
+ </Solid.Match>
294
+ <Solid.Match when={match().status === 'redirected'}>
295
+ {(_) => {
296
+ invariant(isRedirect(match().error), 'Expected a redirect error')
297
+
298
+ const [loaderResult] = Solid.createResource(async () => {
299
+ await new Promise((r) => setTimeout(r, 0))
300
+ return router.getMatch(match().id)?.loadPromise
301
+ })
302
+
303
+ return <>{loaderResult()}</>
304
+ }}
305
+ </Solid.Match>
306
+ <Solid.Match when={match().status === 'error'}>
307
+ {(_) => {
308
+ if (router.isServer) {
309
+ const RouteErrorComponent =
310
+ (route().options.errorComponent ??
311
+ router.options.defaultErrorComponent) ||
312
+ ErrorComponent
313
+
314
+ return (
315
+ <RouteErrorComponent
316
+ error={match().error}
317
+ info={{
318
+ componentStack: '',
319
+ }}
320
+ />
321
+ )
322
+ }
323
+
324
+ throw match().error
325
+ }}
326
+ </Solid.Match>
295
327
  <Solid.Match when={match().status === 'success'}>{out()}</Solid.Match>
296
328
  </Solid.Switch>
297
329
  )
@@ -329,16 +361,6 @@ export const Outlet = () => {
329
361
 
330
362
  return (
331
363
  <Solid.Switch>
332
- <Solid.Match when={router.isShell}>
333
- <Solid.Suspense
334
- fallback={
335
- <Dynamic component={router.options.defaultPendingComponent} />
336
- }
337
- >
338
- <ErrorComponent error={new Error('ShellBoundaryError')} />
339
- </Solid.Suspense>
340
- </Solid.Match>
341
-
342
364
  <Solid.Match when={parentGlobalNotFound()}>
343
365
  {renderRouteNotFound(router, route(), undefined)}
344
366
  </Solid.Match>
package/src/Matches.tsx CHANGED
@@ -30,6 +30,7 @@ declare module '@tanstack/router-core' {
30
30
  meta?: Array<Solid.JSX.IntrinsicElements['meta'] | undefined>
31
31
  links?: Array<Solid.JSX.IntrinsicElements['link'] | undefined>
32
32
  scripts?: Array<Solid.JSX.IntrinsicElements['script'] | undefined>
33
+ styles?: Array<Solid.JSX.IntrinsicElements['style'] | undefined>
33
34
  headScripts?: Array<Solid.JSX.IntrinsicElements['script'] | undefined>
34
35
  }
35
36
  }
@@ -43,13 +44,13 @@ export function Matches() {
43
44
 
44
45
  // Do not render a root Suspense during SSR or hydrating from SSR
45
46
  const ResolvedSuspense =
46
- router.isServer || (typeof document !== 'undefined' && router.clientSsr)
47
+ router.isServer || (typeof document !== 'undefined' && router.ssr)
47
48
  ? SafeFragment
48
49
  : Solid.Suspense
49
50
 
50
51
  const inner = (
51
52
  <ResolvedSuspense fallback={pendingElement}>
52
- <Transitioner />
53
+ {!router.isServer && <Transitioner />}
53
54
  <MatchesInner />
54
55
  </ResolvedSuspense>
55
56
  )
@@ -62,6 +63,7 @@ export function Matches() {
62
63
  }
63
64
 
64
65
  function MatchesInner() {
66
+ const router = useRouter()
65
67
  const matchId = useRouterState({
66
68
  select: (s) => {
67
69
  return s.matches[0]?.id
@@ -72,21 +74,28 @@ function MatchesInner() {
72
74
  select: (s) => s.loadedAt,
73
75
  })
74
76
 
77
+ const matchComponent = () =>
78
+ matchId() ? <Match matchId={matchId()!} /> : null
79
+
75
80
  return (
76
81
  <matchContext.Provider value={matchId}>
77
- <CatchBoundary
78
- getResetKey={() => resetKey()}
79
- errorComponent={ErrorComponent}
80
- onCatch={(error) => {
81
- warning(
82
- false,
83
- `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
84
- )
85
- warning(false, error.message || error.toString())
86
- }}
87
- >
88
- {matchId() ? <Match matchId={matchId()!} /> : null}
89
- </CatchBoundary>
82
+ {router.options.disableGlobalCatchBoundary ? (
83
+ matchComponent()
84
+ ) : (
85
+ <CatchBoundary
86
+ getResetKey={() => resetKey()}
87
+ errorComponent={ErrorComponent}
88
+ onCatch={(error) => {
89
+ warning(
90
+ false,
91
+ `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
92
+ )
93
+ warning(false, error.message || error.toString())
94
+ }}
95
+ >
96
+ {matchComponent()}
97
+ </CatchBoundary>
98
+ )}
90
99
  </matchContext.Provider>
91
100
  )
92
101
  }
@@ -170,12 +179,12 @@ export function MatchRoute<
170
179
  {(_) => {
171
180
  const matchRoute = useMatchRoute()
172
181
  const params = matchRoute(props as any)() as boolean
173
-
174
- if (typeof props.children === 'function') {
175
- return (props.children as any)(params)
182
+ const child = props.children
183
+ if (typeof child === 'function') {
184
+ return (child as any)(params)
176
185
  }
177
186
 
178
- return params ? props.children : null
187
+ return params ? child : null
179
188
  }}
180
189
  </Solid.Show>
181
190
  )
@@ -1,8 +1,5 @@
1
- import jsesc from 'jsesc'
2
-
3
1
  export function ScriptOnce({
4
2
  children,
5
- log,
6
3
  }: {
7
4
  children: string
8
5
  log?: boolean
@@ -15,16 +12,7 @@ export function ScriptOnce({
15
12
  return (
16
13
  <script
17
14
  class="tsr-once"
18
- innerHTML={[
19
- children,
20
- (log ?? true) && process.env.NODE_ENV === 'development'
21
- ? `console.info(\`Injected From Server:
22
- ${jsesc(children.toString(), { quotes: 'backtick' })}\`)`
23
- : '',
24
- 'if (typeof __TSR_SSR__ !== "undefined") __TSR_SSR__.cleanScripts()',
25
- ]
26
- .filter(Boolean)
27
- .join('\n')}
15
+ innerHTML={[children].filter(Boolean).join('\n')}
28
16
  />
29
17
  )
30
18
  }
@@ -30,12 +30,10 @@ export function Transitioner() {
30
30
  const isPagePending = () => isLoading() || hasPendingMatches()
31
31
  const previousIsPagePending = usePrevious(isPagePending)
32
32
 
33
- if (!router.isServer) {
34
- router.startTransition = async (fn: () => void | Promise<void>) => {
35
- setIsTransitioning(true)
36
- await fn()
37
- setIsTransitioning(false)
38
- }
33
+ router.startTransition = async (fn: () => void | Promise<void>) => {
34
+ setIsTransitioning(true)
35
+ await fn()
36
+ setIsTransitioning(false)
39
37
  }
40
38
 
41
39
  // Subscribe to location changes
@@ -68,7 +66,8 @@ export function Transitioner() {
68
66
  Solid.createRenderEffect(() => {
69
67
  Solid.untrack(() => {
70
68
  if (
71
- (typeof window !== 'undefined' && router.clientSsr) ||
69
+ // if we are hydrating from SSR, loading is triggered in ssr-client
70
+ (typeof window !== 'undefined' && router.ssr) ||
72
71
  (mountLoadForRouter.router === router && mountLoadForRouter.mounted)
73
72
  ) {
74
73
  return
@@ -98,6 +97,7 @@ export function Transitioner() {
98
97
  },
99
98
  ),
100
99
  )
100
+
101
101
  Solid.createRenderEffect(
102
102
  Solid.on(
103
103
  [isPagePending, previousIsPagePending],
package/src/index.tsx CHANGED
@@ -1,6 +1,3 @@
1
- export { default as invariant } from 'tiny-invariant'
2
- export { default as warning } from 'tiny-warning'
3
-
4
1
  export {
5
2
  defer,
6
3
  TSR_DEFERRED_PROMISE,
@@ -24,26 +21,18 @@ export {
24
21
  defaultStringifySearch,
25
22
  parseSearchWith,
26
23
  stringifySearchWith,
27
- escapeJSON, // SSR
28
24
  pick,
29
25
  functionalUpdate,
30
26
  replaceEqualDeep,
31
27
  isPlainObject,
32
28
  isPlainArray,
33
29
  deepEqual,
34
- shallow,
35
30
  createControlledPromise,
36
31
  retainSearchParams,
37
32
  stripSearchParams,
38
33
  } from '@tanstack/router-core'
39
34
 
40
35
  export type {
41
- StartSerializer,
42
- Serializable,
43
- SerializerParse,
44
- SerializerParseBy,
45
- SerializerStringify,
46
- SerializerStringifyBy,
47
36
  DeferredPromiseState,
48
37
  DeferredPromise,
49
38
  ParsedLocation,
@@ -91,10 +80,6 @@ export type {
91
80
  SearchSerializer,
92
81
  SearchParser,
93
82
  TrailingSlashOption,
94
- ExtractedEntry,
95
- ExtractedStream,
96
- ExtractedPromise,
97
- StreamState,
98
83
  Manifest,
99
84
  RouterManagedTag,
100
85
  ControlledPromise,
@@ -167,6 +152,7 @@ export type {
167
152
  UseNavigateResult,
168
153
  AnyRedirect,
169
154
  Redirect,
155
+ RedirectOptions,
170
156
  ResolvedRedirect,
171
157
  RouteOptions,
172
158
  FileBaseRouteOptions,
@@ -204,8 +190,6 @@ export type {
204
190
  RouterConstructorOptions,
205
191
  ControllablePromise,
206
192
  InjectedHtmlEntry,
207
- RouterErrorSerializer,
208
- SerializerExtensions,
209
193
  CreateFileRoute,
210
194
  CreateLazyFileRoute,
211
195
  } from '@tanstack/router-core'
@@ -289,7 +273,6 @@ export {
289
273
  export type {
290
274
  AnyRootRoute,
291
275
  SolidNode,
292
- SyncRouteComponent,
293
276
  AsyncRouteComponent,
294
277
  RouteComponent,
295
278
  ErrorRouteComponent,
@@ -1,28 +1,14 @@
1
1
  import { Dynamic } from 'solid-js/web'
2
2
  import { createResource } from 'solid-js'
3
- import { Outlet } from './Match'
4
- import { ClientOnly } from './ClientOnly'
3
+ import { isModuleNotFoundError } from '@tanstack/router-core'
5
4
  import type { AsyncRouteComponent } from './route'
6
5
 
7
- // If the load fails due to module not found, it may mean a new version of
8
- // the build was deployed and the user's browser is still using an old version.
9
- // If this happens, the old version in the user's browser would have an outdated
10
- // URL to the lazy module.
11
- // In that case, we want to attempt one window refresh to get the latest.
12
- function isModuleNotFoundError(error: any): boolean {
13
- return (
14
- typeof error?.message === 'string' &&
15
- /Failed to fetch dynamically imported module/.test(error.message)
16
- )
17
- }
18
-
19
6
  export function lazyRouteComponent<
20
7
  T extends Record<string, any>,
21
8
  TKey extends keyof T = 'default',
22
9
  >(
23
10
  importer: () => Promise<T>,
24
11
  exportName?: TKey,
25
- ssr?: () => boolean,
26
12
  ): T[TKey] extends (props: infer TProps) => any
27
13
  ? AsyncRouteComponent<TProps>
28
14
  : never {
@@ -31,10 +17,6 @@ export function lazyRouteComponent<
31
17
  let error: any
32
18
 
33
19
  const load = () => {
34
- if (typeof document === 'undefined' && ssr?.() === false) {
35
- comp = (() => null) as any
36
- return Promise.resolve(comp)
37
- }
38
20
  if (!loadPromise) {
39
21
  loadPromise = importer()
40
22
  .then((res) => {
@@ -54,6 +36,11 @@ export function lazyRouteComponent<
54
36
  // Now that we're out of preload and into actual render path,
55
37
  // throw the error if it was a module not found error during preload
56
38
  if (error) {
39
+ // If the load fails due to module not found, it may mean a new version of
40
+ // the build was deployed and the user's browser is still using an old version.
41
+ // If this happens, the old version in the user's browser would have an outdated
42
+ // URL to the lazy module.
43
+ // In that case, we want to attempt one window refresh to get the latest.
57
44
  if (isModuleNotFoundError(error)) {
58
45
  // We don't want an error thrown from preload in this case, because
59
46
  // there's nothing we want to do about module not found during preload.
@@ -94,13 +81,6 @@ export function lazyRouteComponent<
94
81
  return <>{compResource()}</>
95
82
  }
96
83
 
97
- if (ssr?.() === false) {
98
- return (
99
- <ClientOnly fallback={<Outlet />}>
100
- <Dynamic component={comp} {...props} />
101
- </ClientOnly>
102
- )
103
- }
104
84
  return <Dynamic component={comp} {...props} />
105
85
  }
106
86