@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,256 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { CopyButton } from "./copy-button.js";
4
+ import { toRem } from "./_rem.js";
5
+ import { mulberry32, usePrefersReducedMotion } from "./_motion.js";
6
+ import * as React from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/instruments/terminal-frame.tsx
9
+ const LINE_TONES = {
10
+ neutral: "text-fg-muted",
11
+ accent: "text-accent",
12
+ ok: "text-ok",
13
+ warn: "text-warn",
14
+ danger: "text-danger",
15
+ info: "text-info"
16
+ };
17
+ /** The braille spinner every CLI in the portfolio uses. */
18
+ const SPINNER_GLYPHS = [
19
+ "⠋",
20
+ "⠙",
21
+ "⠹",
22
+ "⠸",
23
+ "⠼",
24
+ "⠴",
25
+ "⠦",
26
+ "⠧",
27
+ "⠇",
28
+ "⠏"
29
+ ];
30
+ const SPINNER_MS = 80;
31
+ const DEFAULT_KEYSTROKE_MS = 55;
32
+ const DEFAULT_HOLD_MS = 600;
33
+ const DEFAULT_PENDING_MS = 900;
34
+ const DEFAULT_SEED = 1;
35
+ const IDLE = {
36
+ lines: [],
37
+ typing: null,
38
+ spinner: null,
39
+ done: true
40
+ };
41
+ /** Normalise the shorthand so the renderer only ever sees one shape. */
42
+ function toLine(line) {
43
+ return typeof line === "string" ? { text: line } : line;
44
+ }
45
+ /** Every line a script ends on — what reduced motion renders straight away. */
46
+ function finalLines(script) {
47
+ return script.steps.flatMap((step) => [...step.command === void 0 ? [] : [{
48
+ text: step.command,
49
+ command: true
50
+ }], ...(step.output ?? []).map(toLine)]);
51
+ }
52
+ /**
53
+ * A recessed terminal: mono, `$`-prefixed commands, optional typed playback.
54
+ *
55
+ * Recessed rather than raised — `bg-sunken` sits the transcript *into* the page
56
+ * the way a real console does (the snuffle convention, where the terminal
57
+ * surface is the only thing darker than the background).
58
+ *
59
+ * The `simulate` player is deliberately not a GIF or a video: it is text, so it
60
+ * copies, it scales with the type ramp, it re-themes, and it costs nothing to
61
+ * load. Keystrokes are jittered from a seed so a marketing screenshot is
62
+ * reproducible, and the whole animation is replaced by its final frame under
63
+ * `prefers-reduced-motion` — with no timers scheduled at all, rather than an
64
+ * animation that runs invisibly.
65
+ *
66
+ * @example
67
+ * <TerminalFrame
68
+ * title="install"
69
+ * copy
70
+ * lines={[{ text: "pnpm add @cueplusplus/ui", command: true }, "+ 1 package"]}
71
+ * />
72
+ * @example
73
+ * const SCRIPT = { steps: [{ command: "cue build", pending: "compiling", output: ["12 cues"] }] };
74
+ * <TerminalFrame simulate={SCRIPT} />
75
+ */
76
+ const TerminalFrame = React.forwardRef(function TerminalFrame({ className, title, lines, prompt = "$", copy = false, copyValue, simulate, height, children, ...elementProps }, ref) {
77
+ const reduced = usePrefersReducedMotion();
78
+ const [transcript, setTranscript] = React.useState(IDLE);
79
+ React.useEffect(() => {
80
+ if (simulate === void 0) {
81
+ setTranscript(IDLE);
82
+ return;
83
+ }
84
+ if (reduced) {
85
+ setTranscript({
86
+ lines: finalLines(simulate),
87
+ typing: null,
88
+ spinner: null,
89
+ done: true
90
+ });
91
+ return;
92
+ }
93
+ let cancelled = false;
94
+ let timer;
95
+ const sleep = (ms) => new Promise((resolve) => {
96
+ timer = setTimeout(resolve, ms);
97
+ });
98
+ const random = mulberry32(simulate.seed ?? DEFAULT_SEED);
99
+ const keystrokeMs = simulate.keystrokeMs ?? DEFAULT_KEYSTROKE_MS;
100
+ const holdMs = simulate.holdMs ?? DEFAULT_HOLD_MS;
101
+ const printed = [];
102
+ setTranscript({
103
+ lines: [],
104
+ typing: null,
105
+ spinner: null,
106
+ done: false
107
+ });
108
+ (async () => {
109
+ for (const step of simulate.steps) {
110
+ if (step.command !== void 0) {
111
+ for (let index = 1; index <= step.command.length; index += 1) {
112
+ await sleep(keystrokeMs * (.6 + random()));
113
+ if (cancelled) return;
114
+ setTranscript({
115
+ lines: [...printed],
116
+ typing: step.command.slice(0, index),
117
+ spinner: null,
118
+ done: false
119
+ });
120
+ }
121
+ await sleep(holdMs);
122
+ if (cancelled) return;
123
+ printed.push({
124
+ text: step.command,
125
+ command: true
126
+ });
127
+ setTranscript({
128
+ lines: [...printed],
129
+ typing: null,
130
+ spinner: null,
131
+ done: false
132
+ });
133
+ }
134
+ if (step.pending !== void 0) {
135
+ const frames = Math.max(1, Math.round((step.pendingMs ?? DEFAULT_PENDING_MS) / SPINNER_MS));
136
+ for (let index = 0; index < frames; index += 1) {
137
+ setTranscript({
138
+ lines: [...printed],
139
+ typing: null,
140
+ spinner: {
141
+ label: step.pending,
142
+ index
143
+ },
144
+ done: false
145
+ });
146
+ await sleep(SPINNER_MS);
147
+ if (cancelled) return;
148
+ }
149
+ }
150
+ for (const line of step.output ?? []) printed.push(toLine(line));
151
+ setTranscript({
152
+ lines: [...printed],
153
+ typing: null,
154
+ spinner: null,
155
+ done: false
156
+ });
157
+ await sleep(holdMs);
158
+ if (cancelled) return;
159
+ }
160
+ setTranscript({
161
+ lines: [...printed],
162
+ typing: null,
163
+ spinner: null,
164
+ done: true
165
+ });
166
+ })();
167
+ return () => {
168
+ cancelled = true;
169
+ if (timer !== void 0) clearTimeout(timer);
170
+ };
171
+ }, [reduced, simulate]);
172
+ const preamble = (lines ?? []).map(toLine);
173
+ const rendered = [...preamble, ...transcript.lines];
174
+ const commands = [...preamble, ...simulate === void 0 ? [] : finalLines(simulate)].filter((line) => line.command === true);
175
+ const clipboard = copyValue ?? commands.map((line) => line.text).join("\n");
176
+ const simulating = simulate !== void 0 && !transcript.done;
177
+ const promptGlyph = /* @__PURE__ */ jsx("span", {
178
+ "aria-hidden": "true",
179
+ "data-slot": "terminal-frame-prompt",
180
+ className: "mr-(--cue-space-3) shrink-0 text-accent select-none",
181
+ children: prompt
182
+ });
183
+ return /* @__PURE__ */ jsxs("div", {
184
+ ref,
185
+ "data-slot": "terminal-frame",
186
+ "data-simulating": simulate === void 0 ? void 0 : String(simulating),
187
+ className: cn("flex min-w-0 flex-col overflow-hidden rounded-(--radius-surface) border border-border bg-sunken font-mono text-(length:--cue-text-ui) text-fg-muted", className),
188
+ ...elementProps,
189
+ children: [title === void 0 && !copy ? null : /* @__PURE__ */ jsxs("div", {
190
+ "data-slot": "terminal-frame-bar",
191
+ className: "flex h-control-md shrink-0 items-center justify-between gap-(--cue-space-3) border-b border-border px-(--cue-pad-row-x)",
192
+ children: [/* @__PURE__ */ jsx("span", {
193
+ "data-slot": "terminal-frame-title",
194
+ className: "min-w-0 truncate text-(length:--cue-text-label) tracking-[0.15em] text-fg-subtle uppercase",
195
+ children: title
196
+ }), copy ? /* @__PURE__ */ jsx("span", {
197
+ "data-slot": "terminal-frame-copy",
198
+ "data-value": clipboard,
199
+ className: "shrink-0",
200
+ children: /* @__PURE__ */ jsx(CopyButton, {
201
+ value: clipboard,
202
+ variant: "ghost",
203
+ size: "sm"
204
+ })
205
+ }) : null]
206
+ }), /* @__PURE__ */ jsxs("div", {
207
+ "data-slot": "terminal-frame-body",
208
+ className: "min-w-0 flex-1 overflow-auto p-(--cue-space-5) leading-relaxed whitespace-pre-wrap",
209
+ style: height === void 0 ? void 0 : { height: toRem(height) },
210
+ children: [
211
+ rendered.map((line, index) => /* @__PURE__ */ jsxs("div", {
212
+ "data-slot": "terminal-frame-line",
213
+ "data-command": line.command === true ? "" : void 0,
214
+ className: cn("flex min-w-0", LINE_TONES[line.tone ?? "neutral"]),
215
+ children: [line.command === true ? promptGlyph : null, /* @__PURE__ */ jsx("span", {
216
+ className: "min-w-0 break-all",
217
+ children: line.text
218
+ })]
219
+ }, index)),
220
+ transcript.typing === null ? null : /* @__PURE__ */ jsxs("div", {
221
+ "data-slot": "terminal-frame-line",
222
+ "data-typing": "",
223
+ className: "flex min-w-0 text-fg",
224
+ children: [
225
+ promptGlyph,
226
+ /* @__PURE__ */ jsx("span", {
227
+ className: "min-w-0 break-all",
228
+ children: transcript.typing
229
+ }),
230
+ /* @__PURE__ */ jsx("span", {
231
+ "aria-hidden": "true",
232
+ className: "animate-pulse motion-reduce:animate-none",
233
+ children: "▍"
234
+ })
235
+ ]
236
+ }),
237
+ transcript.spinner === null ? null : /* @__PURE__ */ jsxs("div", {
238
+ "data-slot": "terminal-frame-line",
239
+ "data-pending": "",
240
+ className: "flex min-w-0 text-fg-subtle",
241
+ children: [/* @__PURE__ */ jsx("span", {
242
+ "aria-hidden": "true",
243
+ className: "mr-(--cue-space-3) shrink-0 text-accent",
244
+ children: SPINNER_GLYPHS[transcript.spinner.index % SPINNER_GLYPHS.length]
245
+ }), /* @__PURE__ */ jsx("span", {
246
+ className: "min-w-0 break-all",
247
+ children: transcript.spinner.label
248
+ })]
249
+ }),
250
+ children
251
+ ]
252
+ })]
253
+ });
254
+ });
255
+ //#endregion
256
+ export { TerminalFrame };
@@ -0,0 +1,47 @@
1
+ import { ButtonProps } from "../primitives/button.js";
2
+ import * as React from "react";
3
+ //#region src/instruments/two-step-button.d.ts
4
+ /** Which end of the warning scale this action sits at. */
5
+ type TwoStepTone = "danger" | "warn";
6
+ interface TwoStepButtonProps extends Omit<ButtonProps, "onClick" | "variant" | "onConfirm" | "children"> {
7
+ /** Fired once, when the *second* press lands. */
8
+ onConfirm: () => void;
9
+ /** The idle label — name the action, not the button ("Delete rig", not "Delete"). */
10
+ children: React.ReactNode;
11
+ /** Label on the armed half. Defaults to `"Confirm"`. */
12
+ confirmLabel?: React.ReactNode;
13
+ /** Label on the escape hatch. Defaults to `"Cancel"`. */
14
+ cancelLabel?: React.ReactNode;
15
+ /** How severe this is. Defaults to `"danger"`. */
16
+ tone?: TwoStepTone;
17
+ /** ms before an untouched armed state disarms itself. `0` disables. Defaults to `4000`. */
18
+ timeout?: number;
19
+ /** Called with the new armed state on every arm and disarm. */
20
+ onArmedChange?: (armed: boolean) => void;
21
+ }
22
+ /**
23
+ * Arm, then confirm: a destructive action that takes two deliberate presses.
24
+ *
25
+ * The most-reused interaction in the portfolio (fifteen call sites, three
26
+ * hand-rolled implementations) and the right shape for a destructive action
27
+ * that is *routine* — deleting a cue, clearing a patch. A modal
28
+ * `AlertDialog` is the right shape for a rare and expensive one; putting a
29
+ * dialog in front of an action people take twenty times an hour just teaches
30
+ * them to dismiss dialogs.
31
+ *
32
+ * Four ways out, because an armed button left lying around is a trap: Cancel,
33
+ * Escape, moving focus away, and a timeout. Focus lands on **Cancel** when the
34
+ * pair arms, never on the destructive half — the same ruling as a destructive
35
+ * dialog's default button, and it means a stuck Enter key cannot walk through
36
+ * both steps.
37
+ *
38
+ * @example
39
+ * <TwoStepButton onConfirm={() => deleteRig(id)}>Delete rig</TwoStepButton>
40
+ * @example
41
+ * <TwoStepButton tone="warn" timeout={0} confirmLabel="Reset it" onConfirm={reset}>
42
+ * Reset patch
43
+ * </TwoStepButton>
44
+ */
45
+ declare const TwoStepButton: React.ForwardRefExoticComponent<TwoStepButtonProps & React.RefAttributes<HTMLButtonElement>>;
46
+ //#endregion
47
+ export { TwoStepButton, TwoStepButtonProps, TwoStepTone };
@@ -0,0 +1,147 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { Button } from "../primitives/button.js";
4
+ import * as React from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/instruments/two-step-button.tsx
7
+ /**
8
+ * The armed confirm button's fill.
9
+ *
10
+ * The ink is a literal rather than a token because there is no `--cue-warn-fg`
11
+ * or `--cue-danger-fg` in the palette — the same pragmatism as `Button`'s
12
+ * `danger` variant, which is also `text-white`. Every theme's `warn` is an
13
+ * amber and every theme's `danger` is a red, so the two literals hold.
14
+ */
15
+ const CONFIRM_TONES = {
16
+ danger: "border-transparent bg-danger text-white hover:opacity-90",
17
+ warn: "border-transparent bg-warn text-black hover:opacity-90"
18
+ };
19
+ /** The idle trigger: outline only, so a destructive action is never the loudest thing on screen. */
20
+ const IDLE_TONES = {
21
+ danger: "border-danger/40 text-danger hover:border-danger hover:bg-danger/10",
22
+ warn: "border-warn/40 text-warn hover:border-warn hover:bg-warn/10"
23
+ };
24
+ /** ms the armed state survives without input before it gives up. */
25
+ const DEFAULT_TIMEOUT_MS = 4e3;
26
+ /**
27
+ * Arm, then confirm: a destructive action that takes two deliberate presses.
28
+ *
29
+ * The most-reused interaction in the portfolio (fifteen call sites, three
30
+ * hand-rolled implementations) and the right shape for a destructive action
31
+ * that is *routine* — deleting a cue, clearing a patch. A modal
32
+ * `AlertDialog` is the right shape for a rare and expensive one; putting a
33
+ * dialog in front of an action people take twenty times an hour just teaches
34
+ * them to dismiss dialogs.
35
+ *
36
+ * Four ways out, because an armed button left lying around is a trap: Cancel,
37
+ * Escape, moving focus away, and a timeout. Focus lands on **Cancel** when the
38
+ * pair arms, never on the destructive half — the same ruling as a destructive
39
+ * dialog's default button, and it means a stuck Enter key cannot walk through
40
+ * both steps.
41
+ *
42
+ * @example
43
+ * <TwoStepButton onConfirm={() => deleteRig(id)}>Delete rig</TwoStepButton>
44
+ * @example
45
+ * <TwoStepButton tone="warn" timeout={0} confirmLabel="Reset it" onConfirm={reset}>
46
+ * Reset patch
47
+ * </TwoStepButton>
48
+ */
49
+ const TwoStepButton = React.forwardRef(function TwoStepButton({ className, onConfirm, children, confirmLabel = "Confirm", cancelLabel = "Cancel", tone = "danger", timeout = DEFAULT_TIMEOUT_MS, onArmedChange, size, disabled, ...buttonProps }, ref) {
50
+ const [armed, setArmed] = React.useState(false);
51
+ const triggerRef = React.useRef(null);
52
+ const cancelRef = React.useRef(null);
53
+ const groupRef = React.useRef(null);
54
+ const timerRef = React.useRef(void 0);
55
+ const restoreFocusRef = React.useRef(false);
56
+ const setTriggerRef = React.useCallback((element) => {
57
+ triggerRef.current = element;
58
+ if (typeof ref === "function") ref(element);
59
+ else if (ref !== null) ref.current = element;
60
+ }, [ref]);
61
+ const clearTimer = React.useCallback(() => {
62
+ if (timerRef.current !== void 0) clearTimeout(timerRef.current);
63
+ timerRef.current = void 0;
64
+ }, []);
65
+ React.useEffect(() => clearTimer, [clearTimer]);
66
+ const disarm = React.useCallback((restoreFocus) => {
67
+ clearTimer();
68
+ restoreFocusRef.current = restoreFocus;
69
+ setArmed(false);
70
+ onArmedChange?.(false);
71
+ }, [clearTimer, onArmedChange]);
72
+ const arm = React.useCallback(() => {
73
+ setArmed(true);
74
+ onArmedChange?.(true);
75
+ if (timeout > 0) {
76
+ clearTimer();
77
+ timerRef.current = setTimeout(() => {
78
+ timerRef.current = void 0;
79
+ disarm(true);
80
+ }, timeout);
81
+ }
82
+ }, [
83
+ clearTimer,
84
+ disarm,
85
+ onArmedChange,
86
+ timeout
87
+ ]);
88
+ React.useEffect(() => {
89
+ if (armed) {
90
+ cancelRef.current?.focus();
91
+ return;
92
+ }
93
+ if (!restoreFocusRef.current) return;
94
+ restoreFocusRef.current = false;
95
+ triggerRef.current?.focus();
96
+ }, [armed]);
97
+ if (!armed) return /* @__PURE__ */ jsx(Button, {
98
+ ref: setTriggerRef,
99
+ variant: "outline",
100
+ size,
101
+ disabled,
102
+ "data-slot": "two-step-button",
103
+ "data-tone": tone,
104
+ "data-armed": "false",
105
+ className: cn(IDLE_TONES[tone], className),
106
+ onClick: arm,
107
+ ...buttonProps,
108
+ children
109
+ });
110
+ return /* @__PURE__ */ jsxs("span", {
111
+ ref: groupRef,
112
+ "data-slot": "two-step-button-armed",
113
+ "data-tone": tone,
114
+ className: "inline-flex items-center gap-(--cue-space-2)",
115
+ onKeyDown: (event) => {
116
+ if (event.key !== "Escape") return;
117
+ event.stopPropagation();
118
+ disarm(true);
119
+ },
120
+ onBlur: (event) => {
121
+ const next = event.relatedTarget;
122
+ if (next !== null && groupRef.current?.contains(next) === true) return;
123
+ disarm(false);
124
+ },
125
+ children: [/* @__PURE__ */ jsx(Button, {
126
+ ref: cancelRef,
127
+ variant: "ghost",
128
+ size,
129
+ "data-slot": "two-step-button-cancel",
130
+ onClick: () => disarm(true),
131
+ children: cancelLabel
132
+ }), /* @__PURE__ */ jsx(Button, {
133
+ variant: "outline",
134
+ size,
135
+ "data-slot": "two-step-button-confirm",
136
+ className: cn(CONFIRM_TONES[tone], className),
137
+ onClick: () => {
138
+ disarm(true);
139
+ onConfirm();
140
+ },
141
+ ...buttonProps,
142
+ children: confirmLabel
143
+ })]
144
+ });
145
+ });
146
+ //#endregion
147
+ export { TwoStepButton };
@@ -0,0 +1,55 @@
1
+ import * as React from "react";
2
+ //#region src/instruments/usage-chart.d.ts
3
+ /** One sample: a timestamp in ms, and a percentage. */
4
+ interface UsageChartPoint {
5
+ /** Epoch ms. Non-finite and non-positive timestamps are dropped. */
6
+ t: number;
7
+ /** Percentage of the ceiling. Clamped to 0–100 on the way in. */
8
+ v: number;
9
+ }
10
+ /** Stroke colour, in the shared status vocabulary. */
11
+ type UsageChartTone = "accent" | "ok" | "busy" | "warn" | "danger" | "info";
12
+ interface UsageChartProps extends Omit<React.ComponentPropsWithoutRef<"div">, "children"> {
13
+ /** The series. Sorted and cleaned internally; order in is not order out. */
14
+ points: readonly UsageChartPoint[];
15
+ /** Stroke tone. Defaults to `"accent"`. */
16
+ tone?: UsageChartTone;
17
+ /** Plot height in px at the 16px root. Defaults to `120`. */
18
+ height?: number;
19
+ /** Break the line when consecutive samples are further apart than this, in ms. */
20
+ gapMs?: number;
21
+ /** Draw a dashed rule at this percentage — where throttling starts, say. */
22
+ threshold?: number;
23
+ /** The accessible name. Name the series; the shape is not self-describing. */
24
+ label?: string;
25
+ /** What to say when there is nothing to plot. Defaults to `"No data yet"`. */
26
+ emptyLabel?: string;
27
+ /** Format a sample's timestamp for the tooltip. Defaults to a short local date-time. */
28
+ formatTimestamp?: (t: number) => string;
29
+ /** Format a sample's value for the tooltip. Defaults to `"87%"`. */
30
+ formatValue?: (v: number) => string;
31
+ }
32
+ /**
33
+ * A quota trace: where you sit against the ceiling, over time.
34
+ *
35
+ * Dependency-free inline SVG — a charting library is a large price for one
36
+ * line and five gridlines, and none of them draws the three things that make
37
+ * this chart honest:
38
+ *
39
+ * 1. **The y axis is always 0–100.** A quota chart auto-scaled to its own range
40
+ * makes a flat 3% look identical to a flat 95%. The ceiling is the reading,
41
+ * so the ceiling is always drawn.
42
+ * 2. **Gaps are gaps.** When the sweep does not run, the line breaks. Joining
43
+ * across a hole invents data — and worse, invents a *smooth* trend across
44
+ * exactly the window nothing is known about. The area fill stops at the
45
+ * break for the same reason.
46
+ * 3. **Out-of-range values are clamped, not plotted.** Upstream numbers are
47
+ * reverse-engineered and can be anything; 140% should read as a flat line on
48
+ * the ceiling, not as a path drawn over the axis labels.
49
+ *
50
+ * @example
51
+ * <UsageChart label="API requests" points={series} threshold={80} tone="warn" />
52
+ */
53
+ declare const UsageChart: React.ForwardRefExoticComponent<UsageChartProps & React.RefAttributes<HTMLDivElement>>;
54
+ //#endregion
55
+ export { UsageChart, UsageChartPoint, UsageChartProps, UsageChartTone };