@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,45 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import * as React from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/chrome/title-bar.tsx
6
+ /** `app-region` needs the unprefixed and the WebKit form to cover both shells. */
7
+ const DRAG_CLASSES = "[app-region:drag] [-webkit-app-region:drag]";
8
+ const NO_DRAG_CLASSES = "[app-region:no-drag] [-webkit-app-region:no-drag]";
9
+ /**
10
+ * The window's own bar: app mark left, document name centred, controls right.
11
+ *
12
+ * @example
13
+ * <TitleBar platformDrag center="untitled.cue" actions={<WindowControls />}>
14
+ * <Eyebrow>CUE++</Eyebrow>
15
+ * </TitleBar>
16
+ */
17
+ const TitleBar = React.forwardRef(function TitleBar({ className, platformDrag = false, center, actions, children, ...elementProps }, ref) {
18
+ const clusterClasses = cn("flex min-w-0 items-center gap-(--cue-space-2)", platformDrag ? NO_DRAG_CLASSES : void 0);
19
+ return /* @__PURE__ */ jsxs("div", {
20
+ ref,
21
+ "data-slot": "title-bar",
22
+ "data-tauri-drag-region": platformDrag ? "" : void 0,
23
+ className: cn("relative flex h-(--cue-chrome-titlebar) w-full shrink-0 items-center justify-between gap-(--cue-space-3) border-b border-border bg-surface-1 px-(--cue-pad-row-x) select-none", platformDrag ? DRAG_CLASSES : void 0, className),
24
+ ...elementProps,
25
+ children: [
26
+ /* @__PURE__ */ jsx("div", {
27
+ "data-slot": "title-bar-leading",
28
+ className: clusterClasses,
29
+ children
30
+ }),
31
+ center === void 0 ? null : /* @__PURE__ */ jsx("div", {
32
+ "data-slot": "title-bar-center",
33
+ className: "pointer-events-none absolute left-1/2 flex -translate-x-1/2 items-center gap-(--cue-space-2) font-mono text-(length:--cue-text-label) text-fg-muted",
34
+ children: center
35
+ }),
36
+ actions === void 0 ? null : /* @__PURE__ */ jsx("div", {
37
+ "data-slot": "title-bar-actions",
38
+ className: cn(clusterClasses, "shrink-0"),
39
+ children: actions
40
+ })
41
+ ]
42
+ });
43
+ });
44
+ //#endregion
45
+ export { TitleBar };
@@ -0,0 +1,46 @@
1
+ import * as React from "react";
2
+ import { Toolbar } from "@base-ui/react/toolbar";
3
+ //#region src/chrome/toolbar.d.ts
4
+ interface ToolbarRootProps extends Omit<Toolbar.Root.Props, "className"> {
5
+ /** Extra classes for the bar. */
6
+ className?: string;
7
+ }
8
+ interface ToolbarButtonProps extends Omit<Toolbar.Button.Props, "className"> {
9
+ /** Extra classes for the button. */
10
+ className?: string;
11
+ /** Optional leading icon (e.g. a lucide icon), drawn `aria-hidden`. */
12
+ icon?: React.ElementType;
13
+ }
14
+ interface ToolbarGroupProps extends Omit<Toolbar.Group.Props, "className"> {
15
+ /** Extra classes for the group. */
16
+ className?: string;
17
+ }
18
+ interface ToolbarSeparatorProps extends Omit<Toolbar.Separator.Props, "className"> {
19
+ /** Extra classes for the rule. */
20
+ className?: string;
21
+ }
22
+ /**
23
+ * The strip of controls across the top of a view.
24
+ *
25
+ * Wraps Base UI's `Toolbar`, so the whole bar is one tab stop with arrow-key
26
+ * roving focus inside it — which is the entire point of the ARIA toolbar
27
+ * pattern and the reason not to hand-roll this out of a flex row of buttons.
28
+ *
29
+ * @example
30
+ * <Toolbar.Root aria-label="Cue actions">
31
+ * <Toolbar.Group aria-label="Playback">
32
+ * <Toolbar.Button icon={Play}>Go</Toolbar.Button>
33
+ * <Toolbar.Button icon={Square}>Stop</Toolbar.Button>
34
+ * </Toolbar.Group>
35
+ * <Toolbar.Separator />
36
+ * <Toolbar.Button icon={Save}>Save</Toolbar.Button>
37
+ * </Toolbar.Root>
38
+ */
39
+ declare const Toolbar$1: {
40
+ Root: React.ForwardRefExoticComponent<Omit<ToolbarRootProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
41
+ Button: React.ForwardRefExoticComponent<Omit<ToolbarButtonProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
42
+ Group: React.ForwardRefExoticComponent<Omit<ToolbarGroupProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
43
+ Separator: React.ForwardRefExoticComponent<Omit<ToolbarSeparatorProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
44
+ };
45
+ //#endregion
46
+ export { Toolbar$1 as Toolbar, ToolbarButtonProps, ToolbarGroupProps, ToolbarRootProps, ToolbarSeparatorProps };
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import * as React from "react";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { Toolbar } from "@base-ui/react/toolbar";
6
+ /**
7
+ * The strip of controls across the top of a view.
8
+ *
9
+ * Wraps Base UI's `Toolbar`, so the whole bar is one tab stop with arrow-key
10
+ * roving focus inside it — which is the entire point of the ARIA toolbar
11
+ * pattern and the reason not to hand-roll this out of a flex row of buttons.
12
+ *
13
+ * @example
14
+ * <Toolbar.Root aria-label="Cue actions">
15
+ * <Toolbar.Group aria-label="Playback">
16
+ * <Toolbar.Button icon={Play}>Go</Toolbar.Button>
17
+ * <Toolbar.Button icon={Square}>Stop</Toolbar.Button>
18
+ * </Toolbar.Group>
19
+ * <Toolbar.Separator />
20
+ * <Toolbar.Button icon={Save}>Save</Toolbar.Button>
21
+ * </Toolbar.Root>
22
+ */
23
+ const Toolbar$1 = {
24
+ Root: React.forwardRef(function ToolbarRoot({ className, ...elementProps }, ref) {
25
+ return /* @__PURE__ */ jsx(Toolbar.Root, {
26
+ ref,
27
+ "data-slot": "toolbar",
28
+ className: cn("flex h-(--cue-chrome-toolbar) w-full shrink-0 items-center gap-(--cue-space-2) border-b border-border bg-surface-1 px-(--cue-pad-row-x) data-[orientation=vertical]:h-auto data-[orientation=vertical]:w-(--cue-chrome-toolbar) data-[orientation=vertical]:flex-col data-[orientation=vertical]:border-r data-[orientation=vertical]:border-b-0", className),
29
+ ...elementProps
30
+ });
31
+ }),
32
+ Button: React.forwardRef(function ToolbarButton({ className, icon: Icon, children, ...elementProps }, ref) {
33
+ return /* @__PURE__ */ jsxs(Toolbar.Button, {
34
+ ref,
35
+ "data-slot": "toolbar-button",
36
+ className: cn("inline-flex h-control-md shrink-0 cursor-pointer items-center justify-center gap-(--cue-space-2) rounded-(--radius-control) px-(--cue-space-3) font-mono text-(length:--cue-text-ui) whitespace-nowrap text-fg-muted transition-colors duration-150 outline-none select-none hover:bg-surface-2 hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-1 focus-visible:outline-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-40", className),
37
+ ...elementProps,
38
+ children: [Icon === void 0 ? null : /* @__PURE__ */ jsx(Icon, {
39
+ "aria-hidden": "true",
40
+ className: "size-icon-md shrink-0"
41
+ }), children]
42
+ });
43
+ }),
44
+ Group: React.forwardRef(function ToolbarGroup({ className, ...elementProps }, ref) {
45
+ return /* @__PURE__ */ jsx(Toolbar.Group, {
46
+ ref,
47
+ "data-slot": "toolbar-group",
48
+ className: cn("inline-flex items-center gap-(--cue-space-1)", className),
49
+ ...elementProps
50
+ });
51
+ }),
52
+ Separator: React.forwardRef(function ToolbarSeparator({ className, ...elementProps }, ref) {
53
+ return /* @__PURE__ */ jsx(Toolbar.Separator, {
54
+ ref,
55
+ "data-slot": "toolbar-separator",
56
+ className: cn("shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:mx-(--cue-space-1) data-[orientation=vertical]:h-[60%] data-[orientation=vertical]:w-px", className),
57
+ ...elementProps
58
+ });
59
+ })
60
+ };
61
+ //#endregion
62
+ export { Toolbar$1 as Toolbar };
@@ -0,0 +1,98 @@
1
+ import { TreeItem, TreeRow } from "./_tree.js";
2
+ import * as React from "react";
3
+ //#region src/chrome/tree.d.ts
4
+ interface TreeProps extends Omit<React.ComponentPropsWithoutRef<"div">, "onSelect"> {
5
+ /** The roots, in display order. */
6
+ items: readonly TreeItem[];
7
+ /** Expanded ids when controlled. Pass with `onExpandedChange`. */
8
+ expanded?: readonly string[];
9
+ /** Initially expanded ids when uncontrolled. */
10
+ defaultExpanded?: readonly string[];
11
+ /** Called with the whole next expanded set whenever a row is folded or unfolded. */
12
+ onExpandedChange?: (expanded: string[]) => void;
13
+ /** Selected id when controlled. Pass with `onSelect`. */
14
+ selected?: string | null;
15
+ /** Initially selected id when uncontrolled. */
16
+ defaultSelected?: string | null;
17
+ /** Called with the id of the row the user selected. */
18
+ onSelect?: (id: string) => void;
19
+ /**
20
+ * Replace the *body* of a row — the icon, label and badge.
21
+ *
22
+ * The row element itself, its ARIA, its tab index and its indent gutter stay
23
+ * with the component on purpose: those are the parts a call site cannot get
24
+ * wrong without breaking keyboard navigation for everyone.
25
+ */
26
+ renderRow?: (row: TreeRow) => React.ReactNode;
27
+ /**
28
+ * Controls hung off the right of each row, revealed on hover or focus.
29
+ *
30
+ * This is where the three-state visibility idiom goes — see
31
+ * {@link TreeVisibilityToggle} — along with focus, rename and delete
32
+ * affordances. Anything essential belongs in the row body or a context menu
33
+ * instead: hover-revealed controls are invisible on touch.
34
+ */
35
+ rowControls?: (item: TreeItem, row: TreeRow) => React.ReactNode;
36
+ /** Draw the box-drawing indent gutter. Defaults to `true`. */
37
+ guides?: boolean;
38
+ /** Accessible name for the tree. Required in practice — name what it lists. */
39
+ "aria-label"?: string;
40
+ }
41
+ /**
42
+ * A hierarchical outline: a rig, a scene graph, a folder of shows.
43
+ *
44
+ * Hand-built rather than wrapped, because the pattern's whole cost is in three
45
+ * details no primitive here provides together:
46
+ *
47
+ * - **Roving tabindex.** The tree is one tab stop; the arrow keys move inside
48
+ * it. Eighty rows must never mean eighty presses of Tab.
49
+ * - **A flat DOM.** Rows carry `aria-level` / `aria-posinset` / `aria-setsize`
50
+ * instead of nesting `role="group"` wrappers, which is both valid ARIA and the
51
+ * shape a virtualizer needs when the outline grows past a screenful.
52
+ * - **The gutter.** `└ ├ │` in the mono grid, `aria-hidden` — structure you can
53
+ * see at a glance without indentation alone having to carry it.
54
+ *
55
+ * Selection is a tint (`accent-soft` ground, accent ink), never a solid fill —
56
+ * the same ruling as the sidebar item and the active tab.
57
+ *
58
+ * @example
59
+ * <Tree
60
+ * aria-label="Rig"
61
+ * items={rig}
62
+ * selected={selected}
63
+ * onSelect={setSelected}
64
+ * rowControls={(item) => (
65
+ * <TreeVisibilityToggle value={visibility[item.id]} onValueChange={set(item.id)} />
66
+ * )}
67
+ * />
68
+ */
69
+ declare const Tree: React.ForwardRefExoticComponent<TreeProps & React.RefAttributes<HTMLDivElement>>;
70
+ /** The three states a node can be drawn in. */
71
+ type TreeVisibility = "visible" | "ghost" | "hidden";
72
+ interface TreeVisibilityToggleProps extends Omit<React.ComponentPropsWithoutRef<"button">, "value" | "onChange" | "children"> {
73
+ /** The node's current visibility. */
74
+ value: TreeVisibility;
75
+ /** Called with the next state in the cycle. */
76
+ onValueChange: (value: TreeVisibility) => void;
77
+ /** Override the state names used in the accessible label. */
78
+ labels?: Partial<Record<TreeVisibility, string>>;
79
+ }
80
+ /**
81
+ * The outliner's three-state visibility control: shown → ghosted → hidden.
82
+ *
83
+ * Three states rather than a checkbox because a rig has three answers, not two:
84
+ * *there*, *there but out of the way*, and *not drawn*. Ghost is the one that
85
+ * earns the extra state — it is how you keep a truss as spatial reference while
86
+ * working behind it — and collapsing it into "hidden" is what makes people
87
+ * toggle things off and lose their bearings.
88
+ *
89
+ * Meant for {@link TreeProps.rowControls}. The accessible name states the
90
+ * *current* state ("Visibility: ghosted") rather than the next action, because
91
+ * with three states "toggle" names nothing useful; pressing cycles.
92
+ *
93
+ * @example
94
+ * <TreeVisibilityToggle value={state} onValueChange={setState} />
95
+ */
96
+ declare const TreeVisibilityToggle: React.ForwardRefExoticComponent<TreeVisibilityToggleProps & React.RefAttributes<HTMLButtonElement>>;
97
+ //#endregion
98
+ export { Tree, TreeProps, TreeVisibility, TreeVisibilityToggle, TreeVisibilityToggleProps };
@@ -0,0 +1,248 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { TREE_GUIDE_GLYPHS, flattenTree } from "./_tree.js";
4
+ import { ChevronRightGlyph, EyeGlyph, EyeOffGlyph, GhostGlyph } from "./_glyphs.js";
5
+ import * as React from "react";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/chrome/tree.tsx
8
+ /**
9
+ * A hierarchical outline: a rig, a scene graph, a folder of shows.
10
+ *
11
+ * Hand-built rather than wrapped, because the pattern's whole cost is in three
12
+ * details no primitive here provides together:
13
+ *
14
+ * - **Roving tabindex.** The tree is one tab stop; the arrow keys move inside
15
+ * it. Eighty rows must never mean eighty presses of Tab.
16
+ * - **A flat DOM.** Rows carry `aria-level` / `aria-posinset` / `aria-setsize`
17
+ * instead of nesting `role="group"` wrappers, which is both valid ARIA and the
18
+ * shape a virtualizer needs when the outline grows past a screenful.
19
+ * - **The gutter.** `└ ├ │` in the mono grid, `aria-hidden` — structure you can
20
+ * see at a glance without indentation alone having to carry it.
21
+ *
22
+ * Selection is a tint (`accent-soft` ground, accent ink), never a solid fill —
23
+ * the same ruling as the sidebar item and the active tab.
24
+ *
25
+ * @example
26
+ * <Tree
27
+ * aria-label="Rig"
28
+ * items={rig}
29
+ * selected={selected}
30
+ * onSelect={setSelected}
31
+ * rowControls={(item) => (
32
+ * <TreeVisibilityToggle value={visibility[item.id]} onValueChange={set(item.id)} />
33
+ * )}
34
+ * />
35
+ */
36
+ const Tree = React.forwardRef(function Tree({ className, items, expanded: expandedProp, defaultExpanded, onExpandedChange, selected: selectedProp, defaultSelected = null, onSelect, renderRow, rowControls, guides = true, onKeyDown, ...elementProps }, ref) {
37
+ const [uncontrolledExpanded, setUncontrolledExpanded] = React.useState(defaultExpanded ?? []);
38
+ const expandedList = expandedProp ?? uncontrolledExpanded;
39
+ const expandedSet = React.useMemo(() => new Set(expandedList), [expandedList]);
40
+ const [uncontrolledSelected, setUncontrolledSelected] = React.useState(defaultSelected);
41
+ const selected = selectedProp === void 0 ? uncontrolledSelected : selectedProp;
42
+ const rows = React.useMemo(() => flattenTree(items, expandedSet), [items, expandedSet]);
43
+ const [activeId, setActiveId] = React.useState(null);
44
+ const activeRowId = activeId !== null && rows.some((row) => row.item.id === activeId) ? activeId : rows[0]?.item.id ?? null;
45
+ const rowRefs = React.useRef(/* @__PURE__ */ new Map());
46
+ const registerRow = React.useCallback((id, element) => {
47
+ if (element === null) rowRefs.current.delete(id);
48
+ else rowRefs.current.set(id, element);
49
+ }, []);
50
+ const focusRow = React.useCallback((id) => {
51
+ setActiveId(id);
52
+ rowRefs.current.get(id)?.focus();
53
+ }, []);
54
+ const setExpanded = React.useCallback((id, next) => {
55
+ const current = expandedProp ?? uncontrolledExpanded;
56
+ const result = next ? current.includes(id) ? [...current] : [...current, id] : current.filter((entry) => entry !== id);
57
+ if (expandedProp === void 0) setUncontrolledExpanded(result);
58
+ onExpandedChange?.(result);
59
+ }, [
60
+ expandedProp,
61
+ onExpandedChange,
62
+ uncontrolledExpanded
63
+ ]);
64
+ const select = React.useCallback((row) => {
65
+ if (row.item.disabled === true) return;
66
+ if (selectedProp === void 0) setUncontrolledSelected(row.item.id);
67
+ onSelect?.(row.item.id);
68
+ }, [onSelect, selectedProp]);
69
+ const handleKeyDown = React.useCallback((event) => {
70
+ onKeyDown?.(event);
71
+ if (event.defaultPrevented) return;
72
+ if (event.target.getAttribute("data-slot") !== "tree-row") return;
73
+ const index = rows.findIndex((row) => row.item.id === activeRowId);
74
+ const row = rows[index];
75
+ if (row === void 0) return;
76
+ const move = (target) => {
77
+ if (target === void 0) return;
78
+ event.preventDefault();
79
+ focusRow(target.item.id);
80
+ };
81
+ switch (event.key) {
82
+ case "ArrowDown":
83
+ move(rows[index + 1]);
84
+ return;
85
+ case "ArrowUp":
86
+ move(rows[index - 1]);
87
+ return;
88
+ case "Home":
89
+ move(rows[0]);
90
+ return;
91
+ case "End":
92
+ move(rows[rows.length - 1]);
93
+ return;
94
+ case "ArrowRight": {
95
+ event.preventDefault();
96
+ if (row.hasChildren && !row.expanded) {
97
+ setExpanded(row.item.id, true);
98
+ return;
99
+ }
100
+ const child = rows[index + 1];
101
+ if (row.expanded && child?.parentId === row.item.id) focusRow(child.item.id);
102
+ return;
103
+ }
104
+ case "ArrowLeft":
105
+ event.preventDefault();
106
+ if (row.expanded) setExpanded(row.item.id, false);
107
+ else if (row.parentId !== null) focusRow(row.parentId);
108
+ return;
109
+ case "Enter":
110
+ case " ":
111
+ event.preventDefault();
112
+ select(row);
113
+ return;
114
+ }
115
+ }, [
116
+ activeRowId,
117
+ focusRow,
118
+ onKeyDown,
119
+ rows,
120
+ select,
121
+ setExpanded
122
+ ]);
123
+ return /* @__PURE__ */ jsx("div", {
124
+ ref,
125
+ role: "tree",
126
+ "data-slot": "tree",
127
+ className: cn("flex flex-col", className),
128
+ onKeyDown: handleKeyDown,
129
+ ...elementProps,
130
+ children: rows.map((row) => {
131
+ const { item } = row;
132
+ const Icon = item.icon;
133
+ return /* @__PURE__ */ jsxs("div", {
134
+ ref: (element) => registerRow(item.id, element),
135
+ role: "treeitem",
136
+ tabIndex: activeRowId === item.id ? 0 : -1,
137
+ "aria-level": row.level + 1,
138
+ "aria-posinset": row.position,
139
+ "aria-setsize": row.setSize,
140
+ "aria-expanded": row.hasChildren ? row.expanded : void 0,
141
+ "aria-selected": selected === item.id,
142
+ "aria-disabled": item.disabled === true ? true : void 0,
143
+ "data-slot": "tree-row",
144
+ "data-selected": selected === item.id ? "" : void 0,
145
+ "data-disabled": item.disabled === true ? "" : void 0,
146
+ onFocus: () => setActiveId(item.id),
147
+ onClick: () => select(row),
148
+ className: "group/tree-row flex h-control-sm cursor-default items-center gap-(--cue-space-1) rounded-(--radius-control) pr-(--cue-space-2) font-mono text-(length:--cue-text-ui) whitespace-nowrap text-fg-muted outline-none select-none hover:bg-surface-2 hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-1 focus-visible:outline-accent data-[selected]:bg-accent-soft data-[selected]:text-accent data-[disabled]:pointer-events-none data-[disabled]:opacity-40",
149
+ children: [
150
+ guides ? row.guides.map((guide, depth) => /* @__PURE__ */ jsx("span", {
151
+ "aria-hidden": "true",
152
+ "data-slot": "tree-guide",
153
+ className: "w-(--cue-space-4) shrink-0 text-center text-fg-subtle",
154
+ children: TREE_GUIDE_GLYPHS[guide]
155
+ }, depth)) : null,
156
+ row.hasChildren ? /* @__PURE__ */ jsx("span", {
157
+ role: "presentation",
158
+ "data-slot": "tree-toggle",
159
+ "aria-hidden": "true",
160
+ onClick: (event) => {
161
+ event.stopPropagation();
162
+ setExpanded(item.id, !row.expanded);
163
+ },
164
+ className: "flex size-icon-sm shrink-0 cursor-pointer items-center justify-center text-fg-subtle",
165
+ children: /* @__PURE__ */ jsx(ChevronRightGlyph, { className: cn("size-icon-sm transition-transform duration-150 motion-reduce:transition-none", row.expanded ? "rotate-90" : null) })
166
+ }) : /* @__PURE__ */ jsx("span", {
167
+ "aria-hidden": "true",
168
+ className: "size-icon-sm shrink-0"
169
+ }),
170
+ renderRow === void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
171
+ Icon === void 0 ? null : /* @__PURE__ */ jsx(Icon, {
172
+ "aria-hidden": "true",
173
+ className: "size-icon-sm shrink-0"
174
+ }),
175
+ /* @__PURE__ */ jsx("span", {
176
+ "data-slot": "tree-label",
177
+ className: "min-w-0 flex-1 truncate",
178
+ children: item.label
179
+ }),
180
+ item.badge === void 0 ? null : /* @__PURE__ */ jsx("span", {
181
+ "data-slot": "tree-badge",
182
+ className: "shrink-0 text-fg-subtle",
183
+ children: item.badge
184
+ })
185
+ ] }) : /* @__PURE__ */ jsx("span", {
186
+ className: "min-w-0 flex-1 truncate",
187
+ children: renderRow(row)
188
+ }),
189
+ rowControls === void 0 ? null : /* @__PURE__ */ jsx("span", {
190
+ "data-slot": "tree-row-controls",
191
+ onClick: (event) => event.stopPropagation(),
192
+ className: "flex shrink-0 items-center gap-(--cue-space-1) opacity-0 transition-opacity duration-150 group-hover/tree-row:opacity-100 group-focus-within/tree-row:opacity-100 motion-reduce:transition-none",
193
+ children: rowControls(item, row)
194
+ })
195
+ ]
196
+ }, item.id);
197
+ })
198
+ });
199
+ });
200
+ /** Which state the toggle moves to next. */
201
+ const NEXT_VISIBILITY = {
202
+ visible: "ghost",
203
+ ghost: "hidden",
204
+ hidden: "visible"
205
+ };
206
+ /** What each state is called when the button announces itself. */
207
+ const VISIBILITY_LABELS = {
208
+ visible: "visible",
209
+ ghost: "ghosted",
210
+ hidden: "hidden"
211
+ };
212
+ /**
213
+ * The outliner's three-state visibility control: shown → ghosted → hidden.
214
+ *
215
+ * Three states rather than a checkbox because a rig has three answers, not two:
216
+ * *there*, *there but out of the way*, and *not drawn*. Ghost is the one that
217
+ * earns the extra state — it is how you keep a truss as spatial reference while
218
+ * working behind it — and collapsing it into "hidden" is what makes people
219
+ * toggle things off and lose their bearings.
220
+ *
221
+ * Meant for {@link TreeProps.rowControls}. The accessible name states the
222
+ * *current* state ("Visibility: ghosted") rather than the next action, because
223
+ * with three states "toggle" names nothing useful; pressing cycles.
224
+ *
225
+ * @example
226
+ * <TreeVisibilityToggle value={state} onValueChange={setState} />
227
+ */
228
+ const TreeVisibilityToggle = React.forwardRef(function TreeVisibilityToggle({ className, value, onValueChange, labels, onClick, ...elementProps }, ref) {
229
+ const Glyph = value === "visible" ? EyeGlyph : value === "ghost" ? GhostGlyph : EyeOffGlyph;
230
+ const name = labels?.[value] ?? VISIBILITY_LABELS[value];
231
+ return /* @__PURE__ */ jsx("button", {
232
+ ref,
233
+ type: "button",
234
+ "aria-label": `Visibility: ${name}`,
235
+ "data-slot": "tree-visibility-toggle",
236
+ "data-state": value,
237
+ onClick: (event) => {
238
+ onClick?.(event);
239
+ if (event.defaultPrevented) return;
240
+ onValueChange(NEXT_VISIBILITY[value]);
241
+ },
242
+ className: cn("flex size-icon-md shrink-0 cursor-pointer items-center justify-center rounded-(--radius-control) border-0 bg-transparent p-0 outline-none transition-colors duration-150 hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-1 focus-visible:outline-accent motion-reduce:transition-none data-[state=visible]:text-fg-subtle data-[state=ghost]:text-info data-[state=hidden]:text-warn", className),
243
+ ...elementProps,
244
+ children: /* @__PURE__ */ jsx(Glyph, { className: "size-icon-sm" })
245
+ });
246
+ });
247
+ //#endregion
248
+ export { Tree, TreeVisibilityToggle };
@@ -0,0 +1,14 @@
1
+ //#region src/color/_checker.ts
2
+ /**
3
+ * The transparency checkerboard.
4
+ *
5
+ * Anywhere a colour with alpha is shown — a swatch, an alpha rail — something
6
+ * has to sit behind it or "50% transparent white" and "opaque light grey" look
7
+ * identical. Drawn as a token-coloured conic gradient rather than an image so it
8
+ * follows the theme (and stays a two-line class string instead of an asset).
9
+ *
10
+ * @internal Not part of the public API.
11
+ */
12
+ const checkerClasses = "bg-[repeating-conic-gradient(var(--cue-surface-3)_0%_25%,var(--cue-surface-1)_0%_50%)] bg-[length:0.5rem_0.5rem]";
13
+ //#endregion
14
+ export { checkerClasses };
@@ -0,0 +1,52 @@
1
+ //#region src/color/_convert.d.ts
2
+ /**
3
+ * The notations this suite reads and writes.
4
+ *
5
+ * Two, not ten: hex is what a colour picker natively speaks, oklch is what this
6
+ * system's tokens are authored in. Everything else (`rgb()`, `hsl()`, named
7
+ * colours) is *readable* — {@link toHexString} takes whatever CSS understands —
8
+ * but writing back in a third notation would only invite a token file with
9
+ * three spellings of the same colour.
10
+ */
11
+ type ColorFormat = "hex" | "oklch";
12
+ /**
13
+ * Convert any CSS colour string to `#rrggbb` (or `#rrggbbaa` when it carries
14
+ * alpha).
15
+ *
16
+ * The bridge into React Aria's colour parts, which only parse sRGB notations —
17
+ * hand them an `oklch()` token value and they throw. Colours outside the sRGB
18
+ * gamut have their **chroma** pulled in rather than their channels clipped:
19
+ * clipping `oklch(0.7 0.4 30)` gives pure red, losing the lightness the author
20
+ * chose, while clamping keeps it at `#ff6551`.
21
+ *
22
+ * @param input - Any CSS colour string.
23
+ * @returns The lower-case hex string, or `null` if the input is not a colour.
24
+ * @example
25
+ * toHexString("oklch(0.7 0.15 30)") // "#ed7665"
26
+ */
27
+ declare function toHexString(input: string): string | null;
28
+ /**
29
+ * Re-print a colour in one of the two notations the suite writes.
30
+ *
31
+ * The oklch form is emitted at the precision a round trip needs — four decimals
32
+ * of lightness and chroma, two of hue — which is exactly enough for
33
+ * `toHexString(formatColorString(hex, "oklch")) === hex` across the sRGB cube.
34
+ * An achromatic colour has no hue, so it prints `0` rather than `NaN`.
35
+ *
36
+ * @param input - Any CSS colour string.
37
+ * @param format - The notation to write.
38
+ * @returns The formatted colour, or `null` if the input is not a colour.
39
+ * @example
40
+ * formatColorString("#3fa9f5", "oklch") // "oklch(0.7083 0.1466 244.05)"
41
+ */
42
+ declare function formatColorString(input: string, format: ColorFormat): string | null;
43
+ /**
44
+ * Which notation a value is authored in, so a control can hand back what it was
45
+ * given instead of quietly rewriting a token file into hex.
46
+ *
47
+ * @param input - Any CSS colour string.
48
+ * @returns `"oklch"` for an `oklch()` value, `"hex"` for everything else.
49
+ */
50
+ declare function detectColorFormat(input: string): ColorFormat;
51
+ //#endregion
52
+ export { ColorFormat, detectColorFormat, formatColorString, toHexString };
@@ -0,0 +1,66 @@
1
+ import { clampChroma, converter, formatHex, formatHex8, inGamut, parse } from "culori";
2
+ //#region src/color/_convert.ts
3
+ const toOklch = converter("oklch");
4
+ const srgb = inGamut("rgb");
5
+ /** Round to `digits` and drop trailing zeros, so `0.70000` prints as `0.7`. */
6
+ function round(value, digits) {
7
+ return String(Number(value.toFixed(digits)));
8
+ }
9
+ /**
10
+ * Convert any CSS colour string to `#rrggbb` (or `#rrggbbaa` when it carries
11
+ * alpha).
12
+ *
13
+ * The bridge into React Aria's colour parts, which only parse sRGB notations —
14
+ * hand them an `oklch()` token value and they throw. Colours outside the sRGB
15
+ * gamut have their **chroma** pulled in rather than their channels clipped:
16
+ * clipping `oklch(0.7 0.4 30)` gives pure red, losing the lightness the author
17
+ * chose, while clamping keeps it at `#ff6551`.
18
+ *
19
+ * @param input - Any CSS colour string.
20
+ * @returns The lower-case hex string, or `null` if the input is not a colour.
21
+ * @example
22
+ * toHexString("oklch(0.7 0.15 30)") // "#ed7665"
23
+ */
24
+ function toHexString(input) {
25
+ const parsed = parse(input);
26
+ if (parsed === void 0) return null;
27
+ const inSrgb = srgb(parsed) ? parsed : clampChroma(parsed, "oklch", "rgb");
28
+ const alpha = parsed.alpha;
29
+ return alpha === void 0 || alpha >= 1 ? formatHex(inSrgb) : formatHex8(inSrgb);
30
+ }
31
+ /**
32
+ * Re-print a colour in one of the two notations the suite writes.
33
+ *
34
+ * The oklch form is emitted at the precision a round trip needs — four decimals
35
+ * of lightness and chroma, two of hue — which is exactly enough for
36
+ * `toHexString(formatColorString(hex, "oklch")) === hex` across the sRGB cube.
37
+ * An achromatic colour has no hue, so it prints `0` rather than `NaN`.
38
+ *
39
+ * @param input - Any CSS colour string.
40
+ * @param format - The notation to write.
41
+ * @returns The formatted colour, or `null` if the input is not a colour.
42
+ * @example
43
+ * formatColorString("#3fa9f5", "oklch") // "oklch(0.7083 0.1466 244.05)"
44
+ */
45
+ function formatColorString(input, format) {
46
+ const hex = toHexString(input);
47
+ if (hex === null) return null;
48
+ if (format === "hex") return hex;
49
+ const color = toOklch(parse(hex));
50
+ if (color === void 0) return null;
51
+ const body = `${round(color.l, 4)} ${round(color.c, 4)} ${round(color.h ?? 0, 2)}`;
52
+ const alpha = color.alpha;
53
+ return alpha === void 0 || alpha >= 1 ? `oklch(${body})` : `oklch(${body} / ${round(alpha, 3)})`;
54
+ }
55
+ /**
56
+ * Which notation a value is authored in, so a control can hand back what it was
57
+ * given instead of quietly rewriting a token file into hex.
58
+ *
59
+ * @param input - Any CSS colour string.
60
+ * @returns `"oklch"` for an `oklch()` value, `"hex"` for everything else.
61
+ */
62
+ function detectColorFormat(input) {
63
+ return /^\s*oklch\(/i.test(input) ? "oklch" : "hex";
64
+ }
65
+ //#endregion
66
+ export { detectColorFormat, formatColorString, toHexString };
@@ -0,0 +1,28 @@
1
+ import "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/color/_glyphs.tsx
4
+ /**
5
+ * Glyphs for the colour group.
6
+ *
7
+ * Drawn inline for the same reason as `forms/_glyphs.tsx`: one icon on one
8
+ * button should not put an icon dependency on the render path, and hand-set
9
+ * strokes stay hairline-thin at the 8–12px sizes console density asks for.
10
+ *
11
+ * @internal Not part of the public API.
12
+ */
13
+ /** An eyedropper: sample a colour from anywhere on the screen. */
14
+ function EyedropperGlyph(props) {
15
+ return /* @__PURE__ */ jsx("svg", {
16
+ viewBox: "0 0 16 16",
17
+ fill: "none",
18
+ stroke: "currentColor",
19
+ strokeWidth: "1.25",
20
+ strokeLinecap: "round",
21
+ strokeLinejoin: "round",
22
+ "aria-hidden": "true",
23
+ ...props,
24
+ children: /* @__PURE__ */ jsx("path", { d: "M10.5 2.5a1.8 1.8 0 0 1 2.5 2.5l-1.4 1.4 1 1-1.2 1.2-1-1-4.3 4.3-2.6.6.6-2.6 4.3-4.3-1-1L8.6 3.4l1 1z" })
25
+ });
26
+ }
27
+ //#endregion
28
+ export { EyedropperGlyph };