@curvenote/theme-ui 2.0.1 → 2.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 (276) hide show
  1. package/dist/components/index.d.ts +4 -3
  2. package/dist/components/index.d.ts.map +1 -1
  3. package/dist/components/index.js +4 -3
  4. package/dist/components/layout/app-layout.d.ts +3 -3
  5. package/dist/components/layout/app-layout.d.ts.map +1 -1
  6. package/dist/components/layout/app-layout.js +26 -16
  7. package/dist/components/layout/app-sidebar.d.ts +2 -1
  8. package/dist/components/layout/app-sidebar.d.ts.map +1 -1
  9. package/dist/components/layout/app-sidebar.js +8 -8
  10. package/dist/components/layout/article-layout.d.ts +3 -3
  11. package/dist/components/layout/article-layout.d.ts.map +1 -1
  12. package/dist/components/layout/article-layout.js +17 -10
  13. package/dist/components/layout/grid.d.ts +1 -1
  14. package/dist/components/layout/grid.d.ts.map +1 -1
  15. package/dist/components/layout/header.d.ts +5 -3
  16. package/dist/components/layout/header.d.ts.map +1 -1
  17. package/dist/components/layout/header.js +6 -3
  18. package/dist/components/layout/index.d.ts +7 -7
  19. package/dist/components/layout/index.d.ts.map +1 -1
  20. package/dist/components/layout/index.js +7 -7
  21. package/dist/components/layout/layout-header.d.ts +9 -0
  22. package/dist/components/layout/layout-header.d.ts.map +1 -0
  23. package/dist/components/layout/layout-header.js +13 -0
  24. package/dist/components/layout/loading-bar.d.ts +1 -1
  25. package/dist/components/layout/loading-bar.d.ts.map +1 -1
  26. package/dist/components/layout/loading-bar.js +1 -1
  27. package/dist/components/layout/site-header.d.ts +1 -1
  28. package/dist/components/layout/site-header.d.ts.map +1 -1
  29. package/dist/components/layout/site-header.js +21 -9
  30. package/dist/components/layout/types.d.ts +11 -0
  31. package/dist/components/layout/types.d.ts.map +1 -1
  32. package/dist/components/providers/analytics-boundary.d.ts +1 -1
  33. package/dist/components/providers/analytics-boundary.d.ts.map +1 -1
  34. package/dist/components/providers/analytics-boundary.js +3 -3
  35. package/dist/components/providers/analytics-dev-tray.d.ts +1 -1
  36. package/dist/components/providers/analytics-dev-tray.d.ts.map +1 -1
  37. package/dist/components/providers/analytics-dev-tray.js +3 -3
  38. package/dist/components/providers/article-versions-provider.d.ts +1 -1
  39. package/dist/components/providers/article-versions-provider.d.ts.map +1 -1
  40. package/dist/components/providers/compute.d.ts +1 -1
  41. package/dist/components/providers/compute.d.ts.map +1 -1
  42. package/dist/components/providers/curvenote-providers.d.ts +28 -19
  43. package/dist/components/providers/curvenote-providers.d.ts.map +1 -1
  44. package/dist/components/providers/curvenote-providers.js +28 -14
  45. package/dist/components/providers/design.d.ts +1 -1
  46. package/dist/components/providers/design.d.ts.map +1 -1
  47. package/dist/components/providers/design.js +2 -1
  48. package/dist/components/providers/index.d.ts +11 -11
  49. package/dist/components/providers/index.d.ts.map +1 -1
  50. package/dist/components/providers/index.js +11 -11
  51. package/dist/components/providers/lightbox-provider.d.ts +1 -1
  52. package/dist/components/providers/lightbox-provider.d.ts.map +1 -1
  53. package/dist/components/providers/myst-providers.d.ts +1 -1
  54. package/dist/components/providers/myst-providers.d.ts.map +1 -1
  55. package/dist/components/providers/overlay-depth.d.ts +1 -1
  56. package/dist/components/providers/overlay-depth.d.ts.map +1 -1
  57. package/dist/components/providers/page-providers.d.ts +2 -2
  58. package/dist/components/providers/page-providers.d.ts.map +1 -1
  59. package/dist/components/providers/ping-boundary.d.ts +1 -1
  60. package/dist/components/providers/ping-boundary.d.ts.map +1 -1
  61. package/dist/components/providers/platform-providers.d.ts +1 -1
  62. package/dist/components/providers/platform-providers.d.ts.map +1 -1
  63. package/dist/components/site-renderers/host-import-map-script.d.ts +8 -0
  64. package/dist/components/site-renderers/host-import-map-script.d.ts.map +1 -0
  65. package/dist/components/site-renderers/host-import-map-script.js +30 -0
  66. package/dist/components/site-renderers/host-import-map.d.ts +40 -0
  67. package/dist/components/site-renderers/host-import-map.d.ts.map +1 -0
  68. package/dist/components/site-renderers/host-import-map.js +136 -0
  69. package/dist/components/site-renderers/host-react-modules.d.ts +15 -0
  70. package/dist/components/site-renderers/host-react-modules.d.ts.map +1 -0
  71. package/dist/components/site-renderers/host-react-modules.js +17 -0
  72. package/dist/components/site-renderers/index.d.ts +6 -0
  73. package/dist/components/site-renderers/index.d.ts.map +1 -0
  74. package/dist/components/site-renderers/index.js +7 -0
  75. package/dist/components/site-renderers/site-myst-providers.d.ts +8 -0
  76. package/dist/components/site-renderers/site-myst-providers.d.ts.map +1 -0
  77. package/dist/components/site-renderers/site-myst-providers.js +40 -0
  78. package/dist/components/site-renderers/site-renderers.d.ts +23 -0
  79. package/dist/components/site-renderers/site-renderers.d.ts.map +1 -0
  80. package/dist/components/site-renderers/site-renderers.js +48 -0
  81. package/dist/components/ui/Callout.d.ts +1 -1
  82. package/dist/components/ui/Callout.d.ts.map +1 -1
  83. package/dist/components/ui/Callout.js +1 -1
  84. package/dist/components/ui/PageCards.d.ts +2 -1
  85. package/dist/components/ui/PageCards.d.ts.map +1 -1
  86. package/dist/components/ui/abbreviations.d.ts +2 -1
  87. package/dist/components/ui/abbreviations.d.ts.map +1 -1
  88. package/dist/components/ui/abbreviations.js +7 -14
  89. package/dist/components/ui/abstract.d.ts +1 -1
  90. package/dist/components/ui/abstract.d.ts.map +1 -1
  91. package/dist/components/ui/accessibility-skip-to.d.ts +3 -3
  92. package/dist/components/ui/accessibility-skip-to.d.ts.map +1 -1
  93. package/dist/components/ui/accessibility-skip-to.js +1 -1
  94. package/dist/components/ui/acknowledgements.d.ts +1 -1
  95. package/dist/components/ui/acknowledgements.d.ts.map +1 -1
  96. package/dist/components/ui/acknowledgements.js +4 -4
  97. package/dist/components/ui/arrow.d.ts +3 -3
  98. package/dist/components/ui/arrow.d.ts.map +1 -1
  99. package/dist/components/ui/article-actions-downloads.d.ts +24 -3
  100. package/dist/components/ui/article-actions-downloads.d.ts.map +1 -1
  101. package/dist/components/ui/article-actions-downloads.js +58 -16
  102. package/dist/components/ui/article-actions-dropdown.d.ts +1 -1
  103. package/dist/components/ui/article-actions-dropdown.d.ts.map +1 -1
  104. package/dist/components/ui/article-actions-dropdown.js +9 -9
  105. package/dist/components/ui/article-actions-share.d.ts +1 -1
  106. package/dist/components/ui/article-actions-share.d.ts.map +1 -1
  107. package/dist/components/ui/article-actions-share.js +2 -2
  108. package/dist/components/ui/article-actions.d.ts +1 -1
  109. package/dist/components/ui/article-actions.d.ts.map +1 -1
  110. package/dist/components/ui/article-actions.js +29 -8
  111. package/dist/components/ui/article-bar.d.ts +16 -3
  112. package/dist/components/ui/article-bar.d.ts.map +1 -1
  113. package/dist/components/ui/article-bar.js +9 -7
  114. package/dist/components/ui/article-card.d.ts +1 -1
  115. package/dist/components/ui/article-card.d.ts.map +1 -1
  116. package/dist/components/ui/article-card.js +9 -4
  117. package/dist/components/ui/article-footer.d.ts +1 -1
  118. package/dist/components/ui/article-footer.d.ts.map +1 -1
  119. package/dist/components/ui/article-footer.js +1 -1
  120. package/dist/components/ui/author-popover.d.ts +1 -1
  121. package/dist/components/ui/author-popover.d.ts.map +1 -1
  122. package/dist/components/ui/author-popover.js +3 -3
  123. package/dist/components/ui/backmatter.d.ts +41 -3
  124. package/dist/components/ui/backmatter.d.ts.map +1 -1
  125. package/dist/components/ui/backmatter.js +117 -34
  126. package/dist/components/ui/badge.d.ts +1 -1
  127. package/dist/components/ui/badge.d.ts.map +1 -1
  128. package/dist/components/ui/badge.js +1 -1
  129. package/dist/components/ui/banner.d.ts +22 -1
  130. package/dist/components/ui/banner.d.ts.map +1 -1
  131. package/dist/components/ui/banner.js +44 -3
  132. package/dist/components/ui/bibliography.d.ts +1 -1
  133. package/dist/components/ui/bibliography.d.ts.map +1 -1
  134. package/dist/components/ui/bibliography.js +3 -3
  135. package/dist/components/ui/breadcrumb.d.ts +7 -7
  136. package/dist/components/ui/breadcrumb.d.ts.map +1 -1
  137. package/dist/components/ui/breadcrumb.js +1 -1
  138. package/dist/components/ui/button.d.ts +1 -1
  139. package/dist/components/ui/button.d.ts.map +1 -1
  140. package/dist/components/ui/button.js +2 -2
  141. package/dist/components/ui/calendar.d.ts +1 -1
  142. package/dist/components/ui/calendar.d.ts.map +1 -1
  143. package/dist/components/ui/calendar.js +2 -2
  144. package/dist/components/ui/citation.d.ts +2 -2
  145. package/dist/components/ui/citation.d.ts.map +1 -1
  146. package/dist/components/ui/citation.js +5 -5
  147. package/dist/components/ui/collapsible-backmatter-section.d.ts +2 -2
  148. package/dist/components/ui/collapsible-backmatter-section.d.ts.map +1 -1
  149. package/dist/components/ui/collapsible-backmatter-section.js +3 -3
  150. package/dist/components/ui/collapsible.d.ts +3 -3
  151. package/dist/components/ui/collapsible.d.ts.map +1 -1
  152. package/dist/components/ui/cookie-banner.d.ts +2 -1
  153. package/dist/components/ui/cookie-banner.d.ts.map +1 -1
  154. package/dist/components/ui/cookie-banner.js +4 -4
  155. package/dist/components/ui/data-availability.d.ts +1 -1
  156. package/dist/components/ui/data-availability.d.ts.map +1 -1
  157. package/dist/components/ui/data-availability.js +4 -4
  158. package/dist/components/ui/dhr-cta-buttons.d.ts +30 -0
  159. package/dist/components/ui/dhr-cta-buttons.d.ts.map +1 -0
  160. package/dist/components/ui/dhr-cta-buttons.js +40 -0
  161. package/dist/components/ui/dialog.d.ts +10 -10
  162. package/dist/components/ui/dialog.d.ts.map +1 -1
  163. package/dist/components/ui/dialog.js +1 -1
  164. package/dist/components/ui/document-outline.d.ts +11 -2
  165. package/dist/components/ui/document-outline.d.ts.map +1 -1
  166. package/dist/components/ui/document-outline.js +101 -54
  167. package/dist/components/ui/dropdown-menu.d.ts +15 -15
  168. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  169. package/dist/components/ui/dropdown-menu.js +1 -1
  170. package/dist/components/ui/error-page.d.ts +1 -1
  171. package/dist/components/ui/error-page.d.ts.map +1 -1
  172. package/dist/components/ui/error-page.js +1 -1
  173. package/dist/components/ui/font-styles.d.ts +23 -0
  174. package/dist/components/ui/font-styles.d.ts.map +1 -0
  175. package/dist/components/ui/font-styles.js +39 -0
  176. package/dist/components/ui/footer-links.d.ts +1 -1
  177. package/dist/components/ui/footer-links.d.ts.map +1 -1
  178. package/dist/components/ui/footer-links.js +2 -2
  179. package/dist/components/ui/footnotes.d.ts +1 -1
  180. package/dist/components/ui/footnotes.d.ts.map +1 -1
  181. package/dist/components/ui/footnotes.js +3 -2
  182. package/dist/components/ui/frontmatter-badges.d.ts +7 -7
  183. package/dist/components/ui/frontmatter-badges.d.ts.map +1 -1
  184. package/dist/components/ui/frontmatter-badges.js +5 -5
  185. package/dist/components/ui/frontmatter.d.ts +1 -1
  186. package/dist/components/ui/frontmatter.d.ts.map +1 -1
  187. package/dist/components/ui/frontmatter.js +1 -1
  188. package/dist/components/ui/hash-link.d.ts.map +1 -1
  189. package/dist/components/ui/hash-link.js +2 -1
  190. package/dist/components/ui/image.d.ts +2 -2
  191. package/dist/components/ui/image.d.ts.map +1 -1
  192. package/dist/components/ui/image.js +3 -3
  193. package/dist/components/ui/index.d.ts +62 -57
  194. package/dist/components/ui/index.d.ts.map +1 -1
  195. package/dist/components/ui/index.js +59 -56
  196. package/dist/components/ui/input.d.ts +1 -1
  197. package/dist/components/ui/input.d.ts.map +1 -1
  198. package/dist/components/ui/input.js +1 -1
  199. package/dist/components/ui/keywords.d.ts +1 -1
  200. package/dist/components/ui/keywords.d.ts.map +1 -1
  201. package/dist/components/ui/keywords.js +3 -3
  202. package/dist/components/ui/label.js +1 -1
  203. package/dist/components/ui/license-description.d.ts +1 -1
  204. package/dist/components/ui/license-description.d.ts.map +1 -1
  205. package/dist/components/ui/license-description.js +3 -3
  206. package/dist/components/ui/license-frontmatter.d.ts +2 -2
  207. package/dist/components/ui/license-frontmatter.d.ts.map +1 -1
  208. package/dist/components/ui/license-frontmatter.js +4 -4
  209. package/dist/components/ui/lightbox-container.d.ts +2 -2
  210. package/dist/components/ui/lightbox-container.d.ts.map +1 -1
  211. package/dist/components/ui/lightbox-container.js +2 -2
  212. package/dist/components/ui/lightbox.d.ts +3 -2
  213. package/dist/components/ui/lightbox.d.ts.map +1 -1
  214. package/dist/components/ui/lightbox.js +6 -6
  215. package/dist/components/ui/link-card.d.ts +1 -1
  216. package/dist/components/ui/link-card.d.ts.map +1 -1
  217. package/dist/components/ui/link-card.js +1 -1
  218. package/dist/components/ui/pagination.d.ts +7 -7
  219. package/dist/components/ui/pagination.d.ts.map +1 -1
  220. package/dist/components/ui/pagination.js +1 -1
  221. package/dist/components/ui/popover.d.ts +4 -4
  222. package/dist/components/ui/popover.d.ts.map +1 -1
  223. package/dist/components/ui/popover.js +1 -1
  224. package/dist/components/ui/search.d.ts +1 -1
  225. package/dist/components/ui/search.d.ts.map +1 -1
  226. package/dist/components/ui/search.js +2 -2
  227. package/dist/components/ui/select.d.ts +10 -10
  228. package/dist/components/ui/select.d.ts.map +1 -1
  229. package/dist/components/ui/select.js +1 -1
  230. package/dist/components/ui/separator.d.ts +1 -1
  231. package/dist/components/ui/separator.d.ts.map +1 -1
  232. package/dist/components/ui/separator.js +1 -1
  233. package/dist/components/ui/sheet.d.ts +8 -8
  234. package/dist/components/ui/sheet.d.ts.map +1 -1
  235. package/dist/components/ui/sheet.js +1 -1
  236. package/dist/components/ui/sidebar.d.ts +23 -23
  237. package/dist/components/ui/sidebar.d.ts.map +1 -1
  238. package/dist/components/ui/sidebar.js +3 -3
  239. package/dist/components/ui/site-color-styles.d.ts +8 -0
  240. package/dist/components/ui/site-color-styles.d.ts.map +1 -0
  241. package/dist/components/ui/site-color-styles.js +16 -0
  242. package/dist/components/ui/skeleton.d.ts +1 -1
  243. package/dist/components/ui/skeleton.d.ts.map +1 -1
  244. package/dist/components/ui/skeleton.js +1 -1
  245. package/dist/components/ui/sonner.d.ts +1 -1
  246. package/dist/components/ui/sonner.d.ts.map +1 -1
  247. package/dist/components/ui/theme-button.d.ts +1 -1
  248. package/dist/components/ui/theme-button.d.ts.map +1 -1
  249. package/dist/components/ui/theme-button.js +3 -3
  250. package/dist/components/ui/tooltip.d.ts +4 -4
  251. package/dist/components/ui/tooltip.d.ts.map +1 -1
  252. package/dist/components/ui/tooltip.js +2 -2
  253. package/dist/components/ui/types.d.ts +1 -0
  254. package/dist/components/ui/types.d.ts.map +1 -1
  255. package/dist/components/ui/types.js +1 -0
  256. package/dist/hooks/index.d.ts +4 -4
  257. package/dist/hooks/index.d.ts.map +1 -1
  258. package/dist/hooks/index.js +4 -4
  259. package/dist/hooks/use-theme.d.ts +1 -1
  260. package/dist/hooks/use-theme.d.ts.map +1 -1
  261. package/dist/index.d.ts +3 -3
  262. package/dist/index.d.ts.map +1 -1
  263. package/dist/index.js +3 -3
  264. package/dist/lib/dedupeAbbreviations.d.ts +11 -0
  265. package/dist/lib/dedupeAbbreviations.d.ts.map +1 -1
  266. package/dist/lib/dedupeAbbreviations.js +17 -0
  267. package/dist/lib/fonts.d.ts +29 -0
  268. package/dist/lib/fonts.d.ts.map +1 -0
  269. package/dist/lib/fonts.js +148 -0
  270. package/dist/lib/index.d.ts +6 -5
  271. package/dist/lib/index.d.ts.map +1 -1
  272. package/dist/lib/index.js +6 -5
  273. package/dist/lib/site-colors.d.ts +10 -0
  274. package/dist/lib/site-colors.d.ts.map +1 -0
  275. package/dist/lib/site-colors.js +20 -0
  276. package/package.json +22 -4
@@ -0,0 +1,29 @@
1
+ import type { FontSlot, ThemeFontsConfig } from '@curvenote/common';
2
+ /** `family, fallback` — what the `--font-*` token is set to. */
3
+ export declare function fontStack(slot: FontSlot): string;
4
+ /**
5
+ * Google Fonts stylesheet URL for the slots that ask for it, or `undefined` when none do.
6
+ * One request covers every Google-sourced family.
7
+ */
8
+ export declare function googleFontsHref(fonts?: ThemeFontsConfig): string | undefined;
9
+ /** Self-hosted files worth preloading — the body and heading faces the reader sees first. */
10
+ export declare function fontPreloads(fonts?: ThemeFontsConfig): string[];
11
+ /**
12
+ * Fills the slots a site left unset from an app's defaults, so the defaults are only ever
13
+ * downloaded when they will be seen. Slot-level: a site that sets `body` replaces the
14
+ * default body entirely rather than merging into it.
15
+ */
16
+ export declare function withDefaultFonts(fonts?: ThemeFontsConfig, defaults?: ThemeFontsConfig): ThemeFontsConfig | undefined;
17
+ /** The slots of `defaults` that `fonts` does not set — what an app still has to load itself. */
18
+ export declare function unsetDefaultFonts(fonts?: ThemeFontsConfig, defaults?: ThemeFontsConfig): ThemeFontsConfig | undefined;
19
+ /**
20
+ * `@font-face` rules plus `:root` token assignments for a site's font config.
21
+ *
22
+ * Returns an empty string when nothing is configured, so callers can render it
23
+ * unconditionally. Pass `{ tokens: false }` for an app's defaults: their tokens already
24
+ * live in `@curvenote/styles/fonts.css`, so only any self-hosted faces are wanted.
25
+ */
26
+ export declare function buildFontCss(fonts?: ThemeFontsConfig, opts?: {
27
+ tokens?: boolean;
28
+ }): string;
29
+ //# sourceMappingURL=fonts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fonts.d.ts","sourceRoot":"","sources":["../../src/lib/fonts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,QAAQ,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AA4B9E,gEAAgE;AAChE,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAGhD;AA6BD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAiB5E;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAM/D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,CAAC,EAAE,gBAAgB,EACxB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,gBAAgB,GAAG,SAAS,CAO9B;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAC/B,KAAK,CAAC,EAAE,gBAAgB,EACxB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,gBAAgB,GAAG,SAAS,CAO9B;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAsB1F"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Turns a site's `theme_config.fonts` into the CSS that has to reach the page: the
3
+ * `@font-face` rules for self-hosted files, and the `--font-*` token assignments that
4
+ * `@curvenote/styles` and the `.prose` config read.
5
+ *
6
+ * Pure and string-in/string-out so it can be rendered server-side into a `<style>` — no
7
+ * flash of fallback — and unit-tested without a DOM.
8
+ */
9
+ /** Slots in the order they cascade: `heading` and `small` fall back to `body`. */
10
+ const SLOTS = ['body', 'heading', 'small', 'mono'];
11
+ /** Font files are same-origin or CDN URLs; refuse anything that could break out of `url()`. */
12
+ function isSafeUrl(src) {
13
+ if (/["'()\\]|[\s]/.test(src))
14
+ return false;
15
+ return /^https:\/\//.test(src) || /^\//.test(src);
16
+ }
17
+ /** A family name may contain spaces, so quote it unless it already is. */
18
+ function quoteFamily(family) {
19
+ const trimmed = family.trim();
20
+ if (/^["']/.test(trimmed))
21
+ return trimmed;
22
+ return /[^a-zA-Z0-9-]/.test(trimmed) ? `'${trimmed.replace(/'/g, '')}'` : trimmed;
23
+ }
24
+ /** `family, fallback` — what the `--font-*` token is set to. */
25
+ export function fontStack(slot) {
26
+ const fallback = slot.fallback?.trim();
27
+ return fallback ? `${quoteFamily(slot.family)}, ${fallback}` : quoteFamily(slot.family);
28
+ }
29
+ function faceRule(family, face, display) {
30
+ if (!isSafeUrl(face.src))
31
+ return undefined;
32
+ const format = face.src.endsWith('.woff2')
33
+ ? 'woff2'
34
+ : face.src.endsWith('.woff')
35
+ ? 'woff'
36
+ : face.src.endsWith('.otf')
37
+ ? 'opentype'
38
+ : face.src.endsWith('.ttf')
39
+ ? 'truetype'
40
+ : undefined;
41
+ const lines = [
42
+ ` font-family: ${quoteFamily(family)};`,
43
+ ` src: url(${face.src})${format ? ` format('${format}')` : ''};`,
44
+ ` font-weight: ${face.weight ?? 400};`,
45
+ ` font-style: ${face.style ?? 'normal'};`,
46
+ ` font-display: ${display};`,
47
+ ];
48
+ // Metric overrides keep the fallback the same size as the real face, so swapping it in
49
+ // does not reflow the article.
50
+ if (face.sizeAdjust)
51
+ lines.push(` size-adjust: ${face.sizeAdjust};`);
52
+ if (face.ascentOverride)
53
+ lines.push(` ascent-override: ${face.ascentOverride};`);
54
+ if (face.descentOverride)
55
+ lines.push(` descent-override: ${face.descentOverride};`);
56
+ if (face.lineGapOverride)
57
+ lines.push(` line-gap-override: ${face.lineGapOverride};`);
58
+ return `@font-face {\n${lines.join('\n')}\n}`;
59
+ }
60
+ /**
61
+ * Google Fonts stylesheet URL for the slots that ask for it, or `undefined` when none do.
62
+ * One request covers every Google-sourced family.
63
+ */
64
+ export function googleFontsHref(fonts) {
65
+ if (!fonts)
66
+ return undefined;
67
+ const families = SLOTS.map((name) => fonts[name])
68
+ .filter((slot) => slot?.source === 'google')
69
+ .map((slot) => {
70
+ const weights = [...new Set(slot.weights ?? [400, 700])].sort((a, b) => parseInt(String(a), 10) - parseInt(String(b), 10));
71
+ const axis = slot.italic
72
+ ? `:ital,wght@${weights.map((w) => `0,${w}`).join(';')};${weights.map((w) => `1,${w}`).join(';')}`
73
+ : `:wght@${weights.join(';')}`;
74
+ return `family=${slot.family.trim().replace(/\s+/g, '+')}${axis}`;
75
+ });
76
+ const unique = [...new Set(families)];
77
+ return unique.length
78
+ ? `https://fonts.googleapis.com/css2?${unique.join('&')}&display=swap`
79
+ : undefined;
80
+ }
81
+ /** Self-hosted files worth preloading — the body and heading faces the reader sees first. */
82
+ export function fontPreloads(fonts) {
83
+ if (!fonts)
84
+ return [];
85
+ return ['body', 'heading']
86
+ .flatMap((name) => fonts[name]?.faces ?? [])
87
+ .filter((face) => isSafeUrl(face.src) && face.src.endsWith('.woff2'))
88
+ .map((face) => face.src);
89
+ }
90
+ /**
91
+ * Fills the slots a site left unset from an app's defaults, so the defaults are only ever
92
+ * downloaded when they will be seen. Slot-level: a site that sets `body` replaces the
93
+ * default body entirely rather than merging into it.
94
+ */
95
+ export function withDefaultFonts(fonts, defaults) {
96
+ if (!defaults)
97
+ return fonts;
98
+ const merged = { ...defaults };
99
+ for (const name of SLOTS) {
100
+ if (fonts?.[name])
101
+ merged[name] = fonts[name];
102
+ }
103
+ return merged;
104
+ }
105
+ /** The slots of `defaults` that `fonts` does not set — what an app still has to load itself. */
106
+ export function unsetDefaultFonts(fonts, defaults) {
107
+ if (!defaults)
108
+ return undefined;
109
+ const rest = {};
110
+ for (const name of SLOTS) {
111
+ if (defaults[name] && !fonts?.[name])
112
+ rest[name] = defaults[name];
113
+ }
114
+ return Object.keys(rest).length ? rest : undefined;
115
+ }
116
+ /**
117
+ * `@font-face` rules plus `:root` token assignments for a site's font config.
118
+ *
119
+ * Returns an empty string when nothing is configured, so callers can render it
120
+ * unconditionally. Pass `{ tokens: false }` for an app's defaults: their tokens already
121
+ * live in `@curvenote/styles/fonts.css`, so only any self-hosted faces are wanted.
122
+ */
123
+ export function buildFontCss(fonts, opts) {
124
+ if (!fonts)
125
+ return '';
126
+ const wantTokens = opts?.tokens ?? true;
127
+ const faces = [];
128
+ const tokens = [];
129
+ for (const name of SLOTS) {
130
+ const slot = fonts[name];
131
+ if (!slot?.family)
132
+ continue;
133
+ const display = slot.display ?? 'swap';
134
+ if (slot.source !== 'stack') {
135
+ for (const face of slot.faces ?? []) {
136
+ const rule = faceRule(slot.family, face, display);
137
+ if (rule)
138
+ faces.push(rule);
139
+ }
140
+ }
141
+ if (wantTokens)
142
+ tokens.push(` --font-${name}: ${fontStack(slot)};`);
143
+ }
144
+ if (!faces.length && !tokens.length)
145
+ return '';
146
+ const root = tokens.length ? `:root {\n${tokens.join('\n')}\n}` : '';
147
+ return [...faces, root].filter(Boolean).join('\n');
148
+ }
@@ -1,6 +1,7 @@
1
- export * from './knownParts';
2
- export * from './links';
3
- export * from './parse-date';
4
- export * from './utils';
5
- export * from './checkMecaExport';
1
+ export * from './knownParts.js';
2
+ export * from './links.js';
3
+ export * from './parse-date.js';
4
+ export * from './utils.js';
5
+ export * from './checkMecaExport.js';
6
+ export * from './fonts.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,sBAAsB,CAAC;AACrC,cAAc,YAAY,CAAC"}
package/dist/lib/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // Lib utilities
2
- export * from './knownParts';
3
- export * from './links';
4
- export * from './parse-date';
5
- export * from './utils';
6
- export * from './checkMecaExport';
2
+ export * from './knownParts.js';
3
+ export * from './links.js';
4
+ export * from './parse-date.js';
5
+ export * from './utils.js';
6
+ export * from './checkMecaExport.js';
7
+ export * from './fonts.js';
@@ -0,0 +1,10 @@
1
+ import type { SiteThemeConfig } from '@curvenote/common';
2
+ type SiteColors = SiteThemeConfig['colors'];
3
+ /**
4
+ * The `--site-primary` / `--site-secondary` tokens for a site's configured brand colours, as a
5
+ * `:root` rule, or `''` when it sets none. The values come from site config and end up in a
6
+ * `<style>` element, so anything that is not a plain colour value is dropped.
7
+ */
8
+ export declare function buildSiteColorCss(colors: SiteColors): string;
9
+ export {};
10
+ //# sourceMappingURL=site-colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-colors.d.ts","sourceRoot":"","sources":["../../src/lib/site-colors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,KAAK,UAAU,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;AAU5C;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,UAQnD"}
@@ -0,0 +1,20 @@
1
+ /** Hex (`#rgb` to `#rrggbbaa`) or a functional notation with only numbers, units and separators. */
2
+ const COLOR = /^(#[0-9a-f]{3,8}|(rgba?|hsla?|hwb|lab|lch|oklab|oklch)\([0-9a-z.%\s,/+-]+\))$/i;
3
+ function safeColor(value) {
4
+ const trimmed = value?.trim();
5
+ return trimmed && COLOR.test(trimmed) ? trimmed : undefined;
6
+ }
7
+ /**
8
+ * The `--site-primary` / `--site-secondary` tokens for a site's configured brand colours, as a
9
+ * `:root` rule, or `''` when it sets none. The values come from site config and end up in a
10
+ * `<style>` element, so anything that is not a plain colour value is dropped.
11
+ */
12
+ export function buildSiteColorCss(colors) {
13
+ const primary = safeColor(colors?.primary);
14
+ const secondary = safeColor(colors?.secondary);
15
+ const decls = [
16
+ primary && `--site-primary:${primary}`,
17
+ secondary && `--site-secondary:${secondary}`,
18
+ ].filter(Boolean);
19
+ return decls.length ? `:root{${decls.join(';')}}` : '';
20
+ }
package/package.json CHANGED
@@ -1,6 +1,10 @@
1
1
  {
2
2
  "name": "@curvenote/theme-ui",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/curvenote/curvenote.git"
7
+ },
4
8
  "type": "module",
5
9
  "module": "./dist/index.js",
6
10
  "types": "./dist/index.d.ts",
@@ -26,10 +30,13 @@
26
30
  "prepublishOnly": "bun run build"
27
31
  },
28
32
  "dependencies": {
29
- "@curvenote/bridge-jupyter": "^2.0.1",
30
- "@curvenote/footers": "^2.0.1",
33
+ "@curvenote/bridge-jupyter": "^2.1.0",
34
+ "@curvenote/common": "^0.11.0",
35
+ "@curvenote/footers": "^2.1.0",
31
36
  "@curvenote/icons": "^0.0.4",
32
- "@curvenote/react-utils": "^2.0.1",
37
+ "@curvenote/react-utils": "^2.1.0",
38
+ "@myst-theme/common": "^1.3.0",
39
+ "@myst-theme/providers": "^1.3.0",
33
40
  "@myst-theme/search": "^1.3.0",
34
41
  "@myst-theme/search-minisearch": "^1.3.0",
35
42
  "@radix-ui/react-collapsible": "^1.1.11",
@@ -44,8 +51,14 @@
44
51
  "class-variance-authority": "^0.7.1",
45
52
  "clsx": "^2.1.1",
46
53
  "date-fns": "3.6.0",
54
+ "doi-utils": "^2.0.6",
47
55
  "lodash.merge": "^4.6.2",
48
56
  "lucide-react": "^0.525.0",
57
+ "myst-common": "^1.9.5",
58
+ "myst-config": "^1.9.5",
59
+ "myst-frontmatter": "^1.9.5",
60
+ "myst-spec-ext": "^1.9.5",
61
+ "myst-to-react": "^1.3.0",
49
62
  "next-themes": "^0.4.6",
50
63
  "react": "^19.1.0",
51
64
  "react-day-picker": "8",
@@ -54,6 +67,7 @@
54
67
  "sonner": "^2.0.6",
55
68
  "swr": "^2.2.5",
56
69
  "tailwind-merge": "^3.3.1",
70
+ "thebe-core": "0.5.0",
57
71
  "unist-util-select": "^5.1.0",
58
72
  "unist-util-visit": "^4.1.2"
59
73
  },
@@ -62,6 +76,10 @@
62
76
  "react-dom": "^19.1.0"
63
77
  },
64
78
  "devDependencies": {
79
+ "@curvenote/tsconfig": "workspace:*",
80
+ "@types/react": "19.2.18",
81
+ "@types/react-dom": "19.2.4",
82
+ "unist-builder": "^3.0.0",
65
83
  "vitest": "^4.0.16"
66
84
  },
67
85
  "publishConfig": {