@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
@@ -1,4 +1,6 @@
1
1
  "use client";
2
+ import { useIsomorphicLayoutEffect } from "./use-isomorphic-layout-effect.js";
3
+ import { published, usePublish, useRead } from "./published.js";
2
4
  import * as React from "react";
3
5
  import { jsx } from "react/jsx-runtime";
4
6
  //#region src/system/density.tsx
@@ -14,9 +16,16 @@ const DEFAULT_DENSITY = "compact";
14
16
  * Nearest ambient density. `null` means "nothing has stamped a level yet", which
15
17
  * `useDensity()` reports as {@link DEFAULT_DENSITY}.
16
18
  *
19
+ * **Carried as a `Published`** — this and the three contexts below, like every
20
+ * context whose value the root's restore moves. A setter or a prop moves the
21
+ * context, as any context moves; the restore, which lands while a streamed
22
+ * Suspense boundary below can still be server HTML, is posted beside it
23
+ * instead, so no boundary is told anything changed. Readers go through
24
+ * {@link useRead}. See `published.ts`.
25
+ *
17
26
  * Internal: consumers read it through `useDensity()`, never directly.
18
27
  */
19
- const DensityContext = React.createContext(null);
28
+ const DensityContext = React.createContext(published(null));
20
29
  /**
21
30
  * Nearest ambient theme's name, published for exactly one reader: `Density`
22
31
  * below, which stamps it onto its island as `data-cue-theme` so a theme's
@@ -36,7 +45,7 @@ const DensityContext = React.createContext(null);
36
45
  * Internal: `Density` is the only reader. Not `useTheme()` — that throws
37
46
  * outside a provider, and this island has no reason to.
38
47
  */
39
- const AmbientThemeContext = React.createContext(null);
48
+ const AmbientThemeContext = React.createContext(published(null));
40
49
  /**
41
50
  * Nearest ambient style set. `null` means "nothing has stamped a set", which
42
51
  * every reader reports as "no style set" rather than as the default one.
@@ -55,9 +64,9 @@ const AmbientThemeContext = React.createContext(null);
55
64
  * and the portal stamp have to ask, because both leave the DOM they were
56
65
  * written in and have to carry the answer with them.
57
66
  */
58
- const StyleSetContext = React.createContext(null);
67
+ const StyleSetContext = React.createContext(published(null));
59
68
  /**
60
- * The look pack stamped around this subtree, or `null` when none is.
69
+ * The paint pack stamped around this subtree, or `null` when none is.
61
70
  *
62
71
  * The fifth axis's counterpart to {@link StyleSetContext}, and internal for the
63
72
  * same reasons: a provider publishes this and its `ThemeContext.paint` from one
@@ -70,7 +79,143 @@ const StyleSetContext = React.createContext(null);
70
79
  * pack. Collapsing the two would make every unpainted subtree override its
71
80
  * parent instead of inheriting from it.
72
81
  */
73
- const PaintContext = React.createContext(null);
82
+ const PaintContext = React.createContext(published(null));
83
+ /**
84
+ * `true` under a root provider that persists: one whose state, on the server and
85
+ * on the client's first render, is its PROPS, while `<html>` already carries
86
+ * what the visitor stored. Under such a root an island must not restate the set
87
+ * and pack in force until it has mounted — see {@link useRestateReady}.
88
+ *
89
+ * **A constant, not a flag that flips at the restore.** It used to be exactly
90
+ * that flag — `true` until the root restored, then `false` — and a context
91
+ * whose value changes in the root's first commit is an update to every
92
+ * Suspense boundary below it that has not hydrated yet. React cannot hydrate a
93
+ * streamed boundary against a changed value, so it threw the boundary's server
94
+ * HTML away and rendered it on the client: every stage and nested provider in
95
+ * a streamed boundary, on every page, for every visitor, whether or not
96
+ * anything was stored. This value is the root's `persistPreferences`, which the
97
+ * restore does not move.
98
+ *
99
+ * Here rather than in `theme-provider.tsx` for the cycle reason the contexts
100
+ * above give. Only the root provides a value; a nested provider passes it on.
101
+ *
102
+ * Internal.
103
+ */
104
+ const DeferRestateContext = React.createContext(false);
105
+ /**
106
+ * Whether an island may restate the set and pack in force on this render.
107
+ *
108
+ * Its callers are the islands that restate them — a nested `ThemeProvider` that
109
+ * names a theme or a mode, a `Preview` stage with a theme, a mode or a pairing —
110
+ * and `wants` is whether there is anything to restate at all.
111
+ *
112
+ * Under a root that does not persist, always: its props are the truth from the
113
+ * first render, the server's included. Under one that persists, only once this
114
+ * island has mounted. Its server markup and its first client render therefore
115
+ * restate nothing — they agree, and the stored set and pack inherit from
116
+ * `<html>` meanwhile — and the island's own layout effect then re-renders it
117
+ * with them, before the first paint. That update is the island's own, made
118
+ * after it has hydrated, so it reaches no boundary still waiting to; and the
119
+ * root's restore, which runs in the same layout phase when the two mount
120
+ * together, has landed by the time that render reads the contexts. With
121
+ * nothing to restate there is no second render at all.
122
+ *
123
+ * Internal.
124
+ */
125
+ function useRestateReady(wants) {
126
+ const defer = React.useContext(DeferRestateContext);
127
+ const mounted = useMountedWhen(defer && wants);
128
+ return !defer || mounted;
129
+ }
130
+ /**
131
+ * `true` once this component has committed with `wants` set, and for good after
132
+ * that: the island's own layout effect sets it, so the re-render it causes is
133
+ * this island's update, made after it hydrated and before the first paint.
134
+ * With `wants` unset there is nothing to wait for and no second render at all.
135
+ *
136
+ * Internal: the one mechanism behind {@link useRestateReady},
137
+ * {@link useFollowedAxes}, and `ThemeProvider`'s wait on the colour edit of a
138
+ * provider that names neither theme nor mode.
139
+ */
140
+ function useMountedWhen(wants) {
141
+ const [mounted, setMounted] = React.useState(false);
142
+ useIsomorphicLayoutEffect(() => {
143
+ if (wants) setMounted(true);
144
+ }, [wants]);
145
+ return mounted;
146
+ }
147
+ const ROOT_AXES = [false, true].flatMap((theme) => [false, true].flatMap((mode) => [false, true].map((density) => Object.freeze({
148
+ theme,
149
+ mode,
150
+ density
151
+ }))));
152
+ /** The one {@link RootAxes} object for these three answers. Internal. */
153
+ function rootAxes(theme, mode, density) {
154
+ return ROOT_AXES[(theme ? 4 : 0) + (mode ? 2 : 0) + (density ? 1 : 0)];
155
+ }
156
+ /** See {@link RootAxes}. None, outside a persisting root. Internal. */
157
+ const RootAxesContext = React.createContext(rootAxes(false, false, false));
158
+ const FOLLOWS_NOTHING = Object.freeze({
159
+ theme: false,
160
+ mode: false,
161
+ density: false,
162
+ marker: null
163
+ });
164
+ /**
165
+ * Which of the axes an island restates beside the one it names it must leave
166
+ * to `<html>` on this render (tracking plan F13).
167
+ *
168
+ * `restates` names the axes this island would stamp with a value it took from
169
+ * around it rather than named. A theme's light block is the compound
170
+ * `[data-theme][data-mode="light"]`, so an island that names either stamps the
171
+ * other beside it: a nested `ThemeProvider` that names a theme and no mode
172
+ * stamps the ambient mode, and the ambient rung beside that; one that names a
173
+ * mode and no theme stamps the ambient theme; a `Preview` stage does the same
174
+ * with the page's. A rung island — a provider that names only a rung, a
175
+ * `<Density>` island, a stage that names only a rung — stamps the ambient
176
+ * theme as `data-cue-theme`, which is what a theme's own rung retunes are
177
+ * addressed through.
178
+ *
179
+ * Where such an axis is the persisting root's ({@link RootAxesContext}), the
180
+ * value around the island on the server, and on the client's first render, is
181
+ * the root's PROP, while `<html>` already carries what the visitor stored. So
182
+ * until the island has mounted it stamps none of them, and carries
183
+ * `data-cue-follows` naming them instead. Every block a theme stylesheet
184
+ * writes that the settled island would match through one of those attributes
185
+ * has a twin keyed on `:root`'s value and that marker, at the same specificity,
186
+ * so the island paints the visitor's theme, mode and rung from the first frame;
187
+ * a rung node with no `data-cue-theme` is reached by the rung rules' own
188
+ * structural form, and the base rung the island inherits from the element that
189
+ * carries it. Its own layout effect then re-renders it with exactly what it
190
+ * stamped before this existed, and the marker is gone — the
191
+ * {@link useRestateReady} pattern: its server markup and its first client
192
+ * render agree, it waits on its OWN mount rather than on anything the root
193
+ * moves, and the update is its own.
194
+ *
195
+ * Why `<html>`'s value and not the nearest ancestor's is the right one, and why
196
+ * a marker rather than the attribute's absence, is argued beside the
197
+ * selectors, in `@cueplusplus/theme-tools`' `follows`.
198
+ *
199
+ * Internal.
200
+ */
201
+ function useFollowedAxes(restates) {
202
+ const around = React.useContext(RootAxesContext);
203
+ const theme = restates.theme === true && around.theme;
204
+ const mode = restates.mode === true && around.mode;
205
+ const density = restates.density === true && around.density;
206
+ const any = theme || mode || density;
207
+ if (useMountedWhen(any) || !any) return FOLLOWS_NOTHING;
208
+ return {
209
+ theme,
210
+ mode,
211
+ density,
212
+ marker: [
213
+ theme && "theme",
214
+ mode && "mode",
215
+ density && "density"
216
+ ].filter(Boolean).join(" ")
217
+ };
218
+ }
74
219
  /**
75
220
  * Re-scope any subtree to a different density level.
76
221
  *
@@ -85,7 +230,7 @@ const PaintContext = React.createContext(null);
85
230
  * omitted where there is none. It is read by nothing this island does —
86
231
  * theme and mode are deliberately *not* re-scoped here; density was for a long
87
232
  * time the only axis an island could override (spec §6), and a named
88
- * `styleSet` is the second and last — it exists so a theme's own
233
+ * `styleSet` and a named `paint` are the other two — it exists so a theme's own
89
234
  * generated CSS can address exactly this island regardless of how many
90
235
  * *other* themed providers sit between it and the one it belongs to. A CSS
91
236
  * ancestor selector can only ask "does some ancestor carry theme `x`", never
@@ -97,7 +242,8 @@ const PaintContext = React.createContext(null);
97
242
  * is how the axis inherits: custom properties inherit down the DOM, so an island
98
243
  * that stamped the ambient set would be restating an answer it already had, and
99
244
  * an island that stamped a *default* set would silently re-point the rhythm of
100
- * every page that nested one.
245
+ * every page that nested one. `data-paint` joins them on exactly those terms
246
+ * when a `paint` is named.
101
247
  *
102
248
  * @example
103
249
  * <Density density="ultra-compact">
@@ -105,27 +251,44 @@ const PaintContext = React.createContext(null);
105
251
  * </Density>
106
252
  */
107
253
  function Density({ density, styleSet, paint, children, className, style }) {
108
- const theme = React.useContext(AmbientThemeContext);
109
- const ambientStyleSet = React.useContext(StyleSetContext);
110
- const ambientPaint = React.useContext(PaintContext);
111
- return /* @__PURE__ */ jsx(DensityContext.Provider, {
112
- value: density,
113
- children: /* @__PURE__ */ jsx(StyleSetContext.Provider, {
114
- value: styleSet ?? ambientStyleSet,
115
- children: /* @__PURE__ */ jsx(PaintContext.Provider, {
116
- value: paint ?? ambientPaint,
117
- children: /* @__PURE__ */ jsx("div", {
118
- "data-density": density,
119
- "data-cue-theme": theme ?? void 0,
120
- "data-style": styleSet ?? void 0,
121
- "data-paint": paint ?? void 0,
122
- className,
123
- style,
124
- children
254
+ const theme = useRead(AmbientThemeContext);
255
+ const ambientStyleSet = useRead(StyleSetContext);
256
+ const ambientPaint = useRead(PaintContext);
257
+ const inputs = [
258
+ density,
259
+ styleSet,
260
+ paint,
261
+ React.useContext(AmbientThemeContext),
262
+ React.useContext(StyleSetContext),
263
+ React.useContext(PaintContext)
264
+ ];
265
+ const publishedDensity = usePublish(density, inputs);
266
+ const publishedStyleSet = usePublish(styleSet ?? ambientStyleSet, inputs);
267
+ const publishedPaint = usePublish(paint ?? ambientPaint, inputs);
268
+ const around = React.useContext(RootAxesContext);
269
+ const followed = useFollowedAxes({ theme: theme !== null });
270
+ return /* @__PURE__ */ jsx(RootAxesContext.Provider, {
271
+ value: rootAxes(around.theme, around.mode, false),
272
+ children: /* @__PURE__ */ jsx(DensityContext.Provider, {
273
+ value: publishedDensity,
274
+ children: /* @__PURE__ */ jsx(StyleSetContext.Provider, {
275
+ value: publishedStyleSet,
276
+ children: /* @__PURE__ */ jsx(PaintContext.Provider, {
277
+ value: publishedPaint,
278
+ children: /* @__PURE__ */ jsx("div", {
279
+ "data-density": density,
280
+ "data-cue-theme": followed.theme ? void 0 : theme ?? void 0,
281
+ "data-cue-follows": followed.marker ?? void 0,
282
+ "data-style": styleSet ?? void 0,
283
+ "data-paint": paint ?? void 0,
284
+ className,
285
+ style,
286
+ children
287
+ })
125
288
  })
126
289
  })
127
290
  })
128
291
  });
129
292
  }
130
293
  //#endregion
131
- export { AmbientThemeContext, DEFAULT_DENSITY, Density, DensityContext, PaintContext, StyleSetContext };
294
+ export { AmbientThemeContext, DEFAULT_DENSITY, DeferRestateContext, Density, DensityContext, PaintContext, RootAxesContext, StyleSetContext, rootAxes, useFollowedAxes, useMountedWhen, useRestateReady };
@@ -7,6 +7,6 @@ import { ThemeRegistry } from "./vocabulary.js";
7
7
  import { useDensities, useFonts, useThemes } from "./theme-registry.js";
8
8
  import { ControlSize, useControlHeight, useDensity } from "./use-density.js";
9
9
  import { useTheme } from "./use-theme.js";
10
- import { DEFAULT_STYLE_SET, STYLE_SETS, StyleSet } from "@cueplusplus/tokens";
10
+ import { DEFAULT_PAINT, DEFAULT_STYLE_SET, PAINTS, Paint, STYLE_SETS, StyleSet } from "@cueplusplus/tokens";
11
11
  import { Density as DensityLevel, DensityEntry, FontEntry, FontName, Mode, ThemeManifest, ThemeName } from "@cueplusplus/theme-base";
12
- export { type ControlSize, CuePortalFrame, type CuePortalFrameProps, DEFAULT_STORAGE_KEY, DEFAULT_STYLE_SET, Density, type DensityEntry, type DensityLevel, type DensityProps, type FontEntry, type FontFamilies, type FontName, type Mode, type PersistedPreferences, type PrepaintDefaults, type PrepaintOptions, type ResolvedMode, STYLE_SETS, type StyleSet, type ThemeContextValue, type ThemeManifest, type ThemeName, ThemeProvider, type ThemeProviderProps, type ThemeRegistry, type TokenOverrides, isSafeTokenValue, prepaintScript, useControlHeight, useCuePortalProps, useDensities, useDensity, useFonts, useTheme, useThemes };
12
+ export { type ControlSize, CuePortalFrame, type CuePortalFrameProps, DEFAULT_PAINT, DEFAULT_STORAGE_KEY, DEFAULT_STYLE_SET, Density, type DensityEntry, type DensityLevel, type DensityProps, type FontEntry, type FontFamilies, type FontName, type Mode, PAINTS, type Paint, type PersistedPreferences, type PrepaintDefaults, type PrepaintOptions, type ResolvedMode, STYLE_SETS, type StyleSet, type ThemeContextValue, type ThemeManifest, type ThemeName, ThemeProvider, type ThemeProviderProps, type ThemeRegistry, type TokenOverrides, isSafeTokenValue, prepaintScript, useControlHeight, useCuePortalProps, useDensities, useDensity, useFonts, useTheme, useThemes };
@@ -6,5 +6,5 @@ import { ThemeProvider } from "./theme-provider.js";
6
6
  import { CuePortalFrame, useCuePortalProps } from "./portal.js";
7
7
  import { useControlHeight, useDensity } from "./use-density.js";
8
8
  import { useTheme } from "./use-theme.js";
9
- import { DEFAULT_STYLE_SET, STYLE_SETS } from "@cueplusplus/tokens";
10
- export { CuePortalFrame, DEFAULT_STORAGE_KEY, DEFAULT_STYLE_SET, Density, STYLE_SETS, ThemeProvider, isSafeTokenValue, prepaintScript, useControlHeight, useCuePortalProps, useDensities, useDensity, useFonts, useTheme, useThemes };
9
+ import { DEFAULT_PAINT, DEFAULT_STYLE_SET, PAINTS, STYLE_SETS } from "@cueplusplus/tokens";
10
+ export { CuePortalFrame, DEFAULT_PAINT, DEFAULT_STORAGE_KEY, DEFAULT_STYLE_SET, Density, PAINTS, STYLE_SETS, ThemeProvider, isSafeTokenValue, prepaintScript, useControlHeight, useCuePortalProps, useDensities, useDensity, useFonts, useTheme, useThemes };
@@ -1,3 +1,4 @@
1
+ import "./published.js";
1
2
  import "react";
2
3
  import { ColorToken, GeometryToken, ThemeManifest } from "@cueplusplus/theme-base";
3
4
  //#region src/system/overrides.d.ts
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { published } from "./published.js";
2
3
  import { noteOnce, warnOnce } from "./vocabulary.js";
3
4
  import * as React from "react";
4
5
  import { THEME_NAME_PATTERN, resolve } from "@cueplusplus/theme-base";
@@ -57,9 +58,13 @@ const PREFIX = "--cue-";
57
58
  * `null` means "nothing to stamp" — either no provider above, or a provider
58
59
  * whose overrides publish no colour or font for this mode.
59
60
  *
61
+ * Carried as a `Published` (see `published.ts`): it moves with the resolved
62
+ * mode, which a root's restore can change while streamed boundaries below are
63
+ * still hydrating, and a context value that changes then throws them away.
64
+ *
60
65
  * Internal: consumers get this through the provider, never directly.
61
66
  */
62
- const OverridesContext = React.createContext(null);
67
+ const OverridesContext = React.createContext(published(null));
63
68
  /**
64
69
  * The inline declarations for the resolved mode: colours and fonts.
65
70
  *
@@ -188,10 +193,153 @@ function overridesCss(overrides) {
188
193
  declarations.push(`${PREFIX}${token}:${value}`);
189
194
  }
190
195
  if (declarations.length === 0) continue;
191
- rules.push(`[data-density="${rung}"][data-density="${rung}"]{${declarations.join(";")}}`);
196
+ rules.push(`:where(:root[data-density="${rung}"]) [data-cue-follows~="density"][data-cue-follows~="density"],[data-density="${rung}"][data-density="${rung}"]{${declarations.join(";")}}`);
192
197
  }
193
198
  return rules.join("\n");
194
199
  }
200
+ /** A token name that can be written into a selector's declaration block as it stands. */
201
+ const TOKEN_NAME = /^[a-z0-9-]+$/;
202
+ /** One colour block's declarations, each checked before it is written into a stylesheet. */
203
+ function colorDeclarations(block) {
204
+ const out = [];
205
+ for (const [token, value] of Object.entries(block ?? {})) {
206
+ if (value === void 0) continue;
207
+ if (!TOKEN_NAME.test(token) || !SAFE_VALUE.test(value)) {
208
+ warnOnce(`overrides: colour ${JSON.stringify(token)} ${JSON.stringify(value)} cannot be written into a stylesheet; it applies once the provider has mounted`);
209
+ continue;
210
+ }
211
+ out.push(`${PREFIX}${token}:${value}`);
212
+ }
213
+ return out;
214
+ }
215
+ /** FNV-1a over the UTF-16 units, in base 36: the same text on the server and the client. */
216
+ function digest(text) {
217
+ let hash = 2166136261;
218
+ for (let i = 0; i < text.length; i += 1) {
219
+ hash ^= text.charCodeAt(i);
220
+ hash = Math.imul(hash, 16777619);
221
+ }
222
+ return (hash >>> 0).toString(36);
223
+ }
224
+ /** Stands in for the key while the text the key is a digest of is being written. */
225
+ const KEY = "\0";
226
+ /**
227
+ * `overrides.colors` as a stylesheet keyed on `<html>`, for a provider that
228
+ * cannot know its own resolved mode on this render — or `null` when the mode
229
+ * it would resolve to is the same whatever `<html>` says, and the inline
230
+ * declarations {@link inlineOverrides} writes are already right.
231
+ *
232
+ * **Why.** Colour overrides are inline, and only the block for the resolved
233
+ * mode is written. Under a persisting root, the mode a provider resolves on the
234
+ * server — and on the client's first render, which must agree with it — is the
235
+ * root's PROP, while `<html>` already carries the visitor's stored mode: the
236
+ * persisting root itself until it has restored, and a nested provider whose
237
+ * mode (or theme) is the root's until it has mounted (`useFollowedAxes`). The
238
+ * palette under the edit is the visitor's — the root inherits `<html>`'s, and
239
+ * an island that follows carries no `data-mode` of its own — so the edit for
240
+ * the prop's mode sat on the other mode's ground: two palettes on one surface,
241
+ * an accent chosen for a dark ground on a light one, until the restore or the
242
+ * mount wrote the right block.
243
+ *
244
+ * So for those renders the colours come out of the style attribute and into
245
+ * this: one rule per state of `<html>` that resolves differently, each keyed
246
+ * on that state and carrying only the block that state resolves to — so no
247
+ * mode's edit leaks into the other's, which a fallback rule would. `system` is
248
+ * two rules under the two `prefers-color-scheme` queries; a theme with no light
249
+ * palette (where the theme is `<html>`'s, one of `darkOnly`) is dark under
250
+ * every mode. The fonts stay inline: no mode moves them.
251
+ *
252
+ * **The key.** The rules are scoped to the element by `data-cue-colors`, whose
253
+ * value is a digest of the rules themselves, so it is the same on the server
254
+ * and the client, and two elements that share a key share every rule (a
255
+ * `useId` would do, and would also move the id of every `useId` below every
256
+ * provider, which is every Base UI label in an application). The attribute is
257
+ * written twice for (0,2,0), which ties every theme block the element matches
258
+ * and wins on source order, the density layer's arithmetic ({@link overridesCss}):
259
+ * the element is in `<body>`, after every stylesheet in `<head>`.
260
+ *
261
+ * Like the density layer, this is text written into a `<style>`, so every
262
+ * value is held to the density layer's rule, and a value that fails it waits
263
+ * for the mount, inline, where the CSSOM parses it on its own. Where every
264
+ * value fails it, the stylesheet is EMPTY rather than `null`: `null` would
265
+ * tell the provider its inline block is right, and that block is the edit for
266
+ * a mode that is not `<html>`'s. Empty, the provider renders no `<style>`,
267
+ * stamps no key, and keeps only the fonts inline, as it does for a sheet.
268
+ *
269
+ * Internal.
270
+ *
271
+ * @param overrides - The prop, or `undefined`.
272
+ * @param scope - Which of the mode and the theme are `<html>`'s on this render.
273
+ * @returns The key and the stylesheet — an empty one when every value was
274
+ * refused — or `null` when there is no colour edit, or the mode it resolves
275
+ * to is the same whatever `<html>` says.
276
+ * @example
277
+ * followerColorsCss({ colors: { light: { accent: "#b35900" } } }, { mode: null, supportsLight: true, darkOnly: [] });
278
+ * // → { key: "…", css: ':where(:root[data-mode="light"]) [data-cue-colors="…"][data-cue-colors="…"]{--cue-accent:#b35900}\n…' }
279
+ */
280
+ function followerColorsCss(overrides, scope) {
281
+ const edits = (block) => Object.values(block ?? {}).some((value) => value !== void 0);
282
+ if (!edits(overrides?.colors?.dark) && !edits(overrides?.colors?.light)) return null;
283
+ const modes = scope.mode === null ? [
284
+ {
285
+ mode: "dark",
286
+ on: ":not([data-mode=\"light\"]):not([data-mode=\"system\"])"
287
+ },
288
+ {
289
+ mode: "light",
290
+ on: "[data-mode=\"light\"]"
291
+ },
292
+ {
293
+ mode: "system",
294
+ on: "[data-mode=\"system\"]"
295
+ }
296
+ ] : [{
297
+ mode: scope.mode,
298
+ on: ""
299
+ }];
300
+ const states = [];
301
+ if (scope.supportsLight === false) states.push({
302
+ on: [":root"],
303
+ mode: "dark"
304
+ });
305
+ else {
306
+ const lightCapable = scope.supportsLight === null ? scope.darkOnly.map((name) => `:not([data-theme="${name}"])`).join("") : "";
307
+ for (const { mode, on } of modes) states.push({
308
+ on: [`:root${on}${lightCapable}`],
309
+ mode
310
+ });
311
+ if (scope.supportsLight === null && scope.darkOnly.length > 0) states.push({
312
+ on: scope.darkOnly.map((name) => `:root[data-theme="${name}"]`),
313
+ mode: "dark"
314
+ });
315
+ }
316
+ const resolved = new Set(states.map((state) => state.mode));
317
+ if (resolved.size === 1 && !resolved.has("system")) return null;
318
+ const blocks = {
319
+ dark: colorDeclarations(overrides?.colors?.dark),
320
+ light: colorDeclarations(overrides?.colors?.light)
321
+ };
322
+ const element = `[data-cue-colors="${KEY}"][data-cue-colors="${KEY}"]`;
323
+ const rules = [];
324
+ const rule = (on, mode) => blocks[mode].length === 0 ? null : `:where(${on.join(", ")}) ${element}{${blocks[mode].join(";")}}`;
325
+ for (const { on, mode } of states) {
326
+ if (mode !== "system") {
327
+ const text = rule(on, mode);
328
+ if (text !== null) rules.push(text);
329
+ continue;
330
+ }
331
+ for (const scheme of ["dark", "light"]) {
332
+ const text = rule(on, scheme);
333
+ if (text !== null) rules.push(`@media (prefers-color-scheme: ${scheme}){${text}}`);
334
+ }
335
+ }
336
+ const template = rules.join("\n");
337
+ const key = digest(template);
338
+ return {
339
+ key,
340
+ css: template.replaceAll(KEY, key)
341
+ };
342
+ }
195
343
  /**
196
344
  * Measure the palette an override actually produces, and name what it broke.
197
345
  *
@@ -274,4 +422,4 @@ function reportOverrides(manifest, mode, overrides, theme) {
274
422
  for (const check of after.advisories) if (caused(check)) noteOnce(`overrides: ${check.id} at ${check.ratio.toFixed(2)}:1 misses its ${check.minimum} advisory floor under theme "${theme}"`);
275
423
  }
276
424
  //#endregion
277
- export { OverridesContext, inlineOverrides, isSafeTokenValue, overridesCss, reportOverrides };
425
+ export { OverridesContext, followerColorsCss, inlineOverrides, isSafeTokenValue, overridesCss, reportOverrides };
@@ -8,7 +8,8 @@ import * as React from "react";
8
8
  * `data-theme` / `data-density` / `data-font` / `data-mode` (plus
9
9
  * `--cue-font-scale` and any `ThemeProvider` `overrides` colour or font
10
10
  * property) copied from the nearest provider and density island, with
11
- * `data-style` when the caller is inside a style set, and with
11
+ * `data-style` when the caller is inside a style set, `data-paint` when it is
12
+ * inside a pack, and with
12
13
  * `data-cue-skin` / `data-cue-fidelity` when the caller sits inside an
13
14
  * `AgentSurface` island. The container is
14
15
  * `display: contents`, so it changes no layout and creates no containing block —
@@ -43,7 +44,7 @@ interface CuePortalFrameProps {
43
44
  *
44
45
  * Wraps `children` in a `display: contents` element carrying the same
45
46
  * `data-theme` / `data-density` / `data-font` / `data-mode` / `data-style` /
46
- * `data-cue-skin` / `data-cue-fidelity` stamp, `--cue-font-scale` and
47
+ * `data-paint` / `data-cue-skin` / `data-cue-fidelity` stamp, `--cue-font-scale` and
47
48
  * `overrides` properties as {@link useCuePortalProps}. Prefer the hook — a
48
49
  * stamped container costs one element per overlay instead of one per render
49
50
  * tree — and reach for this only when the container prop is not available.
@@ -1,9 +1,10 @@
1
1
  "use client";
2
2
  import { useIsomorphicLayoutEffect } from "./use-isomorphic-layout-effect.js";
3
3
  import { AgentSkinContext } from "./agent-skin.js";
4
+ import { useRead } from "./published.js";
4
5
  import { DensityContext, PaintContext, StyleSetContext } from "./density.js";
5
6
  import { OverridesContext } from "./overrides.js";
6
- import { FontFamiliesContext, FontScaleContext, ThemeContext } from "./theme-provider.js";
7
+ import { FontFamiliesContext, FontScaleContext, PairingSeedContext, ThemeContext } from "./theme-provider.js";
7
8
  import * as React from "react";
8
9
  import { jsx } from "react/jsx-runtime";
9
10
  import { DEFAULT_FONT } from "@cueplusplus/tokens";
@@ -24,14 +25,14 @@ const FONT_MONO_PROPERTY = "--cue-font-mono";
24
25
  * exactly the same reason and by the same route.
25
26
  */
26
27
  function usePortalStamp() {
27
- const theme = React.useContext(ThemeContext);
28
- const island = React.useContext(DensityContext);
28
+ const theme = useRead(ThemeContext);
29
+ const island = useRead(DensityContext);
29
30
  const fontScale = React.useContext(FontScaleContext);
30
31
  const fontFamilies = React.useContext(FontFamiliesContext);
31
- const overrides = React.useContext(OverridesContext);
32
+ const overrides = useRead(OverridesContext);
32
33
  const skin = React.useContext(AgentSkinContext);
33
- const styleSet = React.useContext(StyleSetContext);
34
- const paint = React.useContext(PaintContext);
34
+ const styleSet = useRead(StyleSetContext);
35
+ const paint = useRead(PaintContext);
35
36
  return {
36
37
  theme: theme?.theme ?? DEFAULT_THEME,
37
38
  density: island ?? theme?.density ?? "compact",
@@ -54,7 +55,8 @@ function usePortalStamp() {
54
55
  * `data-theme` / `data-density` / `data-font` / `data-mode` (plus
55
56
  * `--cue-font-scale` and any `ThemeProvider` `overrides` colour or font
56
57
  * property) copied from the nearest provider and density island, with
57
- * `data-style` when the caller is inside a style set, and with
58
+ * `data-style` when the caller is inside a style set, `data-paint` when it is
59
+ * inside a pack, and with
58
60
  * `data-cue-skin` / `data-cue-fidelity` when the caller sits inside an
59
61
  * `AgentSurface` island. The container is
60
62
  * `display: contents`, so it changes no layout and creates no containing block —
@@ -76,13 +78,16 @@ function useCuePortalProps() {
76
78
  const stamp = usePortalStamp();
77
79
  const stampRef = React.useRef(stamp);
78
80
  stampRef.current = stamp;
81
+ const seed = React.useContext(PairingSeedContext);
82
+ const seedRef = React.useRef(seed);
83
+ seedRef.current = seed;
79
84
  const [container, setContainer] = React.useState(null);
80
85
  useIsomorphicLayoutEffect(() => {
81
86
  if (typeof document === "undefined") return;
82
87
  const element = document.createElement("div");
83
88
  element.setAttribute("data-cue-portal", "");
84
89
  element.style.display = "contents";
85
- applyStamp(element, stampRef.current);
90
+ applyStamp(element, seeded(stampRef.current, seedRef.current()));
86
91
  document.body.appendChild(element);
87
92
  setContainer(element);
88
93
  return () => {
@@ -92,7 +97,7 @@ function useCuePortalProps() {
92
97
  }, []);
93
98
  useIsomorphicLayoutEffect(() => {
94
99
  if (container === null) return;
95
- applyStamp(container, stamp);
100
+ applyStamp(container, seeded(stamp, seedRef.current()));
96
101
  }, [
97
102
  container,
98
103
  stamp.theme,
@@ -127,6 +132,13 @@ function useCuePortalProps() {
127
132
  * and collected with it, which is what makes the weak reference the right one.
128
133
  */
129
134
  const stampedOverrides = /* @__PURE__ */ new WeakMap();
135
+ /** `stamp`, in the pairing `seed` names when it names one (see `PairingSeedContext`). */
136
+ function seeded(stamp, seed) {
137
+ return seed === null ? stamp : {
138
+ ...stamp,
139
+ font: seed
140
+ };
141
+ }
130
142
  /** Write a stamp onto a live element (the imperative half of the contract). */
131
143
  function applyStamp(element, stamp) {
132
144
  element.setAttribute("data-theme", stamp.theme);
@@ -162,7 +174,7 @@ function setOptionalProperty(element, property, value) {
162
174
  *
163
175
  * Wraps `children` in a `display: contents` element carrying the same
164
176
  * `data-theme` / `data-density` / `data-font` / `data-mode` / `data-style` /
165
- * `data-cue-skin` / `data-cue-fidelity` stamp, `--cue-font-scale` and
177
+ * `data-paint` / `data-cue-skin` / `data-cue-fidelity` stamp, `--cue-font-scale` and
166
178
  * `overrides` properties as {@link useCuePortalProps}. Prefer the hook — a
167
179
  * stamped container costs one element per overlay instead of one per render
168
180
  * tree — and reach for this only when the container prop is not available.
@@ -22,7 +22,7 @@ interface PersistedPreferences {
22
22
  */
23
23
  style?: string;
24
24
  /**
25
- * Last look pack the user picked, or absent — which is what "no pack" means,
25
+ * Last paint pack the user picked, or absent — which is what "no pack" means,
26
26
  * for exactly the reason `style` above gives. An application that never
27
27
  * touches this axis keeps storing the object it always stored, and the
28
28
  * pre-paint script has no sixth value to hold an opinion about.
@@ -60,7 +60,7 @@ interface PrepaintDefaults {
60
60
  */
61
61
  styleSet?: StyleSet;
62
62
  /**
63
- * The look pack an unstamped page opens on, or omitted for none.
63
+ * The paint pack an unstamped page opens on, or omitted for none.
64
64
  *
65
65
  * The second axis whose absence is a value, and it behaves exactly as
66
66
  * `styleSet` does: omitted means the script REMOVES `data-paint` rather than
@@ -92,12 +92,28 @@ interface PrepaintOptions {
92
92
  * every returning visitor's first frame in a theme they did not choose.
93
93
  */
94
94
  themes?: readonly ThemeManifest[];
95
+ /**
96
+ * The root provider's `fontScale`, when it is not `1` — pass the same number
97
+ * you pass `<ThemeProvider fontScale>`.
98
+ *
99
+ * Every `--cue-text-*` token is `calc(<rung size> * var(--cue-font-scale, 1))`,
100
+ * and a custom property's `var()` is substituted where it is declared. The
101
+ * provider publishes the scale on its own element, but a root that persists
102
+ * restates no rung there until it has restored the visitor's, so until then
103
+ * the type tokens are declared on `<html>` — and without this, `<html>`
104
+ * declares no scale: the first frame sets every word at 1.0x and the restore
105
+ * moves it to the root's. Given, the script writes `--cue-font-scale` on
106
+ * `<html>`, and the root keeps it there once it has hydrated.
107
+ *
108
+ * Omitted or `1`, the script writes nothing and is byte for byte what it was.
109
+ */
110
+ fontScale?: number;
95
111
  }
96
112
  /**
97
113
  * Build the blocking inline script that stamps `data-theme`, `data-density`,
98
- * `data-font`, `data-mode`, `data-style` and `color-scheme` on `<html>` from
99
- * localStorage before the first paint, and removes `data-style` when nothing
100
- * chose one.
114
+ * `data-font`, `data-mode`, `data-style`, `data-paint` and `color-scheme` on
115
+ * `<html>` from localStorage before the first paint, and removes `data-style`
116
+ * and `data-paint` when nothing chose a set or a pack.
101
117
  *
102
118
  * Render it as `<script dangerouslySetInnerHTML={{ __html: prepaintScript() }} />`
103
119
  * in `<head>`, above everything else. The output never contains `</script>` and
@@ -50,6 +50,8 @@ function prepaintScript(storageKeyOrOptions = DEFAULT_STORAGE_KEY, defaultTheme
50
50
  const storageKey = options.storageKey ?? "cue-ui";
51
51
  if (typeof storageKey !== "string") throw new TypeError("prepaintScript storageKey must be a string");
52
52
  const readStoredPreferences = options.readStoredPreferences ?? true;
53
+ const fontScale = options.fontScale ?? 1;
54
+ if (typeof fontScale !== "number" || !Number.isFinite(fontScale) || fontScale <= 0) throw new TypeError(`prepaintScript fontScale must be a positive number, not ${String(fontScale)}`);
53
55
  const key = jsStringLiteral(storageKey);
54
56
  const fallbackTheme = jsStringLiteral(defaults.theme);
55
57
  const fallbackDensity = jsStringLiteral(defaults.density ?? vocab.preferredDensity(defaults.theme));
@@ -120,7 +122,7 @@ function prepaintScript(storageKeyOrOptions = DEFAULT_STORAGE_KEY, defaultTheme
120
122
  */
121
123
  const paints = scriptSafe(JSON.stringify([...PAINTS]));
122
124
  const fallbackPaint = defaults.paint === void 0 ? "null" : jsStringLiteral(defaults.paint);
123
- return `!function(){try{var k=${key},e=document.documentElement,s=null;` + (readStoredPreferences ? "try{var r=localStorage.getItem(k);s=r?JSON.parse(r):null}catch(_){}" : "") + `s=s&&typeof s=="object"?s:{};var T=${themes},A=${axes},P=/^[a-z][a-z0-9-]*$/i;var t=T?(T.indexOf(s.theme)>-1?s.theme:${fallbackTheme}):(typeof s.theme=="string"&&P.test(s.theme)?s.theme:${fallbackTheme});var a=A[T?t:""]||A[""]||{d:[],f:[]};var d=a.d.indexOf(s.density)>-1?s.density:(a.d.indexOf(${fallbackDensity})>-1?${fallbackDensity}:(a.p&&a.d.indexOf(a.p)>-1?a.p:${baseDensity}));var f=a.f.indexOf(s.font)>-1?s.font:(a.f.indexOf(${fallbackFont})>-1?${fallbackFont}:(a.q&&a.f.indexOf(a.q)>-1?a.q:${baseFont}));var m=${modes}.indexOf(s.mode)>-1?s.mode:${fallbackMode};var S=${styleSets},y=S.indexOf(s.style)>-1?s.style:${fallbackStyleSet};var G=${paints},g=G.indexOf(s.paint)>-1?s.paint:${fallbackPaint};e.setAttribute("data-theme",t);e.setAttribute("data-density",d);e.setAttribute("data-font",f);e.setAttribute("data-mode",m);y?e.setAttribute("data-style",y):e.removeAttribute("data-style");g?e.setAttribute("data-paint",g):e.removeAttribute("data-paint");e.style.colorScheme=a.l===false?"dark":(m==="system"?"light dark":m)}catch(_){}}()`;
125
+ return `!function(){try{var k=${key},e=document.documentElement,s=null;` + (readStoredPreferences ? "try{var r=localStorage.getItem(k);s=r?JSON.parse(r):null}catch(_){}" : "") + `s=s&&typeof s=="object"?s:{};var T=${themes},A=${axes},P=/^[a-z][a-z0-9-]*$/i;var t=T?(T.indexOf(s.theme)>-1?s.theme:${fallbackTheme}):(typeof s.theme=="string"&&P.test(s.theme)?s.theme:${fallbackTheme});var a=A[T?t:""]||A[""]||{d:[],f:[]};var d=a.d.indexOf(s.density)>-1?s.density:(a.d.indexOf(${fallbackDensity})>-1?${fallbackDensity}:(a.p&&a.d.indexOf(a.p)>-1?a.p:${baseDensity}));var f=a.f.indexOf(s.font)>-1?s.font:(a.f.indexOf(${fallbackFont})>-1?${fallbackFont}:(a.q&&a.f.indexOf(a.q)>-1?a.q:${baseFont}));var m=${modes}.indexOf(s.mode)>-1?s.mode:${fallbackMode};var S=${styleSets},y=S.indexOf(s.style)>-1?s.style:${fallbackStyleSet};var G=${paints},g=G.indexOf(s.paint)>-1?s.paint:${fallbackPaint};e.setAttribute("data-theme",t);e.setAttribute("data-density",d);e.setAttribute("data-font",f);e.setAttribute("data-mode",m);y?e.setAttribute("data-style",y):e.removeAttribute("data-style");g?e.setAttribute("data-paint",g):e.removeAttribute("data-paint");` + (fontScale === 1 ? "" : `e.style.setProperty("--cue-font-scale",${jsStringLiteral(String(fontScale))});`) + "e.style.colorScheme=a.l===false?\"dark\":(m===\"system\"?\"light dark\":m)}catch(_){}}()";
124
126
  }
125
127
  //#endregion
126
128
  export { DEFAULT_STORAGE_KEY, prepaintScript };