@lovrozagar/flare 0.1.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 (387) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/package.json +146 -0
  4. package/scripts/download-fonts.ts +136 -0
  5. package/scripts/populate-fonts.ts +721 -0
  6. package/src/await.ts +2 -0
  7. package/src/boundaries/index.ts +99 -0
  8. package/src/broadcast/channel.ts +65 -0
  9. package/src/broadcast/context.ts +12 -0
  10. package/src/broadcast/index.ts +75 -0
  11. package/src/broadcast/provider.tsx +7 -0
  12. package/src/build-location.ts +2 -0
  13. package/src/caches/index.ts +384 -0
  14. package/src/client/index.ts +75 -0
  15. package/src/client.tsx +2 -0
  16. package/src/codegen/index.ts +41 -0
  17. package/src/components/await.tsx +140 -0
  18. package/src/components/dev-error-overlay.tsx +154 -0
  19. package/src/components/direction-script.tsx +22 -0
  20. package/src/components/index.ts +150 -0
  21. package/src/components/locale-script.tsx +26 -0
  22. package/src/components/reset-css.tsx +14 -0
  23. package/src/components/ssr-context.tsx +37 -0
  24. package/src/components/theme-script.tsx +22 -0
  25. package/src/components/view-transition-css.tsx +21 -0
  26. package/src/config/index.ts +84 -0
  27. package/src/create-client-only-fn.ts +1 -0
  28. package/src/create-isomorphic-fn.ts +2 -0
  29. package/src/create-layout.ts +1 -0
  30. package/src/create-page.ts +1 -0
  31. package/src/create-path-segment.ts +1 -0
  32. package/src/create-query-client-getter.ts +2 -0
  33. package/src/create-root-layout.ts +1 -0
  34. package/src/create-router.ts +8 -0
  35. package/src/create-server-only-fn.ts +1 -0
  36. package/src/dedupe/index.ts +151 -0
  37. package/src/defer/index.ts +82 -0
  38. package/src/direction/index.tsx +163 -0
  39. package/src/direction.ts +3 -0
  40. package/src/duration/index.ts +18 -0
  41. package/src/env-fn/index.ts +101 -0
  42. package/src/env-fn.ts +2 -0
  43. package/src/errors/index.ts +166 -0
  44. package/src/fonts/abeezee.ts +50 -0
  45. package/src/fonts/abel.ts +26 -0
  46. package/src/fonts/abril-fatface.ts +34 -0
  47. package/src/fonts/acme.ts +26 -0
  48. package/src/fonts/advent-pro.ts +92 -0
  49. package/src/fonts/alegreya-sans.ts +228 -0
  50. package/src/fonts/alegreya.ts +228 -0
  51. package/src/fonts/alex-brush.ts +42 -0
  52. package/src/fonts/alfa-slab-one.ts +42 -0
  53. package/src/fonts/alice.ts +48 -0
  54. package/src/fonts/amatic-sc.ts +94 -0
  55. package/src/fonts/amiri.ts +114 -0
  56. package/src/fonts/antic-slab.ts +26 -0
  57. package/src/fonts/anton.ts +42 -0
  58. package/src/fonts/archivo-black.ts +34 -0
  59. package/src/fonts/archivo-narrow.ts +114 -0
  60. package/src/fonts/archivo.ts +66 -0
  61. package/src/fonts/arimo.ts +256 -0
  62. package/src/fonts/arvo.ts +50 -0
  63. package/src/fonts/asap.ts +66 -0
  64. package/src/fonts/assistant.ts +64 -0
  65. package/src/fonts/baloo-2.ts +82 -0
  66. package/src/fonts/barlow-condensed.ts +114 -0
  67. package/src/fonts/barlow-semi-condensed.ts +114 -0
  68. package/src/fonts/barlow.ts +114 -0
  69. package/src/fonts/be-vietnam-pro.ts +114 -0
  70. package/src/fonts/bebas-neue.ts +34 -0
  71. package/src/fonts/besley.ts +82 -0
  72. package/src/fonts/biorhyme.ts +50 -0
  73. package/src/fonts/bitter.ts +94 -0
  74. package/src/fonts/black-ops-one.ts +49 -0
  75. package/src/fonts/bree-serif.ts +34 -0
  76. package/src/fonts/bricolage-grotesque.ts +66 -0
  77. package/src/fonts/cabin.ts +114 -0
  78. package/src/fonts/cairo.ts +66 -0
  79. package/src/fonts/cardo.ts +193 -0
  80. package/src/fonts/catamaran.ts +41 -0
  81. package/src/fonts/caveat.ts +78 -0
  82. package/src/fonts/chakra-petch.ts +142 -0
  83. package/src/fonts/chivo.ts +66 -0
  84. package/src/fonts/cinzel.ts +50 -0
  85. package/src/fonts/comfortaa.ts +109 -0
  86. package/src/fonts/commissioner.ts +64 -0
  87. package/src/fonts/component.tsx +27 -0
  88. package/src/fonts/cormorant-garamond.ts +171 -0
  89. package/src/fonts/cormorant.ts +170 -0
  90. package/src/fonts/courgette.ts +34 -0
  91. package/src/fonts/courier-prime.ts +82 -0
  92. package/src/fonts/create-font.ts +47 -0
  93. package/src/fonts/create-registry-font.ts +40 -0
  94. package/src/fonts/crete-round.ts +50 -0
  95. package/src/fonts/crimson-text.ts +114 -0
  96. package/src/fonts/css.ts +86 -0
  97. package/src/fonts/dancing-script.ts +66 -0
  98. package/src/fonts/dm-mono.ts +50 -0
  99. package/src/fonts/dm-sans.ts +50 -0
  100. package/src/fonts/dm-serif-display.ts +50 -0
  101. package/src/fonts/domine.ts +50 -0
  102. package/src/fonts/dosis.ts +66 -0
  103. package/src/fonts/eb-garamond.ts +228 -0
  104. package/src/fonts/eczar.ts +94 -0
  105. package/src/fonts/encode-sans.ts +42 -0
  106. package/src/fonts/epilogue.ts +66 -0
  107. package/src/fonts/exo-2.ts +94 -0
  108. package/src/fonts/exo.ts +66 -0
  109. package/src/fonts/figtree.ts +82 -0
  110. package/src/fonts/fira-code.ts +121 -0
  111. package/src/fonts/fira-sans-condensed.ts +228 -0
  112. package/src/fonts/fira-sans.ts +228 -0
  113. package/src/fonts/fjalla-one.ts +49 -0
  114. package/src/fonts/font-urls.gen.json +1962 -0
  115. package/src/fonts/fraunces.ts +66 -0
  116. package/src/fonts/fredoka.ts +64 -0
  117. package/src/fonts/gelasio.ts +114 -0
  118. package/src/fonts/gloria-hallelujah.ts +34 -0
  119. package/src/fonts/gothic-a1.ts +124 -0
  120. package/src/fonts/great-vibes.ts +64 -0
  121. package/src/fonts/gudea.ts +66 -0
  122. package/src/fonts/heebo.ts +57 -0
  123. package/src/fonts/hind-siliguri.ts +66 -0
  124. package/src/fonts/hind.ts +66 -0
  125. package/src/fonts/ibm-plex-mono.ts +172 -0
  126. package/src/fonts/ibm-plex-sans-arabic.ts +80 -0
  127. package/src/fonts/ibm-plex-sans.ts +199 -0
  128. package/src/fonts/ibm-plex-serif.ts +171 -0
  129. package/src/fonts/inconsolata.ts +66 -0
  130. package/src/fonts/index.ts +4 -0
  131. package/src/fonts/indie-flower.ts +34 -0
  132. package/src/fonts/instrument-sans.ts +82 -0
  133. package/src/fonts/instrument-serif.ts +50 -0
  134. package/src/fonts/inter-display.ts +52 -0
  135. package/src/fonts/inter-tight.ts +124 -0
  136. package/src/fonts/inter.ts +123 -0
  137. package/src/fonts/jetbrains-mono.ts +199 -0
  138. package/src/fonts/josefin-sans.ts +114 -0
  139. package/src/fonts/josefin-slab.ts +50 -0
  140. package/src/fonts/jost.ts +64 -0
  141. package/src/fonts/kalam.ts +66 -0
  142. package/src/fonts/kanit.ts +142 -0
  143. package/src/fonts/karla.ts +82 -0
  144. package/src/fonts/khand.ts +66 -0
  145. package/src/fonts/lato.ts +82 -0
  146. package/src/fonts/league-spartan.ts +42 -0
  147. package/src/fonts/lexend-deca.ts +42 -0
  148. package/src/fonts/lexend.ts +42 -0
  149. package/src/fonts/libre-baskerville.ts +82 -0
  150. package/src/fonts/libre-franklin.ts +95 -0
  151. package/src/fonts/lilita-one.ts +34 -0
  152. package/src/fonts/lobster-two.ts +50 -0
  153. package/src/fonts/lobster.ts +56 -0
  154. package/src/fonts/lora.ts +235 -0
  155. package/src/fonts/m-plus-rounded-1c.ts +138 -0
  156. package/src/fonts/manrope.ts +109 -0
  157. package/src/fonts/maven-pro.ts +66 -0
  158. package/src/fonts/merriweather-sans.ts +142 -0
  159. package/src/fonts/merriweather.ts +171 -0
  160. package/src/fonts/montserrat-alternates.ts +171 -0
  161. package/src/fonts/montserrat.ts +94 -0
  162. package/src/fonts/mukta.ts +66 -0
  163. package/src/fonts/mulish.ts +170 -0
  164. package/src/fonts/nanum-gothic.ts +34 -0
  165. package/src/fonts/nanum-myeongjo.ts +34 -0
  166. package/src/fonts/neuton.ts +66 -0
  167. package/src/fonts/newsreader.ts +114 -0
  168. package/src/fonts/noticia-text.ts +114 -0
  169. package/src/fonts/noto-sans-arabic.ts +58 -0
  170. package/src/fonts/noto-sans-hk.ts +49 -0
  171. package/src/fonts/noto-sans-jp.ts +49 -0
  172. package/src/fonts/noto-sans-kr.ts +49 -0
  173. package/src/fonts/noto-sans-sc.ts +49 -0
  174. package/src/fonts/noto-sans-tc.ts +49 -0
  175. package/src/fonts/noto-sans.ts +140 -0
  176. package/src/fonts/noto-serif-jp.ts +80 -0
  177. package/src/fonts/noto-serif.ts +140 -0
  178. package/src/fonts/nunito-sans.ts +170 -0
  179. package/src/fonts/nunito.ts +170 -0
  180. package/src/fonts/old-standard-tt.ts +133 -0
  181. package/src/fonts/onest.ts +48 -0
  182. package/src/fonts/open-sans.ts +340 -0
  183. package/src/fonts/orbitron.ts +34 -0
  184. package/src/fonts/oswald.ts +94 -0
  185. package/src/fonts/outfit.ts +34 -0
  186. package/src/fonts/overpass.ts +94 -0
  187. package/src/fonts/oxygen.ts +50 -0
  188. package/src/fonts/pacifico.ts +56 -0
  189. package/src/fonts/passion-one.ts +50 -0
  190. package/src/fonts/pathway-gothic-one.ts +34 -0
  191. package/src/fonts/permanent-marker.ts +26 -0
  192. package/src/fonts/philosopher.ts +172 -0
  193. package/src/fonts/play.ts +109 -0
  194. package/src/fonts/playfair-display.ts +142 -0
  195. package/src/fonts/plus-jakarta-sans.ts +142 -0
  196. package/src/fonts/poppins.ts +114 -0
  197. package/src/fonts/prompt.ts +142 -0
  198. package/src/fonts/pt-sans-narrow.ts +78 -0
  199. package/src/fonts/pt-sans.ts +138 -0
  200. package/src/fonts/pt-serif.ts +138 -0
  201. package/src/fonts/public-sans.ts +66 -0
  202. package/src/fonts/questrial.ts +42 -0
  203. package/src/fonts/quicksand.ts +66 -0
  204. package/src/fonts/rajdhani.ts +66 -0
  205. package/src/fonts/raleway.ts +94 -0
  206. package/src/fonts/recursive.ts +80 -0
  207. package/src/fonts/red-hat-display.ts +82 -0
  208. package/src/fonts/red-rose.ts +66 -0
  209. package/src/fonts/registry.gen.ts +173 -0
  210. package/src/fonts/righteous.ts +34 -0
  211. package/src/fonts/roboto-condensed.ts +124 -0
  212. package/src/fonts/roboto-flex.ts +64 -0
  213. package/src/fonts/roboto-mono.ts +199 -0
  214. package/src/fonts/roboto-slab.ts +72 -0
  215. package/src/fonts/roboto.ts +156 -0
  216. package/src/fonts/rokkitt.ts +66 -0
  217. package/src/fonts/rubik.ts +199 -0
  218. package/src/fonts/sacramento.ts +34 -0
  219. package/src/fonts/saira.ts +66 -0
  220. package/src/fonts/sarabun.ts +142 -0
  221. package/src/fonts/satisfy.ts +26 -0
  222. package/src/fonts/sawarabi-mincho.ts +41 -0
  223. package/src/fonts/shadows-into-light.ts +34 -0
  224. package/src/fonts/signika-negative.ts +66 -0
  225. package/src/fonts/signika.ts +66 -0
  226. package/src/fonts/slabo-27px.ts +34 -0
  227. package/src/fonts/sora.ts +50 -0
  228. package/src/fonts/source-code-pro.ts +228 -0
  229. package/src/fonts/source-sans-3.ts +228 -0
  230. package/src/fonts/source-serif-4.ts +199 -0
  231. package/src/fonts/space-grotesk.ts +66 -0
  232. package/src/fonts/space-mono.ts +114 -0
  233. package/src/fonts/spectral.ts +170 -0
  234. package/src/fonts/tajawal.ts +50 -0
  235. package/src/fonts/teko.ts +66 -0
  236. package/src/fonts/tenor-sans.ts +41 -0
  237. package/src/fonts/tinos.ts +256 -0
  238. package/src/fonts/titillium-web.ts +82 -0
  239. package/src/fonts/types.ts +43 -0
  240. package/src/fonts/ubuntu-condensed.ts +63 -0
  241. package/src/fonts/ubuntu-mono.ts +195 -0
  242. package/src/fonts/ubuntu.ts +195 -0
  243. package/src/fonts/unbounded.ts +94 -0
  244. package/src/fonts/unicode-ranges.gen.ts +28 -0
  245. package/src/fonts/urbanist.ts +50 -0
  246. package/src/fonts/varela-round.ts +49 -0
  247. package/src/fonts/vollkorn.ts +199 -0
  248. package/src/fonts/work-sans.ts +66 -0
  249. package/src/fonts/yanone-kaffeesatz.ts +128 -0
  250. package/src/fonts/yantramanav.ts +66 -0
  251. package/src/fonts/yellowtail.ts +34 -0
  252. package/src/fonts/young-serif.ts +34 -0
  253. package/src/fonts/zen-kaku-gothic-new.ts +64 -0
  254. package/src/fonts/zilla-slab.ts +82 -0
  255. package/src/form/index.tsx +205 -0
  256. package/src/generators/index.ts +1589 -0
  257. package/src/head-client/index.ts +649 -0
  258. package/src/history/index.ts +210 -0
  259. package/src/hooks.ts +61 -0
  260. package/src/hydrate/index.tsx +381 -0
  261. package/src/hydration/index.ts +187 -0
  262. package/src/i18n/index.ts +250 -0
  263. package/src/i18n/jsx.tsx +42 -0
  264. package/src/i18n/message-format.ts +174 -0
  265. package/src/image/index.tsx +473 -0
  266. package/src/image.ts +12 -0
  267. package/src/intercept-outlet/index.tsx +18 -0
  268. package/src/intercept-outlet.ts +2 -0
  269. package/src/internal/index.ts +143 -0
  270. package/src/internal/once-idle.ts +24 -0
  271. package/src/internal.ts +12 -0
  272. package/src/lazy/index.tsx +205 -0
  273. package/src/link/index.tsx +367 -0
  274. package/src/loader-pipeline/index.ts +639 -0
  275. package/src/locale/index.tsx +137 -0
  276. package/src/locale.ts +3 -0
  277. package/src/logger.ts +22 -0
  278. package/src/middleware/builtins/api-proxy.ts +64 -0
  279. package/src/middleware/builtins/cdn-proxy.ts +58 -0
  280. package/src/middleware/builtins/i18n.ts +256 -0
  281. package/src/middleware/builtins/keepalive.ts +24 -0
  282. package/src/middleware/builtins/markdown-negotiation.ts +141 -0
  283. package/src/middleware/builtins/static-assets.ts +32 -0
  284. package/src/middleware/index.ts +223 -0
  285. package/src/module-graph/index.ts +181 -0
  286. package/src/mount/index.ts +146 -0
  287. package/src/navigate.ts +1 -0
  288. package/src/navigation/index.ts +1278 -0
  289. package/src/navigation/types.ts +59 -0
  290. package/src/navigation-progress/index.tsx +247 -0
  291. package/src/navigation-progress.ts +1 -0
  292. package/src/ndjson-client/index.ts +376 -0
  293. package/src/ndjson-server/index.ts +284 -0
  294. package/src/outlet/index.tsx +633 -0
  295. package/src/outlet/types.ts +243 -0
  296. package/src/plugins/css-transform.ts +70 -0
  297. package/src/plugins/dev-cdn-cache.ts +454 -0
  298. package/src/plugins/dev-dashboard/client.tsx +2603 -0
  299. package/src/plugins/dev-dashboard/match-route-tree.ts +159 -0
  300. package/src/plugins/dev-dashboard/plugin.ts +404 -0
  301. package/src/plugins/dev-prerender.ts +168 -0
  302. package/src/plugins/dev-server.ts +327 -0
  303. package/src/plugins/generate-watch.ts +32 -0
  304. package/src/plugins/image-plugin.ts +171 -0
  305. package/src/plugins/index.ts +445 -0
  306. package/src/plugins/options.ts +37 -0
  307. package/src/plugins/parse-utils.ts +59 -0
  308. package/src/plugins/prerender-plugin.ts +144 -0
  309. package/src/plugins/purge.ts +242 -0
  310. package/src/plugins/server-fn.ts +641 -0
  311. package/src/plugins/service-worker.ts +225 -0
  312. package/src/plugins/solid-jsx.d.ts +12 -0
  313. package/src/plugins/sx-ast/atomic.ts +166 -0
  314. package/src/plugins/sx-ast/evaluator.ts +235 -0
  315. package/src/plugins/sx-ast/index.ts +372 -0
  316. package/src/plugins/sx-ast/parser.ts +22 -0
  317. package/src/plugins/sx-ast/rewrite.ts +763 -0
  318. package/src/plugins/sx.d.ts +14 -0
  319. package/src/plugins/tw-compile.ts +240 -0
  320. package/src/plugins/types.ts +41 -0
  321. package/src/plugins/virtual.d.ts +110 -0
  322. package/src/plugins/virtual.ts +184 -0
  323. package/src/preload/index.ts +77 -0
  324. package/src/prerender/index.ts +431 -0
  325. package/src/query-client/index.tsx +168 -0
  326. package/src/registry/index.ts +88 -0
  327. package/src/reset-css.ts +1 -0
  328. package/src/revalidation/index.ts +84 -0
  329. package/src/rewrite/index.ts +83 -0
  330. package/src/route-builder/create-layout.ts +655 -0
  331. package/src/route-builder/create-page.ts +806 -0
  332. package/src/route-builder/create-path-segment.ts +34 -0
  333. package/src/route-builder/create-root-layout.ts +608 -0
  334. package/src/route-builder/index.ts +49 -0
  335. package/src/route-builder/register.ts +242 -0
  336. package/src/route-builder/types.ts +294 -0
  337. package/src/router-config/index.ts +91 -0
  338. package/src/router-primitives/index.ts +25 -0
  339. package/src/router-primitives/location.ts +29 -0
  340. package/src/router-primitives/match-id.ts +111 -0
  341. package/src/router-primitives/paths.ts +109 -0
  342. package/src/router-primitives/tree.ts +243 -0
  343. package/src/router-primitives/types.ts +74 -0
  344. package/src/router.ts +31 -0
  345. package/src/search-engine/bing.ts +32 -0
  346. package/src/search-engine/google-jwt.ts +95 -0
  347. package/src/search-engine/google.ts +139 -0
  348. package/src/search-engine/index-now.ts +64 -0
  349. package/src/search-engine/index.ts +12 -0
  350. package/src/security/index.ts +230 -0
  351. package/src/server/index.ts +286 -0
  352. package/src/server-context/browser.ts +113 -0
  353. package/src/server-context/index.ts +217 -0
  354. package/src/server-fn/index.ts +710 -0
  355. package/src/server-fn-query.ts +169 -0
  356. package/src/server-handler/etag.ts +51 -0
  357. package/src/server-handler/headers.ts +5 -0
  358. package/src/server-handler/index.ts +1664 -0
  359. package/src/server-handler/types.ts +24 -0
  360. package/src/server-handler/validate-static-params.ts +130 -0
  361. package/src/server.ts +2 -0
  362. package/src/service-worker/template.ts +153 -0
  363. package/src/service-worker-hook/index.ts +70 -0
  364. package/src/sitemap/index.ts +231 -0
  365. package/src/ssr/critical-css.ts +150 -0
  366. package/src/ssr/head-prefix.ts +65 -0
  367. package/src/ssr/head.ts +259 -0
  368. package/src/ssr/index.tsx +879 -0
  369. package/src/state-parser/index.ts +266 -0
  370. package/src/store/filesystem.ts +131 -0
  371. package/src/store/index.ts +29 -0
  372. package/src/styles/index.ts +1200 -0
  373. package/src/styles/sx-types.ts +11 -0
  374. package/src/testing/index.ts +251 -0
  375. package/src/testing.ts +2 -0
  376. package/src/theme/index.tsx +232 -0
  377. package/src/theme.ts +3 -0
  378. package/src/tracing/index.ts +4 -0
  379. package/src/tracing/noop.ts +13 -0
  380. package/src/tracing/otel.ts +37 -0
  381. package/src/tracing/timing.ts +34 -0
  382. package/src/tracing/types.ts +9 -0
  383. package/src/url/index.ts +140 -0
  384. package/src/use-router.ts +11 -0
  385. package/src/use-suspense-query.ts +2 -0
  386. package/src/validation/index.ts +57 -0
  387. package/src/view-transition-css.ts +1 -0
@@ -0,0 +1,633 @@
1
+ import {
2
+ type Accessor,
3
+ createContext,
4
+ createEffect,
5
+ createMemo,
6
+ createSignal,
7
+ ErrorBoundary,
8
+ type JSX,
9
+ onCleanup,
10
+ onMount,
11
+ Show,
12
+ Suspense,
13
+ useContext,
14
+ } from "solid-js";
15
+ import type { GlobalBoundaries } from "../boundaries/index.ts";
16
+ import type { ChannelMessage, SerializedInvalidateOptions } from "../broadcast/channel.ts";
17
+ import { BroadcastCtx } from "../broadcast/context.ts";
18
+ import { NotFoundError, UnauthenticatedError, UnauthorizedError } from "../errors/index.ts";
19
+ import { createTranslator } from "../i18n/index.ts";
20
+ import { clearPendingNavigation, proceedPendingNavigation, setActiveBlocker } from "../navigation/index.ts";
21
+ import { matchRoute, toLocaleMatch } from "../router-primitives/tree.ts";
22
+ import { buildUrl, parseSearchParams, type SearchParams } from "../url/index.ts";
23
+ import type {
24
+ BrowserViewTransition,
25
+ ClientMatch,
26
+ FlareProviderContext,
27
+ FlareProviderProps,
28
+ FlareRouter,
29
+ InterceptedState,
30
+ InternalNavigateOptions,
31
+ NavigationPhase,
32
+ } from "./types.ts";
33
+
34
+ export type {
35
+ BlockerState,
36
+ BrowserViewTransition,
37
+ ClientErrorRenderProps,
38
+ ClientMatch,
39
+ ClientNotFoundRenderProps,
40
+ ClientUnauthenticatedRenderProps,
41
+ ClientUnauthorizedRenderProps,
42
+ DeferredResolver,
43
+ FlareProviderContext,
44
+ FlareProviderProps,
45
+ FlareRouter,
46
+ InterceptedState,
47
+ InternalNavigateOptions,
48
+ LocationChangeInfo,
49
+ NavigateOptions,
50
+ NavigationPhase,
51
+ PrefetchOptions,
52
+ ProviderLocation,
53
+ RenderProps,
54
+ ViewTransitionConfig,
55
+ ViewTransitionDirection,
56
+ ViewTransitionOptions,
57
+ } from "./types.ts";
58
+
59
+ /** Exported for SSR — SSR injects context directly on sharedConfig.context */
60
+ export const RouterContext = createContext<FlareProviderContext>();
61
+ export const DepthContext = createContext<number>(0);
62
+
63
+ export function FlareProvider(props: FlareProviderProps): JSX.Element {
64
+ const [hydrated, setHydrated] = createSignal(false);
65
+ const [intercepted, setIntercepted] = createSignal<InterceptedState | null>(null);
66
+ const [navigationPhase, setNavigationPhase] = createSignal<NavigationPhase>("idle");
67
+ const isNavigating = createMemo(() => navigationPhase() !== "idle");
68
+ const [viewTransitionSignal, setViewTransition] = createSignal<BrowserViewTransition | null>(null);
69
+ const [matches, setMatches] = createSignal<ClientMatch[]>(props.matches);
70
+ const [notFound, setNotFound] = createSignal(false);
71
+ const [params, setParams] = createSignal<Record<string, string | string[]>>(props.params);
72
+ const [search, setSearch] = createSignal<SearchParams>(props.search ?? {});
73
+
74
+ const location = createMemo(() => {
75
+ const allMatches = matches();
76
+ const lastMatch = allMatches[allMatches.length - 1];
77
+ const p = params();
78
+ const s = search();
79
+ const il = props.initialLocation;
80
+ /* Client: read from window.location (updated by pushState before signals fire).
81
+ * SSR: no window, fall back to initialLocation from the request. */
82
+ const win = typeof window !== "undefined" ? window : null;
83
+ const pathname = win?.location.pathname ?? il?.pathname ?? "/";
84
+ const href = win?.location.href ?? il?.url?.href ?? "http://localhost/";
85
+ const hash = win?.location.hash ?? il?.hash ?? "";
86
+
87
+ return {
88
+ hash,
89
+ params: p,
90
+ pathname,
91
+ search: s,
92
+ url: new URL(href),
93
+ variablePath: lastMatch?.variablePath ?? il?.variablePath ?? "",
94
+ virtualPath: lastMatch?.virtualPath ?? "",
95
+ };
96
+ });
97
+
98
+ /* Stub navigate/prefetch — replaced by setupNavigation */
99
+ let navigateFn: (options: InternalNavigateOptions) => Promise<void> = () => Promise.resolve();
100
+ let prefetchFn: (options: {
101
+ params?: Record<string, unknown>;
102
+ search?: Record<string, unknown>;
103
+ to: string;
104
+ }) => Promise<void> = () => Promise.resolve();
105
+
106
+ const channel = useContext(BroadcastCtx);
107
+
108
+ function invalidate(options?: Parameters<FlareProviderContext["invalidate"]>[0]): void {
109
+ props.matchCache.invalidate(options);
110
+ navigateFn({
111
+ replace: true,
112
+ revalidate: true,
113
+ to: typeof window !== "undefined" ? window.location.href : "/",
114
+ });
115
+ if (options?.broadcast) {
116
+ const serialized: SerializedInvalidateOptions = {};
117
+ if (options.matchId) serialized.matchId = options.matchId;
118
+ if (options.routeId) serialized.routeId = options.routeId;
119
+ if (options.tags) serialized.tags = options.tags;
120
+ channel.broadcast({ options: serialized, type: "invalidate" });
121
+ }
122
+ }
123
+
124
+ const ctx: FlareProviderContext = {
125
+ boundaries: props.boundaries,
126
+ caseSensitive: props.caseSensitive,
127
+ hydrated,
128
+ intercepted,
129
+ invalidate,
130
+ isNavigating,
131
+ layouts: props.layouts,
132
+ localeConfig: props.localeConfig,
133
+ location,
134
+ matchCache: props.matchCache,
135
+ matches,
136
+ navigate: (opts) => {
137
+ if (opts.broadcast) {
138
+ channel.broadcast({ replace: opts.replace, to: opts.to, type: "navigate" });
139
+ }
140
+ return navigateFn(opts);
141
+ },
142
+ navigationPhase,
143
+ notFound,
144
+ params,
145
+ prefetch: (opts) => prefetchFn(opts),
146
+ prefetchCache: props.prefetchCache,
147
+ resolvers: props.resolvers,
148
+ routeTree: props.routeTree,
149
+ routerCacheDefaults: props.routerCacheDefaults,
150
+ search,
151
+ setHydrated,
152
+ setIntercepted,
153
+ setMatches,
154
+ setNavigationPhase,
155
+ setNotFound,
156
+ setParams,
157
+ setSearch,
158
+ setViewTransition,
159
+ viewTransition: viewTransitionSignal,
160
+ };
161
+
162
+ /* Allow external code to bind navigate/prefetch implementations */
163
+ Object.defineProperty(ctx, "_setNavigate", {
164
+ value: (fn: typeof navigateFn) => {
165
+ navigateFn = fn;
166
+ },
167
+ });
168
+ Object.defineProperty(ctx, "_setPrefetch", {
169
+ value: (fn: typeof prefetchFn) => {
170
+ prefetchFn = fn;
171
+ },
172
+ });
173
+
174
+ /* Expose matches + cache to devtools in dev mode */
175
+ if (typeof window !== "undefined" && import.meta.env.DEV) {
176
+ Object.defineProperty(window, "__flare_devtools_matches__", {
177
+ configurable: true,
178
+ get: () =>
179
+ matches().map((m) => ({
180
+ loaderData: m.loaderData,
181
+ preloaderContext: m.preloaderContext,
182
+ type: m._type,
183
+ virtualPath: m.virtualPath,
184
+ })),
185
+ });
186
+ Object.defineProperty(window, "__flare_devtools_cache__", {
187
+ configurable: true,
188
+ get: () => props.matchCache.getAll(),
189
+ });
190
+ Object.defineProperty(window, "__flare_devtools_actions__", {
191
+ configurable: true,
192
+ get: () => ({
193
+ clearError: () => {
194
+ const current = matches();
195
+ const restored = current.map((m) => {
196
+ if (m.error === undefined) return m;
197
+ const { error: _, ...rest } = m;
198
+ return rest as typeof m;
199
+ });
200
+ setMatches(restored);
201
+ },
202
+ clearPrefetchCache: () => props.prefetchCache.clear(),
203
+ getCacheStats: () => ({
204
+ entries: props.matchCache.getAll().map((c) => ({
205
+ age: Date.now() - c.updatedAt,
206
+ matchId: c.matchId,
207
+ })),
208
+ matchCount: props.matchCache.getAll().length,
209
+ prefetchCount: props.prefetchCache.size(),
210
+ }),
211
+ invalidate: (opts?: Parameters<FlareProviderContext["invalidate"]>[0]) => invalidate(opts),
212
+ navigate: (opts: InternalNavigateOptions) => navigateFn(opts),
213
+ prefetch: (opts: { to: string }) => prefetchFn(opts),
214
+ setError: (error: unknown) => {
215
+ const current = matches();
216
+ if (current.length === 0) return;
217
+ const updated = current.map((m, i) => (i === current.length - 1 ? { ...m, error } : m));
218
+ setMatches(updated);
219
+ },
220
+ setNotFound: (v: boolean) => setNotFound(v),
221
+ }),
222
+ });
223
+ }
224
+
225
+ /* Cross-tab broadcast: receive invalidate/navigate from other tabs */
226
+ onMount(() => {
227
+ const unsubscribe = channel.onMessage((msg: ChannelMessage) => {
228
+ if (msg.type === "invalidate") {
229
+ props.matchCache.invalidate(msg.options);
230
+ props.prefetchCache.clear();
231
+ navigateFn({
232
+ replace: true,
233
+ revalidate: true,
234
+ to: typeof window !== "undefined" ? window.location.href : "/",
235
+ });
236
+ } else if (msg.type === "navigate") {
237
+ navigateFn({
238
+ replace: msg.replace,
239
+ to: msg.to,
240
+ });
241
+ }
242
+ });
243
+ onCleanup(unsubscribe);
244
+ });
245
+
246
+ createEffect(() => {
247
+ if (props.onContextReady) {
248
+ props.onContextReady(ctx);
249
+ }
250
+ });
251
+
252
+ return <RouterContext.Provider value={ctx}>{props.children}</RouterContext.Provider>;
253
+ }
254
+
255
+ export function useRouterContext(): FlareProviderContext {
256
+ const ctx = useContext(RouterContext);
257
+ if (!ctx)
258
+ throw new Error("useRouterContext() called outside FlareProvider. Ensure <FlareProvider> wraps your app root.");
259
+ return ctx;
260
+ }
261
+
262
+ export function useRouter(): FlareRouter {
263
+ const ctx = useRouterContext();
264
+
265
+ return {
266
+ buildLocation: (options) => {
267
+ const url = buildUrl({
268
+ hash: options.hash,
269
+ params: options.params,
270
+ search: options.search,
271
+ to: options.to,
272
+ });
273
+ const parsed = new URL(url, "http://localhost");
274
+ const result = matchRoute(ctx.routeTree, parsed.pathname, ctx.caseSensitive, toLocaleMatch(ctx.localeConfig));
275
+ return {
276
+ hash: parsed.hash,
277
+ params: result?.params ?? {},
278
+ pathname: parsed.pathname,
279
+ search: parseSearchParams(parsed.searchParams),
280
+ url: parsed,
281
+ variablePath: result?.route.v ?? "",
282
+ virtualPath: result?.route.x ?? "",
283
+ };
284
+ },
285
+ buildUrl: (options) =>
286
+ buildUrl({
287
+ hash: options.hash,
288
+ params: options.params,
289
+ search: options.search,
290
+ to: options.to,
291
+ }),
292
+ clearCache: () => ctx.matchCache.clear(),
293
+ hydrated: ctx.hydrated,
294
+ intercepted: ctx.intercepted,
295
+ invalidate: ctx.invalidate,
296
+ isNavigating: ctx.isNavigating,
297
+ locale: () => {
298
+ const lc = ctx.localeConfig;
299
+ if (!lc) return undefined;
300
+ const p = ctx.params();
301
+ const val = p[lc.paramName ?? "locale"];
302
+ return (typeof val === "string" ? val : undefined) ?? lc.defaultLocale;
303
+ },
304
+ location: ctx.location,
305
+ matches: ctx.matches,
306
+ navigate: (options) => ctx.navigate(options),
307
+ navigationPhase: ctx.navigationPhase,
308
+ params: ctx.params,
309
+ prefetch: ctx.prefetch,
310
+ refetch: () =>
311
+ ctx.navigate({
312
+ replace: true,
313
+ revalidate: true,
314
+ to: typeof window !== "undefined" ? window.location.href : "/",
315
+ }),
316
+ search: ctx.search,
317
+ useBlocker: (when) => {
318
+ const [blocked, setBlocked] = createSignal(false);
319
+
320
+ /* Register SPA blocker — navigate() checks this before proceeding */
321
+ setActiveBlocker(when, () => setBlocked(true));
322
+ onCleanup(() => setActiveBlocker(null));
323
+
324
+ /* Also handle browser-level unload (tab close, external nav) */
325
+ const handler = (e: BeforeUnloadEvent) => {
326
+ if (when()) {
327
+ e.preventDefault();
328
+ setBlocked(true);
329
+ }
330
+ };
331
+ if (typeof window !== "undefined") {
332
+ window.addEventListener("beforeunload", handler);
333
+ onCleanup(() => window.removeEventListener("beforeunload", handler));
334
+ }
335
+
336
+ return {
337
+ blocked,
338
+ proceed: () => {
339
+ setBlocked(false);
340
+ proceedPendingNavigation();
341
+ },
342
+ reset: () => {
343
+ setBlocked(false);
344
+ clearPendingNavigation();
345
+ },
346
+ };
347
+ },
348
+ useLoaderData: ((options: { from: string }) =>
349
+ createMemo(() => {
350
+ const m = ctx.matches().find((match) => match.virtualPath === options.from);
351
+ return m?.loaderData;
352
+ })) as never,
353
+ useLoaderT: ((options: { from: string }) => {
354
+ const data = createMemo(() => {
355
+ const m = ctx.matches().find((match) => match.virtualPath === options.from);
356
+ return (m?.loaderData as Record<string, unknown> | undefined)?.t;
357
+ });
358
+ const lc = ctx.localeConfig;
359
+ const locale = () => {
360
+ if (!lc) return undefined;
361
+ const p = ctx.params();
362
+ const val = p[lc.paramName ?? "locale"];
363
+ return (typeof val === "string" ? val : undefined) ?? lc.defaultLocale;
364
+ };
365
+ return createTranslator((data() ?? {}) as Record<string, Record<string, string>>, locale());
366
+ }) as never,
367
+ useMatch: (options) => createMemo(() => ctx.matches().find((match) => match.virtualPath === options.from)),
368
+ useParams: ((_options: { from: string }) => createMemo(() => ctx.params())) as never,
369
+ usePreloaderContext: ((options: { from: string }) =>
370
+ createMemo(() => {
371
+ const m = ctx.matches().find((match) => match.virtualPath === options.from);
372
+ return m?.preloaderContext;
373
+ })) as never,
374
+ usePreloaderT: ((options: { from: string }) => {
375
+ const data = createMemo(() => {
376
+ const m = ctx.matches().find((match) => match.virtualPath === options.from);
377
+ return (m?.preloaderContext as Record<string, unknown> | undefined)?.t;
378
+ });
379
+ const lc = ctx.localeConfig;
380
+ const locale = () => {
381
+ if (!lc) return undefined;
382
+ const p = ctx.params();
383
+ const val = p[lc.paramName ?? "locale"];
384
+ return (typeof val === "string" ? val : undefined) ?? lc.defaultLocale;
385
+ };
386
+ return createTranslator((data() ?? {}) as Record<string, Record<string, string>>, locale());
387
+ }) as never,
388
+ useSearch: ((_options: { from: string }) => createMemo(() => ctx.search())) as never,
389
+ viewTransition: ctx.viewTransition,
390
+ };
391
+ }
392
+
393
+ function useDepth(): number {
394
+ return useContext(DepthContext) ?? 0;
395
+ }
396
+
397
+ export interface OutletProps {
398
+ fallback?: JSX.Element;
399
+ }
400
+
401
+ export function Outlet(props?: OutletProps): JSX.Element {
402
+ const depth = useDepth();
403
+ const ctx = useRouterContext();
404
+
405
+ return (
406
+ <Show when={!ctx.notFound() || depth === 0}>
407
+ <DepthContext.Provider value={depth + 1}>
408
+ <OutletContent depth={depth} fallback={props?.fallback} />
409
+ </DepthContext.Provider>
410
+ </Show>
411
+ ) as JSX.Element;
412
+ }
413
+
414
+ function OutletContent(props: { depth: number; fallback?: JSX.Element }): JSX.Element {
415
+ const ctx = useRouterContext();
416
+ const router = useRouter();
417
+ const match: Accessor<ClientMatch | undefined> = createMemo(() => ctx.matches()[props.depth]);
418
+
419
+ return (
420
+ <Show
421
+ fallback={ctx.notFound() && props.depth === 0 ? resolveNotFoundBoundary(ctx, props.depth) : null}
422
+ when={match()}
423
+ >
424
+ {(m) => {
425
+ const isPage = () => m()._type === "render";
426
+ const renderFn = () => m().render;
427
+ const hasError = createMemo(() => m().error);
428
+ const renderProps = () => ({
429
+ children: isPage() ? undefined : <Outlet fallback={props.fallback} />,
430
+ loaderData: m().loaderData,
431
+ location: ctx.location(),
432
+ preloaderContext: m().preloaderContext,
433
+ router,
434
+ });
435
+
436
+ /*
437
+ * Pipeline errors rendered via reactive Show — must react to SPA nav
438
+ * match updates. Static `if (current.error)` only works for SSR initial render.
439
+ */
440
+ return (
441
+ <Show
442
+ fallback={
443
+ <ErrorBoundaryWrapper depth={props.depth} match={m()}>
444
+ <Suspense fallback={props.fallback ?? null}>
445
+ {(() => {
446
+ const fn = renderFn();
447
+ const p = renderProps();
448
+ return fn(p);
449
+ })()}
450
+ </Suspense>
451
+ </ErrorBoundaryWrapper>
452
+ }
453
+ when={hasError()}
454
+ >
455
+ {renderMatchError(ctx, props.depth, hasError())}
456
+ </Show>
457
+ );
458
+ }}
459
+ </Show>
460
+ ) as JSX.Element;
461
+ }
462
+
463
+ /**
464
+ * Re-run loaders for the current URL. Used by error boundaries
465
+ * to let users retry after transient failures.
466
+ */
467
+ function makeRetry(ctx: FlareProviderContext): () => void {
468
+ return () => {
469
+ const to = typeof window !== "undefined" ? `${window.location.pathname}${window.location.search}` : "/";
470
+ ctx.navigate({
471
+ replace: true,
472
+ revalidate: true,
473
+ to,
474
+ });
475
+ };
476
+ }
477
+
478
+ /**
479
+ * Render the correct boundary for a pipeline error on a match.
480
+ * Same logic as ErrorBoundaryWrapper fallback, but called directly
481
+ * so it works during both SSR and client hydration.
482
+ */
483
+ function renderMatchError(ctx: FlareProviderContext, depth: number, error: unknown): JSX.Element {
484
+ const retry = makeRetry(ctx);
485
+ if (error instanceof NotFoundError) {
486
+ return resolveNotFoundBoundary(ctx, depth);
487
+ }
488
+ if (error instanceof UnauthenticatedError) {
489
+ return resolveUnauthenticatedBoundary(ctx, depth, error, retry);
490
+ }
491
+ if (error instanceof UnauthorizedError) {
492
+ return resolveUnauthorizedBoundary(ctx, depth, error, retry);
493
+ }
494
+ /* Pipeline errors: reset = retry (no ErrorBoundary to clear, must re-run loaders) */
495
+ return resolveErrorBoundary(ctx, depth, error, retry, retry);
496
+ }
497
+
498
+ function ErrorBoundaryWrapper(props: { children: JSX.Element; depth: number; match: ClientMatch }): JSX.Element {
499
+ const ctx = useRouterContext();
500
+ let resetFn: (() => void) | undefined;
501
+
502
+ /*
503
+ * When match changes (SPA navigation), reset ErrorBoundary so it exits
504
+ * fallback mode. Without this, navigating from error page → valid page
505
+ * stays stuck in ErrorBoundary fallback.
506
+ */
507
+ createEffect(() => {
508
+ /* Track reactive deps — resets ErrorBoundary on SPA navigation */
509
+ void props.match.virtualPath;
510
+ void props.match.error;
511
+ if (resetFn) resetFn();
512
+ });
513
+
514
+ const retry = makeRetry(ctx);
515
+
516
+ return (
517
+ <ErrorBoundary
518
+ fallback={(error, reset) => {
519
+ resetFn = reset;
520
+ if (error instanceof NotFoundError) {
521
+ return resolveNotFoundBoundary(ctx, props.depth);
522
+ }
523
+ if (error instanceof UnauthenticatedError) {
524
+ return resolveUnauthenticatedBoundary(ctx, props.depth, error, retry);
525
+ }
526
+ if (error instanceof UnauthorizedError) {
527
+ return resolveUnauthorizedBoundary(ctx, props.depth, error, retry);
528
+ }
529
+ return resolveErrorBoundary(ctx, props.depth, error, reset, retry);
530
+ }}
531
+ >
532
+ {props.children}
533
+ </ErrorBoundary>
534
+ ) as JSX.Element;
535
+ }
536
+
537
+ /* Boundary resolution uses ClientMatch render fns (wide types) and falls back to GlobalBoundaries.
538
+ GlobalBoundaries uses narrower Location type — safe to pass ProviderLocation at runtime. */
539
+
540
+ function resolveErrorBoundary(
541
+ ctx: FlareProviderContext,
542
+ depth: number,
543
+ error: unknown,
544
+ reset: () => void,
545
+ retry: () => void,
546
+ ): JSX.Element {
547
+ const allMatches = ctx.matches();
548
+ const loc = ctx.location();
549
+ for (let i = depth; i >= 0; i--) {
550
+ const m = allMatches[i];
551
+ if (m?.errorRender) {
552
+ return m.errorRender({ error, location: loc, reset, retry });
553
+ }
554
+ }
555
+ if (ctx.boundaries?.error) {
556
+ /* GlobalBoundaries expects Error + narrower Location — cast safe at runtime */
557
+ const errorVal = error instanceof Error ? error : new Error(String(error));
558
+ return ctx.boundaries.error({
559
+ error: errorVal,
560
+ location: loc as Parameters<NonNullable<GlobalBoundaries["error"]>>[0]["location"],
561
+ reset,
562
+ retry,
563
+ }) as JSX.Element;
564
+ }
565
+ return (<div>Something went wrong</div>) as JSX.Element;
566
+ }
567
+
568
+ function resolveNotFoundBoundary(ctx: FlareProviderContext, depth: number): JSX.Element {
569
+ const allMatches = ctx.matches();
570
+ const loc = ctx.location();
571
+ for (let i = depth; i >= 0; i--) {
572
+ const m = allMatches[i];
573
+ if (m?.notFoundRender) {
574
+ return m.notFoundRender({ location: loc });
575
+ }
576
+ }
577
+ if (ctx.boundaries?.notFound) {
578
+ return ctx.boundaries.notFound({
579
+ location: loc as Parameters<NonNullable<GlobalBoundaries["notFound"]>>[0]["location"],
580
+ }) as JSX.Element;
581
+ }
582
+ return (<div>Page not found</div>) as JSX.Element;
583
+ }
584
+
585
+ function resolveUnauthenticatedBoundary(
586
+ ctx: FlareProviderContext,
587
+ depth: number,
588
+ error: unknown,
589
+ retry: () => void,
590
+ ): JSX.Element {
591
+ const allMatches = ctx.matches();
592
+ const loc = ctx.location();
593
+ for (let i = depth; i >= 0; i--) {
594
+ const m = allMatches[i];
595
+ if (m?.unauthenticatedRender) {
596
+ return m.unauthenticatedRender({ error, location: loc, retry });
597
+ }
598
+ }
599
+ if (ctx.boundaries?.unauthenticated) {
600
+ const errVal = error instanceof UnauthenticatedError ? error : new UnauthenticatedError();
601
+ return ctx.boundaries.unauthenticated({
602
+ error: errVal,
603
+ location: loc as Parameters<NonNullable<GlobalBoundaries["unauthenticated"]>>[0]["location"],
604
+ retry,
605
+ }) as JSX.Element;
606
+ }
607
+ return (<div>Please log in</div>) as JSX.Element;
608
+ }
609
+
610
+ function resolveUnauthorizedBoundary(
611
+ ctx: FlareProviderContext,
612
+ depth: number,
613
+ error: unknown,
614
+ retry: () => void,
615
+ ): JSX.Element {
616
+ const allMatches = ctx.matches();
617
+ const loc = ctx.location();
618
+ for (let i = depth; i >= 0; i--) {
619
+ const m = allMatches[i];
620
+ if (m?.unauthorizedRender) {
621
+ return m.unauthorizedRender({ error, location: loc, retry });
622
+ }
623
+ }
624
+ if (ctx.boundaries?.unauthorized) {
625
+ const errVal = error instanceof UnauthorizedError ? error : new UnauthorizedError();
626
+ return ctx.boundaries.unauthorized({
627
+ error: errVal,
628
+ location: loc as Parameters<NonNullable<GlobalBoundaries["unauthorized"]>>[0]["location"],
629
+ retry,
630
+ }) as JSX.Element;
631
+ }
632
+ return (<div>Access denied</div>) as JSX.Element;
633
+ }