@cueplusplus/ui 0.16.0 → 0.17.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 (480) hide show
  1. package/CHANGELOG.md +825 -0
  2. package/README.md +1 -1
  3. package/dist/agent-runtime/tool-call-card.js +7 -3
  4. package/dist/brand/_chassis.d.ts +1 -1
  5. package/dist/brand/cue-mark.d.ts +1 -1
  6. package/dist/brand/cue-mark.js +1 -1
  7. package/dist/charts/ramps.js +1 -1
  8. package/dist/chat/agent-pile.js +2 -1
  9. package/dist/chat/ask-box.js +4 -3
  10. package/dist/chat/delegation-card.js +3 -2
  11. package/dist/chat/message-list.js +3 -2
  12. package/dist/chat/message.js +17 -7
  13. package/dist/chrome/_edge-scroller.js +2 -1
  14. package/dist/chrome/_status-bar.js +9 -3
  15. package/dist/chrome/_tabs-scroll.d.ts +1 -1
  16. package/dist/chrome/_tabs-scroll.js +1 -1
  17. package/dist/chrome/app-bar.js +9 -3
  18. package/dist/chrome/app-shell.js +2 -1
  19. package/dist/chrome/band.d.ts +18 -12
  20. package/dist/chrome/band.js +18 -32
  21. package/dist/chrome/eyebrow.d.ts +13 -5
  22. package/dist/chrome/eyebrow.js +18 -7
  23. package/dist/chrome/footer.d.ts +5 -0
  24. package/dist/chrome/footer.js +14 -3
  25. package/dist/chrome/navigation-menu.js +4 -2
  26. package/dist/chrome/page-shell.js +8 -5
  27. package/dist/chrome/panel.d.ts +5 -2
  28. package/dist/chrome/panel.js +8 -4
  29. package/dist/chrome/row.js +6 -3
  30. package/dist/chrome/scroll-area.js +2 -1
  31. package/dist/chrome/section-header.js +13 -4
  32. package/dist/chrome/segmented-control.js +12 -3
  33. package/dist/chrome/status-bar.js +2 -1
  34. package/dist/chrome/tabs.js +11 -3
  35. package/dist/chrome/toolbar.js +2 -1
  36. package/dist/chrome/tree.js +3 -2
  37. package/dist/color/_thumb.js +9 -3
  38. package/dist/color/color-area.js +1 -1
  39. package/dist/color/color-swatch.js +1 -1
  40. package/dist/configurator/_overrides.js +13 -4
  41. package/dist/configurator/configurator.js +4 -1
  42. package/dist/configurator/export-dialog.js +5 -2
  43. package/dist/configurator/panel-sections.js +6 -2
  44. package/dist/configurator/token-editor.js +4 -1
  45. package/dist/date/calendar.js +12 -8
  46. package/dist/dmx/channel-matrix.js +3 -2
  47. package/dist/dmx/dmx-bar.js +1 -1
  48. package/dist/dmx/dmx-strip.js +1 -1
  49. package/dist/dmx/universe-grid.js +3 -2
  50. package/dist/elements/activity-graph.js +3 -3
  51. package/dist/elements/agent-card.js +3 -3
  52. package/dist/elements/approval-card.js +3 -3
  53. package/dist/elements/artifact-card.js +2 -2
  54. package/dist/elements/background-inbox.js +2 -2
  55. package/dist/elements/canvas-split.js +2 -2
  56. package/dist/elements/chart.js +1 -1
  57. package/dist/elements/chat-panel.js +2 -2
  58. package/dist/elements/checkpoint-history.js +2 -2
  59. package/dist/elements/clamp.js +2 -1
  60. package/dist/elements/code-diff.js +1 -1
  61. package/dist/elements/code-runner.js +1 -1
  62. package/dist/elements/command-palette.js +6 -5
  63. package/dist/elements/comparison-card.js +2 -2
  64. package/dist/elements/composer.js +9 -8
  65. package/dist/elements/computer-use.js +1 -1
  66. package/dist/elements/confidence-marker.js +2 -1
  67. package/dist/elements/connection-state.js +1 -1
  68. package/dist/elements/context-breakdown.js +1 -1
  69. package/dist/elements/context-usage.js +1 -1
  70. package/dist/elements/conversation-search.js +4 -3
  71. package/dist/elements/cost-meter.js +1 -1
  72. package/dist/elements/data-table.js +2 -2
  73. package/dist/elements/day-separator.js +1 -1
  74. package/dist/elements/diagram.js +1 -1
  75. package/dist/elements/document-reference.js +3 -3
  76. package/dist/elements/draft-restore.js +1 -1
  77. package/dist/elements/edit-message.js +4 -3
  78. package/dist/elements/elements.css +26 -5
  79. package/dist/elements/elicitation-form.js +3 -3
  80. package/dist/elements/empty-state.js +2 -1
  81. package/dist/elements/error-state.js +1 -1
  82. package/dist/elements/feedback-dialog.js +4 -3
  83. package/dist/elements/file-tree.js +2 -2
  84. package/dist/elements/flow-graph.js +2 -2
  85. package/dist/elements/guardrail-notice.js +3 -3
  86. package/dist/elements/image-generation.js +1 -1
  87. package/dist/elements/inline-citation.js +3 -3
  88. package/dist/elements/job-progress.js +3 -3
  89. package/dist/elements/launcher-bubble.js +2 -2
  90. package/dist/elements/loading-state.js +1 -1
  91. package/dist/elements/map-answer.js +3 -2
  92. package/dist/elements/markdown.js +5 -4
  93. package/dist/elements/math-block.js +1 -1
  94. package/dist/elements/mcp-server-panel.js +3 -3
  95. package/dist/elements/message-attachment.js +4 -4
  96. package/dist/elements/message-pair.js +1 -1
  97. package/dist/elements/message-queue.js +2 -2
  98. package/dist/elements/mobile-composer.js +4 -3
  99. package/dist/elements/model-picker.js +3 -3
  100. package/dist/elements/onboarding.js +2 -2
  101. package/dist/elements/permission-grant.js +2 -2
  102. package/dist/elements/permission-scopes.js +5 -4
  103. package/dist/elements/prompt-library.js +7 -6
  104. package/dist/elements/queue-dock.js +4 -3
  105. package/dist/elements/quota-banner.js +1 -1
  106. package/dist/elements/quote-reply.js +1 -1
  107. package/dist/elements/read-aloud.js +2 -2
  108. package/dist/elements/reasoning-panel.js +2 -1
  109. package/dist/elements/recommendation-card.d.ts +1 -1
  110. package/dist/elements/recommendation-card.js +2 -2
  111. package/dist/elements/regenerate-menu.js +2 -2
  112. package/dist/elements/research-report.js +1 -1
  113. package/dist/elements/retrieval-chunks.js +1 -1
  114. package/dist/elements/revert-dock.js +5 -4
  115. package/dist/elements/reviewable-diff.js +1 -1
  116. package/dist/elements/schedule-card.js +3 -3
  117. package/dist/elements/score-breakdown.js +1 -1
  118. package/dist/elements/scroll-anchor.js +2 -2
  119. package/dist/elements/settings-panel.js +3 -2
  120. package/dist/elements/shared-conversation.js +2 -2
  121. package/dist/elements/sources.js +4 -3
  122. package/dist/elements/speaker-identity.js +1 -1
  123. package/dist/elements/spec-sheet.js +1 -1
  124. package/dist/elements/streaming-text.js +1 -1
  125. package/dist/elements/subagent-list.js +2 -2
  126. package/dist/elements/suggestions.js +1 -1
  127. package/dist/elements/surfaces.d.ts +1 -1
  128. package/dist/elements/surfaces.js +2 -1
  129. package/dist/elements/tail-status.js +1 -1
  130. package/dist/elements/terminal-block.js +1 -1
  131. package/dist/elements/thread-list.js +1 -1
  132. package/dist/elements/thread-search.js +5 -4
  133. package/dist/elements/timeline.js +1 -1
  134. package/dist/elements/todo-list.js +2 -2
  135. package/dist/elements/tool-call.js +4 -3
  136. package/dist/elements/tool-error.js +2 -2
  137. package/dist/elements/tool-group.js +1 -1
  138. package/dist/elements/tool-timeline.js +4 -3
  139. package/dist/elements/trace-waterfall.js +1 -1
  140. package/dist/elements/verdict-row.js +2 -2
  141. package/dist/elements/voice-conversation.js +3 -2
  142. package/dist/elements/web-preview.js +1 -1
  143. package/dist/elements/web-search.js +2 -2
  144. package/dist/elements/work-collapse.js +2 -1
  145. package/dist/flow/node-card.js +3 -2
  146. package/dist/flow/use-flow-theme.js +2 -1
  147. package/dist/forms/_chassis.d.ts +26 -6
  148. package/dist/forms/_chassis.js +33 -8
  149. package/dist/forms/_listbox.js +8 -5
  150. package/dist/forms/checkbox.js +8 -2
  151. package/dist/forms/env-var-input.js +3 -2
  152. package/dist/forms/field.d.ts +2 -1
  153. package/dist/forms/field.js +15 -4
  154. package/dist/forms/file-upload.js +3 -2
  155. package/dist/forms/number-field.js +2 -1
  156. package/dist/forms/password-input.js +4 -2
  157. package/dist/forms/radio-group.js +6 -2
  158. package/dist/forms/rating.js +2 -1
  159. package/dist/forms/scrub-input.js +2 -1
  160. package/dist/forms/search-input.js +2 -1
  161. package/dist/forms/select.js +5 -2
  162. package/dist/forms/slider.js +6 -2
  163. package/dist/forms/switch.js +6 -2
  164. package/dist/forms/textarea.js +2 -1
  165. package/dist/forms/toggle.js +3 -1
  166. package/dist/index.d.ts +2 -2
  167. package/dist/index.js +2 -2
  168. package/dist/instruments/_data-row.js +2 -1
  169. package/dist/instruments/app-window-frame.js +1 -1
  170. package/dist/instruments/code-block.js +8 -2
  171. package/dist/instruments/group-bar.js +1 -1
  172. package/dist/instruments/ledger.js +6 -2
  173. package/dist/instruments/log-viewer.js +4 -3
  174. package/dist/instruments/progress.js +5 -2
  175. package/dist/instruments/seam-grid.js +5 -3
  176. package/dist/instruments/stat.js +10 -3
  177. package/dist/instruments/table.js +28 -10
  178. package/dist/instruments/terminal-frame.js +4 -2
  179. package/dist/instruments/usage-chart.js +1 -1
  180. package/dist/layout/_collapse.js +6 -1
  181. package/dist/layout/bento.js +7 -4
  182. package/dist/layout/breadcrumb.js +7 -3
  183. package/dist/layout/card.js +12 -6
  184. package/dist/layout/carousel.js +3 -2
  185. package/dist/layout/collapsible.js +5 -1
  186. package/dist/layout/container.js +2 -1
  187. package/dist/layout/description-list.js +4 -1
  188. package/dist/layout/frames.js +11 -5
  189. package/dist/layout/item.js +3 -2
  190. package/dist/layout/link.d.ts +16 -0
  191. package/dist/layout/link.js +22 -3
  192. package/dist/layout/pagination.js +2 -1
  193. package/dist/layout/preview.d.ts +32 -12
  194. package/dist/layout/preview.js +149 -40
  195. package/dist/layout/resizable.js +2 -1
  196. package/dist/layout/sidebar.js +11 -3
  197. package/dist/layout/stepper.js +6 -2
  198. package/dist/lib/cn.js +29 -2
  199. package/dist/midi/piano-keyboard.js +3 -2
  200. package/dist/midi/spectrum-visualizer.js +1 -1
  201. package/dist/midi/threshold-rail.js +2 -1
  202. package/dist/midi/timeline-ruler.js +1 -1
  203. package/dist/overlays/_surface.d.ts +72 -12
  204. package/dist/overlays/_surface.js +84 -12
  205. package/dist/overlays/command-palette.js +9 -5
  206. package/dist/overlays/dialog.d.ts +5 -0
  207. package/dist/overlays/dialog.js +6 -1
  208. package/dist/overlays/info-tip.js +2 -1
  209. package/dist/overlays/menubar.js +3 -1
  210. package/dist/overlays/popover.js +2 -1
  211. package/dist/overlays/toast.js +6 -2
  212. package/dist/overlays/tooltip.js +4 -1
  213. package/dist/primitives/button.d.ts +15 -0
  214. package/dist/primitives/button.js +40 -11
  215. package/dist/primitives/chip.d.ts +19 -1
  216. package/dist/primitives/chip.js +39 -17
  217. package/dist/primitives/kbd.d.ts +6 -0
  218. package/dist/primitives/kbd.js +10 -1
  219. package/dist/primitives/skeleton.js +1 -1
  220. package/dist/system/_focus-ring-field.js +29 -0
  221. package/dist/system/_focus-ring.js +125 -0
  222. package/dist/system/_paint-glow.js +22 -3
  223. package/dist/system/_paint-rest-shade.js +32 -0
  224. package/dist/system/_paint-rim.js +22 -4
  225. package/dist/system/_paint-stroke-surface-1.js +1 -1
  226. package/dist/system/_paint-stroke-surface-2.js +14 -1
  227. package/dist/system/_paint-texture.js +5 -2
  228. package/dist/system/_style-app-bar.js +65 -0
  229. package/dist/system/_style-band.js +57 -0
  230. package/dist/system/_style-body-leading.js +21 -0
  231. package/dist/system/_style-body-size.js +30 -0
  232. package/dist/system/_style-body-weight.js +24 -0
  233. package/dist/system/_style-body.js +27 -0
  234. package/dist/system/_style-caption.js +19 -0
  235. package/dist/system/_style-card-pad.js +43 -0
  236. package/dist/system/_style-check.js +33 -0
  237. package/dist/system/_style-chip.js +103 -0
  238. package/dist/system/_style-code.js +13 -0
  239. package/dist/system/_style-collapse.js +14 -0
  240. package/dist/system/_style-control-face.js +29 -0
  241. package/dist/system/_style-control-label.js +22 -0
  242. package/dist/system/_style-control-step.js +22 -0
  243. package/dist/system/_style-control.js +76 -0
  244. package/dist/system/_style-data-face.js +28 -0
  245. package/dist/system/_style-description.js +23 -0
  246. package/dist/system/_style-eyebrow.js +43 -0
  247. package/dist/system/_style-footer-rule.js +47 -0
  248. package/dist/system/_style-gutter.js +17 -0
  249. package/dist/system/_style-help-ink.js +14 -0
  250. package/dist/system/_style-help.js +29 -0
  251. package/dist/system/_style-input-face.js +34 -0
  252. package/dist/system/_style-kbd.js +46 -0
  253. package/dist/system/_style-label-case.js +36 -0
  254. package/dist/system/_style-label-face.js +32 -0
  255. package/dist/system/_style-label-ink.js +29 -0
  256. package/dist/system/_style-label-leading.js +14 -0
  257. package/dist/system/_style-label-size.js +36 -0
  258. package/dist/system/_style-label-tracking.js +45 -0
  259. package/dist/system/_style-label-weight.js +40 -0
  260. package/dist/system/_style-lede.js +49 -0
  261. package/dist/system/_style-link.js +46 -0
  262. package/dist/system/_style-menu.js +30 -0
  263. package/dist/system/_style-nav-item.js +41 -0
  264. package/dist/system/_style-nav-voice.js +43 -0
  265. package/dist/system/_style-option.js +42 -0
  266. package/dist/system/_style-overlay-title.js +35 -0
  267. package/dist/system/_style-page-title.js +48 -0
  268. package/dist/system/_style-popover-pad.js +13 -0
  269. package/dist/system/_style-quiet-ink.js +13 -0
  270. package/dist/system/_style-row-pad.js +13 -0
  271. package/dist/system/_style-seam.js +43 -0
  272. package/dist/system/_style-section-rule.js +26 -0
  273. package/dist/system/_style-segment.js +30 -0
  274. package/dist/system/_style-segmented-control.js +86 -0
  275. package/dist/system/_style-selected.js +36 -0
  276. package/dist/system/_style-stage-marks.js +26 -0
  277. package/dist/system/_style-tab.js +71 -0
  278. package/dist/system/_style-textarea.js +21 -0
  279. package/dist/system/_style-title.js +37 -0
  280. package/dist/system/_style-tooltip.js +17 -0
  281. package/dist/system/density.d.ts +15 -5
  282. package/dist/system/density.js +188 -25
  283. package/dist/system/index.d.ts +2 -2
  284. package/dist/system/index.js +2 -2
  285. package/dist/system/overrides.d.ts +1 -0
  286. package/dist/system/overrides.js +151 -3
  287. package/dist/system/portal.d.ts +3 -2
  288. package/dist/system/portal.js +22 -10
  289. package/dist/system/prepaint.d.ts +21 -5
  290. package/dist/system/prepaint.js +3 -1
  291. package/dist/system/published.d.ts +1 -0
  292. package/dist/system/published.js +131 -0
  293. package/dist/system/theme-provider.d.ts +118 -21
  294. package/dist/system/theme-provider.js +362 -73
  295. package/dist/system/theme-registry.d.ts +2 -1
  296. package/dist/system/theme-registry.js +27 -10
  297. package/dist/system/use-density.js +4 -3
  298. package/dist/system/use-theme.d.ts +5 -2
  299. package/dist/system/use-theme.js +7 -4
  300. package/dist/system/vocabulary.js +2 -2
  301. package/dist/theming/create-theme.js +12 -6
  302. package/dist/theming/serialize.d.ts +34 -2
  303. package/dist/theming/serialize.js +86 -4
  304. package/manifest/components/accordion.json +7 -1
  305. package/manifest/components/agent-pile.json +3 -0
  306. package/manifest/components/alert-dialog.json +29 -3
  307. package/manifest/components/app-bar.json +19 -2
  308. package/manifest/components/app-shell.json +5 -0
  309. package/manifest/components/ask-box.json +3 -1
  310. package/manifest/components/autocomplete.json +38 -1
  311. package/manifest/components/band.json +7 -3
  312. package/manifest/components/bento.json +12 -1
  313. package/manifest/components/breadcrumb.json +8 -1
  314. package/manifest/components/button.json +27 -3
  315. package/manifest/components/calendar.json +7 -0
  316. package/manifest/components/card.json +22 -1
  317. package/manifest/components/carousel.json +4 -1
  318. package/manifest/components/channel-matrix.json +31 -3
  319. package/manifest/components/chart-tooltip-content.json +29 -3
  320. package/manifest/components/chat-empty-state.json +3 -1
  321. package/manifest/components/checkbox-group.json +14 -0
  322. package/manifest/components/checkbox.json +14 -0
  323. package/manifest/components/chip.json +16 -1
  324. package/manifest/components/clamp.json +3 -1
  325. package/manifest/components/code-block.json +10 -1
  326. package/manifest/components/collapsible.json +13 -2
  327. package/manifest/components/color-area.json +4 -2
  328. package/manifest/components/color-field.json +10 -0
  329. package/manifest/components/color-picker.json +10 -0
  330. package/manifest/components/color-slider.json +3 -1
  331. package/manifest/components/colors-section.json +9 -1
  332. package/manifest/components/combobox.json +38 -1
  333. package/manifest/components/command-palette.json +28 -3
  334. package/manifest/components/composer-actions.json +3 -0
  335. package/manifest/components/composer-attach-button.json +3 -0
  336. package/manifest/components/composer-attachment-chip.json +3 -0
  337. package/manifest/components/composer-attachments.json +3 -0
  338. package/manifest/components/composer-bar.json +3 -0
  339. package/manifest/components/composer-command-item.json +3 -0
  340. package/manifest/components/composer-context.json +3 -0
  341. package/manifest/components/composer-input.json +3 -0
  342. package/manifest/components/composer-menu-item.json +3 -0
  343. package/manifest/components/composer-menu.json +3 -0
  344. package/manifest/components/composer-model-item.json +3 -0
  345. package/manifest/components/composer-model-trigger.json +3 -0
  346. package/manifest/components/composer-person-item.json +3 -0
  347. package/manifest/components/composer-send.json +3 -0
  348. package/manifest/components/composer-toolbar.json +3 -0
  349. package/manifest/components/composer-voice-button.json +3 -0
  350. package/manifest/components/composer-voice.json +3 -0
  351. package/manifest/components/composer.json +10 -0
  352. package/manifest/components/confidence-marker.json +3 -1
  353. package/manifest/components/container.json +2 -1
  354. package/manifest/components/context-menu.json +29 -3
  355. package/manifest/components/conversation-search.json +3 -1
  356. package/manifest/components/cue-mark.json +2 -2
  357. package/manifest/components/cue-portal-frame.json +1 -1
  358. package/manifest/components/data-row.json +3 -1
  359. package/manifest/components/data-tree.json +3 -1
  360. package/manifest/components/date-field.json +10 -0
  361. package/manifest/components/date-picker.json +10 -0
  362. package/manifest/components/date-range-picker.json +10 -0
  363. package/manifest/components/delegation-card.json +3 -1
  364. package/manifest/components/density.json +15 -7
  365. package/manifest/components/description-list.json +6 -1
  366. package/manifest/components/dialog.json +30 -3
  367. package/manifest/components/disclosure.json +13 -2
  368. package/manifest/components/dmx-bar.json +28 -3
  369. package/manifest/components/dmx-strip.json +28 -3
  370. package/manifest/components/drawer.json +29 -3
  371. package/manifest/components/dropdown-menu.json +29 -3
  372. package/manifest/components/edit-message.json +3 -1
  373. package/manifest/components/elements-command-palette.json +3 -1
  374. package/manifest/components/elements-composer.json +3 -0
  375. package/manifest/components/empty-state-composer.json +3 -1
  376. package/manifest/components/empty-state-greeting.json +3 -1
  377. package/manifest/components/empty-state-suggestion.json +3 -1
  378. package/manifest/components/empty-state-suggestions.json +3 -1
  379. package/manifest/components/env-var-input.json +10 -1
  380. package/manifest/components/export-dialog.json +6 -1
  381. package/manifest/components/eyebrow.json +13 -2
  382. package/manifest/components/feedback-dialog.json +3 -0
  383. package/manifest/components/field-description.json +14 -0
  384. package/manifest/components/field-error.json +14 -0
  385. package/manifest/components/field-label.json +15 -1
  386. package/manifest/components/field.json +14 -0
  387. package/manifest/components/file-upload.json +3 -0
  388. package/manifest/components/footer.json +14 -1
  389. package/manifest/components/frames.json +14 -1
  390. package/manifest/components/hover-card.json +29 -3
  391. package/manifest/components/info-tip.json +3 -0
  392. package/manifest/components/input-group.json +10 -0
  393. package/manifest/components/input.json +10 -0
  394. package/manifest/components/item.json +3 -1
  395. package/manifest/components/kbd.json +10 -1
  396. package/manifest/components/ledger.json +9 -2
  397. package/manifest/components/link.json +10 -0
  398. package/manifest/components/log-viewer.json +3 -0
  399. package/manifest/components/map-answer.json +3 -1
  400. package/manifest/components/markdown-text.json +3 -0
  401. package/manifest/components/menubar.json +32 -4
  402. package/manifest/components/message-list.json +3 -0
  403. package/manifest/components/message.json +6 -1
  404. package/manifest/components/mobile-composer.json +3 -1
  405. package/manifest/components/multi-select.json +38 -1
  406. package/manifest/components/musical-time-input.json +10 -0
  407. package/manifest/components/navigation-menu.json +32 -3
  408. package/manifest/components/node-card.json +3 -0
  409. package/manifest/components/number-field.json +10 -1
  410. package/manifest/components/otp-field.json +9 -0
  411. package/manifest/components/page-shell.json +14 -0
  412. package/manifest/components/pagination.json +3 -0
  413. package/manifest/components/panel-header.json +10 -0
  414. package/manifest/components/panel.json +11 -1
  415. package/manifest/components/password-input.json +10 -1
  416. package/manifest/components/permission-scopes.json +3 -1
  417. package/manifest/components/piano-keyboard.json +3 -0
  418. package/manifest/components/popover.json +30 -3
  419. package/manifest/components/preset-section.json +9 -1
  420. package/manifest/components/preview.json +24 -10
  421. package/manifest/components/progress.json +6 -1
  422. package/manifest/components/prompt-library.json +3 -1
  423. package/manifest/components/queue-dock.json +3 -1
  424. package/manifest/components/radio-group.json +8 -0
  425. package/manifest/components/radio.json +8 -0
  426. package/manifest/components/rating.json +4 -1
  427. package/manifest/components/reasoning-panel.json +3 -1
  428. package/manifest/components/recommendation-card.json +1 -1
  429. package/manifest/components/resizable.json +4 -1
  430. package/manifest/components/revert-dock.json +3 -1
  431. package/manifest/components/row.json +5 -1
  432. package/manifest/components/scroll-area.json +4 -2
  433. package/manifest/components/scrollable-tabs-list.json +18 -0
  434. package/manifest/components/scrub-input.json +10 -1
  435. package/manifest/components/seam-cell.json +1 -0
  436. package/manifest/components/seam-grid.json +1 -0
  437. package/manifest/components/seam-list.json +5 -1
  438. package/manifest/components/search-input.json +10 -1
  439. package/manifest/components/section-header.json +15 -2
  440. package/manifest/components/segmented-control.json +16 -0
  441. package/manifest/components/select.json +17 -0
  442. package/manifest/components/settings-panel.json +3 -0
  443. package/manifest/components/shape-section.json +9 -1
  444. package/manifest/components/sheet.json +29 -3
  445. package/manifest/components/shimmer-label.json +3 -0
  446. package/manifest/components/sidebar.json +19 -2
  447. package/manifest/components/slider.json +8 -0
  448. package/manifest/components/sources.json +3 -1
  449. package/manifest/components/stat.json +9 -0
  450. package/manifest/components/status-bar.json +4 -0
  451. package/manifest/components/stepper.json +8 -0
  452. package/manifest/components/swap-label.json +3 -0
  453. package/manifest/components/switch.json +8 -0
  454. package/manifest/components/table-scroll-region.json +20 -2
  455. package/manifest/components/table.json +20 -2
  456. package/manifest/components/tabs.json +19 -1
  457. package/manifest/components/tags-input.json +38 -1
  458. package/manifest/components/terminal-frame.json +3 -0
  459. package/manifest/components/textarea.json +12 -0
  460. package/manifest/components/theme-configurator.json +29 -3
  461. package/manifest/components/theme-provider.json +31 -19
  462. package/manifest/components/thread-search.json +3 -1
  463. package/manifest/components/threshold-rail.json +3 -0
  464. package/manifest/components/time-field.json +10 -0
  465. package/manifest/components/toast.json +30 -2
  466. package/manifest/components/toggle.json +4 -0
  467. package/manifest/components/token-editor.json +6 -1
  468. package/manifest/components/tool-call-card.json +9 -2
  469. package/manifest/components/tool-call.json +3 -1
  470. package/manifest/components/tool-timeline.json +3 -1
  471. package/manifest/components/toolbar.json +3 -1
  472. package/manifest/components/tooltip.json +31 -3
  473. package/manifest/components/tree-visibility-toggle.json +3 -0
  474. package/manifest/components/tree.json +3 -0
  475. package/manifest/components/universe-grid.json +3 -0
  476. package/manifest/components/voice-conversation.json +3 -0
  477. package/manifest/components/work-collapse.json +3 -1
  478. package/manifest/manifest.json +204 -184
  479. package/manifest/tokens.json +241 -4
  480. package/package.json +5 -5
@@ -55,15 +55,29 @@ interface PreviewProps extends Omit<React.ComponentPropsWithoutRef<"div">, "chil
55
55
  mode?: Mode;
56
56
  /** A rung of the density ladder for the stage only, as a `<Density>` island would set it. */
57
57
  density?: Density$1;
58
- /** A font pairing for the stage only, as `data-font`. Portals still follow the root's pairing. */
58
+ /**
59
+ * A font pairing for the stage only, stamped as `data-font` and republished to
60
+ * React, so an overlay opened on the stage wears the stage's pairing rather
61
+ * than the page's, and `useTheme().font` read on the stage reports it. The
62
+ * stage also takes `font-sans` when a pairing is named: `data-font` re-declares
63
+ * the family's custom properties, but `font-family` inherits as an already
64
+ * computed value, so unclassed text on the stage would otherwise keep the
65
+ * family it resolved above it. Unset, the stage inherits and adds neither.
66
+ */
59
67
  font?: FontName;
60
68
  /**
61
- * A style set for the stage only: `console`, `editorial` or `marketing`.
69
+ * A style set for the stage only: `console`, `editorial`, `marketing` or
70
+ * `graphite`.
62
71
  *
63
72
  * Unset, the stage inherits and **no attribute is emitted at all** — the same
64
- * rule the other four follow here. Unlike `theme`, naming one loads nothing
65
- * and needs nothing: the three sets are emitted by `@cueplusplus/tokens` into
66
- * the stylesheet every consumer already imports, so a stage is scoped to
73
+ * rule the other four follow here — unless the stage names a `theme`, a `mode`
74
+ * or a `font`. Then it restates the set in force around it, because a set's
75
+ * block declares values that read those axes (its seam ink and band rule
76
+ * read the theme, its control and display faces read the pairing) and a
77
+ * custom property resolves where it is declared: restated, they resolve
78
+ * against the stage. Unlike `theme`, naming one loads nothing and needs
79
+ * nothing: every set is emitted by `@cueplusplus/tokens` into the stylesheet
80
+ * every consumer already imports, so a stage is scoped to
67
81
  * `[data-style="<name>"]` and the block is on the page by construction.
68
82
  *
69
83
  * The set is republished to React as well as stamped, so a popover opened on
@@ -72,15 +86,18 @@ interface PreviewProps extends Omit<React.ComponentPropsWithoutRef<"div">, "chil
72
86
  */
73
87
  styleSet?: StyleSet;
74
88
  /**
75
- * A look pack for the stage: the finish its surfaces wear.
89
+ * A paint pack for the stage: the finish its surfaces wear.
76
90
  *
77
91
  * Stamped as `data-paint` on the stage element, and republished to React for
78
92
  * the same reason `styleSet` is — a popover opened on the stage mounts on
79
93
  * `<body>` and inherits nothing from the stage's DOM, so it has to be told.
80
94
  *
81
- * Absent means inherit. `none` is a value that opts OUT of an ambient pack,
82
- * which is what a stage uses to show a component unpainted inside a page that
83
- * is not.
95
+ * Absent means inherit — and a stage that names a `theme`, a `mode` or a
96
+ * `font` restates the pack in force around it, so the pack's strokes and
97
+ * inks, which are the theme's colours mixed, resolve against the stage's
98
+ * theme rather than the page's. `none` is a value that opts OUT of an ambient
99
+ * pack, which is what a stage uses to show a component unpainted inside a
100
+ * page that is not.
84
101
  */
85
102
  paint?: Paint;
86
103
  /**
@@ -151,12 +168,15 @@ interface PreviewProps extends Omit<React.ComponentPropsWithoutRef<"div">, "chil
151
168
  *
152
169
  * **The stage is the island; the chrome is not.** `theme`, `mode`, `density`,
153
170
  * `font` and `styleSet` land on the stage element only, and the stage
154
- * republishes the theme, density and style-set contexts so an overlay opened on
155
- * it follows it. The tools, the footer, the grips and anything they open stay
171
+ * republishes the theme (pairing included), density and style-set contexts so
172
+ * an overlay opened on it follows it. The tools, the footer, the grips and anything they open stay
156
173
  * in the scope around the Preview — a `terminal` preview's own controls do not
157
174
  * turn cyan. With none of the five set, the stage carries no attribute and
158
175
  * costs what a `<div>` costs. A stage `theme` with no `mode` repeats the page's
159
- * mode beside it.
176
+ * mode beside it, a stage `theme` or `mode` with no `density` the page's rung,
177
+ * and a stage `theme`, `mode` or `font` restates the page's
178
+ * style set and paint pack beside it, so their theme-reading values resolve
179
+ * against the stage.
160
180
  *
161
181
  * **`resizable` is handles of its own**, both axes by default: an edge grip per
162
182
  * axis that is a keyboard-operable `separator` valued in pixels, and a corner
@@ -1,10 +1,12 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { useIsomorphicLayoutEffect } from "../system/use-isomorphic-layout-effect.js";
4
- import { AmbientThemeContext, DensityContext, PaintContext, StyleSetContext } from "../system/density.js";
4
+ import { usePublish, useRead } from "../system/published.js";
5
+ import { AmbientThemeContext, DensityContext, PaintContext, RootAxesContext, StyleSetContext, rootAxes, useFollowedAxes, useRestateReady } from "../system/density.js";
5
6
  import { OverridesContext } from "../system/overrides.js";
6
- import { ThemeContext } from "../system/theme-provider.js";
7
+ import { NO_PAIRING_SEED, PairingSeedContext, ThemeContext } from "../system/theme-provider.js";
7
8
  import { GROUND_CLASSES } from "./_ground.js";
9
+ import { STAGE_MARKS } from "../system/_style-stage-marks.js";
8
10
  import * as React from "react";
9
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
12
  //#region src/layout/preview.tsx
@@ -18,8 +20,8 @@ const RESIZE_DEFAULTS = {
18
20
  /** One arrow press, in px, and one Shift+arrow press. */
19
21
  const STEP = 8;
20
22
  const BIG_STEP = 64;
21
- const ROOT_CLASS = "relative flex min-w-0 flex-col rounded-(--radius-surface) border border-border bg-surface-1 text-fg";
22
- const BENCH_CLASS = "relative flex min-w-0 flex-1 overflow-auto rounded-t-(--radius-surface)";
23
+ const ROOT_CLASS = "relative flex min-w-0 flex-col rounded-surface border border-border bg-surface-1 text-fg";
24
+ const BENCH_CLASS = "relative flex min-w-0 flex-1 overflow-auto rounded-t-surface";
23
25
  /**
24
26
  * The stage: centred, grounded, and at least three top rungs of the space
25
27
  * ladder tall so a preview reserves its room before its specimen arrives.
@@ -44,7 +46,7 @@ const DEFAULT_GROUND = {
44
46
  panel: "dots",
45
47
  frame: "none"
46
48
  };
47
- const TOOLS_CLASS = "absolute top-(--cue-space-2) right-(--cue-space-2) z-10 flex items-center gap-px rounded-(--radius-control) border border-border bg-surface-2 p-px";
49
+ const TOOLS_CLASS = "absolute top-(--cue-space-2) right-(--cue-space-2) z-10 flex items-center gap-px rounded-control border border-border bg-surface-2 p-px";
48
50
  /**
49
51
  * The room the tools take, kept clear on the stage — only when there are tools.
50
52
  *
@@ -130,8 +132,12 @@ const CAPTIONS_OFF = "[--preview-captions:0] [--preview-captions-pe:none]";
130
132
  * Not a border and not an SVG. A border would have to be on the stage, and the
131
133
  * stage is the theme island: a frame's chrome that moved with a stage theme is
132
134
  * the one thing ruling 7 forbids.
135
+ *
136
+ * A style set may take the marks away (`STAGE_MARKS`, `style-stage-marks`):
137
+ * they are this library's furniture, and a Look whose source draws none says
138
+ * `none`.
133
139
  */
134
- const CROSS_CLASS = "pointer-events-none absolute z-10 size-[11px] bg-[linear-gradient(var(--cue-fg-subtle),var(--cue-fg-subtle)),linear-gradient(var(--cue-fg-subtle),var(--cue-fg-subtle))] bg-[length:1px_11px,11px_1px] bg-[position:center,center] bg-no-repeat";
140
+ const CROSS_CLASS = `pointer-events-none absolute z-10 size-[11px] bg-[linear-gradient(var(--cue-fg-subtle),var(--cue-fg-subtle)),linear-gradient(var(--cue-fg-subtle),var(--cue-fg-subtle))] bg-[length:1px_11px,11px_1px] bg-[position:center,center] bg-no-repeat ${STAGE_MARKS}`;
135
141
  /** The four corners, each half outside the box so the cross straddles the corner. */
136
142
  const CROSS_CORNERS = [
137
143
  "-top-[5px] -left-[5px]",
@@ -143,7 +149,7 @@ const GRIP_FOCUS = "touch-none outline-none hover:bg-(--cue-border-strong) focus
143
149
  const GRIP_X_CLASS = `absolute top-0 right-0 z-10 h-full w-(--cue-space-2) cursor-col-resize ${GRIP_FOCUS}`;
144
150
  const GRIP_Y_CLASS = `absolute bottom-0 left-0 z-10 h-(--cue-space-2) w-full cursor-row-resize ${GRIP_FOCUS}`;
145
151
  const GRIP_CORNER_CLASS = "absolute right-0 bottom-0 z-20 size-(--cue-space-4) cursor-nwse-resize touch-none";
146
- const READOUT_CLASS = "pointer-events-none absolute right-(--cue-space-5) bottom-(--cue-space-5) z-20 rounded-(--radius-control) bg-surface-3 px-(--cue-space-2) py-px font-mono text-(length:--cue-text-label) text-fg-muted";
152
+ const READOUT_CLASS = "pointer-events-none absolute right-(--cue-space-5) bottom-(--cue-space-5) z-20 rounded-control bg-surface-3 px-(--cue-space-2) py-px font-mono text-(length:--cue-text-label) text-fg-muted";
147
153
  function clamp(value, min, max) {
148
154
  return Math.min(max, Math.max(min, value));
149
155
  }
@@ -223,25 +229,74 @@ function effectiveBounds(options, available) {
223
229
  * A theme's density overrides are addressed through `data-cue-theme`, the
224
230
  * stamp `<Density>` writes, so a density names the nearest theme the same way.
225
231
  *
232
+ * A stage that ends up naming a theme and no rung — its own theme, or the
233
+ * page's restated beside a mode (`scoped`, below) — restates the rung in force
234
+ * around it, as `data-density` with the theme as `data-cue-theme` (spec
235
+ * 2026-09-26-looks-fidelity §4.1.1). A theme's rung retunes are keyed on the
236
+ * theme and the rung on one element, or a rung below the theme, so a stage that
237
+ * re-themes with no `data-density` of its own inherits the rung already
238
+ * resolved against the PAGE's theme, and its own theme's retune of that rung
239
+ * never applies. `/looks` opens every stage this way: a theme and no rung. It
240
+ * is what a nested `ThemeProvider` that names a theme already does — theme,
241
+ * rung and mode together. The rung is the one `DensityContext` carries: `null`
242
+ * outside every provider, where nothing is restated, and never `useDensity()`'s
243
+ * `compact` fallback, which would invent one.
244
+ *
226
245
  * The style set adds no second attribute, and that is the difference worth
227
246
  * writing down beside the three that do: a `[data-style]` block is a single
228
247
  * attribute selector naming no other axis, so a set stamped alone matches on
229
248
  * its own.
249
+ *
250
+ * But a stage that re-themes, re-modes or re-faces restates the set and the pack
251
+ * in force around it (`around`), for a reason in custom properties rather than
252
+ * in selectors. Their blocks declare names whose values read those axes — a
253
+ * pack's stroke stops are the theme's borders, a set's band rule and ground are
254
+ * the theme's border and surface — and a custom property's `var()`s are
255
+ * substituted where it is declared. Declared only on the page, they arrive at
256
+ * the stage already resolved against the page's theme and pairing; restated on
257
+ * the stage, beside its own `data-theme` or `data-font`, they resolve against
258
+ * those. A rung alone changes no ink and restates nothing. `around` is `null`
259
+ * until the stage may restate: under a root that persists, not before the stage
260
+ * has mounted, when the set and pack in force are the root's props rather than
261
+ * the visitor's (see `useRestateReady`).
262
+ *
263
+ * The page's mode and rung, restated beside a stage theme — and the page's
264
+ * theme, restated beside a stage mode or as a stage rung's `data-cue-theme` —
265
+ * wait for the same mount on the same terms (tracking plan F13): under a
266
+ * persisting root each is the root's, whose value on the server is its prop
267
+ * while `<html>` carries the visitor's. So until then `followed` holds it back,
268
+ * and `data-cue-follows` names it instead — the theme stylesheets' blocks each
269
+ * have a twin keyed on `<html>`'s value and that marker (a followed rung
270
+ * included: the base rung's twin in `axes.css`, and each theme's retune of it
271
+ * keyed on the stage's own `data-theme`), and a rung node with no
272
+ * `data-cue-theme` is reached by the rung rules' structural form, so the stage
273
+ * paints the visitor's theme, mode and rung from the first frame (see
274
+ * `useFollowedAxes`). A theme, mode or rung the stage names, or one named
275
+ * between it and the root, is stamped as it always was. A followed rung takes
276
+ * its `data-cue-theme` with it: the stamp addresses a `data-density` on the
277
+ * same element, and there is none to address until the rung is stamped.
230
278
  */
231
- function stageAttributes(asked, page) {
279
+ function stageAttributes(asked, page, around, aroundDensity, followed) {
232
280
  const attributes = {};
233
281
  const scoped = asked.theme ?? (asked.mode === void 0 ? null : page?.theme ?? null);
234
- if (scoped !== null) attributes["data-theme"] = scoped;
282
+ if (scoped !== null && (asked.theme !== void 0 || !followed.theme)) attributes["data-theme"] = scoped;
235
283
  const moded = asked.mode ?? (asked.theme === void 0 ? void 0 : page?.mode);
236
- if (moded !== void 0) attributes["data-mode"] = moded;
284
+ if (moded !== void 0 && !followed.mode) attributes["data-mode"] = moded;
237
285
  if (asked.density !== void 0) {
238
286
  attributes["data-density"] = asked.density;
239
287
  const nearest = asked.theme ?? page?.theme ?? null;
240
- if (nearest !== null) attributes["data-cue-theme"] = nearest;
288
+ if (nearest !== null && (asked.theme !== void 0 || !followed.theme)) attributes["data-cue-theme"] = nearest;
289
+ } else if (scoped !== null && aroundDensity !== null && !followed.density) {
290
+ attributes["data-density"] = aroundDensity;
291
+ if (asked.theme !== void 0 || !followed.theme) attributes["data-cue-theme"] = scoped;
241
292
  }
293
+ if (followed.marker !== null) attributes["data-cue-follows"] = followed.marker;
242
294
  if (asked.font !== void 0) attributes["data-font"] = asked.font;
243
295
  if (asked.styleSet !== void 0) attributes["data-style"] = asked.styleSet;
244
296
  if (asked.paint !== void 0) attributes["data-paint"] = asked.paint;
297
+ const restates = around !== null && (scoped !== null || moded !== void 0 || asked.font !== void 0);
298
+ if (restates && asked.styleSet === void 0 && around.styleSet !== null) attributes["data-style"] = around.styleSet;
299
+ if (restates && asked.paint === void 0 && around.paint !== null) attributes["data-paint"] = around.paint;
245
300
  return attributes;
246
301
  }
247
302
  /**
@@ -258,43 +313,81 @@ function stageAttributes(asked, page) {
258
313
  * The style set travels with the density for the same reason and by the same
259
314
  * route: `useCuePortalProps()` stamps a portal container from `StyleSetContext`,
260
315
  * and a popup opened on the stage inherits nothing from the stage's DOM.
316
+ *
317
+ * And the pairing travels in the theme context, because that is where the
318
+ * portal stamp reads `data-font` from (`theme?.font`). It used not to: the
319
+ * stage stamped `data-font` on its own element and republished nothing, so a
320
+ * popover opened on a `plex` stage came up in the root's pairing — a limit the
321
+ * `font` prop's docblock stated rather than a rule anybody chose. A pairing on
322
+ * the stage is the stage's, exactly as its theme is; `setFont` read here still
323
+ * drives the root, because the pairing's setter has no island form.
261
324
  */
262
- function StageScope({ theme, mode, density, styleSet, paint, children }) {
263
- const outer = React.useContext(ThemeContext);
264
- const outerOverrides = React.useContext(OverridesContext);
265
- const outerDensity = React.useContext(DensityContext);
266
- const outerAmbient = React.useContext(AmbientThemeContext);
267
- const outerStyleSet = React.useContext(StyleSetContext);
268
- const outerPaint = React.useContext(PaintContext);
325
+ function StageScope({ theme, mode, density, font, styleSet, paint, children }) {
326
+ const outer = useRead(ThemeContext);
327
+ const outerOverrides = useRead(OverridesContext);
328
+ const outerDensity = useRead(DensityContext);
329
+ const outerAmbient = useRead(AmbientThemeContext);
330
+ const outerStyleSet = useRead(StyleSetContext);
331
+ const outerPaint = useRead(PaintContext);
269
332
  const value = React.useMemo(() => {
270
- if (outer === null || theme === void 0 && mode === void 0) return outer;
333
+ if (outer === null || theme === void 0 && mode === void 0 && font === void 0) return outer;
271
334
  const scoped = theme ?? outer.theme;
272
335
  return {
273
336
  ...outer,
274
337
  theme: scoped,
275
338
  manifest: scoped === outer.theme ? outer.manifest : null,
276
339
  mode: mode ?? outer.mode,
340
+ font: font ?? outer.font,
277
341
  resolvedMode: mode === "dark" || mode === "light" ? mode : outer.resolvedMode
278
342
  };
279
343
  }, [
280
344
  outer,
281
345
  theme,
282
- mode
346
+ mode,
347
+ font
283
348
  ]);
284
349
  const stamped = theme !== void 0 || mode !== void 0;
285
- return /* @__PURE__ */ jsx(AmbientThemeContext.Provider, {
286
- value: theme ?? outerAmbient,
287
- children: /* @__PURE__ */ jsx(DensityContext.Provider, {
288
- value: density ?? outerDensity,
289
- children: /* @__PURE__ */ jsx(StyleSetContext.Provider, {
290
- value: styleSet ?? outerStyleSet,
291
- children: /* @__PURE__ */ jsx(PaintContext.Provider, {
292
- value: paint ?? outerPaint,
293
- children: /* @__PURE__ */ jsx(OverridesContext.Provider, {
294
- value: stamped ? null : outerOverrides,
295
- children: /* @__PURE__ */ jsx(ThemeContext.Provider, {
296
- value,
297
- children
350
+ const inputs = [
351
+ theme,
352
+ mode,
353
+ density,
354
+ font,
355
+ styleSet,
356
+ paint,
357
+ React.useContext(ThemeContext),
358
+ React.useContext(OverridesContext),
359
+ React.useContext(DensityContext),
360
+ React.useContext(AmbientThemeContext),
361
+ React.useContext(StyleSetContext),
362
+ React.useContext(PaintContext)
363
+ ];
364
+ const publishedAmbient = usePublish(theme ?? outerAmbient, inputs);
365
+ const publishedDensity = usePublish(density ?? outerDensity, inputs);
366
+ const publishedStyleSet = usePublish(styleSet ?? outerStyleSet, inputs);
367
+ const publishedPaint = usePublish(paint ?? outerPaint, inputs);
368
+ const publishedOverrides = usePublish(stamped ? null : outerOverrides, inputs);
369
+ const publishedValue = usePublish(value, inputs);
370
+ const outerPairingSeed = React.useContext(PairingSeedContext);
371
+ const outerRootAxes = React.useContext(RootAxesContext);
372
+ return /* @__PURE__ */ jsx(RootAxesContext.Provider, {
373
+ value: rootAxes(outerRootAxes.theme && theme === void 0, outerRootAxes.mode && mode === void 0, outerRootAxes.density && density === void 0),
374
+ children: /* @__PURE__ */ jsx(AmbientThemeContext.Provider, {
375
+ value: publishedAmbient,
376
+ children: /* @__PURE__ */ jsx(DensityContext.Provider, {
377
+ value: publishedDensity,
378
+ children: /* @__PURE__ */ jsx(StyleSetContext.Provider, {
379
+ value: publishedStyleSet,
380
+ children: /* @__PURE__ */ jsx(PaintContext.Provider, {
381
+ value: publishedPaint,
382
+ children: /* @__PURE__ */ jsx(OverridesContext.Provider, {
383
+ value: publishedOverrides,
384
+ children: /* @__PURE__ */ jsx(PairingSeedContext.Provider, {
385
+ value: font === void 0 ? outerPairingSeed : NO_PAIRING_SEED,
386
+ children: /* @__PURE__ */ jsx(ThemeContext.Provider, {
387
+ value: publishedValue,
388
+ children
389
+ })
390
+ })
298
391
  })
299
392
  })
300
393
  })
@@ -477,12 +570,15 @@ function Grips({ label, options, size }) {
477
570
  *
478
571
  * **The stage is the island; the chrome is not.** `theme`, `mode`, `density`,
479
572
  * `font` and `styleSet` land on the stage element only, and the stage
480
- * republishes the theme, density and style-set contexts so an overlay opened on
481
- * it follows it. The tools, the footer, the grips and anything they open stay
573
+ * republishes the theme (pairing included), density and style-set contexts so
574
+ * an overlay opened on it follows it. The tools, the footer, the grips and anything they open stay
482
575
  * in the scope around the Preview — a `terminal` preview's own controls do not
483
576
  * turn cyan. With none of the five set, the stage carries no attribute and
484
577
  * costs what a `<div>` costs. A stage `theme` with no `mode` repeats the page's
485
- * mode beside it.
578
+ * mode beside it, a stage `theme` or `mode` with no `density` the page's rung,
579
+ * and a stage `theme`, `mode` or `font` restates the page's
580
+ * style set and paint pack beside it, so their theme-reading values resolve
581
+ * against the stage.
486
582
  *
487
583
  * **`resizable` is handles of its own**, both axes by default: an edge grip per
488
584
  * axis that is a keyboard-operable `separator` valued in pixels, and a corner
@@ -511,7 +607,16 @@ function Grips({ label, options, size }) {
511
607
  * </Preview>
512
608
  */
513
609
  const Preview = React.forwardRef(function Preview({ children, label, theme, mode, density, font, styleSet, paint, resizable, tools, footer, presentation = "panel", name, count, ground, captions = true, className, ...elementProps }, ref) {
514
- const outer = React.useContext(ThemeContext);
610
+ const outer = useRead(ThemeContext);
611
+ const aroundStyleSet = useRead(StyleSetContext);
612
+ const aroundPaint = useRead(PaintContext);
613
+ const aroundDensity = useRead(DensityContext);
614
+ const restateReady = useRestateReady((theme !== void 0 || mode !== void 0 || font !== void 0) && (aroundStyleSet !== null || aroundPaint !== null));
615
+ const followed = useFollowedAxes({
616
+ theme: theme === void 0 && (mode !== void 0 || density !== void 0),
617
+ mode: theme !== void 0 && mode === void 0,
618
+ density: (theme !== void 0 || mode !== void 0 && outer !== null) && density === void 0 && aroundDensity !== null
619
+ });
515
620
  const bench = React.useRef(null);
516
621
  const given = resolveResize(resizable);
517
622
  const available = useAvailableWidth(bench, given !== null);
@@ -524,17 +629,21 @@ const Preview = React.forwardRef(function Preview({ children, label, theme, mode
524
629
  font,
525
630
  styleSet,
526
631
  paint
527
- }, outer);
632
+ }, outer, restateReady ? {
633
+ styleSet: aroundStyleSet,
634
+ paint: aroundPaint
635
+ } : null, aroundDensity, followed);
528
636
  const framed = presentation === "frame";
529
637
  const stage = /* @__PURE__ */ jsx("div", {
530
638
  "data-slot": "preview-stage",
531
639
  ...attributes,
532
- className: cn(STAGE_HEAD, GROUND_CLASSES[ground ?? DEFAULT_GROUND[presentation]], STAGE_TAIL, options !== null && "flex-1", !framed && tools !== void 0 && TOOLS_RESERVE_STAGE, !captions && CAPTIONS_OFF),
640
+ className: cn(STAGE_HEAD, GROUND_CLASSES[ground ?? DEFAULT_GROUND[presentation]], STAGE_TAIL, options !== null && "flex-1", font !== void 0 && "font-sans", !framed && tools !== void 0 && TOOLS_RESERVE_STAGE, !captions && CAPTIONS_OFF),
533
641
  style: size.height === null ? void 0 : { minHeight: 0 },
534
642
  children: /* @__PURE__ */ jsx(StageScope, {
535
643
  theme,
536
644
  mode,
537
645
  density,
646
+ font,
538
647
  styleSet,
539
648
  paint,
540
649
  children
@@ -543,7 +652,7 @@ const Preview = React.forwardRef(function Preview({ children, label, theme, mode
543
652
  const benched = /* @__PURE__ */ jsx("div", {
544
653
  ref: bench,
545
654
  "data-slot": "preview-bench",
546
- className: cn(BENCH_CLASS, footer === void 0 && "rounded-b-(--radius-surface)", !framed && tools !== void 0 && TOOLS_RESERVE_BENCH),
655
+ className: cn(BENCH_CLASS, footer === void 0 && "rounded-b-surface", !framed && tools !== void 0 && TOOLS_RESERVE_BENCH),
547
656
  children: options === null ? stage : /* @__PURE__ */ jsxs("div", {
548
657
  ref: size.sizer,
549
658
  "data-slot": "preview-sizer",
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { FOCUS_RING_INSET_2 } from "../system/_focus-ring.js";
3
4
  import * as React from "react";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  import { Group, Panel, Separator } from "react-resizable-panels";
@@ -54,7 +55,7 @@ const Resizable = {
54
55
  return /* @__PURE__ */ jsxs(Separator, {
55
56
  elementRef: elementRef ?? ref,
56
57
  "data-slot": "resizable-handle",
57
- className: cn("relative flex items-center justify-center bg-border transition-colors duration-150 outline-none data-[separator=hover]:bg-accent data-[separator=active]:bg-accent data-[separator=focus]:bg-accent focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-accent data-[separator=disabled]:opacity-40 motion-reduce:transition-none", orientation === "vertical" ? "h-[0.25rem] w-full" : "w-[0.25rem] self-stretch", className),
58
+ className: cn(`relative flex items-center justify-center bg-border transition-colors duration-150 outline-none data-[separator=hover]:bg-accent data-[separator=active]:bg-accent data-[separator=focus]:bg-accent ${FOCUS_RING_INSET_2} data-[separator=disabled]:opacity-40 motion-reduce:transition-none`, orientation === "vertical" ? "h-[0.25rem] w-full" : "w-[0.25rem] self-stretch", className),
58
59
  ...elementProps,
59
60
  children: [withGrip ? /* @__PURE__ */ jsx("span", {
60
61
  "data-slot": "resizable-grip",
@@ -1,5 +1,13 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { FOCUS_RING_INSET, FOCUS_RING_INSET_2 } from "../system/_focus-ring.js";
4
+ import { LABEL_INK_SUBTLE } from "../system/_style-label-ink.js";
5
+ import { LABEL_FACE } from "../system/_style-label-face.js";
6
+ import { LABEL_WEIGHT } from "../system/_style-label-weight.js";
7
+ import { LABEL_CASE } from "../system/_style-label-case.js";
8
+ import { LABEL_TRACKING } from "../system/_style-label-tracking.js";
9
+ import { LABEL_SIZE } from "../system/_style-label-size.js";
10
+ import { NAV_ITEM } from "../system/_style-nav-item.js";
3
11
  import * as React from "react";
4
12
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
13
  import { useRender } from "@base-ui/react/use-render";
@@ -101,7 +109,7 @@ const Sidebar = {
101
109
  ...elementProps,
102
110
  children: [label === void 0 || collapsed ? null : /* @__PURE__ */ jsx("div", {
103
111
  "data-slot": "sidebar-section-label",
104
- className: "flex h-control-sm items-center px-(--cue-space-2) font-mono text-(length:--cue-text-label) tracking-(--cue-tracking-caps) text-fg-subtle uppercase",
112
+ className: cn("flex h-control-sm items-center px-(--cue-space-2)", LABEL_SIZE, LABEL_INK_SUBTLE, LABEL_WEIGHT, LABEL_FACE, LABEL_TRACKING, LABEL_CASE),
105
113
  children: label
106
114
  }), children]
107
115
  });
@@ -117,7 +125,7 @@ const Sidebar = {
117
125
  "data-slot": "sidebar-item",
118
126
  "data-active": active ? "" : void 0,
119
127
  "aria-current": active ? "page" : void 0,
120
- className: cn("relative flex h-control-md w-full cursor-pointer items-center gap-(--cue-space-3) rounded-(--radius-control) border-0 bg-transparent px-(--cue-space-3) text-left font-mono text-(length:--cue-text-ui) text-fg-muted no-underline 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-[active]:bg-accent-soft data-[active]:text-accent disabled:pointer-events-none disabled:opacity-40", className),
128
+ className: cn(`relative flex h-control-md w-full cursor-pointer items-center gap-(--cue-space-3) rounded-control border-0 bg-transparent px-(--cue-space-3) text-left font-mono text-(length:--cue-text-ui) no-underline transition-colors duration-150 outline-none select-none hover:bg-surface-2 hover:text-fg ${FOCUS_RING_INSET} ${NAV_ITEM} disabled:pointer-events-none disabled:opacity-40`, className),
121
129
  children: /* @__PURE__ */ jsxs(Fragment, { children: [
122
130
  Icon === void 0 ? null : /* @__PURE__ */ jsx(Icon, {
123
131
  "aria-hidden": "true",
@@ -149,7 +157,7 @@ const Sidebar = {
149
157
  onClick?.(event);
150
158
  if (!event.defaultPrevented) toggle();
151
159
  },
152
- className: cn("absolute inset-y-0 right-0 w-[0.25rem] translate-x-1/2 cursor-ew-resize border-0 bg-transparent p-0 transition-colors duration-150 outline-none hover:bg-accent focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-accent motion-reduce:transition-none", className),
160
+ className: cn(`absolute inset-y-0 right-0 w-[0.25rem] translate-x-1/2 cursor-ew-resize border-0 bg-transparent p-0 transition-colors duration-150 outline-none hover:bg-accent ${FOCUS_RING_INSET_2} motion-reduce:transition-none`, className),
153
161
  ...elementProps
154
162
  });
155
163
  })
@@ -1,5 +1,9 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { FOCUS_RING_OFFSET_2 } from "../system/_focus-ring.js";
4
+ import { LABEL_FACE } from "../system/_style-label-face.js";
5
+ import { LABEL_CASE } from "../system/_style-label-case.js";
6
+ import { LABEL_TRACKING_TIGHT } from "../system/_style-label-tracking.js";
3
7
  import * as React from "react";
4
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
9
  //#region src/layout/stepper.tsx
@@ -15,7 +19,7 @@ const INDEX_TONES = {
15
19
  current: "text-accent",
16
20
  upcoming: "text-fg-subtle"
17
21
  };
18
- const STEP_BUTTON_CLASSES = "inline-flex cursor-pointer items-center gap-(--cue-space-2) rounded-(--radius-control) border-0 bg-transparent p-0 font-mono text-[length:inherit] tracking-[inherit] text-inherit uppercase transition-colors duration-150 outline-none hover:text-fg focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-accent";
22
+ const STEP_BUTTON_CLASSES = `inline-flex cursor-pointer items-center gap-(--cue-space-2) rounded-control border-0 bg-transparent p-0 ${LABEL_FACE} text-[length:inherit] tracking-[inherit] text-inherit ${LABEL_CASE} transition-colors duration-150 outline-none hover:text-fg ${FOCUS_RING_OFFSET_2}`;
19
23
  /**
20
24
  * The step trail: `1 target · 2 preview · 3 apply`.
21
25
  *
@@ -43,7 +47,7 @@ const Stepper = React.forwardRef(function Stepper({ className, steps, current, o
43
47
  className: cn("min-w-0", className),
44
48
  ...elementProps,
45
49
  children: /* @__PURE__ */ jsx("ol", {
46
- className: "m-0 flex list-none flex-wrap items-center gap-(--cue-space-3) p-0 font-mono text-(length:--cue-text-label) tracking-(--cue-tracking-caps-tight) uppercase",
50
+ className: cn("m-0 flex list-none flex-wrap items-center gap-(--cue-space-3) p-0 text-(length:--cue-text-label)", LABEL_FACE, LABEL_TRACKING_TIGHT, LABEL_CASE),
47
51
  children: steps.map((step, index) => {
48
52
  const state = currentIndex === -1 || index > currentIndex ? "upcoming" : index === currentIndex ? "current" : "complete";
49
53
  const navigable = onStepChange !== void 0 && state === "complete";
package/dist/lib/cn.js CHANGED
@@ -1,7 +1,34 @@
1
1
  import { clsx } from "clsx";
2
- import { twMerge } from "tailwind-merge";
2
+ import { extendTailwindMerge } from "tailwind-merge";
3
3
  //#region src/lib/cn.ts
4
4
  /**
5
+ * Stock `tailwind-merge` only knows Tailwind's own radius scale
6
+ * (`rounded-sm`, `rounded-lg`, `rounded-full`, …), because it has no way to
7
+ * see the three rungs `packages/tokens/build.mjs` adds to the `@theme
8
+ * inline` bridge: `rounded-control`, `rounded-surface` and `rounded-overlay`
9
+ * (spec 2026-09-26-looks-fidelity §4.1.1, the radius codemod). Left
10
+ * unextended, `twMerge("rounded-surface", "rounded-full")` keeps BOTH
11
+ * classes instead of dropping the first — they read as two different
12
+ * utilities rather than a rung being overridden — and which one wins then
13
+ * depends on the two classes' alphabetical order in the built CSS rather
14
+ * than on which was passed last. Two shipped components regressed on this:
15
+ * `elements/speaker-identity.tsx`'s subagent avatar (`cn("… rounded-surface
16
+ * …", "rounded-full")`) drew a rounded square instead of a circle, and
17
+ * `configurator/configurator.tsx`'s docked-right panel (`cn(overlaySurfaceClasses,
18
+ * "… rounded-none …")`) kept its corners against the viewport edge instead of
19
+ * squaring them off.
20
+ *
21
+ * `extendTailwindMerge` teaches it the three rungs as members of Tailwind's
22
+ * own `radius` theme scale, which is also what makes `rounded-t-control`,
23
+ * `rounded-br-overlay` and the rest of the per-corner rungs resolve against
24
+ * the same conflict group as their bare form and each other.
25
+ */
26
+ const twMergeCue = extendTailwindMerge({ extend: { theme: { radius: [
27
+ "control",
28
+ "surface",
29
+ "overlay"
30
+ ] } } });
31
+ /**
5
32
  * Join class names and resolve conflicting Tailwind utilities, last one wins.
6
33
  *
7
34
  * Every component in the system funnels its computed classes plus the caller's
@@ -13,6 +40,6 @@ import { twMerge } from "tailwind-merge";
13
40
  * @example
14
41
  * cn("h-4 px-2", isLarge && "h-8") // "px-2 h-8" when isLarge
15
42
  */
16
- const cn = (...inputs) => twMerge(clsx(inputs));
43
+ const cn = (...inputs) => twMergeCue(clsx(inputs));
17
44
  //#endregion
18
45
  export { cn };
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { FOCUS_RING } from "../system/_focus-ring.js";
3
4
  import { toRem } from "../instruments/_rem.js";
4
5
  import { keyboardLayout, keyboardWindow, noteAtOffset, noteName } from "./_notes.js";
5
6
  import * as React from "react";
@@ -117,7 +118,7 @@ const PianoKeyboard = React.forwardRef(function PianoKeyboard({ className, range
117
118
  style: boardStyle,
118
119
  children: [/* @__PURE__ */ jsx("div", {
119
120
  "data-slot": "piano-keyboard-keys",
120
- className: "relative overflow-hidden rounded-(--radius-control) border border-border bg-sunken",
121
+ className: "relative overflow-hidden rounded-control border border-border bg-sunken",
121
122
  style: { height: toRem(keyHeight) },
122
123
  children: layout.keys.map((key) => {
123
124
  const inRange = key.note >= range.start && key.note <= range.end;
@@ -162,7 +163,7 @@ const PianoKeyboard = React.forwardRef(function PianoKeyboard({ className, range
162
163
  onPointerUp: endDrag,
163
164
  onPointerCancel: endDrag,
164
165
  onKeyDown: onKeyDown(edge),
165
- className: cn("absolute top-0 flex h-full -translate-x-1/2 touch-none items-start justify-center rounded-(--radius-control) px-px outline-none", "focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-1 focus-visible:outline-accent", disabled ? "cursor-default opacity-40" : "cursor-ew-resize"),
166
+ className: cn("absolute top-0 flex h-full -translate-x-1/2 touch-none items-start justify-center rounded-control px-px outline-none", `${FOCUS_RING}`, disabled ? "cursor-default opacity-40" : "cursor-ew-resize"),
166
167
  style: { left: toRem(key.left + key.width / 2) },
167
168
  children: /* @__PURE__ */ jsx("span", {
168
169
  "aria-hidden": "true",
@@ -141,7 +141,7 @@ const SpectrumVisualizer = React.forwardRef(function SpectrumVisualizer({ classN
141
141
  "aria-label": summary,
142
142
  "data-slot": "spectrum-visualizer-canvas",
143
143
  "data-mode": mode,
144
- className: "block w-full rounded-(--radius-control) border border-border bg-(--cue-data-ground)",
144
+ className: "block w-full rounded-control border border-border bg-(--cue-data-ground)",
145
145
  style: { height: toRem(height) }
146
146
  }), labels ? /* @__PURE__ */ jsx("div", {
147
147
  "data-slot": "spectrum-visualizer-legend",
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
+ import { FOCUS_RING_OFFSET_2 } from "../system/_focus-ring.js";
3
4
  import * as React from "react";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
5
6
  //#region src/midi/threshold-rail.tsx
@@ -187,7 +188,7 @@ const ThresholdRail = React.forwardRef(function ThresholdRail({ className, value
187
188
  onPointerUp: endDrag,
188
189
  onPointerCancel: endDrag,
189
190
  onKeyDown: onKeyDown(edge),
190
- className: cn("absolute top-1/2 z-10 size-3 -translate-x-1/2 -translate-y-1/2 touch-none rounded-full border-2 bg-bg outline-none transition-transform", "motion-reduce:transition-none data-[dragging=true]:scale-125", "focus-visible:outline-2 focus-visible:outline-solid focus-visible:outline-offset-2 focus-visible:outline-accent", edge === "upper" ? HANDLE_TONES[aboveTone] : HANDLE_TONES[belowTone], disabled ? "cursor-default" : drag?.edge === edge ? "cursor-grabbing" : "cursor-grab hover:scale-110"),
191
+ className: cn("absolute top-1/2 z-10 size-3 -translate-x-1/2 -translate-y-1/2 touch-none rounded-full border-2 bg-bg outline-none transition-transform", "motion-reduce:transition-none data-[dragging=true]:scale-125", `${FOCUS_RING_OFFSET_2}`, edge === "upper" ? HANDLE_TONES[aboveTone] : HANDLE_TONES[belowTone], disabled ? "cursor-default" : drag?.edge === edge ? "cursor-grabbing" : "cursor-grab hover:scale-110"),
191
192
  style: { left: percent(current) }
192
193
  }, edge);
193
194
  })
@@ -143,7 +143,7 @@ const TimelineRuler = React.forwardRef(function TimelineRuler({ className, total
143
143
  ]
144
144
  }), typeof tempo === "number" ? /* @__PURE__ */ jsx("div", {
145
145
  "data-slot": "timeline-ruler-readout",
146
- className: "pointer-events-none absolute top-px right-px rounded-(--radius-control) bg-surface-1/80 px-(--cue-space-1) font-mono text-(length:--cue-text-micro) text-fg-subtle tabular-nums",
146
+ className: "pointer-events-none absolute top-px right-px rounded-control bg-surface-1/80 px-(--cue-space-1) font-mono text-(length:--cue-text-micro) text-fg-subtle tabular-nums",
147
147
  children: `${tempo.toFixed(1)} BPM · ${signature}`
148
148
  }) : null]
149
149
  });