@cueplusplus/ui 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 (372) hide show
  1. package/dist/charts/_token.js +39 -0
  2. package/dist/charts/container.d.ts +58 -0
  3. package/dist/charts/container.js +77 -0
  4. package/dist/charts/index.d.ts +5 -0
  5. package/dist/charts/index.js +5 -0
  6. package/dist/charts/ramps.d.ts +140 -0
  7. package/dist/charts/ramps.js +615 -0
  8. package/dist/charts/theme.d.ts +112 -0
  9. package/dist/charts/theme.js +165 -0
  10. package/dist/charts/tones.d.ts +111 -0
  11. package/dist/charts/tones.js +127 -0
  12. package/dist/chat/_glyphs.js +55 -0
  13. package/dist/chat/agent-color.d.ts +84 -0
  14. package/dist/chat/agent-color.js +101 -0
  15. package/dist/chat/agent-pile.d.ts +55 -0
  16. package/dist/chat/agent-pile.js +121 -0
  17. package/dist/chat/ask-box.d.ts +88 -0
  18. package/dist/chat/ask-box.js +341 -0
  19. package/dist/chat/composer.d.ts +66 -0
  20. package/dist/chat/composer.js +144 -0
  21. package/dist/chat/delegation-card.d.ts +60 -0
  22. package/dist/chat/delegation-card.js +129 -0
  23. package/dist/chat/index.d.ts +8 -0
  24. package/dist/chat/index.js +8 -0
  25. package/dist/chat/message-list.d.ts +39 -0
  26. package/dist/chat/message-list.js +105 -0
  27. package/dist/chat/message.d.ts +47 -0
  28. package/dist/chat/message.js +108 -0
  29. package/dist/chrome/_glyphs.js +101 -0
  30. package/dist/chrome/_tabs-scroll.d.ts +62 -0
  31. package/dist/chrome/_tabs-scroll.js +68 -0
  32. package/dist/chrome/_tree.d.ts +75 -0
  33. package/dist/chrome/_tree.js +49 -0
  34. package/dist/chrome/empty-state.d.ts +37 -0
  35. package/dist/chrome/empty-state.js +57 -0
  36. package/dist/chrome/eyebrow.d.ts +29 -0
  37. package/dist/chrome/eyebrow.js +36 -0
  38. package/dist/chrome/index.d.ts +17 -0
  39. package/dist/chrome/index.js +17 -0
  40. package/dist/chrome/navigation-menu.d.ts +80 -0
  41. package/dist/chrome/navigation-menu.js +121 -0
  42. package/dist/chrome/page-shell.d.ts +38 -0
  43. package/dist/chrome/page-shell.js +66 -0
  44. package/dist/chrome/panel.d.ts +55 -0
  45. package/dist/chrome/panel.js +67 -0
  46. package/dist/chrome/row.d.ts +82 -0
  47. package/dist/chrome/row.js +106 -0
  48. package/dist/chrome/scroll-area.d.ts +39 -0
  49. package/dist/chrome/scroll-area.js +70 -0
  50. package/dist/chrome/section-header.d.ts +42 -0
  51. package/dist/chrome/section-header.js +79 -0
  52. package/dist/chrome/segmented-control.d.ts +58 -0
  53. package/dist/chrome/segmented-control.js +76 -0
  54. package/dist/chrome/status-bar.d.ts +46 -0
  55. package/dist/chrome/status-bar.js +56 -0
  56. package/dist/chrome/tabs.d.ts +80 -0
  57. package/dist/chrome/tabs.js +176 -0
  58. package/dist/chrome/title-bar.d.ts +37 -0
  59. package/dist/chrome/title-bar.js +45 -0
  60. package/dist/chrome/toolbar.d.ts +46 -0
  61. package/dist/chrome/toolbar.js +62 -0
  62. package/dist/chrome/tree.d.ts +98 -0
  63. package/dist/chrome/tree.js +248 -0
  64. package/dist/color/_checker.js +14 -0
  65. package/dist/color/_convert.d.ts +52 -0
  66. package/dist/color/_convert.js +66 -0
  67. package/dist/color/_glyphs.js +28 -0
  68. package/dist/color/_thumb.js +15 -0
  69. package/dist/color/_value.js +28 -0
  70. package/dist/color/color-area.d.ts +27 -0
  71. package/dist/color/color-area.js +40 -0
  72. package/dist/color/color-field.d.ts +32 -0
  73. package/dist/color/color-field.js +43 -0
  74. package/dist/color/color-picker.d.ts +71 -0
  75. package/dist/color/color-picker.js +178 -0
  76. package/dist/color/color-slider.d.ts +31 -0
  77. package/dist/color/color-slider.js +51 -0
  78. package/dist/color/color-swatch.d.ts +32 -0
  79. package/dist/color/color-swatch.js +44 -0
  80. package/dist/color/index.d.ts +7 -0
  81. package/dist/color/index.js +7 -0
  82. package/dist/configurator/_export.d.ts +78 -0
  83. package/dist/configurator/_export.js +261 -0
  84. package/dist/configurator/_glyphs.js +92 -0
  85. package/dist/configurator/_overrides.d.ts +247 -0
  86. package/dist/configurator/_overrides.js +514 -0
  87. package/dist/configurator/configurator.d.ts +71 -0
  88. package/dist/configurator/configurator.js +279 -0
  89. package/dist/configurator/export-dialog.d.ts +30 -0
  90. package/dist/configurator/export-dialog.js +121 -0
  91. package/dist/configurator/index.d.ts +8 -0
  92. package/dist/configurator/index.js +8 -0
  93. package/dist/configurator/panel-sections.d.ts +86 -0
  94. package/dist/configurator/panel-sections.js +316 -0
  95. package/dist/configurator/token-editor.d.ts +74 -0
  96. package/dist/configurator/token-editor.js +149 -0
  97. package/dist/configurator/use-zoom.d.ts +87 -0
  98. package/dist/configurator/use-zoom.js +113 -0
  99. package/dist/date/_glyphs.js +34 -0
  100. package/dist/date/_segments.js +55 -0
  101. package/dist/date/_trigger.js +31 -0
  102. package/dist/date/calendar.d.ts +25 -0
  103. package/dist/date/calendar.js +125 -0
  104. package/dist/date/date-field.d.ts +34 -0
  105. package/dist/date/date-field.js +41 -0
  106. package/dist/date/date-picker.d.ts +69 -0
  107. package/dist/date/date-picker.js +89 -0
  108. package/dist/date/date-range-picker.d.ts +65 -0
  109. package/dist/date/date-range-picker.js +92 -0
  110. package/dist/date/index.d.ts +6 -0
  111. package/dist/date/index.js +6 -0
  112. package/dist/date/time-field.d.ts +29 -0
  113. package/dist/date/time-field.js +36 -0
  114. package/dist/dmx/_ramp.d.ts +77 -0
  115. package/dist/dmx/_ramp.js +169 -0
  116. package/dist/dmx/_readout.js +53 -0
  117. package/dist/dmx/_universe.d.ts +105 -0
  118. package/dist/dmx/_universe.js +112 -0
  119. package/dist/dmx/channel-matrix.d.ts +81 -0
  120. package/dist/dmx/channel-matrix.js +285 -0
  121. package/dist/dmx/dmx-bar.d.ts +50 -0
  122. package/dist/dmx/dmx-bar.js +107 -0
  123. package/dist/dmx/dmx-strip.d.ts +41 -0
  124. package/dist/dmx/dmx-strip.js +196 -0
  125. package/dist/dmx/index.d.ts +7 -0
  126. package/dist/dmx/index.js +7 -0
  127. package/dist/dmx/universe-grid.d.ts +61 -0
  128. package/dist/dmx/universe-grid.js +182 -0
  129. package/dist/flow/_frame.d.ts +52 -0
  130. package/dist/flow/_frame.js +38 -0
  131. package/dist/flow/controls.d.ts +41 -0
  132. package/dist/flow/controls.js +53 -0
  133. package/dist/flow/flow.css +121 -0
  134. package/dist/flow/handles.d.ts +40 -0
  135. package/dist/flow/handles.js +61 -0
  136. package/dist/flow/index.d.ts +7 -0
  137. package/dist/flow/index.js +7 -0
  138. package/dist/flow/node-card.d.ts +71 -0
  139. package/dist/flow/node-card.js +102 -0
  140. package/dist/flow/signal-edge.d.ts +60 -0
  141. package/dist/flow/signal-edge.js +108 -0
  142. package/dist/flow/use-flow-theme.d.ts +69 -0
  143. package/dist/flow/use-flow-theme.js +109 -0
  144. package/dist/forms/_chassis.d.ts +64 -0
  145. package/dist/forms/_chassis.js +59 -0
  146. package/dist/forms/_glyphs.js +143 -0
  147. package/dist/forms/_listbox.js +55 -0
  148. package/dist/forms/autocomplete.d.ts +61 -0
  149. package/dist/forms/autocomplete.js +88 -0
  150. package/dist/forms/button-group.d.ts +47 -0
  151. package/dist/forms/button-group.js +52 -0
  152. package/dist/forms/checkbox.d.ts +51 -0
  153. package/dist/forms/checkbox.js +98 -0
  154. package/dist/forms/combobox.d.ts +73 -0
  155. package/dist/forms/combobox.js +108 -0
  156. package/dist/forms/env-var-input.d.ts +74 -0
  157. package/dist/forms/env-var-input.js +116 -0
  158. package/dist/forms/field.d.ts +89 -0
  159. package/dist/forms/field.js +102 -0
  160. package/dist/forms/file-upload.d.ts +113 -0
  161. package/dist/forms/file-upload.js +232 -0
  162. package/dist/forms/index.d.ts +26 -0
  163. package/dist/forms/index.js +26 -0
  164. package/dist/forms/input-group.d.ts +31 -0
  165. package/dist/forms/input-group.js +54 -0
  166. package/dist/forms/input.d.ts +33 -0
  167. package/dist/forms/input.js +36 -0
  168. package/dist/forms/multi-select.d.ts +62 -0
  169. package/dist/forms/multi-select.js +107 -0
  170. package/dist/forms/number-field.d.ts +38 -0
  171. package/dist/forms/number-field.js +64 -0
  172. package/dist/forms/otp-field.d.ts +54 -0
  173. package/dist/forms/otp-field.js +59 -0
  174. package/dist/forms/password-input.d.ts +46 -0
  175. package/dist/forms/password-input.js +62 -0
  176. package/dist/forms/radio-group.d.ts +50 -0
  177. package/dist/forms/radio-group.js +64 -0
  178. package/dist/forms/rating.d.ts +69 -0
  179. package/dist/forms/rating.js +103 -0
  180. package/dist/forms/scrub-input.d.ts +81 -0
  181. package/dist/forms/scrub-input.js +249 -0
  182. package/dist/forms/search-input.d.ts +54 -0
  183. package/dist/forms/search-input.js +112 -0
  184. package/dist/forms/select.d.ts +75 -0
  185. package/dist/forms/select.js +91 -0
  186. package/dist/forms/slider.d.ts +44 -0
  187. package/dist/forms/slider.js +65 -0
  188. package/dist/forms/switch.d.ts +36 -0
  189. package/dist/forms/switch.js +71 -0
  190. package/dist/forms/tags-input.d.ts +69 -0
  191. package/dist/forms/tags-input.js +148 -0
  192. package/dist/forms/textarea.d.ts +27 -0
  193. package/dist/forms/textarea.js +37 -0
  194. package/dist/forms/toggle-group.d.ts +41 -0
  195. package/dist/forms/toggle-group.js +56 -0
  196. package/dist/forms/toggle.d.ts +41 -0
  197. package/dist/forms/toggle.js +100 -0
  198. package/dist/index.d.ts +112 -0
  199. package/dist/index.js +104 -0
  200. package/dist/instruments/_ansi.js +116 -0
  201. package/dist/instruments/_glyphs.js +90 -0
  202. package/dist/instruments/_motion.js +56 -0
  203. package/dist/instruments/_rem.js +21 -0
  204. package/dist/instruments/app-window-frame.d.ts +48 -0
  205. package/dist/instruments/app-window-frame.js +76 -0
  206. package/dist/instruments/copy-button.d.ts +41 -0
  207. package/dist/instruments/copy-button.js +112 -0
  208. package/dist/instruments/data-table.d.ts +168 -0
  209. package/dist/instruments/data-table.js +212 -0
  210. package/dist/instruments/group-bar.d.ts +63 -0
  211. package/dist/instruments/group-bar.js +122 -0
  212. package/dist/instruments/index.d.ts +13 -0
  213. package/dist/instruments/index.js +13 -0
  214. package/dist/instruments/log-viewer.d.ts +74 -0
  215. package/dist/instruments/log-viewer.js +215 -0
  216. package/dist/instruments/meter.d.ts +77 -0
  217. package/dist/instruments/meter.js +96 -0
  218. package/dist/instruments/progress.d.ts +45 -0
  219. package/dist/instruments/progress.js +61 -0
  220. package/dist/instruments/seam-grid.d.ts +66 -0
  221. package/dist/instruments/seam-grid.js +78 -0
  222. package/dist/instruments/sparkline.d.ts +39 -0
  223. package/dist/instruments/sparkline.js +85 -0
  224. package/dist/instruments/stat.d.ts +35 -0
  225. package/dist/instruments/stat.js +59 -0
  226. package/dist/instruments/table.d.ts +51 -0
  227. package/dist/instruments/table.js +92 -0
  228. package/dist/instruments/terminal-frame.d.ts +89 -0
  229. package/dist/instruments/terminal-frame.js +256 -0
  230. package/dist/instruments/two-step-button.d.ts +47 -0
  231. package/dist/instruments/two-step-button.js +147 -0
  232. package/dist/instruments/usage-chart.d.ts +55 -0
  233. package/dist/instruments/usage-chart.js +235 -0
  234. package/dist/layout/_collapse.js +46 -0
  235. package/dist/layout/_glyphs.js +45 -0
  236. package/dist/layout/accordion.d.ts +52 -0
  237. package/dist/layout/accordion.js +81 -0
  238. package/dist/layout/breadcrumb.d.ts +35 -0
  239. package/dist/layout/breadcrumb.js +67 -0
  240. package/dist/layout/card.d.ts +51 -0
  241. package/dist/layout/card.js +76 -0
  242. package/dist/layout/carousel.d.ts +96 -0
  243. package/dist/layout/carousel.js +211 -0
  244. package/dist/layout/collapsible.d.ts +74 -0
  245. package/dist/layout/collapsible.js +126 -0
  246. package/dist/layout/container.d.ts +27 -0
  247. package/dist/layout/container.js +40 -0
  248. package/dist/layout/description-list.d.ts +24 -0
  249. package/dist/layout/description-list.js +37 -0
  250. package/dist/layout/grid.d.ts +40 -0
  251. package/dist/layout/grid.js +48 -0
  252. package/dist/layout/index.d.ts +15 -0
  253. package/dist/layout/index.js +15 -0
  254. package/dist/layout/item.d.ts +65 -0
  255. package/dist/layout/item.js +100 -0
  256. package/dist/layout/link.d.ts +48 -0
  257. package/dist/layout/link.js +63 -0
  258. package/dist/layout/pagination.d.ts +54 -0
  259. package/dist/layout/pagination.js +121 -0
  260. package/dist/layout/resizable.d.ts +38 -0
  261. package/dist/layout/resizable.js +68 -0
  262. package/dist/layout/sidebar.d.ts +67 -0
  263. package/dist/layout/sidebar.js +129 -0
  264. package/dist/layout/stack.d.ts +46 -0
  265. package/dist/layout/stack.js +62 -0
  266. package/dist/layout/stepper.d.ts +49 -0
  267. package/dist/layout/stepper.js +81 -0
  268. package/dist/layout/timeline.d.ts +43 -0
  269. package/dist/layout/timeline.js +63 -0
  270. package/dist/lib/aria-class.js +24 -0
  271. package/dist/lib/cn.js +18 -0
  272. package/dist/lib/compose.js +38 -0
  273. package/dist/lib/cva.d.ts +18 -0
  274. package/dist/lib/cva.js +65 -0
  275. package/dist/midi/_notes.d.ts +101 -0
  276. package/dist/midi/_notes.js +183 -0
  277. package/dist/midi/_ruler.d.ts +100 -0
  278. package/dist/midi/_ruler.js +105 -0
  279. package/dist/midi/_time.d.ts +107 -0
  280. package/dist/midi/_time.js +130 -0
  281. package/dist/midi/index.d.ts +9 -0
  282. package/dist/midi/index.js +9 -0
  283. package/dist/midi/musical-time-input.d.ts +48 -0
  284. package/dist/midi/musical-time-input.js +154 -0
  285. package/dist/midi/piano-keyboard.d.ts +50 -0
  286. package/dist/midi/piano-keyboard.js +193 -0
  287. package/dist/midi/spectrum-visualizer.d.ts +65 -0
  288. package/dist/midi/spectrum-visualizer.js +213 -0
  289. package/dist/midi/threshold-rail.d.ts +72 -0
  290. package/dist/midi/threshold-rail.js +214 -0
  291. package/dist/midi/timeline-ruler.d.ts +83 -0
  292. package/dist/midi/timeline-ruler.js +152 -0
  293. package/dist/overlays/_debounce.js +34 -0
  294. package/dist/overlays/_glyphs.js +59 -0
  295. package/dist/overlays/_surface.d.ts +70 -0
  296. package/dist/overlays/_surface.js +70 -0
  297. package/dist/overlays/_wheel.js +42 -0
  298. package/dist/overlays/alert-dialog.d.ts +67 -0
  299. package/dist/overlays/alert-dialog.js +117 -0
  300. package/dist/overlays/command-palette.d.ts +93 -0
  301. package/dist/overlays/command-palette.js +193 -0
  302. package/dist/overlays/context-menu.d.ts +64 -0
  303. package/dist/overlays/context-menu.js +78 -0
  304. package/dist/overlays/dialog.d.ts +72 -0
  305. package/dist/overlays/dialog.js +124 -0
  306. package/dist/overlays/drawer.d.ts +75 -0
  307. package/dist/overlays/drawer.js +151 -0
  308. package/dist/overlays/dropdown-menu.d.ts +79 -0
  309. package/dist/overlays/dropdown-menu.js +156 -0
  310. package/dist/overlays/hover-card.d.ts +58 -0
  311. package/dist/overlays/hover-card.js +91 -0
  312. package/dist/overlays/index.d.ts +15 -0
  313. package/dist/overlays/index.js +15 -0
  314. package/dist/overlays/info-tip.d.ts +41 -0
  315. package/dist/overlays/info-tip.js +45 -0
  316. package/dist/overlays/menubar.d.ts +72 -0
  317. package/dist/overlays/menubar.js +100 -0
  318. package/dist/overlays/popover.d.ts +66 -0
  319. package/dist/overlays/popover.js +114 -0
  320. package/dist/overlays/sheet.d.ts +78 -0
  321. package/dist/overlays/sheet.js +131 -0
  322. package/dist/overlays/toast.d.ts +106 -0
  323. package/dist/overlays/toast.js +146 -0
  324. package/dist/overlays/tooltip.d.ts +57 -0
  325. package/dist/overlays/tooltip.js +95 -0
  326. package/dist/primitives/avatar.d.ts +51 -0
  327. package/dist/primitives/avatar.js +93 -0
  328. package/dist/primitives/button.d.ts +46 -0
  329. package/dist/primitives/button.js +94 -0
  330. package/dist/primitives/chip.d.ts +47 -0
  331. package/dist/primitives/chip.js +152 -0
  332. package/dist/primitives/icon-button.d.ts +41 -0
  333. package/dist/primitives/icon-button.js +59 -0
  334. package/dist/primitives/index.d.ts +10 -0
  335. package/dist/primitives/index.js +10 -0
  336. package/dist/primitives/kbd.d.ts +17 -0
  337. package/dist/primitives/kbd.js +24 -0
  338. package/dist/primitives/separator.d.ts +25 -0
  339. package/dist/primitives/separator.js +30 -0
  340. package/dist/primitives/skeleton.d.ts +20 -0
  341. package/dist/primitives/skeleton.js +27 -0
  342. package/dist/primitives/spinner.d.ts +26 -0
  343. package/dist/primitives/spinner.js +31 -0
  344. package/dist/primitives/status-dot.d.ts +44 -0
  345. package/dist/primitives/status-dot.js +50 -0
  346. package/dist/styles.css +19 -0
  347. package/dist/system/density.d.ts +33 -0
  348. package/dist/system/density.js +49 -0
  349. package/dist/system/index.d.ts +8 -0
  350. package/dist/system/index.js +7 -0
  351. package/dist/system/portal.d.ts +51 -0
  352. package/dist/system/portal.js +122 -0
  353. package/dist/system/prepaint.d.ts +38 -0
  354. package/dist/system/prepaint.js +37 -0
  355. package/dist/system/theme-provider.d.ts +72 -0
  356. package/dist/system/theme-provider.js +252 -0
  357. package/dist/system/use-density.d.ts +33 -0
  358. package/dist/system/use-density.js +84 -0
  359. package/dist/system/use-isomorphic-layout-effect.js +15 -0
  360. package/dist/system/use-theme.d.ts +19 -0
  361. package/dist/system/use-theme.js +25 -0
  362. package/dist/theming/_presets.d.ts +11 -0
  363. package/dist/theming/_presets.js +487 -0
  364. package/dist/theming/contrast.d.ts +110 -0
  365. package/dist/theming/contrast.js +167 -0
  366. package/dist/theming/create-theme.d.ts +165 -0
  367. package/dist/theming/create-theme.js +442 -0
  368. package/dist/theming/index.d.ts +5 -0
  369. package/dist/theming/index.js +5 -0
  370. package/dist/theming/serialize.d.ts +145 -0
  371. package/dist/theming/serialize.js +165 -0
  372. package/package.json +216 -0
@@ -0,0 +1,167 @@
1
+ import { converter, parse } from "culori";
2
+ //#region src/theming/contrast.ts
3
+ /**
4
+ * WCAG contrast, and the eight pairs a theme is judged on.
5
+ *
6
+ * A generator that only derived colours would be a colour toy: the reason to
7
+ * compute a palette instead of picking one is that the computer can then *check*
8
+ * it, on every build, against the one part of visual design that is not a matter
9
+ * of taste. So `createTheme()` never hands back a theme without a report, and
10
+ * the report is the deliverable — a failing pair is information, not an error to
11
+ * swallow.
12
+ *
13
+ * The maths is WCAG 2.x relative luminance (sRGB, linearised, 0.2126/0.7152/
14
+ * 0.0722), deliberately not APCA. APCA is better, and it is also not what
15
+ * anyone's compliance checklist says; a theme that has to survive an audit needs
16
+ * the number the audit will compute.
17
+ */
18
+ const toRgb = converter("rgb");
19
+ /** Non-text and large-text AA: UI components, graphics, status dots. */
20
+ const WCAG_AA_NON_TEXT = 3;
21
+ /** Body-text AA. The floor for anything a reader is expected to read. */
22
+ const WCAG_AA_TEXT = 4.5;
23
+ /** Body-text AAA. What this portfolio holds its primary ink to. */
24
+ const WCAG_AAA_TEXT = 7;
25
+ /** sRGB gamma decode, per WCAG's definition of relative luminance. */
26
+ function linearize(channel) {
27
+ return channel <= .04045 ? channel / 12.92 : ((channel + .055) / 1.055) ** 2.4;
28
+ }
29
+ /** Parse to sRGB, or say which value could not be read. */
30
+ function toSrgb(input, label = "colour") {
31
+ const color = toRgb(parse(input));
32
+ if (color === void 0) throw new TypeError(`${label} is not a colour this can measure: ${JSON.stringify(input)}`);
33
+ return color;
34
+ }
35
+ /** Source-over composite of `over` onto `under`, in (non-linear) sRGB. */
36
+ function composite(over, under) {
37
+ const alpha = over.alpha ?? 1;
38
+ if (alpha >= 1) return over;
39
+ return {
40
+ r: over.r * alpha + under.r * (1 - alpha),
41
+ g: over.g * alpha + under.g * (1 - alpha),
42
+ b: over.b * alpha + under.b * (1 - alpha)
43
+ };
44
+ }
45
+ function luminanceOf(color) {
46
+ return .2126 * linearize(color.r) + .7152 * linearize(color.g) + .0722 * linearize(color.b);
47
+ }
48
+ /**
49
+ * WCAG relative luminance: 0 for black, 1 for white.
50
+ *
51
+ * Alpha is ignored — a translucent colour has no luminance of its own, only one
52
+ * in front of something. {@link contrastRatio} is where that composite happens.
53
+ *
54
+ * @param color - Any CSS colour string.
55
+ * @returns Relative luminance in `[0, 1]`.
56
+ * @throws TypeError if the value is not a colour.
57
+ * @example
58
+ * relativeLuminance("#767676"); // → 0.1845…
59
+ */
60
+ function relativeLuminance(color) {
61
+ return luminanceOf(toSrgb(color));
62
+ }
63
+ /**
64
+ * WCAG contrast ratio between two colours, from 1:1 to 21:1.
65
+ *
66
+ * Symmetric, because a ratio has no direction — the arguments are named for
67
+ * readability, not for order. A **translucent foreground is composited over the
68
+ * background first**, which is not decoration: half this system's `fg-muted`
69
+ * tokens are white-alpha ink, and measuring them raw would report the ratio of
70
+ * pure white and pass everything.
71
+ *
72
+ * @param foreground - The ink. Composited over `background` if it has alpha.
73
+ * @param background - The ground. Its own alpha is ignored — nothing is behind it.
74
+ * @returns The ratio, `>= 1`.
75
+ * @throws TypeError naming whichever value could not be read.
76
+ * @example
77
+ * contrastRatio("#767676", "#ffffff"); // → 4.5422…
78
+ */
79
+ function contrastRatio(foreground, background) {
80
+ const ground = toSrgb(background, "background");
81
+ const [high, low] = [luminanceOf(composite(toSrgb(foreground, "foreground"), ground)), luminanceOf(ground)].toSorted((a, b) => b - a);
82
+ return (high + .05) / (low + .05);
83
+ }
84
+ /**
85
+ * The eight pairs that decide whether a theme is usable.
86
+ *
87
+ * Not every pair in the palette: the ones a reader's comprehension actually
88
+ * depends on. Primary ink is held to AAA because it carries the prose; secondary
89
+ * ink and accent ink to AA because they carry labels; the five status colours to
90
+ * the non-text AA floor because they are read as *signals* — a dot, a rim, a bar
91
+ * — never as body copy.
92
+ */
93
+ const CONTRAST_REQUIREMENTS = [
94
+ {
95
+ id: "fg/bg",
96
+ foreground: "fg",
97
+ background: "bg",
98
+ minimum: 7,
99
+ reason: "Primary ink carries the prose, and this portfolio holds it to AAA."
100
+ },
101
+ {
102
+ id: "fg-muted/bg",
103
+ foreground: "fg-muted",
104
+ background: "bg",
105
+ minimum: WCAG_AA_TEXT,
106
+ reason: "Secondary ink is still text: labels, captions, table headers."
107
+ },
108
+ {
109
+ id: "accent-fg/accent",
110
+ foreground: "accent-fg",
111
+ background: "accent",
112
+ minimum: WCAG_AA_TEXT,
113
+ reason: "The label on a solid accent button has to be readable."
114
+ },
115
+ ...[
116
+ "ok",
117
+ "busy",
118
+ "warn",
119
+ "danger",
120
+ "info"
121
+ ].map((status) => ({
122
+ id: `${status}/bg`,
123
+ foreground: status,
124
+ background: "bg",
125
+ minimum: 3,
126
+ reason: `The ${status} tone is read as a signal — dot, rim, bar — not as body copy.`
127
+ }))
128
+ ];
129
+ /**
130
+ * Measure every requirement against every block handed in.
131
+ *
132
+ * A pair whose tokens are missing is **skipped**, not failed: the report says
133
+ * what it measured, and a caller checking a partial palette should not be told
134
+ * that a colour it never supplied is unreadable.
135
+ *
136
+ * @param inputs - One entry per block, dark first by convention.
137
+ * @returns The report.
138
+ * @example
139
+ * contrastReport([{ mode: "dark", tokens: { fg: "#fff", bg: "#000" } }]).passes; // → true
140
+ */
141
+ function contrastReport(inputs) {
142
+ const checks = [];
143
+ for (const { mode, tokens, provisional = false } of inputs) for (const requirement of CONTRAST_REQUIREMENTS) {
144
+ const foregroundValue = tokens[requirement.foreground];
145
+ const backgroundValue = tokens[requirement.background];
146
+ if (foregroundValue === void 0 || backgroundValue === void 0) continue;
147
+ const ratio = contrastRatio(foregroundValue, backgroundValue);
148
+ checks.push({
149
+ ...requirement,
150
+ mode,
151
+ foregroundValue,
152
+ backgroundValue,
153
+ ratio,
154
+ passes: ratio >= requirement.minimum,
155
+ provisional
156
+ });
157
+ }
158
+ const failures = checks.filter((check) => !check.passes);
159
+ return {
160
+ passes: failures.length === 0,
161
+ provisional: checks.some((check) => check.provisional),
162
+ checks,
163
+ failures
164
+ };
165
+ }
166
+ //#endregion
167
+ export { CONTRAST_REQUIREMENTS, WCAG_AAA_TEXT, WCAG_AA_NON_TEXT, WCAG_AA_TEXT, contrastRatio, contrastReport, relativeLuminance };
@@ -0,0 +1,165 @@
1
+ import { ContrastReport } from "./contrast.js";
2
+ import { THEME_COLOR_TOKENS, ThemeColorToken } from "./_presets.js";
3
+ import { ThemeName } from "@cueplusplus/tokens";
4
+ //#region src/theming/create-theme.d.ts
5
+ /**
6
+ * `createTheme()` — the typed generator behind the spec's second theming tier.
7
+ *
8
+ * Three things it is not, because each of them is a trap this deliberately
9
+ * avoids:
10
+ *
11
+ * - **Not a runtime engine.** It is a pure function of its arguments, called at
12
+ * build time (or once, in the configurator's export dialog), and what comes
13
+ * out is a plain `[data-theme]` stylesheet — tier 1, the guaranteed contract.
14
+ * Nothing about a shipped app depends on this module existing.
15
+ * - **Not a palette generator.** Handed a preset and nothing else it returns the
16
+ * preset, byte for byte. Derivation is what happens to the tokens hanging off
17
+ * an anchor you actually moved, and only those: swap the accent and the hover,
18
+ * the ink on it, the focus ring and the selection wash follow; the ground, the
19
+ * ink and the five status tones do not. That rule is the whole reason
20
+ * "start from `terminal`, make it orange" is a two-line call rather than a
21
+ * fork of a palette.
22
+ * - **Not a colour opinion.** Every derivation happens in oklch, where a
23
+ * lightness step is a step the eye agrees with, and every result is measured
24
+ * against WCAG before you are told it is fine. A failing pair comes back in
25
+ * the report rather than being silently repaired — with one exception, noted
26
+ * below, where the value was this module's invention in the first place.
27
+ */
28
+ /** The preset a theme starts from when the caller names none. */
29
+ declare const DEFAULT_THEME_BASE: ThemeName;
30
+ /**
31
+ * How far the sunken ground sits below the page, in oklch lightness.
32
+ *
33
+ * Small on purpose: sunken is a well, not a second theme. Across the eight
34
+ * shipped presets the authored gap runs −0.011 to −0.031.
35
+ */
36
+ declare const SUNKEN_LIGHTNESS_STEP = -0.02;
37
+ /**
38
+ * The three raised surfaces, as lightness above the ground.
39
+ *
40
+ * Even spacing, because the ladder encodes *elevation* and a reader counts
41
+ * rungs. The shipped presets cluster around these three values.
42
+ */
43
+ declare const SURFACE_LIGHTNESS_STEPS: readonly number[];
44
+ /**
45
+ * The hairline and its stronger sibling, as lightness above the ground.
46
+ *
47
+ * Above the top surface, so a border still reads as a line when it is drawn on
48
+ * `surface-3`. `border-overlay` reuses the strong value: an overlay floats over
49
+ * everything, so its rim has to hold against the brightest thing under it.
50
+ */
51
+ declare const BORDER_LIGHTNESS_STEPS: readonly number[];
52
+ /** How far secondary ink recedes from primary ink. */
53
+ declare const FG_MUTED_LIGHTNESS_STEP = -0.25;
54
+ /** How far tertiary ink recedes from primary ink. */
55
+ declare const FG_SUBTLE_LIGHTNESS_STEP = -0.45;
56
+ /**
57
+ * Chroma each rung of the ink ramp keeps from the rung above.
58
+ *
59
+ * Ink greys as it recedes rather than staying saturated: a muted label that held
60
+ * full chroma would read as a *coloured* label — a status, a link — instead of a
61
+ * quiet one. The hue is preserved throughout, so the ramp still belongs to the
62
+ * theme. `fg-subtle` takes the square, being two rungs down.
63
+ */
64
+ declare const INK_RAMP_CHROMA_SCALE = 0.6;
65
+ /** How far the accent darkens on hover. */
66
+ declare const ACCENT_HOVER_LIGHTNESS_STEP = -0.05;
67
+ /** How much accent a derived selection wash carries. */
68
+ declare const SELECTION_ACCENT_PERCENT = 22;
69
+ /** What a label on a solid accent has to reach before this module accepts it. */
70
+ declare const ACCENT_FG_MINIMUM = 4.5;
71
+ /**
72
+ * How much of the dark ground's lightness survives the flip to paper.
73
+ *
74
+ * A ground's job is to be the extreme, so inverting it means going to the *other*
75
+ * extreme rather than to the arithmetic mirror: `1 − L` of a 0.16 near-black is a
76
+ * 0.84 mid-grey, which is not a page. Compressing instead maps the ladder of
77
+ * dark grounds onto a narrow paper band — a deeper dark theme gets a cleaner
78
+ * white page — and lands within 0.01 of all eight authored light presets.
79
+ */
80
+ declare const LIGHT_GROUND_COMPRESSION = 0.1;
81
+ interface ThemeAnchors {
82
+ /**
83
+ * The theme's name. Lands in `[data-theme="…"]`, so it must be a CSS
84
+ * identifier: letters, digits and dashes, starting with a letter.
85
+ */
86
+ name: string;
87
+ /**
88
+ * The preset to start from. Every token you do not move comes back verbatim.
89
+ * Defaults to {@link DEFAULT_THEME_BASE}.
90
+ */
91
+ base?: ThemeName;
92
+ /**
93
+ * The ground. Moving it re-derives the sunken well, the three raised surfaces
94
+ * and the three border weights.
95
+ */
96
+ bg?: string;
97
+ /** Primary ink. Moving it re-derives `fg-muted` and `fg-subtle`. */
98
+ fg?: string;
99
+ /**
100
+ * The accent. Moving it re-derives `accent-hover`, `accent-fg`, `focus` and
101
+ * `selection`.
102
+ */
103
+ accent?: string;
104
+ /** Individual rungs of the surface ladder, overriding whatever would be derived. */
105
+ surfaces?: Partial<Record<"sunken" | "surface-1" | "surface-2" | "surface-3", string>>;
106
+ /** Individual status tones. Never derived — a signal colour is a decision. */
107
+ status?: Partial<Record<"ok" | "busy" | "warn" | "danger" | "info", string>>;
108
+ /**
109
+ * Font stacks. `mono` is the one the presets themselves override; `sans` and
110
+ * `display` are emitted only when given. Values pass through verbatim, so they
111
+ * are checked for CSS punctuation rather than parsed.
112
+ */
113
+ fonts?: Partial<{
114
+ sans: string;
115
+ mono: string;
116
+ display: string;
117
+ }>;
118
+ /**
119
+ * Multiplier on every corner radius. Crossed with the density ladder rather
120
+ * than declared flat, so `ultra-compact` keeps its tighter corners.
121
+ */
122
+ radiusScale?: number;
123
+ /**
124
+ * Whether to emit a light block. Defaults to whether the base preset has one.
125
+ * Setting it `true` on a dark-only preset derives one, and marks the report
126
+ * provisional.
127
+ */
128
+ supportsLight?: boolean;
129
+ }
130
+ interface CreatedTheme {
131
+ /** The name that was asked for, once validated. */
132
+ name: string;
133
+ /**
134
+ * The stylesheet: the dark block, the light block if there is one, and one
135
+ * crossed density rule per radius scale that differs from the default's.
136
+ */
137
+ css: string;
138
+ /**
139
+ * The dark block as a map, keyed by the exact `--cue-*` property names the
140
+ * tokens build emits. Says the same thing as the dark block of {@link css}.
141
+ */
142
+ tokens: Record<string, string>;
143
+ /** The light block as a map, or `null` when the theme is dark-only. */
144
+ light: Record<string, string> | null;
145
+ /** Every WCAG pair, measured. Read it — a failing theme still returns. */
146
+ report: ContrastReport;
147
+ }
148
+ /**
149
+ * Generate a theme: a stylesheet, its token map, and a contrast report.
150
+ *
151
+ * Pure and synchronous. Call it in a build script, in a test, or in the
152
+ * configurator's export dialog — never in a render path, because there is
153
+ * nothing here a stylesheet is not already doing faster.
154
+ *
155
+ * @param anchors - The name, the preset to start from, and whatever you moved.
156
+ * @returns The stylesheet, the resolved tokens for both modes, and the report.
157
+ * @throws TypeError if the name is not a CSS identifier, an anchor is not a
158
+ * colour, a font stack carries CSS punctuation, or the base preset is unknown.
159
+ * @example
160
+ * const { css, report } = createTheme({ name: "acme", base: "terminal", accent: "#ff8800" });
161
+ * if (!report.passes) console.warn(report.failures);
162
+ */
163
+ declare function createTheme(anchors: ThemeAnchors): CreatedTheme;
164
+ //#endregion
165
+ export { ACCENT_FG_MINIMUM, ACCENT_HOVER_LIGHTNESS_STEP, BORDER_LIGHTNESS_STEPS, CreatedTheme, DEFAULT_THEME_BASE, FG_MUTED_LIGHTNESS_STEP, FG_SUBTLE_LIGHTNESS_STEP, INK_RAMP_CHROMA_SCALE, LIGHT_GROUND_COMPRESSION, SELECTION_ACCENT_PERCENT, SUNKEN_LIGHTNESS_STEP, SURFACE_LIGHTNESS_STEPS, THEME_COLOR_TOKENS, ThemeAnchors, type ThemeColorToken, createTheme };