@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,121 @@
1
+ /*! @cueplusplus/ui — React Flow theme layer.
2
+ *
3
+ * Consumer app CSS, in this order:
4
+ * @import "@xyflow/react/dist/style.css";
5
+ * @import "@cueplusplus/ui/flow.css";
6
+ *
7
+ * Plain CSS, no Tailwind: this file only re-inks chrome the *library* paints,
8
+ * so it has to work in a lane-B app that never installed Tailwind at all.
9
+ *
10
+ * Two mechanisms, deliberately:
11
+ *
12
+ * 1. Custom properties. React Flow consults `--xy-<thing>` before its own
13
+ * `--xy-<thing>-default` for every colour it paints, so declaring them on
14
+ * `.react-flow` re-themes edges, handles, controls, the minimap and the
15
+ * selection box without touching specificity at all — this block wins over
16
+ * the library's defaults whichever stylesheet loads last. It is the same map
17
+ * `useFlowTheme().style` publishes, and a test asserts the two agree.
18
+ * 2. Two extra rules for the things with no property hook — the controls
19
+ * capsule's shape and the pulse's keyframes. Those are scoped
20
+ * `.react-flow .react-flow__…`, one class more specific than the library's
21
+ * own rule, so they also win regardless of import order.
22
+ *
23
+ * Nothing here is required: every component in `@cueplusplus/ui/flow` publishes
24
+ * the same map on its own root. Import this to theme a canvas built from raw
25
+ * `@xyflow/react` parts, or to keep the token map out of your React tree.
26
+ */
27
+
28
+ .react-flow {
29
+ /* The pane itself. Left to the library this is a hard-coded #141414 in dark
30
+ mode, which is nobody's ground. */
31
+ --xy-background-color: var(--cue-bg);
32
+ --xy-background-pattern-color: var(--cue-surface-2);
33
+
34
+ /* Wires. `border-strong` rather than a fg rung: an edge nobody has said
35
+ anything about is structure, not content. */
36
+ --xy-edge-stroke: var(--cue-border-strong);
37
+ --xy-edge-stroke-width: 1.5;
38
+ --xy-edge-stroke-selected: var(--cue-fg);
39
+ --xy-connectionline-stroke: var(--cue-accent);
40
+ --xy-connectionline-stroke-width: 1.5;
41
+ --xy-edge-label-background-color: var(--cue-surface-2);
42
+ --xy-edge-label-color: var(--cue-fg);
43
+
44
+ /* Connection points, for a plain `Handle`. `NodeHandle` paints itself. */
45
+ --xy-handle-background-color: var(--cue-accent);
46
+ --xy-handle-border-color: var(--cue-bg);
47
+
48
+ /* The library's built-in node types. A `NodeCard` uses none of this. */
49
+ --xy-node-background-color: var(--cue-surface-1);
50
+ --xy-node-border: 1px solid var(--cue-border);
51
+ --xy-node-border-radius: var(--cue-radius-surface);
52
+ --xy-node-color: var(--cue-fg);
53
+ --xy-node-group-background-color: var(--cue-surface-2);
54
+ /* Rings rather than drops: this portfolio spends its one shadow on overlays. */
55
+ --xy-node-boxshadow-hover: 0 0 0 1px var(--cue-border-strong);
56
+ --xy-node-boxshadow-selected: 0 0 0 1px var(--cue-fg);
57
+
58
+ /* The zoom capsule, which is an overlay surface like any other. */
59
+ --xy-controls-button-background-color: var(--cue-surface-2);
60
+ --xy-controls-button-background-color-hover: var(--cue-surface-3);
61
+ --xy-controls-button-color: var(--cue-fg-muted);
62
+ --xy-controls-button-color-hover: var(--cue-accent);
63
+ --xy-controls-button-border-color: var(--cue-border);
64
+ --xy-controls-box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
65
+
66
+ --xy-minimap-background-color: var(--cue-surface-1);
67
+ --xy-minimap-mask-background-color: color-mix(in oklch, var(--cue-bg) 70%, transparent);
68
+ --xy-minimap-mask-stroke-color: var(--cue-border);
69
+ --xy-minimap-node-background-color: var(--cue-surface-3);
70
+ --xy-minimap-node-stroke-color: var(--cue-border);
71
+
72
+ /* Lasso select and the node-resize grips. */
73
+ --xy-selection-background-color: var(--cue-accent-soft);
74
+ --xy-selection-border: 1px dashed var(--cue-accent);
75
+ --xy-resize-background-color: var(--cue-accent);
76
+
77
+ --xy-attribution-background-color: color-mix(in oklch, var(--cue-bg) 70%, transparent);
78
+ }
79
+
80
+ /* The capsule's shape: no `--xy-*` hook exists for it, so it is a rule.
81
+ `overflow: hidden` is what makes the first and last buttons take the
82
+ capsule's corners instead of squaring them off. */
83
+ .react-flow .react-flow__controls {
84
+ border: 1px solid var(--cue-border-overlay);
85
+ border-radius: var(--cue-radius-overlay);
86
+ overflow: hidden;
87
+ }
88
+
89
+ /* The buttons are operable, so they keep a real focus ring. Inset, because the
90
+ capsule clips anything drawn outside it. */
91
+ .react-flow .react-flow__controls-button:focus-visible {
92
+ outline: 2px solid var(--cue-focus);
93
+ outline-offset: -2px;
94
+ }
95
+
96
+ /* The attribution's own link colour is a hard-coded #999 in the library. */
97
+ .react-flow .react-flow__attribution a {
98
+ color: var(--cue-fg-subtle);
99
+ }
100
+
101
+ /* The pulse on a live wire (`SignalEdge`). The dash pattern is inline on the
102
+ path; only the march lives here, because keyframes cannot be. The offset is a
103
+ whole number of dash periods (2 x (3 + 8)) — anything else visibly jumps as
104
+ the animation loops. */
105
+ @keyframes cue-signal-dash {
106
+ to {
107
+ stroke-dashoffset: -22;
108
+ }
109
+ }
110
+
111
+ .cue-signal-flow {
112
+ animation: cue-signal-dash 700ms linear infinite;
113
+ }
114
+
115
+ /* Reduced motion keeps the highlight and stops the march: the pulse carries no
116
+ information the wire's own opacity does not. */
117
+ @media (prefers-reduced-motion: reduce) {
118
+ .cue-signal-flow {
119
+ animation: none;
120
+ }
121
+ }
@@ -0,0 +1,40 @@
1
+ import * as React from "react";
2
+ import { HandleProps } from "@xyflow/react";
3
+ //#region src/flow/handles.d.ts
4
+ /** What a connection point is carrying, or refusing to. */
5
+ type FlowHandleTone = "accent" | "muted" | "ok" | "busy" | "warn" | "danger" | "info";
6
+ /**
7
+ * Pin diameter in px at the 16px root.
8
+ *
9
+ * The library's own 6px is a hard target with a mouse and an impossible one with
10
+ * a trackpad; 9px is what dmxhub's bridge settled on after the same complaint.
11
+ */
12
+ declare const FLOW_HANDLE_SIZE = 9;
13
+ interface NodeHandleProps extends HandleProps {
14
+ /** What the connection carries. Defaults to `"accent"`. */
15
+ tone?: FlowHandleTone;
16
+ /** Diameter in px at the 16px root, emitted as `rem`. Defaults to `9`. */
17
+ size?: number;
18
+ }
19
+ /**
20
+ * A connection point on a node, drawn as a pin rather than a dot.
21
+ *
22
+ * Everything visual is **inline style, not a class**, and that is deliberate:
23
+ * `.react-flow__handle` sets `background-color`, `border` and `width`/`height`
24
+ * from the library's own unlayered stylesheet, while Tailwind's utilities live in
25
+ * a cascade layer — and any layered rule loses to an unlayered one of the same
26
+ * specificity, whatever order the files load in. An inline declaration is the
27
+ * only paint that reliably wins, which is also how the port did it.
28
+ *
29
+ * The pin is ringed in `--cue-bg` rather than in the card's own surface, so it
30
+ * reads as lifted off the edge it straddles no matter which surface rung the
31
+ * node is on.
32
+ *
33
+ * @example
34
+ * <NodeHandle type="source" position={Position.Right} id="u1" />
35
+ * @example
36
+ * <NodeHandle type="target" position={Position.Left} id="in" tone="muted" />
37
+ */
38
+ declare const NodeHandle: React.ForwardRefExoticComponent<NodeHandleProps & React.RefAttributes<HTMLDivElement>>;
39
+ //#endregion
40
+ export { FLOW_HANDLE_SIZE, FlowHandleTone, NodeHandle, NodeHandleProps };
@@ -0,0 +1,61 @@
1
+ "use client";
2
+ import { toRem } from "../instruments/_rem.js";
3
+ import * as React from "react";
4
+ import { jsx } from "react/jsx-runtime";
5
+ import { Handle } from "@xyflow/react";
6
+ //#region src/flow/handles.tsx
7
+ /**
8
+ * Pin diameter in px at the 16px root.
9
+ *
10
+ * The library's own 6px is a hard target with a mouse and an impossible one with
11
+ * a trackpad; 9px is what dmxhub's bridge settled on after the same complaint.
12
+ */
13
+ const FLOW_HANDLE_SIZE = 9;
14
+ const TONE_COLORS = {
15
+ accent: "var(--cue-accent)",
16
+ muted: "var(--cue-border-strong)",
17
+ ok: "var(--cue-ok)",
18
+ busy: "var(--cue-busy)",
19
+ warn: "var(--cue-warn)",
20
+ danger: "var(--cue-danger)",
21
+ info: "var(--cue-info)"
22
+ };
23
+ /**
24
+ * A connection point on a node, drawn as a pin rather than a dot.
25
+ *
26
+ * Everything visual is **inline style, not a class**, and that is deliberate:
27
+ * `.react-flow__handle` sets `background-color`, `border` and `width`/`height`
28
+ * from the library's own unlayered stylesheet, while Tailwind's utilities live in
29
+ * a cascade layer — and any layered rule loses to an unlayered one of the same
30
+ * specificity, whatever order the files load in. An inline declaration is the
31
+ * only paint that reliably wins, which is also how the port did it.
32
+ *
33
+ * The pin is ringed in `--cue-bg` rather than in the card's own surface, so it
34
+ * reads as lifted off the edge it straddles no matter which surface rung the
35
+ * node is on.
36
+ *
37
+ * @example
38
+ * <NodeHandle type="source" position={Position.Right} id="u1" />
39
+ * @example
40
+ * <NodeHandle type="target" position={Position.Left} id="in" tone="muted" />
41
+ */
42
+ const NodeHandle = React.forwardRef(function NodeHandle({ className, style, tone = "accent", size = 9, ...handleProps }, ref) {
43
+ return /* @__PURE__ */ jsx(Handle, {
44
+ ref,
45
+ "data-slot": "node-handle",
46
+ "data-tone": tone,
47
+ className,
48
+ style: {
49
+ width: toRem(size),
50
+ height: toRem(size),
51
+ minWidth: toRem(size),
52
+ minHeight: toRem(size),
53
+ backgroundColor: TONE_COLORS[tone],
54
+ borderColor: "var(--cue-bg)",
55
+ ...style
56
+ },
57
+ ...handleProps
58
+ });
59
+ });
60
+ //#endregion
61
+ export { FLOW_HANDLE_SIZE, NodeHandle };
@@ -0,0 +1,7 @@
1
+ import { FLOW_NODE_FRAME_COLOR, FLOW_NODE_FRAME_FALLBACK, FLOW_NODE_FRAME_PROPERTY, FlowNodeState, FlowNodeTone, flowFrameColor } from "./_frame.js";
2
+ import { FlowBackground, FlowBackgroundProps, FlowControls, FlowControlsProps } from "./controls.js";
3
+ import { FLOW_HANDLE_SIZE, FlowHandleTone, NodeHandle, NodeHandleProps } from "./handles.js";
4
+ import { NodeCard, NodeCardProps } from "./node-card.js";
5
+ import { SIGNAL_EDGE_FLOW_CLASS, SIGNAL_EDGE_INTERACTION_WIDTH, SignalEdge, SignalEdgeData, SignalEdgeProps, SignalEdgeType, SignalTone } from "./signal-edge.js";
6
+ import { FLOW_THEME_VARIABLES, FlowTheme, useFlowTheme } from "./use-flow-theme.js";
7
+ export { FLOW_HANDLE_SIZE, FLOW_NODE_FRAME_COLOR, FLOW_NODE_FRAME_FALLBACK, FLOW_NODE_FRAME_PROPERTY, FLOW_THEME_VARIABLES, FlowBackground, type FlowBackgroundProps, FlowControls, type FlowControlsProps, type FlowHandleTone, type FlowNodeState, type FlowNodeTone, type FlowTheme, NodeCard, type NodeCardProps, NodeHandle, type NodeHandleProps, SIGNAL_EDGE_FLOW_CLASS, SIGNAL_EDGE_INTERACTION_WIDTH, SignalEdge, type SignalEdgeData, type SignalEdgeProps, type SignalEdgeType, type SignalTone, flowFrameColor, useFlowTheme };
@@ -0,0 +1,7 @@
1
+ import { FLOW_NODE_FRAME_COLOR, FLOW_NODE_FRAME_FALLBACK, FLOW_NODE_FRAME_PROPERTY, flowFrameColor } from "./_frame.js";
2
+ import { SIGNAL_EDGE_FLOW_CLASS, SIGNAL_EDGE_INTERACTION_WIDTH, SignalEdge } from "./signal-edge.js";
3
+ import { FLOW_THEME_VARIABLES, useFlowTheme } from "./use-flow-theme.js";
4
+ import { FlowBackground, FlowControls } from "./controls.js";
5
+ import { FLOW_HANDLE_SIZE, NodeHandle } from "./handles.js";
6
+ import { NodeCard } from "./node-card.js";
7
+ export { FLOW_HANDLE_SIZE, FLOW_NODE_FRAME_COLOR, FLOW_NODE_FRAME_FALLBACK, FLOW_NODE_FRAME_PROPERTY, FLOW_THEME_VARIABLES, FlowBackground, FlowControls, NodeCard, NodeHandle, SIGNAL_EDGE_FLOW_CLASS, SIGNAL_EDGE_INTERACTION_WIDTH, SignalEdge, flowFrameColor, useFlowTheme };
@@ -0,0 +1,71 @@
1
+ import { FlowNodeState, FlowNodeTone } from "./_frame.js";
2
+ import * as React from "react";
3
+ //#region src/flow/node-card.d.ts
4
+ interface NodeCardProps extends React.ComponentPropsWithoutRef<"div"> {
5
+ /** Where the node sits in the signal path. Inks the frame at rest. */
6
+ tone?: FlowNodeTone;
7
+ /**
8
+ * What the node is doing right now. Outranks `tone`.
9
+ *
10
+ * Pass React Flow's own `selected` through:
11
+ * `state={selected ? "selected" : "idle"}`.
12
+ */
13
+ state?: FlowNodeState;
14
+ /** The summary band: a label, a toggle, a badge. Also the drag handle. */
15
+ header?: React.ReactNode;
16
+ /** Whether the body is shown. Defaults to `true`; `false` renders the band alone. */
17
+ expanded?: boolean;
18
+ /**
19
+ * Called with the requested state when the caret is clicked. Supplying it is
20
+ * what makes the caret appear — a card nobody can collapse should not offer to.
21
+ */
22
+ onExpandedChange?: (expanded: boolean) => void;
23
+ /** Accessible name for the caret. Defaults to `"Collapse"` / `"Expand"`. */
24
+ toggleLabel?: string;
25
+ /** The body: rows, bars, fields. Full-bleed — rows own their own padding. */
26
+ children?: React.ReactNode;
27
+ }
28
+ /**
29
+ * A node on a graph canvas, drawn in this system's language.
30
+ *
31
+ * Framed with an **outline, never a border**. React Flow is told a node's height
32
+ * up front — every layout that stacks nodes computes it — and a 1px border on
33
+ * each side makes the rendered box 2px taller than the number the layout used,
34
+ * which is how node stacks end up overlapping by a hairline that grows with the
35
+ * node count. An outline is painted outside the box model entirely and costs
36
+ * nothing, so the formula and the DOM agree. `-outline-offset-1` then pulls it
37
+ * back inside the corner radius.
38
+ *
39
+ * The frame's colour is the node's state (see `_frame.ts`): selected beats live
40
+ * beats identity. When neither `tone` nor `state` is given the card paints no
41
+ * colour of its own and inherits `--cue-node-frame` from the node wrapper, which
42
+ * is how `useFlowTheme().nodeStyles` colours a whole class of nodes at once.
43
+ *
44
+ * The header band is the drag handle — pass
45
+ * `dragHandle: '[data-slot="node-card-header"]'` on the node so a pointer inside
46
+ * the body edits instead of dragging.
47
+ *
48
+ * Nothing here imports `@xyflow/react`: a node card is a div, and the same card
49
+ * draws a static diagram on a marketing page with no graph engine shipped. It
50
+ * also never clips — handles straddle the rim, so an `overflow-hidden` in
51
+ * `className` would slice every connection point in half.
52
+ *
53
+ * @example
54
+ * function MergeNode({ selected }: NodeProps) {
55
+ * const [open, setOpen] = React.useState(true);
56
+ * return (
57
+ * <NodeCard
58
+ * tone="processing"
59
+ * state={selected ? "selected" : "live"}
60
+ * header={<span className="truncate">merge · universe 3</span>}
61
+ * expanded={open}
62
+ * onExpandedChange={setOpen}
63
+ * >
64
+ * <DmxBar data={frame} />
65
+ * </NodeCard>
66
+ * );
67
+ * }
68
+ */
69
+ declare const NodeCard: React.ForwardRefExoticComponent<NodeCardProps & React.RefAttributes<HTMLDivElement>>;
70
+ //#endregion
71
+ export { NodeCard, NodeCardProps };
@@ -0,0 +1,102 @@
1
+ "use client";
2
+ import { cn } from "../lib/cn.js";
3
+ import { FLOW_NODE_FRAME_COLOR, FLOW_NODE_FRAME_PROPERTY, flowFrameColor } from "./_frame.js";
4
+ import * as React from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/flow/node-card.tsx
7
+ /**
8
+ * React Flow's two opt-outs, on every control a card owns.
9
+ *
10
+ * Without `nodrag` a click on the chevron drags the node out from under the
11
+ * pointer; without `nopan` a drag that starts inside the card pans the whole
12
+ * viewport. They are class names because that is the only interface the library
13
+ * offers for it.
14
+ */
15
+ const NO_CANVAS_GESTURE = "nodrag nopan";
16
+ /**
17
+ * A node on a graph canvas, drawn in this system's language.
18
+ *
19
+ * Framed with an **outline, never a border**. React Flow is told a node's height
20
+ * up front — every layout that stacks nodes computes it — and a 1px border on
21
+ * each side makes the rendered box 2px taller than the number the layout used,
22
+ * which is how node stacks end up overlapping by a hairline that grows with the
23
+ * node count. An outline is painted outside the box model entirely and costs
24
+ * nothing, so the formula and the DOM agree. `-outline-offset-1` then pulls it
25
+ * back inside the corner radius.
26
+ *
27
+ * The frame's colour is the node's state (see `_frame.ts`): selected beats live
28
+ * beats identity. When neither `tone` nor `state` is given the card paints no
29
+ * colour of its own and inherits `--cue-node-frame` from the node wrapper, which
30
+ * is how `useFlowTheme().nodeStyles` colours a whole class of nodes at once.
31
+ *
32
+ * The header band is the drag handle — pass
33
+ * `dragHandle: '[data-slot="node-card-header"]'` on the node so a pointer inside
34
+ * the body edits instead of dragging.
35
+ *
36
+ * Nothing here imports `@xyflow/react`: a node card is a div, and the same card
37
+ * draws a static diagram on a marketing page with no graph engine shipped. It
38
+ * also never clips — handles straddle the rim, so an `overflow-hidden` in
39
+ * `className` would slice every connection point in half.
40
+ *
41
+ * @example
42
+ * function MergeNode({ selected }: NodeProps) {
43
+ * const [open, setOpen] = React.useState(true);
44
+ * return (
45
+ * <NodeCard
46
+ * tone="processing"
47
+ * state={selected ? "selected" : "live"}
48
+ * header={<span className="truncate">merge · universe 3</span>}
49
+ * expanded={open}
50
+ * onExpandedChange={setOpen}
51
+ * >
52
+ * <DmxBar data={frame} />
53
+ * </NodeCard>
54
+ * );
55
+ * }
56
+ */
57
+ const NodeCard = React.forwardRef(function NodeCard({ className, style, tone, state, header, expanded = true, onExpandedChange, toggleLabel, children, ...elementProps }, ref) {
58
+ const bodyId = React.useId();
59
+ const frame = flowFrameColor(tone, state);
60
+ const hasBody = expanded && children !== void 0 && children !== null;
61
+ return /* @__PURE__ */ jsxs("div", {
62
+ ref,
63
+ "data-slot": "node-card",
64
+ "data-tone": tone,
65
+ "data-state": state,
66
+ className: cn("relative flex min-w-0 flex-col rounded-(--radius-surface) bg-surface-1 font-mono text-(length:--cue-text-label) text-fg outline-1 outline-solid -outline-offset-1", state === "disabled" && "opacity-50", className),
67
+ style: {
68
+ outlineColor: FLOW_NODE_FRAME_COLOR,
69
+ ...frame === void 0 ? null : { [FLOW_NODE_FRAME_PROPERTY]: frame },
70
+ ...style
71
+ },
72
+ ...elementProps,
73
+ children: [header === void 0 ? null : /* @__PURE__ */ jsxs("div", {
74
+ "data-slot": "node-card-header",
75
+ className: cn("flex h-control-sm min-w-0 shrink-0 items-center gap-(--cue-space-2) px-(--cue-space-3) font-medium", hasBody && "shadow-[inset_0_-1px_0_var(--cue-border)]"),
76
+ children: [/* @__PURE__ */ jsx("span", {
77
+ "data-slot": "node-card-title",
78
+ className: "min-w-0 flex-1 truncate",
79
+ children: header
80
+ }), onExpandedChange === void 0 ? null : /* @__PURE__ */ jsx("button", {
81
+ type: "button",
82
+ "data-slot": "node-card-toggle",
83
+ "aria-expanded": expanded,
84
+ "aria-controls": hasBody ? bodyId : void 0,
85
+ "aria-label": toggleLabel ?? (expanded ? "Collapse" : "Expand"),
86
+ className: cn(NO_CANVAS_GESTURE, "shrink-0 cursor-pointer border-0 bg-transparent p-0 text-(length:--cue-text-micro) leading-none text-fg-subtle outline-none select-none hover:text-fg-muted focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-accent"),
87
+ onClick: () => onExpandedChange(!expanded),
88
+ children: /* @__PURE__ */ jsx("span", {
89
+ "aria-hidden": "true",
90
+ children: expanded ? "▾" : "▸"
91
+ })
92
+ })]
93
+ }), hasBody ? /* @__PURE__ */ jsx("div", {
94
+ id: bodyId,
95
+ "data-slot": "node-card-body",
96
+ className: "flex min-w-0 flex-col",
97
+ children
98
+ }) : null]
99
+ });
100
+ });
101
+ //#endregion
102
+ export { NodeCard };
@@ -0,0 +1,60 @@
1
+ import * as React from "react";
2
+ import { Edge, EdgeProps } from "@xyflow/react";
3
+ //#region src/flow/signal-edge.d.ts
4
+ /** What a wire is carrying. `muted` is a link that exists but is switched off. */
5
+ type SignalTone = "accent" | "ok" | "busy" | "warn" | "danger" | "info";
6
+ /**
7
+ * The class the animated overlay carries.
8
+ *
9
+ * `flow.css` owns its `@keyframes` and its reduced-motion switch; the dash
10
+ * pattern itself is inline, so an app that never imported the stylesheet still
11
+ * gets a legible dashed highlight instead of a mystery second line.
12
+ */
13
+ declare const SIGNAL_EDGE_FLOW_CLASS = "cue-signal-flow";
14
+ /**
15
+ * Width of the invisible path the pointer actually hits, in px.
16
+ *
17
+ * A 1.6px wire is a nearly impossible click target and an outright impossible
18
+ * touch target. The library's own default is 20; 16 is the port's, and it is
19
+ * wide enough without swallowing the gap between two parallel wires.
20
+ */
21
+ declare const SIGNAL_EDGE_INTERACTION_WIDTH = 16;
22
+ interface SignalEdgeData extends Record<string, unknown> {
23
+ /** Signal is actually moving right now: full opacity plus the animated dash. */
24
+ live?: boolean;
25
+ /** The link exists but is switched off: grey, thin and dim. */
26
+ muted?: boolean;
27
+ /** What the wire carries. Defaults to `"accent"`. */
28
+ tone?: SignalTone;
29
+ }
30
+ /** The edge shape this component reads. Use it to type your `edges` array. */
31
+ type SignalEdgeType = Edge<SignalEdgeData, "signal">;
32
+ /** Props React Flow hands the edge — both endpoints already in viewport space. */
33
+ type SignalEdgeProps = EdgeProps<SignalEdgeType>;
34
+ /**
35
+ * A wire between two nodes, drawn as three paths.
36
+ *
37
+ * 1. **The wire.** A bezier in the tone's colour, thin and half-lit at rest.
38
+ * 2. **The hit path.** Sixteen invisible pixels of it, because nobody can click
39
+ * 1.6px. `BaseEdge` draws this one, and the edge label, for free.
40
+ * 3. **The pulse.** Only while `data.live` — a pale dashed overlay of the same
41
+ * colour, marching along the wire. This is the only animation in the group,
42
+ * it carries no information the opacity does not, and `flow.css` stops it
43
+ * dead under `prefers-reduced-motion`.
44
+ *
45
+ * State is read from props rather than from a store on purpose: an edge that
46
+ * subscribed to "is this route live" would re-render on every frame of a 40Hz
47
+ * telemetry feed, times the number of edges. The host decides when the answer
48
+ * changed; this component only draws it. It also means the component is a pure
49
+ * function of its props — no hooks, no context, no canvas needed to test it.
50
+ *
51
+ * Selection outranks everything, including the pulse: two loud treatments on one
52
+ * wire read as neither.
53
+ *
54
+ * @example
55
+ * const edges = [{ id: "r1", source: "s1", target: "m1", type: "signal", data: { live: true } }];
56
+ * <ReactFlow edges={edges} edgeTypes={theme.edgeTypes} />
57
+ */
58
+ declare function SignalEdge({ id, sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, selected, data, style, markerStart, markerEnd, interactionWidth, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius }: SignalEdgeProps): React.JSX.Element;
59
+ //#endregion
60
+ export { SIGNAL_EDGE_FLOW_CLASS, SIGNAL_EDGE_INTERACTION_WIDTH, SignalEdge, SignalEdgeData, SignalEdgeProps, SignalEdgeType, SignalTone };
@@ -0,0 +1,108 @@
1
+ import "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { BaseEdge, getBezierPath } from "@xyflow/react";
4
+ //#region src/flow/signal-edge.tsx
5
+ const TONE_COLORS = {
6
+ accent: "var(--cue-accent)",
7
+ ok: "var(--cue-ok)",
8
+ busy: "var(--cue-busy)",
9
+ warn: "var(--cue-warn)",
10
+ danger: "var(--cue-danger)",
11
+ info: "var(--cue-info)"
12
+ };
13
+ /** A wire nobody has switched on. */
14
+ const MUTED_COLOR = "var(--cue-fg-subtle)";
15
+ /** Selection is the loudest thing on the canvas, and it is never a hue. */
16
+ const SELECTED_COLOR = "var(--cue-fg)";
17
+ /**
18
+ * The class the animated overlay carries.
19
+ *
20
+ * `flow.css` owns its `@keyframes` and its reduced-motion switch; the dash
21
+ * pattern itself is inline, so an app that never imported the stylesheet still
22
+ * gets a legible dashed highlight instead of a mystery second line.
23
+ */
24
+ const SIGNAL_EDGE_FLOW_CLASS = "cue-signal-flow";
25
+ /**
26
+ * Width of the invisible path the pointer actually hits, in px.
27
+ *
28
+ * A 1.6px wire is a nearly impossible click target and an outright impossible
29
+ * touch target. The library's own default is 20; 16 is the port's, and it is
30
+ * wide enough without swallowing the gap between two parallel wires.
31
+ */
32
+ const SIGNAL_EDGE_INTERACTION_WIDTH = 16;
33
+ /** The dash and gap of the flowing overlay, in px. */
34
+ const FLOW_DASH = "3 8";
35
+ /** A pale mix of the wire's own colour: the same signal, not a second one. */
36
+ function flowHighlight(stroke) {
37
+ return `color-mix(in oklch, ${stroke} 55%, var(--cue-fg))`;
38
+ }
39
+ /**
40
+ * A wire between two nodes, drawn as three paths.
41
+ *
42
+ * 1. **The wire.** A bezier in the tone's colour, thin and half-lit at rest.
43
+ * 2. **The hit path.** Sixteen invisible pixels of it, because nobody can click
44
+ * 1.6px. `BaseEdge` draws this one, and the edge label, for free.
45
+ * 3. **The pulse.** Only while `data.live` — a pale dashed overlay of the same
46
+ * colour, marching along the wire. This is the only animation in the group,
47
+ * it carries no information the opacity does not, and `flow.css` stops it
48
+ * dead under `prefers-reduced-motion`.
49
+ *
50
+ * State is read from props rather than from a store on purpose: an edge that
51
+ * subscribed to "is this route live" would re-render on every frame of a 40Hz
52
+ * telemetry feed, times the number of edges. The host decides when the answer
53
+ * changed; this component only draws it. It also means the component is a pure
54
+ * function of its props — no hooks, no context, no canvas needed to test it.
55
+ *
56
+ * Selection outranks everything, including the pulse: two loud treatments on one
57
+ * wire read as neither.
58
+ *
59
+ * @example
60
+ * const edges = [{ id: "r1", source: "s1", target: "m1", type: "signal", data: { live: true } }];
61
+ * <ReactFlow edges={edges} edgeTypes={theme.edgeTypes} />
62
+ */
63
+ function SignalEdge({ id, sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, selected, data, style, markerStart, markerEnd, interactionWidth = 16, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius }) {
64
+ const [path, labelX, labelY] = getBezierPath({
65
+ sourceX,
66
+ sourceY,
67
+ sourcePosition,
68
+ targetX,
69
+ targetY,
70
+ targetPosition
71
+ });
72
+ const muted = data?.muted === true;
73
+ const live = data?.live === true && !muted && selected !== true;
74
+ const stroke = selected === true ? SELECTED_COLOR : muted ? MUTED_COLOR : TONE_COLORS[data?.tone ?? "accent"];
75
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(BaseEdge, {
76
+ id,
77
+ path,
78
+ markerStart,
79
+ markerEnd,
80
+ interactionWidth,
81
+ label,
82
+ labelX,
83
+ labelY,
84
+ labelStyle,
85
+ labelShowBg,
86
+ labelBgStyle,
87
+ labelBgPadding,
88
+ labelBgBorderRadius,
89
+ style: {
90
+ stroke,
91
+ strokeWidth: selected === true ? 2.4 : muted ? 1 : 1.6,
92
+ opacity: selected === true || live ? 1 : muted ? .4 : .6,
93
+ ...style
94
+ }
95
+ }), live ? /* @__PURE__ */ jsx("path", {
96
+ d: path,
97
+ fill: "none",
98
+ pointerEvents: "none",
99
+ className: SIGNAL_EDGE_FLOW_CLASS,
100
+ style: {
101
+ stroke: flowHighlight(stroke),
102
+ strokeWidth: 1.9,
103
+ strokeDasharray: FLOW_DASH
104
+ }
105
+ }) : null] });
106
+ }
107
+ //#endregion
108
+ export { SIGNAL_EDGE_FLOW_CLASS, SIGNAL_EDGE_INTERACTION_WIDTH, SignalEdge };
@@ -0,0 +1,69 @@
1
+ import { ResolvedMode } from "../system/theme-provider.js";
2
+ import { FlowNodeTone } from "./_frame.js";
3
+ import { SignalEdge } from "./signal-edge.js";
4
+ import * as React from "react";
5
+ //#region src/flow/use-flow-theme.d.ts
6
+ /**
7
+ * React Flow paints its own chrome — edges, handles, controls, the minimap, the
8
+ * selection box — from a documented set of `--xy-*` custom properties, each one
9
+ * consulted before the library's built-in default. Mapping that set onto this
10
+ * system's tokens is the whole theme: no wrapper components, no props threaded
11
+ * through a graph, and a theme, mode or density switch that costs nothing
12
+ * because every value is a *reference*, re-resolved by the browser.
13
+ *
14
+ * The map is published two ways, and they are checked against each other
15
+ * (`test/flow/flow-css.test.ts`):
16
+ *
17
+ * - as this object, to spread on the canvas: `<ReactFlow style={theme.style}>`;
18
+ * - as the `.react-flow` block of `flow.css`, for apps that would rather import
19
+ * a stylesheet than thread a prop.
20
+ *
21
+ * Either is enough. Both is harmless.
22
+ */
23
+ declare const FLOW_THEME_VARIABLES: Readonly<Record<string, string>>;
24
+ interface FlowTheme {
25
+ /**
26
+ * The resolved mode, for `<ReactFlow colorMode>`.
27
+ *
28
+ * Only a fallback: with {@link FlowTheme.style} spread (or `flow.css`
29
+ * imported) every value the library would pick from its own light/dark
30
+ * defaults has already been overridden. It costs one prop to be right anyway
31
+ * for the one that has not.
32
+ */
33
+ colorMode: ResolvedMode;
34
+ /** The `--xy-*` token map. Spread on `<ReactFlow style>`. */
35
+ style: Readonly<Record<string, string>>;
36
+ /** `{ signal: SignalEdge }`, stable across renders. */
37
+ edgeTypes: Readonly<Record<"signal", typeof SignalEdge>>;
38
+ /** `{ type: "signal", interactionWidth }`, stable across renders. */
39
+ defaultEdgeOptions: Readonly<{
40
+ type: "signal";
41
+ interactionWidth: number;
42
+ }>;
43
+ /** Frame colour per node kind, for a node's own `style`. */
44
+ nodeStyles: Readonly<Record<FlowNodeTone, React.CSSProperties>>;
45
+ }
46
+ /**
47
+ * Everything a `<ReactFlow>` needs to look like it belongs to this system.
48
+ *
49
+ * @example
50
+ * const theme = useFlowTheme();
51
+ * <ReactFlow
52
+ * nodes={nodes}
53
+ * edges={edges}
54
+ * nodeTypes={nodeTypes}
55
+ * edgeTypes={theme.edgeTypes}
56
+ * defaultEdgeOptions={theme.defaultEdgeOptions}
57
+ * colorMode={theme.colorMode}
58
+ * style={theme.style}
59
+ * >
60
+ * <FlowBackground />
61
+ * <FlowControls />
62
+ * </ReactFlow>
63
+ * @example
64
+ * // Colour a whole class of nodes at once — the cards inherit the frame.
65
+ * const nodes = inputs.map((input) => ({ ...input, style: theme.nodeStyles.input }));
66
+ */
67
+ declare function useFlowTheme(): FlowTheme;
68
+ //#endregion
69
+ export { FLOW_THEME_VARIABLES, FlowTheme, useFlowTheme };