@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,75 @@
1
+ import type { RouterArg } from "../hydrate/index.tsx";
2
+ import type { FlareProviderContext } from "../outlet/types.ts";
3
+
4
+ /* ── Types ─────────────────────────────────────────────────────────────── */
5
+
6
+ export interface ClientBuilder {
7
+ onHydrated(fn: () => void): ClientBuilder;
8
+ onIdle(fn: () => void): ClientBuilder;
9
+ onInteraction(fn: () => void): ClientBuilder;
10
+ onReady(fn: (ctx: FlareProviderContext) => void): ClientBuilder;
11
+ }
12
+
13
+ /* ── Builder ───────────────────────────────────────────────────────────── */
14
+
15
+ export function createClient(router: RouterArg): ClientBuilder {
16
+ const onHydratedFns: Array<() => void> = [];
17
+ const onIdleFns: Array<() => void> = [];
18
+ const onInteractionFns: Array<() => void> = [];
19
+ const onReadyFns: Array<(ctx: FlareProviderContext) => void> = [];
20
+
21
+ const builder: ClientBuilder = {
22
+ onHydrated(fn) {
23
+ onHydratedFns.push(fn);
24
+ return builder;
25
+ },
26
+ onIdle(fn) {
27
+ onIdleFns.push(fn);
28
+ return builder;
29
+ },
30
+ onInteraction(fn) {
31
+ onInteractionFns.push(fn);
32
+ return builder;
33
+ },
34
+ onReady(fn) {
35
+ onReadyFns.push(fn);
36
+ return builder;
37
+ },
38
+ };
39
+
40
+ /*
41
+ * Defer hydration to next microtask so builder methods are registered
42
+ * before hydrate() reads them.
43
+ */
44
+ queueMicrotask(async () => {
45
+ const { hydrate } = await import("../hydrate");
46
+ await hydrate(router, {
47
+ onContextReady:
48
+ onReadyFns.length > 0
49
+ ? (ctx) => {
50
+ for (const fn of onReadyFns) fn(ctx);
51
+ }
52
+ : undefined,
53
+ onHydrated:
54
+ onHydratedFns.length > 0
55
+ ? () => {
56
+ for (const fn of onHydratedFns) fn();
57
+ }
58
+ : undefined,
59
+ onIdle:
60
+ onIdleFns.length > 0
61
+ ? () => {
62
+ for (const fn of onIdleFns) fn();
63
+ }
64
+ : undefined,
65
+ onInteraction:
66
+ onInteractionFns.length > 0
67
+ ? () => {
68
+ for (const fn of onInteractionFns) fn();
69
+ }
70
+ : undefined,
71
+ });
72
+ });
73
+
74
+ return builder;
75
+ }
package/src/client.tsx ADDED
@@ -0,0 +1,2 @@
1
+ /* test stub */
2
+ export {};
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Codegen barrel — merges internal + register exports.
3
+ * Used by generated routes.gen.ts files only.
4
+ */
5
+ export {
6
+ applyResponseHeaders,
7
+ concatArrays,
8
+ isChunkLoadError,
9
+ isRenderFn,
10
+ mergeHeadConfigs,
11
+ mergeResponseHeaders,
12
+ retryImport,
13
+ } from "../internal/index.ts";
14
+ export { preload } from "../preload/index.ts";
15
+ export type { InferParams, InferSearchParams } from "../route-builder/index.ts";
16
+ export type {
17
+ ExtractPathParams,
18
+ FlareRegister,
19
+ InferAuthMode,
20
+ InferLoaderData,
21
+ InferPreloaderContext,
22
+ ParentAuthResolution,
23
+ ParentPreloaderContext,
24
+ PreloaderChain,
25
+ ResolvedAuth,
26
+ ResolvedEnv,
27
+ ResolvedQueryClient,
28
+ ResolvedServerContext,
29
+ RouteAuthMode,
30
+ RouteLoaderData,
31
+ RouteModule,
32
+ RouteParams,
33
+ RouteParamsProps,
34
+ RoutePathParams,
35
+ RoutePaths,
36
+ RouteSearchParams,
37
+ RouteSearchProps,
38
+ RouteSearchType,
39
+ RouteVirtualPaths,
40
+ } from "../route-builder/register.ts";
41
+ export type { RouteData, TreeNode } from "../router-primitives/index.ts";
@@ -0,0 +1,140 @@
1
+ import { batch, createEffect, createSignal, type JSX } from "solid-js";
2
+
3
+ export interface Deferred<T> {
4
+ __deferred: true;
5
+ __error?: { message: string };
6
+ __key?: string;
7
+ __resolved?: T;
8
+ promise: Promise<T>;
9
+ }
10
+
11
+ export type AwaitStatus = "error" | "pending" | "success";
12
+
13
+ export interface AwaitProps<T> {
14
+ children: (data: T) => JSX.Element;
15
+ error?: ((err: Error, reset: () => void) => JSX.Element) | null;
16
+ pending?: JSX.Element;
17
+ promise: Deferred<T> | Promise<T>;
18
+ }
19
+
20
+ export function isDeferred<T>(value: unknown): value is Deferred<T> {
21
+ return (
22
+ value !== null &&
23
+ value !== undefined &&
24
+ typeof value === "object" &&
25
+ (value as Record<string, unknown>).__deferred === true
26
+ );
27
+ }
28
+
29
+ export function getPromise<T>(value: Deferred<T> | Promise<T> | null | undefined): Promise<T> | undefined {
30
+ if (isDeferred<T>(value)) {
31
+ return value.promise instanceof Promise ? value.promise : undefined;
32
+ }
33
+ if (value != null && typeof (value as Promise<T>).then === "function") {
34
+ return value as Promise<T>;
35
+ }
36
+ return undefined;
37
+ }
38
+
39
+ export function getResolvedValue<T>(value: Deferred<T> | Promise<T>): T | undefined {
40
+ return isDeferred<T>(value) ? value.__resolved : undefined;
41
+ }
42
+
43
+ export function getResolvedError(value: unknown): Error | undefined {
44
+ if (!isDeferred(value)) return undefined;
45
+ if (value.__error) return new Error(value.__error.message);
46
+ return undefined;
47
+ }
48
+
49
+ export function Await<T>(props: AwaitProps<T>): JSX.Element {
50
+ const initialResolved = getResolvedValue(props.promise);
51
+ const initialError = getResolvedError(props.promise);
52
+
53
+ function computeInitialStatus(): AwaitStatus {
54
+ if (initialResolved !== undefined) return "success";
55
+ if (initialError) return "error";
56
+ return "pending";
57
+ }
58
+
59
+ const [status, setStatus] = createSignal<AwaitStatus>(computeInitialStatus());
60
+ const [data, setData] = createSignal<T | undefined>(initialResolved);
61
+ const [error, setError] = createSignal<Error | undefined>(initialError);
62
+
63
+ let currentPromise = getPromise(props.promise);
64
+
65
+ if (initialResolved === undefined && !initialError && currentPromise) {
66
+ trackPromise(currentPromise);
67
+ }
68
+
69
+ function trackPromise(p: Promise<T>): void {
70
+ p.then(
71
+ (result) => {
72
+ if (currentPromise === p) {
73
+ batch(() => {
74
+ setData(() => result);
75
+ setStatus("success");
76
+ });
77
+ }
78
+ },
79
+ (err: unknown) => {
80
+ if (currentPromise === p) {
81
+ batch(() => {
82
+ setError(() => (err instanceof Error ? err : new Error(String(err))));
83
+ setStatus("error");
84
+ });
85
+ }
86
+ },
87
+ );
88
+ }
89
+
90
+ function reset(): void {
91
+ const p = getPromise(props.promise);
92
+ currentPromise = p;
93
+ batch(() => {
94
+ setStatus("pending");
95
+ setData(undefined);
96
+ setError(undefined);
97
+ });
98
+ if (p) trackPromise(p);
99
+ }
100
+
101
+ /* Watch for promise prop changes */
102
+ createEffect(() => {
103
+ const newPromise = getPromise(props.promise);
104
+ if (newPromise === currentPromise) return;
105
+ currentPromise = newPromise;
106
+
107
+ const resolved = getResolvedValue(props.promise);
108
+ const resolvedError = getResolvedError(props.promise);
109
+
110
+ if (resolved !== undefined) {
111
+ batch(() => {
112
+ setData(() => resolved);
113
+ setStatus("success");
114
+ });
115
+ return;
116
+ }
117
+ if (resolvedError) {
118
+ batch(() => {
119
+ setError(() => resolvedError);
120
+ setStatus("error");
121
+ });
122
+ return;
123
+ }
124
+
125
+ setStatus("pending");
126
+ if (newPromise) trackPromise(newPromise);
127
+ });
128
+
129
+ return (() => {
130
+ const s = status();
131
+ if (s === "success") {
132
+ return props.children(data() as T);
133
+ }
134
+ if (s === "error") {
135
+ if (props.error) return props.error(error() as Error, reset);
136
+ return null;
137
+ }
138
+ return props.pending ?? null;
139
+ }) as unknown as JSX.Element;
140
+ }
@@ -0,0 +1,154 @@
1
+ import { createSignal, For, type JSX, onCleanup, onMount, Show } from "solid-js";
2
+ import { Portal } from "solid-js/web";
3
+ import { createDevErrorStore, type DevErrorStore } from "./index.ts";
4
+
5
+ let globalStore: DevErrorStore | undefined;
6
+
7
+ export function getDevErrorStore(): DevErrorStore {
8
+ if (!globalStore) {
9
+ globalStore = createDevErrorStore();
10
+ }
11
+ return globalStore;
12
+ }
13
+
14
+ export function resetDevErrorStore(): void {
15
+ globalStore = undefined;
16
+ }
17
+
18
+ export function DevErrorOverlay(): JSX.Element {
19
+ const store = getDevErrorStore();
20
+ const [errors, setErrors] = createSignal(store.errors().filter((e) => !e.dismissed));
21
+
22
+ function refresh(): void {
23
+ setErrors(store.errors().filter((e) => !e.dismissed));
24
+ }
25
+
26
+ function handleWindowError(event: ErrorEvent): void {
27
+ store.register(event.error instanceof Error ? event.error : new Error(event.message), "window.onerror");
28
+ refresh();
29
+ }
30
+
31
+ function handleUnhandledRejection(event: PromiseRejectionEvent): void {
32
+ const err = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
33
+ store.register(err, "unhandledrejection");
34
+ refresh();
35
+ }
36
+
37
+ onMount(() => {
38
+ if (typeof window === "undefined") return;
39
+ window.addEventListener("error", handleWindowError);
40
+ window.addEventListener("unhandledrejection", handleUnhandledRejection);
41
+ });
42
+
43
+ onCleanup(() => {
44
+ if (typeof window === "undefined") return;
45
+ window.removeEventListener("error", handleWindowError);
46
+ window.removeEventListener("unhandledrejection", handleUnhandledRejection);
47
+ });
48
+
49
+ function dismiss(id: string): void {
50
+ store.dismiss(id);
51
+ refresh();
52
+ }
53
+
54
+ function clearAll(): void {
55
+ store.clear();
56
+ refresh();
57
+ }
58
+
59
+ return (
60
+ <Show when={errors().length > 0}>
61
+ <Portal>
62
+ <div
63
+ data-flare-dev-overlay
64
+ style={{
65
+ background: "rgba(0,0,0,0.85)",
66
+ bottom: "0",
67
+ color: "#fff",
68
+ "font-family": "monospace",
69
+ "font-size": "14px",
70
+ left: "0",
71
+ overflow: "auto",
72
+ padding: "24px",
73
+ position: "fixed",
74
+ right: "0",
75
+ top: "0",
76
+ "z-index": "99999",
77
+ }}
78
+ >
79
+ <div
80
+ style={{
81
+ display: "flex",
82
+ "justify-content": "space-between",
83
+ "margin-bottom": "16px",
84
+ }}
85
+ >
86
+ <h2 style={{ "font-size": "18px", margin: "0" }}>
87
+ {`${errors().length} error${errors().length === 1 ? "" : "s"}`}
88
+ </h2>
89
+ <button
90
+ onClick={clearAll}
91
+ style={{
92
+ background: "#333",
93
+ border: "1px solid #555",
94
+ "border-radius": "4px",
95
+ color: "#fff",
96
+ cursor: "pointer",
97
+ padding: "4px 12px",
98
+ }}
99
+ type="button"
100
+ >
101
+ Clear all
102
+ </button>
103
+ </div>
104
+ <For each={errors()}>
105
+ {(entry) => (
106
+ <div
107
+ style={{
108
+ background: "#1a1a2e",
109
+ border: "1px solid #e74c3c",
110
+ "border-radius": "8px",
111
+ "margin-bottom": "12px",
112
+ padding: "16px",
113
+ }}
114
+ >
115
+ <div style={{ display: "flex", "justify-content": "space-between" }}>
116
+ <strong style={{ color: "#e74c3c" }}>
117
+ {entry.error.name}: {entry.error.message}
118
+ </strong>
119
+ <button
120
+ onClick={() => dismiss(entry.id)}
121
+ style={{
122
+ background: "none",
123
+ border: "none",
124
+ color: "#888",
125
+ cursor: "pointer",
126
+ "font-size": "16px",
127
+ }}
128
+ type="button"
129
+ >
130
+ x
131
+ </button>
132
+ </div>
133
+ <div style={{ color: "#888", "font-size": "12px", "margin-top": "4px" }}>{entry.source}</div>
134
+ <Show when={entry.error.stack}>
135
+ <pre
136
+ style={{
137
+ color: "#ccc",
138
+ "font-size": "12px",
139
+ "margin-top": "8px",
140
+ "overflow-x": "auto",
141
+ "white-space": "pre-wrap",
142
+ }}
143
+ >
144
+ {entry.error.stack}
145
+ </pre>
146
+ </Show>
147
+ </div>
148
+ )}
149
+ </For>
150
+ </div>
151
+ </Portal>
152
+ </Show>
153
+ ) as unknown as JSX.Element;
154
+ }
@@ -0,0 +1,22 @@
1
+ import type { JSX } from "solid-js";
2
+ import { NoHydration } from "solid-js/web";
3
+ import type { DirectionConfig } from "../direction.ts";
4
+ import { getDirectionScript } from "../direction.ts";
5
+ import { useSSRContext } from "./ssr-context.tsx";
6
+
7
+ export interface DirectionScriptProps {
8
+ config?: DirectionConfig;
9
+ }
10
+
11
+ export function DirectionScript(props: DirectionScriptProps): JSX.Element {
12
+ const ctx = useSSRContext();
13
+ const nonce = ctx?.nonce ?? "";
14
+ const config = props.config ?? ctx?.direction;
15
+ const script = getDirectionScript(config);
16
+
17
+ return (
18
+ <NoHydration>
19
+ <script innerHTML={script} nonce={nonce} />
20
+ </NoHydration>
21
+ ) as unknown as JSX.Element;
22
+ }
@@ -0,0 +1,150 @@
1
+ export { NavigationProgress, type NavigationProgressProps } from "../navigation-progress/index.tsx";
2
+ export {
3
+ Await,
4
+ type AwaitProps,
5
+ type AwaitStatus,
6
+ type Deferred,
7
+ getPromise,
8
+ getResolvedError,
9
+ getResolvedValue,
10
+ isDeferred,
11
+ } from "./await.tsx";
12
+ export { DirectionScript, type DirectionScriptProps } from "./direction-script.tsx";
13
+ export { ResetCSS } from "./reset-css.tsx";
14
+ export { SSRContextProvider, type SSRContextValue, setSSRContext, useSSRContext } from "./ssr-context.tsx";
15
+ export { ThemeScript, type ThemeScriptProps } from "./theme-script.tsx";
16
+ export { ViewTransitionCSS, type ViewTransitionCSSProps } from "./view-transition-css.tsx";
17
+
18
+ export interface SerializedError {
19
+ message: string;
20
+ name: string;
21
+ source: string;
22
+ stack?: string;
23
+ }
24
+
25
+ export interface CapturedError {
26
+ dismissed: boolean;
27
+ error: Error;
28
+ id: string;
29
+ source: string;
30
+ timestamp: number;
31
+ }
32
+
33
+ export interface DevErrorStore {
34
+ clear: () => void;
35
+ dismiss: (id: string) => void;
36
+ errors: () => CapturedError[];
37
+ hasErrors: () => boolean;
38
+ register: (error: Error | SerializedError, source?: string) => void;
39
+ }
40
+
41
+ function hashError(name: string, message: string, source: string, stack?: string): string {
42
+ /* Use first 100 chars of stack to avoid huge keys while still differentiating call sites */
43
+ const stackPrefix = stack ? stack.slice(0, 100) : "";
44
+ const raw = `${name}|${message}|${source}|${stackPrefix}`;
45
+ let hash = 0;
46
+ for (let i = 0; i < raw.length; i++) {
47
+ const ch = raw.charCodeAt(i);
48
+ hash = ((hash << 5) - hash + ch) | 0;
49
+ }
50
+ return hash.toString(36);
51
+ }
52
+
53
+ function isSerializedError(value: unknown): value is SerializedError {
54
+ return (
55
+ value !== null &&
56
+ typeof value === "object" &&
57
+ "message" in (value as Record<string, unknown>) &&
58
+ "name" in (value as Record<string, unknown>) &&
59
+ "source" in (value as Record<string, unknown>)
60
+ );
61
+ }
62
+
63
+ const MAX_DEV_ERRORS = 100;
64
+
65
+ /* Benign dev-mode errors that should not surface in the overlay */
66
+ const DEV_IGNORE_PATTERNS = [/ServiceWorker.*SSL certificate error/i];
67
+
68
+ /**
69
+ * Error names benign during navigation — WebKit surfaces AbortError as
70
+ * unhandledrejection for both fetch cancellation (NDJSON stream aborted
71
+ * when navigating away) and view transition overlap (new startViewTransition
72
+ * aborts previous). Chromium suppresses these internally.
73
+ */
74
+ const DEV_IGNORE_NAMES = new Set(["AbortError"]);
75
+
76
+ export function createDevErrorStore(): DevErrorStore {
77
+ let store: CapturedError[] = [];
78
+
79
+ function errors(): CapturedError[] {
80
+ return store;
81
+ }
82
+
83
+ function hasErrors(): boolean {
84
+ return store.some((e) => !e.dismissed);
85
+ }
86
+
87
+ function register(error: Error | SerializedError, source?: string): void {
88
+ const src = source ?? (isSerializedError(error) ? error.source : "unknown");
89
+ let err: Error;
90
+ if (error instanceof Error) {
91
+ err = error;
92
+ } else {
93
+ err = new Error(error.message);
94
+ err.name = error.name;
95
+ if (error.stack) {
96
+ err.stack = error.stack;
97
+ }
98
+ }
99
+
100
+ /* Skip benign dev-mode errors (e.g. SW cert during local HTTPS, fetch abort during nav) */
101
+ if (DEV_IGNORE_PATTERNS.some((p) => p.test(err.message))) return;
102
+ if (DEV_IGNORE_NAMES.has(err.name)) return;
103
+
104
+ const id = hashError(err.name, err.message, src, err.stack);
105
+
106
+ /* Dedup: skip if already tracked (even if dismissed) */
107
+ if (store.some((e) => e.id === id)) return;
108
+
109
+ /* Cap: evict dismissed first, then oldest */
110
+ if (store.length >= MAX_DEV_ERRORS) {
111
+ const dismissedIdx = store.findIndex((e) => e.dismissed);
112
+ store.splice(dismissedIdx >= 0 ? dismissedIdx : 0, 1);
113
+ }
114
+
115
+ store.push({
116
+ dismissed: false,
117
+ error: err,
118
+ id,
119
+ source: src,
120
+ timestamp: Date.now(),
121
+ });
122
+ }
123
+
124
+ function dismiss(id: string): void {
125
+ const entry = store.find((e) => e.id === id);
126
+ if (entry) {
127
+ entry.dismissed = true;
128
+ }
129
+ }
130
+
131
+ function clear(): void {
132
+ store = [];
133
+ }
134
+
135
+ return { clear, dismiss, errors, hasErrors, register };
136
+ }
137
+
138
+ /* Tailwind CSS v4 preflight — --theme() calls resolved to fallback values */
139
+ export const resetCss =
140
+ "@layer reset {*,::after,::before,::backdrop,::file-selector-button{box-sizing:border-box;margin:0;padding:0;border:0 solid}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji';font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea,::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;border-radius:0;background-color:transparent;opacity:1}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not (-webkit-appearance:-apple-pay-button)) or (contain-intrinsic-size:1px){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type='button'],[type='reset'],[type='submit']),::file-selector-button{appearance:button}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden='until-found'])){display:none!important}}";
141
+
142
+ function buildViewTransitionCss(duration: number): string {
143
+ return `@view-transition{navigation:auto}::view-transition-old(*),::view-transition-new(*){animation-duration:${duration}ms}`;
144
+ }
145
+
146
+ export const viewTransitionCss: string = buildViewTransitionCss(175);
147
+
148
+ export function getViewTransitionCss(duration: number): string {
149
+ return buildViewTransitionCss(duration);
150
+ }
@@ -0,0 +1,26 @@
1
+ import type { JSX } from "solid-js";
2
+ import { NoHydration } from "solid-js/web";
3
+ import type { LocaleConfig } from "../locale/index.tsx";
4
+ import { getLocaleScript } from "../locale/index.tsx";
5
+ import { useSSRContext } from "./ssr-context.tsx";
6
+
7
+ export interface LocaleScriptProps {
8
+ config?: LocaleConfig;
9
+ }
10
+
11
+ export function LocaleScript(props: LocaleScriptProps): JSX.Element {
12
+ const ctx = useSSRContext();
13
+ const nonce = ctx?.nonce ?? "";
14
+ const config = props.config ?? ctx?.locale;
15
+ if (!config)
16
+ throw new Error(
17
+ "LocaleScript requires a config prop or locale in SSRContext. Pass <LocaleScript config={...} /> or set locale via router.locale().",
18
+ );
19
+ const script = getLocaleScript(config);
20
+
21
+ return (
22
+ <NoHydration>
23
+ <script innerHTML={script} nonce={nonce} />
24
+ </NoHydration>
25
+ ) as unknown as JSX.Element;
26
+ }
@@ -0,0 +1,14 @@
1
+ import type { JSX } from "solid-js";
2
+ import { useSSRContext } from "./ssr-context.tsx";
3
+
4
+ /* Duplicated from index.ts to avoid circular import (index re-exports this component) */
5
+ export const RESET =
6
+ "@layer reset {*,::after,::before,::backdrop,::file-selector-button{box-sizing:border-box;margin:0;padding:0;border:0 solid}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Noto Color Emoji';font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,'Liberation Mono','Courier New',monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea,::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;border-radius:0;background-color:transparent;opacity:1}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not (-webkit-appearance:-apple-pay-button)) or (contain-intrinsic-size:1px){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type='button'],[type='reset'],[type='submit']),::file-selector-button{appearance:button}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden='until-found'])){display:none!important}}";
7
+
8
+ export function ResetCSS(): JSX.Element {
9
+ const ctx = useSSRContext();
10
+ const nonce = ctx?.nonce ?? "";
11
+
12
+ /* oxlint-disable-next-line solid/no-innerhtml -- RESET is a hardcoded static string, not user input */
13
+ return (<style innerHTML={RESET} nonce={nonce} />) as unknown as JSX.Element;
14
+ }
@@ -0,0 +1,37 @@
1
+ import { createContext, type JSX, sharedConfig, useContext } from "solid-js";
2
+ import type { DirectionConfig } from "../direction.ts";
3
+ import type { LocaleConfig } from "../locale/index.tsx";
4
+ import type { HeadConfig } from "../route-builder/types.ts";
5
+ import type { ThemeConfig } from "../theme.ts";
6
+
7
+ export interface SSRContextValue {
8
+ direction?: DirectionConfig;
9
+ entryScript?: string;
10
+ flareStateScript: string;
11
+ isServer: boolean;
12
+ locale?: LocaleConfig;
13
+ nonce: string;
14
+ resolvedHead?: HeadConfig;
15
+ theme?: ThemeConfig;
16
+ }
17
+
18
+ const SSRCtx = createContext<SSRContextValue>();
19
+
20
+ export function setSSRContext(value: SSRContextValue): void {
21
+ if (sharedConfig.context) {
22
+ (sharedConfig.context as Record<string, unknown>).flare = value;
23
+ }
24
+ }
25
+
26
+ export function useSSRContext(): SSRContextValue | undefined {
27
+ /* SSR path: read from sharedConfig.context */
28
+ if (sharedConfig.context) {
29
+ return (sharedConfig.context as Record<string, unknown>).flare as SSRContextValue | undefined;
30
+ }
31
+ /* Testing fallback: read from Solid context provider */
32
+ return useContext(SSRCtx);
33
+ }
34
+
35
+ export function SSRContextProvider(props: { children: JSX.Element; value: SSRContextValue }): JSX.Element {
36
+ return <SSRCtx.Provider value={props.value}>{props.children}</SSRCtx.Provider>;
37
+ }