@bleedingdev/modern-js-renderer-solid 0.0.0-stage → 3.9.3-ultramodern.10

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 (301) hide show
  1. package/dist/esm/actions.js +282 -0
  2. package/dist/esm/application-router.js +30 -0
  3. package/dist/esm/client.js +49 -0
  4. package/dist/esm/entry-application.js +60 -0
  5. package/dist/esm/entry-client.js +24 -0
  6. package/dist/esm/federation-context.js +25 -0
  7. package/dist/esm/federation-ssr.js +92 -0
  8. package/dist/esm/federation.js +87 -0
  9. package/dist/esm/i18n/I18nProvider.js +33 -0
  10. package/dist/esm/i18n/LocalizedLink.js +52 -0
  11. package/dist/esm/i18n/context.js +3 -0
  12. package/dist/esm/i18n/index.js +8 -0
  13. package/dist/esm/i18n/languageSync.js +50 -0
  14. package/dist/esm/i18n/types.js +0 -0
  15. package/dist/esm/i18n/useI18n.js +74 -0
  16. package/dist/esm/index.js +58 -0
  17. package/dist/esm/manifest.js +150 -0
  18. package/dist/esm/route-completion.js +151 -0
  19. package/dist/esm/route-data-error.js +108 -0
  20. package/dist/esm/router-binding/Asset.js +202 -0
  21. package/dist/esm/router-binding/CatchBoundary.js +94 -0
  22. package/dist/esm/router-binding/ClientOnly.js +26 -0
  23. package/dist/esm/router-binding/HeadContent.js +8 -0
  24. package/dist/esm/router-binding/LICENSE +21 -0
  25. package/dist/esm/router-binding/Match.js +319 -0
  26. package/dist/esm/router-binding/Matches.js +124 -0
  27. package/dist/esm/router-binding/PROVENANCE.json +94 -0
  28. package/dist/esm/router-binding/RouterProvider.js +52 -0
  29. package/dist/esm/router-binding/SafeFragment.js +5 -0
  30. package/dist/esm/router-binding/ScriptOnce.js +15 -0
  31. package/dist/esm/router-binding/Scripts.js +30 -0
  32. package/dist/esm/router-binding/ScrollRestoration.js +16 -0
  33. package/dist/esm/router-binding/Transitioner.js +109 -0
  34. package/dist/esm/router-binding/awaited.js +48 -0
  35. package/dist/esm/router-binding/fileRoute.js +83 -0
  36. package/dist/esm/router-binding/flightData.js +23 -0
  37. package/dist/esm/router-binding/headContentUtils.js +168 -0
  38. package/dist/esm/router-binding/history.js +0 -0
  39. package/dist/esm/router-binding/index.js +35 -0
  40. package/dist/esm/router-binding/lazyRouteComponent.js +30 -0
  41. package/dist/esm/router-binding/link.js +387 -0
  42. package/dist/esm/router-binding/matchContext.js +7 -0
  43. package/dist/esm/router-binding/nonRouteComponentContext.js +13 -0
  44. package/dist/esm/router-binding/not-found.js +35 -0
  45. package/dist/esm/router-binding/publicMatchData.js +447 -0
  46. package/dist/esm/router-binding/registryTransfer.js +223 -0
  47. package/dist/esm/router-binding/renderRouteNotFound.js +23 -0
  48. package/dist/esm/router-binding/route.js +143 -0
  49. package/dist/esm/router-binding/router.js +14 -0
  50. package/dist/esm/router-binding/routerContext.js +3 -0
  51. package/dist/esm/router-binding/routerOptions.js +0 -0
  52. package/dist/esm/router-binding/routerStores.js +50 -0
  53. package/dist/esm/router-binding/scroll-restoration.js +13 -0
  54. package/dist/esm/router-binding/typePrimitives.js +0 -0
  55. package/dist/esm/router-binding/useBlocker.js +152 -0
  56. package/dist/esm/router-binding/useCanGoBack.js +7 -0
  57. package/dist/esm/router-binding/useLoaderData.js +8 -0
  58. package/dist/esm/router-binding/useLoaderDeps.js +8 -0
  59. package/dist/esm/router-binding/useLocation.js +14 -0
  60. package/dist/esm/router-binding/useMatch.js +28 -0
  61. package/dist/esm/router-binding/useNavigate.js +25 -0
  62. package/dist/esm/router-binding/useParams.js +11 -0
  63. package/dist/esm/router-binding/useRouteContext.js +8 -0
  64. package/dist/esm/router-binding/useRouter.js +10 -0
  65. package/dist/esm/router-binding/useRouterState.js +19 -0
  66. package/dist/esm/router-binding/useSearch.js +11 -0
  67. package/dist/esm/router-binding/utils.js +23 -0
  68. package/dist/esm/router.js +187 -0
  69. package/dist/esm-node/actions.js +263 -0
  70. package/dist/esm-node/application-router.js +30 -0
  71. package/dist/esm-node/client.js +49 -0
  72. package/dist/esm-node/entry-application.js +110 -0
  73. package/dist/esm-node/entry-client.js +24 -0
  74. package/dist/esm-node/entry-server.js +47 -0
  75. package/dist/esm-node/federation-context.js +25 -0
  76. package/dist/esm-node/federation-ssr.js +92 -0
  77. package/dist/esm-node/federation.js +87 -0
  78. package/dist/esm-node/i18n/I18nProvider.js +42 -0
  79. package/dist/esm-node/i18n/LocalizedLink.js +88 -0
  80. package/dist/esm-node/i18n/context.js +3 -0
  81. package/dist/esm-node/i18n/index.js +8 -0
  82. package/dist/esm-node/i18n/languageSync.js +50 -0
  83. package/dist/esm-node/i18n/types.js +1 -0
  84. package/dist/esm-node/i18n/useI18n.js +74 -0
  85. package/dist/esm-node/index.js +58 -0
  86. package/dist/esm-node/manifest.js +150 -0
  87. package/dist/esm-node/native-promise-serialization.js +113 -0
  88. package/dist/esm-node/plugin/compiler.js +209 -0
  89. package/dist/esm-node/plugin/create.js +236 -0
  90. package/dist/esm-node/plugin/index.js +70 -0
  91. package/dist/esm-node/plugin/profile.js +51 -0
  92. package/dist/esm-node/route-completion.js +161 -0
  93. package/dist/esm-node/route-data-error.js +108 -0
  94. package/dist/esm-node/router-binding/Asset.js +172 -0
  95. package/dist/esm-node/router-binding/CatchBoundary.js +136 -0
  96. package/dist/esm-node/router-binding/ClientOnly.js +46 -0
  97. package/dist/esm-node/router-binding/HeadContent.js +8 -0
  98. package/dist/esm-node/router-binding/LICENSE +21 -0
  99. package/dist/esm-node/router-binding/Match.js +660 -0
  100. package/dist/esm-node/router-binding/Matches.js +161 -0
  101. package/dist/esm-node/router-binding/PROVENANCE.json +94 -0
  102. package/dist/esm-node/router-binding/RouterProvider.js +88 -0
  103. package/dist/esm-node/router-binding/SafeFragment.js +5 -0
  104. package/dist/esm-node/router-binding/ScriptOnce.js +16 -0
  105. package/dist/esm-node/router-binding/Scripts.js +49 -0
  106. package/dist/esm-node/router-binding/ScrollRestoration.js +16 -0
  107. package/dist/esm-node/router-binding/Transitioner.js +109 -0
  108. package/dist/esm-node/router-binding/awaited.js +75 -0
  109. package/dist/esm-node/router-binding/fileRoute.js +83 -0
  110. package/dist/esm-node/router-binding/flightData.js +23 -0
  111. package/dist/esm-node/router-binding/headContentUtils.js +168 -0
  112. package/dist/esm-node/router-binding/history.js +1 -0
  113. package/dist/esm-node/router-binding/index.js +35 -0
  114. package/dist/esm-node/router-binding/lazyRouteComponent.js +30 -0
  115. package/dist/esm-node/router-binding/link.js +399 -0
  116. package/dist/esm-node/router-binding/matchContext.js +7 -0
  117. package/dist/esm-node/router-binding/nonRouteComponentContext.js +22 -0
  118. package/dist/esm-node/router-binding/not-found.js +49 -0
  119. package/dist/esm-node/router-binding/publicMatchData.js +447 -0
  120. package/dist/esm-node/router-binding/registryTransfer.js +223 -0
  121. package/dist/esm-node/router-binding/renderRouteNotFound.js +22 -0
  122. package/dist/esm-node/router-binding/route.js +162 -0
  123. package/dist/esm-node/router-binding/router.js +14 -0
  124. package/dist/esm-node/router-binding/routerContext.js +3 -0
  125. package/dist/esm-node/router-binding/routerOptions.js +1 -0
  126. package/dist/esm-node/router-binding/routerStores.js +50 -0
  127. package/dist/esm-node/router-binding/scroll-restoration.js +12 -0
  128. package/dist/esm-node/router-binding/typePrimitives.js +1 -0
  129. package/dist/esm-node/router-binding/useBlocker.js +152 -0
  130. package/dist/esm-node/router-binding/useCanGoBack.js +7 -0
  131. package/dist/esm-node/router-binding/useLoaderData.js +8 -0
  132. package/dist/esm-node/router-binding/useLoaderDeps.js +8 -0
  133. package/dist/esm-node/router-binding/useLocation.js +14 -0
  134. package/dist/esm-node/router-binding/useMatch.js +28 -0
  135. package/dist/esm-node/router-binding/useNavigate.js +25 -0
  136. package/dist/esm-node/router-binding/useParams.js +11 -0
  137. package/dist/esm-node/router-binding/useRouteContext.js +8 -0
  138. package/dist/esm-node/router-binding/useRouter.js +10 -0
  139. package/dist/esm-node/router-binding/useRouterState.js +19 -0
  140. package/dist/esm-node/router-binding/useSearch.js +11 -0
  141. package/dist/esm-node/router-binding/utils.js +23 -0
  142. package/dist/esm-node/router.js +187 -0
  143. package/dist/esm-node/server.js +396 -0
  144. package/dist/types/actions.d.ts +45 -0
  145. package/dist/types/application-router.d.ts +5 -0
  146. package/dist/types/client.d.ts +23 -0
  147. package/dist/types/entry-application.d.ts +10 -0
  148. package/dist/types/entry-client.d.ts +5 -0
  149. package/dist/types/entry-server.d.ts +5 -0
  150. package/dist/types/federation-context.d.ts +16 -0
  151. package/dist/types/federation-ssr.d.ts +19 -0
  152. package/dist/types/federation.d.ts +30 -0
  153. package/dist/types/i18n/I18nProvider.d.ts +21 -0
  154. package/dist/types/i18n/LocalizedLink.d.ts +15 -0
  155. package/dist/types/i18n/context.d.ts +11 -0
  156. package/dist/types/i18n/index.d.ts +9 -0
  157. package/dist/types/i18n/languageSync.d.ts +31 -0
  158. package/dist/types/i18n/types.d.ts +33 -0
  159. package/dist/types/i18n/useI18n.d.ts +24 -0
  160. package/dist/types/index.d.ts +41 -0
  161. package/dist/types/manifest.d.ts +55 -0
  162. package/dist/types/native-promise-serialization.d.ts +9 -0
  163. package/dist/types/plugin/compiler.d.ts +6 -0
  164. package/dist/types/plugin/create.d.ts +21 -0
  165. package/dist/types/plugin/index.d.ts +3 -0
  166. package/dist/types/plugin/lazy-modules.d.cts +15 -0
  167. package/dist/types/plugin/preserve-import-loader.d.cts +3 -0
  168. package/dist/types/plugin/profile.d.ts +2 -0
  169. package/dist/types/plugin/solid-loader.d.cts +2 -0
  170. package/dist/types/plugin/svg-component-template.d.cts +6 -0
  171. package/dist/types/route-completion.d.ts +21 -0
  172. package/dist/types/route-data-error.d.ts +17 -0
  173. package/dist/types/router-binding/Asset.d.ts +3 -0
  174. package/dist/types/router-binding/CatchBoundary.d.ts +13 -0
  175. package/dist/types/router-binding/ClientOnly.d.ts +31 -0
  176. package/dist/types/router-binding/HeadContent.d.ts +13 -0
  177. package/dist/types/router-binding/Match.d.ts +6 -0
  178. package/dist/types/router-binding/Matches.d.ts +26 -0
  179. package/dist/types/router-binding/RouterProvider.d.ts +11 -0
  180. package/dist/types/router-binding/SafeFragment.d.ts +2 -0
  181. package/dist/types/router-binding/ScriptOnce.d.ts +6 -0
  182. package/dist/types/router-binding/Scripts.d.ts +2 -0
  183. package/dist/types/router-binding/ScrollRestoration.d.ts +14 -0
  184. package/dist/types/router-binding/Transitioner.d.ts +2 -0
  185. package/dist/types/router-binding/awaited.d.ts +11 -0
  186. package/dist/types/router-binding/fileRoute.d.ts +54 -0
  187. package/dist/types/router-binding/flightData.d.ts +38 -0
  188. package/dist/types/router-binding/headContentUtils.d.ts +15 -0
  189. package/dist/types/router-binding/history.d.ts +8 -0
  190. package/dist/types/router-binding/index.d.ts +46 -0
  191. package/dist/types/router-binding/lazyRouteComponent.d.ts +2 -0
  192. package/dist/types/router-binding/link.d.ts +43 -0
  193. package/dist/types/router-binding/matchContext.d.ts +7 -0
  194. package/dist/types/router-binding/nonRouteComponentContext.d.ts +5 -0
  195. package/dist/types/router-binding/not-found.d.ts +11 -0
  196. package/dist/types/router-binding/publicMatchData.d.ts +19 -0
  197. package/dist/types/router-binding/registryTransfer.d.ts +49 -0
  198. package/dist/types/router-binding/renderRouteNotFound.d.ts +11 -0
  199. package/dist/types/router-binding/route.d.ts +105 -0
  200. package/dist/types/router-binding/router.d.ts +70 -0
  201. package/dist/types/router-binding/routerContext.d.ts +3 -0
  202. package/dist/types/router-binding/routerOptions.d.ts +6 -0
  203. package/dist/types/router-binding/routerStores.d.ts +2 -0
  204. package/dist/types/router-binding/scroll-restoration.d.ts +2 -0
  205. package/dist/types/router-binding/typePrimitives.d.ts +10 -0
  206. package/dist/types/router-binding/useBlocker.d.ts +70 -0
  207. package/dist/types/router-binding/useCanGoBack.d.ts +2 -0
  208. package/dist/types/router-binding/useLoaderData.d.ts +8 -0
  209. package/dist/types/router-binding/useLoaderDeps.d.ts +8 -0
  210. package/dist/types/router-binding/useLocation.d.ts +7 -0
  211. package/dist/types/router-binding/useMatch.d.ts +10 -0
  212. package/dist/types/router-binding/useNavigate.d.ts +5 -0
  213. package/dist/types/router-binding/useParams.d.ts +9 -0
  214. package/dist/types/router-binding/useRouteContext.d.ts +4 -0
  215. package/dist/types/router-binding/useRouter.d.ts +4 -0
  216. package/dist/types/router-binding/useRouterState.d.ts +8 -0
  217. package/dist/types/router-binding/useSearch.d.ts +9 -0
  218. package/dist/types/router-binding/utils.d.ts +25 -0
  219. package/dist/types/router.d.ts +31 -0
  220. package/dist/types/server.d.ts +47 -0
  221. package/package.json +130 -4
  222. package/src/actions.tsx +441 -0
  223. package/src/application-router.tsx +47 -0
  224. package/src/client.ts +106 -0
  225. package/src/entry-application.tsx +73 -0
  226. package/src/entry-client.tsx +49 -0
  227. package/src/entry-server.tsx +85 -0
  228. package/src/federation-context.ts +47 -0
  229. package/src/federation-ssr.ts +136 -0
  230. package/src/federation.tsx +197 -0
  231. package/src/i18n/I18nProvider.tsx +54 -0
  232. package/src/i18n/LocalizedLink.tsx +83 -0
  233. package/src/i18n/context.ts +13 -0
  234. package/src/i18n/index.ts +31 -0
  235. package/src/i18n/languageSync.ts +113 -0
  236. package/src/i18n/types.ts +35 -0
  237. package/src/i18n/useI18n.ts +121 -0
  238. package/src/index.ts +41 -0
  239. package/src/manifest.ts +337 -0
  240. package/src/native-promise-serialization.ts +167 -0
  241. package/src/plugin/compiler.ts +320 -0
  242. package/src/plugin/create.ts +271 -0
  243. package/src/plugin/index.ts +69 -0
  244. package/src/plugin/lazy-modules.cjs +146 -0
  245. package/src/plugin/preserve-import-loader.cjs +46 -0
  246. package/src/plugin/profile.ts +42 -0
  247. package/src/plugin/solid-loader.cjs +83 -0
  248. package/src/plugin/svg-component-template.cjs +19 -0
  249. package/src/route-completion.tsx +226 -0
  250. package/src/route-data-error.ts +175 -0
  251. package/src/router-binding/Asset.tsx +284 -0
  252. package/src/router-binding/CatchBoundary.tsx +130 -0
  253. package/src/router-binding/ClientOnly.tsx +76 -0
  254. package/src/router-binding/HeadContent.tsx +23 -0
  255. package/src/router-binding/LICENSE +21 -0
  256. package/src/router-binding/Match.tsx +397 -0
  257. package/src/router-binding/Matches.tsx +242 -0
  258. package/src/router-binding/PROVENANCE.json +94 -0
  259. package/src/router-binding/RouterProvider.tsx +128 -0
  260. package/src/router-binding/SafeFragment.tsx +5 -0
  261. package/src/router-binding/ScriptOnce.tsx +23 -0
  262. package/src/router-binding/Scripts.tsx +44 -0
  263. package/src/router-binding/ScrollRestoration.tsx +49 -0
  264. package/src/router-binding/Transitioner.tsx +177 -0
  265. package/src/router-binding/awaited.tsx +71 -0
  266. package/src/router-binding/fileRoute.ts +268 -0
  267. package/src/router-binding/flightData.ts +90 -0
  268. package/src/router-binding/headContentUtils.tsx +292 -0
  269. package/src/router-binding/history.ts +9 -0
  270. package/src/router-binding/index.tsx +315 -0
  271. package/src/router-binding/lazyRouteComponent.tsx +70 -0
  272. package/src/router-binding/link.tsx +865 -0
  273. package/src/router-binding/matchContext.tsx +15 -0
  274. package/src/router-binding/nonRouteComponentContext.tsx +23 -0
  275. package/src/router-binding/not-found.tsx +65 -0
  276. package/src/router-binding/publicMatchData.ts +674 -0
  277. package/src/router-binding/registryTransfer.ts +400 -0
  278. package/src/router-binding/renderRouteNotFound.tsx +53 -0
  279. package/src/router-binding/route.tsx +665 -0
  280. package/src/router-binding/router.ts +123 -0
  281. package/src/router-binding/routerContext.tsx +6 -0
  282. package/src/router-binding/routerOptions.ts +26 -0
  283. package/src/router-binding/routerStores.ts +85 -0
  284. package/src/router-binding/scroll-restoration.tsx +15 -0
  285. package/src/router-binding/typePrimitives.ts +74 -0
  286. package/src/router-binding/useBlocker.tsx +359 -0
  287. package/src/router-binding/useCanGoBack.ts +9 -0
  288. package/src/router-binding/useLoaderData.tsx +51 -0
  289. package/src/router-binding/useLoaderDeps.tsx +46 -0
  290. package/src/router-binding/useLocation.tsx +43 -0
  291. package/src/router-binding/useMatch.tsx +111 -0
  292. package/src/router-binding/useNavigate.tsx +45 -0
  293. package/src/router-binding/useParams.tsx +70 -0
  294. package/src/router-binding/useRouteContext.ts +30 -0
  295. package/src/router-binding/useRouter.tsx +17 -0
  296. package/src/router-binding/useRouterState.tsx +50 -0
  297. package/src/router-binding/useSearch.tsx +70 -0
  298. package/src/router-binding/utils.ts +59 -0
  299. package/src/router.ts +376 -0
  300. package/src/server.ts +645 -0
  301. package/README.md +0 -3
@@ -0,0 +1,130 @@
1
+ import type { JSX } from '@solidjs/web';
2
+ import { Dynamic } from '@solidjs/web';
3
+ import * as Solid from 'solid-js';
4
+ import { renderInNonRouteComponentContext } from './nonRouteComponentContext';
5
+ import type { ErrorRouteComponent } from './route';
6
+
7
+ export function CatchBoundary(
8
+ props: {
9
+ getResetKey: () => unknown;
10
+ children?: JSX.Element;
11
+ render?: () => JSX.Element;
12
+ errorComponent?: ErrorRouteComponent;
13
+ onCatch?: (error: Error) => void;
14
+ } & Solid.ParentProps,
15
+ ) {
16
+ const [retryKey, setRetryKey] = Solid.createSignal<object>({});
17
+ let resetBoundary: (() => void) | undefined;
18
+ let initialized = false;
19
+ let previousKey: unknown;
20
+
21
+ Solid.onCleanup(() => {
22
+ resetBoundary = undefined;
23
+ });
24
+
25
+ Solid.createEffect(props.getResetKey, key => {
26
+ if (!initialized) {
27
+ initialized = true;
28
+ previousKey = key;
29
+ return;
30
+ }
31
+
32
+ // The effect re-runs on every recompute of the key function, not only
33
+ // on value changes — gate on the value so an unchanged key can't
34
+ // recreate the retried subtree while it settles.
35
+ if (key === previousKey) {
36
+ return;
37
+ }
38
+ previousKey = key;
39
+
40
+ const reset = resetBoundary;
41
+ if (reset) {
42
+ queueMicrotask(() => {
43
+ if (resetBoundary !== reset) {
44
+ return;
45
+ }
46
+ setRetryKey({});
47
+ reset();
48
+ Solid.flush();
49
+ });
50
+ }
51
+ });
52
+
53
+ return (
54
+ <Solid.Errored
55
+ fallback={(error, reset) => {
56
+ const resolvedError = Solid.untrack(() => error() as Error);
57
+
58
+ props.onCatch?.(resolvedError);
59
+ resetBoundary = reset;
60
+
61
+ return process.env.NODE_ENV !== 'production' ? (
62
+ renderInNonRouteComponentContext(
63
+ () => (
64
+ <Dynamic
65
+ component={props.errorComponent ?? ErrorComponent}
66
+ error={resolvedError}
67
+ reset={reset}
68
+ />
69
+ ),
70
+ 'errorComponent',
71
+ )
72
+ ) : (
73
+ <Dynamic
74
+ component={props.errorComponent ?? ErrorComponent}
75
+ error={resolvedError}
76
+ reset={reset}
77
+ />
78
+ );
79
+ }}
80
+ >
81
+ <Solid.Show when={retryKey()} keyed>
82
+ {_retryKey => props.render?.() ?? props.children}
83
+ </Solid.Show>
84
+ </Solid.Errored>
85
+ );
86
+ }
87
+
88
+ export function ErrorComponent({ error }: { error: any }) {
89
+ const [show, setShow] = Solid.createSignal(
90
+ process.env.NODE_ENV !== 'production',
91
+ );
92
+
93
+ return (
94
+ <div style={{ padding: '.5rem', 'max-width': '100%' }}>
95
+ <div style={{ display: 'flex', 'align-items': 'center', gap: '.5rem' }}>
96
+ <strong style={{ 'font-size': '1rem' }}>Something went wrong!</strong>
97
+ <button
98
+ style={{
99
+ appearance: 'none',
100
+ 'font-size': '.6em',
101
+ border: '1px solid currentColor',
102
+ padding: '.1rem .2rem',
103
+ 'font-weight': 'bold',
104
+ 'border-radius': '.25rem',
105
+ }}
106
+ onClick={() => setShow(d => !d)}
107
+ >
108
+ {show() ? 'Hide Error' : 'Show Error'}
109
+ </button>
110
+ </div>
111
+ <div style={{ height: '.25rem' }} />
112
+ {show() ? (
113
+ <div>
114
+ <pre
115
+ style={{
116
+ 'font-size': '.7em',
117
+ border: '1px solid red',
118
+ 'border-radius': '.25rem',
119
+ padding: '.3rem',
120
+ color: 'red',
121
+ overflow: 'auto',
122
+ }}
123
+ >
124
+ {error.message ? <code>{error.message}</code> : null}
125
+ </pre>
126
+ </div>
127
+ ) : null}
128
+ </div>
129
+ );
130
+ }
@@ -0,0 +1,76 @@
1
+ import type { JSX } from '@solidjs/web';
2
+ import * as Solid from 'solid-js';
3
+
4
+ export interface ClientOnlyProps {
5
+ /**
6
+ * The children to render when the JS is loaded.
7
+ */
8
+ children: JSX.Element;
9
+ /**
10
+ * The fallback component to render if the JS is not yet loaded.
11
+ */
12
+ fallback?: JSX.Element;
13
+ }
14
+
15
+ /**
16
+ * Render the children only after the JS has loaded client-side. Use an optional
17
+ * fallback component if the JS is not yet loaded.
18
+ *
19
+ * @example
20
+ * Render a Chart component if JS loads, renders a simple FakeChart
21
+ * component server-side or if there is no JS. The FakeChart can have only the
22
+ * UI without the behavior or be a loading spinner or skeleton.
23
+ *
24
+ * ```tsx
25
+ * return (
26
+ * <ClientOnly fallback={<FakeChart />}>
27
+ * <Chart />
28
+ * </ClientOnly>
29
+ * )
30
+ * ```
31
+ */
32
+ export function ClientOnly(props: ClientOnlyProps) {
33
+ const hydrated = useHydrated();
34
+ return (
35
+ <Solid.Show when={hydrated()} fallback={props.fallback ?? null}>
36
+ {props.children}
37
+ </Solid.Show>
38
+ );
39
+ }
40
+
41
+ /**
42
+ * Return a boolean indicating if the JS has been hydrated already.
43
+ * When doing Server-Side Rendering, the result will always be false.
44
+ * When doing Client-Side Rendering, the result will always be false on the
45
+ * first render and true from then on. Even if a new component renders it will
46
+ * always start with true.
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * // Disable a button that needs JS to work.
51
+ * const hydrated = useHydrated()
52
+ * return (
53
+ * <button type="button" disabled={!hydrated()} onClick={doSomethingCustom}>
54
+ * Click me
55
+ * </button>
56
+ * )
57
+ * ```
58
+ * @returns True if the JS has been hydrated already, false otherwise.
59
+ */
60
+ let globalHydrated = false;
61
+
62
+ export function useHydrated(): Solid.Accessor<boolean> {
63
+ const [hydrated, setHydrated] = Solid.createSignal(
64
+ globalHydrated && !Solid.isHydrating(),
65
+ );
66
+
67
+ Solid.createEffect(
68
+ () => true,
69
+ () => {
70
+ globalHydrated = true;
71
+ setHydrated(true);
72
+ },
73
+ );
74
+
75
+ return hydrated;
76
+ }
@@ -0,0 +1,23 @@
1
+ import type { JSX } from '@solidjs/web';
2
+ import { HydrationScript, useHead } from '@solidjs/web';
3
+ import type { AssetCrossOriginConfig } from '@tanstack/router-core';
4
+ import { toHeadTags, useTags } from './headContentUtils';
5
+
6
+ export interface HeadContentProps {
7
+ assetCrossOrigin?: AssetCrossOriginConfig;
8
+ }
9
+
10
+ /**
11
+ * @description The `HeadContent` component registers the current route's meta
12
+ * tags, links, and scripts with Solid's head registry, which owns emission
13
+ * into `<head>` (SSR splicing/streaming and client-side patching alike). It
14
+ * can be rendered anywhere in the tree, though placing it inside the `<head>`
15
+ * of your document keeps the hydration script in the right place.
16
+ */
17
+ export function HeadContent(props: HeadContentProps): JSX.Element {
18
+ const tags = useTags(props.assetCrossOrigin);
19
+
20
+ useHead(() => toHeadTags(tags()));
21
+
22
+ return <HydrationScript />;
23
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021-present Tanner Linsley
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,397 @@
1
+ import type { JSX } from '@solidjs/web';
2
+ import { Dynamic } from '@solidjs/web';
3
+ import type {
4
+ AnyRoute,
5
+ AnyRouter,
6
+ RootRouteOptions,
7
+ } from '@tanstack/router-core';
8
+ import { rootRouteId } from '@tanstack/router-core';
9
+ import { isServer } from '@tanstack/router-core/isServer';
10
+ import * as Solid from 'solid-js';
11
+ import { CatchBoundary, ErrorComponent } from './CatchBoundary';
12
+ import { ClientOnly } from './ClientOnly';
13
+ import { nearestMatchContext } from './matchContext';
14
+ import {
15
+ nonRouteComponentContext,
16
+ renderInNonRouteComponentContext,
17
+ } from './nonRouteComponentContext';
18
+ import { CatchNotFound, getNotFound } from './not-found';
19
+ import { renderRouteNotFound } from './renderRouteNotFound';
20
+ import { SafeFragment } from './SafeFragment';
21
+ import { ScrollRestoration } from './scroll-restoration';
22
+ import { useRouter } from './useRouter';
23
+
24
+ const NearestMatchContext = nearestMatchContext as unknown as Solid.Component<{
25
+ value: any;
26
+ children?: any;
27
+ }>;
28
+
29
+ // Keep the client constant undefined so the server-only script can be dropped.
30
+ const renderScrollRestoration =
31
+ isServer === false
32
+ ? undefined
33
+ : (router: AnyRouter, route: AnyRoute) =>
34
+ (isServer ?? router.isServer) &&
35
+ route.parentRoute?.id === rootRouteId &&
36
+ router.options.scrollRestoration ? (
37
+ <ScrollRestoration />
38
+ ) : null;
39
+
40
+ export const Match = (props: { routeId: string }): JSX.Element => {
41
+ const router = useRouter();
42
+ const currentMatch = Solid.createMemo(() =>
43
+ router.stores.getMatchStore(props.routeId).get(),
44
+ );
45
+ const matchState = Solid.createMemo(() => {
46
+ const match = currentMatch();
47
+ if (!match) {
48
+ return null;
49
+ }
50
+
51
+ return {
52
+ routeId: match.routeId,
53
+ ssr: match.ssr,
54
+ status: match.status,
55
+ };
56
+ });
57
+ const nearestMatch = [() => props.routeId, currentMatch] as const;
58
+
59
+ return (
60
+ <Solid.Show when={matchState()}>
61
+ {currentMatchState => {
62
+ const route = router.routesById[props.routeId] as AnyRoute;
63
+ const routeOptions = () => {
64
+ // Lazy route options become observable with the next publication.
65
+ currentMatchState();
66
+ return route.options;
67
+ };
68
+ const resolvePendingComponent = Solid.createMemo(
69
+ () =>
70
+ routeOptions().pendingComponent ??
71
+ router.options.defaultPendingComponent,
72
+ );
73
+ const routeErrorComponent = Solid.createMemo(
74
+ () =>
75
+ routeOptions().errorComponent ??
76
+ router.options.defaultErrorComponent,
77
+ );
78
+ const routeNotFoundComponent = Solid.createMemo(() =>
79
+ route.isRoot
80
+ ? (routeOptions().notFoundComponent ??
81
+ router.options.notFoundRoute?.options.component ??
82
+ router.options.defaultNotFoundComponent)
83
+ : (routeOptions().notFoundComponent ??
84
+ router.options.defaultNotFoundComponent),
85
+ );
86
+ const resolvedNoSsr = Solid.createMemo(
87
+ () =>
88
+ currentMatchState().ssr === false ||
89
+ currentMatchState().ssr === 'data-only',
90
+ );
91
+ const ResolvedNotFoundBoundary = Solid.createMemo(() =>
92
+ routeNotFoundComponent() ? CatchNotFound : SafeFragment,
93
+ );
94
+ const ShellComponent = Solid.createMemo(() =>
95
+ route.isRoot
96
+ ? ((route.options as RootRouteOptions).shellComponent ??
97
+ SafeFragment)
98
+ : SafeFragment,
99
+ );
100
+
101
+ const MatchContent = () => (
102
+ <Solid.Show
103
+ when={currentMatchState().status !== 'pending'}
104
+ fallback={(() => {
105
+ if (process.env.NODE_ENV !== 'production') {
106
+ return renderInNonRouteComponentContext(
107
+ () => <Dynamic component={resolvePendingComponent()} />,
108
+ 'pendingComponent',
109
+ );
110
+ }
111
+ return <Dynamic component={resolvePendingComponent()} />;
112
+ })()}
113
+ >
114
+ <MatchInner />
115
+ </Solid.Show>
116
+ );
117
+ const RouteContent = () => (
118
+ <Dynamic
119
+ component={ResolvedNotFoundBoundary()}
120
+ fallback={(error: any) => {
121
+ const notFoundError = getNotFound(error) ?? error;
122
+ notFoundError.routeId ??= currentMatchState().routeId;
123
+
124
+ if (notFoundError.routeId !== currentMatchState().routeId) {
125
+ throw notFoundError;
126
+ }
127
+
128
+ return process.env.NODE_ENV !== 'production' ? (
129
+ renderInNonRouteComponentContext(
130
+ () => (
131
+ <Dynamic
132
+ component={routeNotFoundComponent()}
133
+ {...notFoundError}
134
+ />
135
+ ),
136
+ 'notFoundComponent',
137
+ )
138
+ ) : (
139
+ <Dynamic
140
+ component={routeNotFoundComponent()}
141
+ {...notFoundError}
142
+ />
143
+ );
144
+ }}
145
+ >
146
+ <Solid.Switch>
147
+ <Solid.Match when={resolvedNoSsr()}>
148
+ <ClientOnly
149
+ fallback={(() => {
150
+ if (process.env.NODE_ENV !== 'production') {
151
+ return renderInNonRouteComponentContext(
152
+ () => <Dynamic component={resolvePendingComponent()} />,
153
+ 'pendingComponent',
154
+ );
155
+ }
156
+ return <Dynamic component={resolvePendingComponent()} />;
157
+ })()}
158
+ >
159
+ <MatchContent />
160
+ </ClientOnly>
161
+ </Solid.Match>
162
+ <Solid.Match when={!resolvedNoSsr()}>
163
+ <MatchContent />
164
+ </Solid.Match>
165
+ </Solid.Switch>
166
+ </Dynamic>
167
+ );
168
+
169
+ return (
170
+ <Dynamic component={ShellComponent()}>
171
+ <NearestMatchContext value={nearestMatch}>
172
+ <Solid.Show
173
+ when={routeErrorComponent()}
174
+ fallback={<RouteContent />}
175
+ >
176
+ {errorComponent => (
177
+ <CatchBoundary
178
+ // Scope the reset key to this match and its
179
+ // descendants (whose errors bubble here when they
180
+ // have no errorComponent of their own): resetting on
181
+ // unrelated matches' transitions just re-throws the
182
+ // still-stale error and recreates the retried
183
+ // subtree mid-settle.
184
+ getResetKey={() => {
185
+ const matches = router.stores.matches.get();
186
+ const index = matches.findIndex(
187
+ match => match.routeId === props.routeId,
188
+ );
189
+ if (index === -1) {
190
+ return '';
191
+ }
192
+ let key = '';
193
+ for (let i = index; i < matches.length; i++) {
194
+ const match = matches[i]!;
195
+ key += `${match.status}|${match.updatedAt},`;
196
+ }
197
+ return key;
198
+ }}
199
+ errorComponent={errorComponent() as any}
200
+ onCatch={(error: Error) => {
201
+ const notFoundError = getNotFound(error);
202
+ if (notFoundError) {
203
+ notFoundError.routeId ??= currentMatchState().routeId;
204
+ throw notFoundError;
205
+ }
206
+ if (process.env.NODE_ENV !== 'production') {
207
+ console.warn(
208
+ `Warning: Error in route match: ${currentMatchState().routeId}`,
209
+ );
210
+ }
211
+ (
212
+ routeOptions().onCatch ?? router.options.defaultOnCatch
213
+ )?.(error);
214
+ }}
215
+ render={RouteContent}
216
+ />
217
+ )}
218
+ </Solid.Show>
219
+ </NearestMatchContext>
220
+
221
+ {renderScrollRestoration?.(router, route)}
222
+ </Dynamic>
223
+ );
224
+ }}
225
+ </Solid.Show>
226
+ );
227
+ };
228
+
229
+ export const MatchInner = (): any => {
230
+ const router = useRouter();
231
+ const nearestMatch = Solid.useContext(nearestMatchContext);
232
+ const match = nearestMatch[1 /* match */];
233
+ const routeId = nearestMatch[0 /* route id */];
234
+
235
+ const matchState = Solid.createMemo(() => {
236
+ const currentMatch = match();
237
+ const currentRouteId = routeId();
238
+ if (!currentMatch || !currentRouteId) {
239
+ return null;
240
+ }
241
+
242
+ const route = router.routesById[currentRouteId] as AnyRoute;
243
+ const remount =
244
+ route.options.remountDeps ?? router.options.defaultRemountDeps;
245
+ let componentKey: string;
246
+ if (!remount) {
247
+ componentKey = currentRouteId;
248
+ } else {
249
+ const deps = remount({
250
+ routeId: currentRouteId,
251
+ loaderDeps: currentMatch.loaderDeps,
252
+ params: currentMatch._strictParams,
253
+ search: currentMatch._strictSearch,
254
+ });
255
+ componentKey = JSON.stringify(deps) ?? currentRouteId;
256
+ }
257
+
258
+ return {
259
+ route,
260
+ routeId: currentRouteId,
261
+ match: {
262
+ id: currentMatch.id,
263
+ status: currentMatch.status,
264
+ error: currentMatch.error,
265
+ },
266
+ componentKey,
267
+ };
268
+ });
269
+
270
+ return (
271
+ <Solid.Show when={matchState()}>
272
+ {currentMatchState => {
273
+ const route = Solid.createMemo(() => currentMatchState().route);
274
+ const currentMatch = Solid.createMemo(() => currentMatchState().match);
275
+ const componentKey = Solid.createMemo(
276
+ () => currentMatchState().componentKey,
277
+ );
278
+ const OutComponent = Solid.createMemo(
279
+ () =>
280
+ route().options.component ??
281
+ router.options.defaultComponent ??
282
+ Outlet,
283
+ );
284
+ const keyedOut = () => (
285
+ <Solid.Show when={componentKey()} keyed>
286
+ {_key => <Dynamic component={OutComponent()} />}
287
+ </Solid.Show>
288
+ );
289
+
290
+ return (
291
+ <Solid.Switch>
292
+ <Solid.Match when={currentMatch().status === 'notFound'}>
293
+ {_ =>
294
+ Solid.untrack(() =>
295
+ renderRouteNotFound(router, route(), currentMatch().error),
296
+ )
297
+ }
298
+ </Solid.Match>
299
+ <Solid.Match when={currentMatch().status === 'error'}>
300
+ {_ => {
301
+ const matchError = Solid.untrack(
302
+ () => currentMatch().error,
303
+ ) as Error;
304
+ if (isServer ?? router.isServer) {
305
+ const RouteErrorComponent =
306
+ (route().options.errorComponent ??
307
+ router.options.defaultErrorComponent) ||
308
+ ErrorComponent;
309
+
310
+ return process.env.NODE_ENV !== 'production' ? (
311
+ renderInNonRouteComponentContext(
312
+ () => (
313
+ <RouteErrorComponent
314
+ error={matchError}
315
+ reset={undefined as any}
316
+ info={{ componentStack: '' }}
317
+ />
318
+ ),
319
+ 'errorComponent',
320
+ )
321
+ ) : (
322
+ <RouteErrorComponent
323
+ error={matchError}
324
+ reset={undefined as any}
325
+ info={{ componentStack: '' }}
326
+ />
327
+ );
328
+ }
329
+
330
+ throw matchError;
331
+ }}
332
+ </Solid.Match>
333
+ <Solid.Match when={currentMatch().status === 'success'}>
334
+ {keyedOut()}
335
+ </Solid.Match>
336
+ </Solid.Switch>
337
+ );
338
+ }}
339
+ </Solid.Show>
340
+ );
341
+ };
342
+
343
+ export const Outlet = (): JSX.Element => {
344
+ if (process.env.NODE_ENV !== 'production') {
345
+ const nonRouteComponent = Solid.useContext(nonRouteComponentContext!);
346
+ if (nonRouteComponent) {
347
+ console.warn(
348
+ `Warning: An <Outlet /> was rendered inside a ${nonRouteComponent}. <Outlet /> should only be rendered inside a route component.`,
349
+ );
350
+ }
351
+ }
352
+
353
+ const router = useRouter();
354
+ const nearestParentMatch = Solid.useContext(nearestMatchContext);
355
+ const parentMatch = nearestParentMatch[1 /* match */];
356
+ const routeId = nearestParentMatch[0 /* route id */];
357
+ const route = Solid.createMemo(() => {
358
+ const currentRouteId = routeId();
359
+ return currentRouteId
360
+ ? (router.routesById[currentRouteId] as AnyRoute)
361
+ : undefined;
362
+ });
363
+ const parentNotFound = Solid.createMemo(() => parentMatch()?._notFound);
364
+ const parentNotFoundError = Solid.createMemo(() => parentMatch()?.error);
365
+ const childRouteId = Solid.createMemo(() => {
366
+ if (parentNotFound()) {
367
+ return undefined;
368
+ }
369
+ const currentRouteId = routeId();
370
+ if (!currentRouteId) {
371
+ return undefined;
372
+ }
373
+ const ids = router.stores.ids.get();
374
+ return ids[ids.indexOf(currentRouteId) + 1];
375
+ });
376
+ return (
377
+ <Solid.Show
378
+ when={childRouteId()}
379
+ keyed
380
+ fallback={
381
+ <Solid.Show when={parentNotFound() && route()}>
382
+ {resolvedRoute =>
383
+ Solid.untrack(() =>
384
+ renderRouteNotFound(
385
+ router,
386
+ resolvedRoute(),
387
+ parentNotFoundError(),
388
+ ),
389
+ )
390
+ }
391
+ </Solid.Show>
392
+ }
393
+ >
394
+ {currentChildRouteId => <Match routeId={currentChildRouteId} />}
395
+ </Solid.Show>
396
+ );
397
+ };