@cueplusplus/ui 0.16.0 → 0.18.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 (548) hide show
  1. package/CHANGELOG.md +901 -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/empty-state.js +8 -4
  22. package/dist/chrome/eyebrow.d.ts +13 -5
  23. package/dist/chrome/eyebrow.js +18 -7
  24. package/dist/chrome/footer.d.ts +5 -0
  25. package/dist/chrome/footer.js +14 -3
  26. package/dist/chrome/navigation-menu.js +6 -3
  27. package/dist/chrome/page-shell.js +8 -5
  28. package/dist/chrome/panel.d.ts +5 -2
  29. package/dist/chrome/panel.js +10 -5
  30. package/dist/chrome/row.js +9 -5
  31. package/dist/chrome/scroll-area.js +6 -4
  32. package/dist/chrome/section-header.js +13 -4
  33. package/dist/chrome/segmented-control.js +14 -4
  34. package/dist/chrome/status-bar.js +2 -1
  35. package/dist/chrome/tabs.js +14 -3
  36. package/dist/chrome/toolbar.js +6 -3
  37. package/dist/chrome/tree.js +3 -2
  38. package/dist/color/_thumb.js +9 -3
  39. package/dist/color/color-area.js +1 -1
  40. package/dist/color/color-swatch.js +1 -1
  41. package/dist/configurator/_overrides.js +13 -4
  42. package/dist/configurator/configurator.js +4 -1
  43. package/dist/configurator/export-dialog.js +5 -2
  44. package/dist/configurator/panel-sections.js +6 -2
  45. package/dist/configurator/token-editor.js +4 -1
  46. package/dist/date/_trigger.js +4 -1
  47. package/dist/date/calendar.js +22 -12
  48. package/dist/dmx/channel-matrix.js +3 -2
  49. package/dist/dmx/dmx-bar.js +1 -1
  50. package/dist/dmx/dmx-strip.js +1 -1
  51. package/dist/dmx/universe-grid.js +3 -2
  52. package/dist/elements/activity-graph.js +3 -3
  53. package/dist/elements/agent-card.js +3 -3
  54. package/dist/elements/approval-card.js +3 -3
  55. package/dist/elements/artifact-card.js +2 -2
  56. package/dist/elements/background-inbox.js +2 -2
  57. package/dist/elements/canvas-split.js +2 -2
  58. package/dist/elements/chart.js +1 -1
  59. package/dist/elements/chat-panel.js +2 -2
  60. package/dist/elements/checkpoint-history.js +2 -2
  61. package/dist/elements/clamp.js +2 -1
  62. package/dist/elements/code-diff.js +1 -1
  63. package/dist/elements/code-runner.js +1 -1
  64. package/dist/elements/command-palette.js +6 -5
  65. package/dist/elements/comparison-card.js +2 -2
  66. package/dist/elements/composer.js +9 -8
  67. package/dist/elements/computer-use.js +1 -1
  68. package/dist/elements/confidence-marker.js +2 -1
  69. package/dist/elements/connection-state.js +1 -1
  70. package/dist/elements/context-breakdown.js +1 -1
  71. package/dist/elements/context-usage.js +1 -1
  72. package/dist/elements/conversation-search.js +4 -3
  73. package/dist/elements/cost-meter.js +1 -1
  74. package/dist/elements/data-table.js +2 -2
  75. package/dist/elements/day-separator.js +1 -1
  76. package/dist/elements/diagram.js +1 -1
  77. package/dist/elements/document-reference.js +3 -3
  78. package/dist/elements/draft-restore.js +1 -1
  79. package/dist/elements/edit-message.js +4 -3
  80. package/dist/elements/elements.css +26 -5
  81. package/dist/elements/elicitation-form.js +3 -3
  82. package/dist/elements/empty-state.js +2 -1
  83. package/dist/elements/error-state.js +1 -1
  84. package/dist/elements/feedback-dialog.js +4 -3
  85. package/dist/elements/file-tree.js +2 -2
  86. package/dist/elements/flow-graph.js +2 -2
  87. package/dist/elements/guardrail-notice.js +3 -3
  88. package/dist/elements/image-generation.js +1 -1
  89. package/dist/elements/inline-citation.js +3 -3
  90. package/dist/elements/job-progress.js +3 -3
  91. package/dist/elements/launcher-bubble.js +2 -2
  92. package/dist/elements/loading-state.js +1 -1
  93. package/dist/elements/map-answer.js +3 -2
  94. package/dist/elements/markdown.js +5 -4
  95. package/dist/elements/math-block.js +1 -1
  96. package/dist/elements/mcp-server-panel.js +3 -3
  97. package/dist/elements/message-attachment.js +4 -4
  98. package/dist/elements/message-pair.js +1 -1
  99. package/dist/elements/message-queue.js +2 -2
  100. package/dist/elements/mobile-composer.js +4 -3
  101. package/dist/elements/model-picker.js +3 -3
  102. package/dist/elements/onboarding.js +2 -2
  103. package/dist/elements/permission-grant.js +2 -2
  104. package/dist/elements/permission-scopes.js +5 -4
  105. package/dist/elements/prompt-library.js +7 -6
  106. package/dist/elements/queue-dock.js +4 -3
  107. package/dist/elements/quota-banner.js +1 -1
  108. package/dist/elements/quote-reply.js +1 -1
  109. package/dist/elements/read-aloud.js +2 -2
  110. package/dist/elements/reasoning-panel.js +2 -1
  111. package/dist/elements/recommendation-card.d.ts +1 -1
  112. package/dist/elements/recommendation-card.js +2 -2
  113. package/dist/elements/regenerate-menu.js +2 -2
  114. package/dist/elements/research-report.js +1 -1
  115. package/dist/elements/retrieval-chunks.js +1 -1
  116. package/dist/elements/revert-dock.js +5 -4
  117. package/dist/elements/reviewable-diff.js +1 -1
  118. package/dist/elements/schedule-card.js +3 -3
  119. package/dist/elements/score-breakdown.js +1 -1
  120. package/dist/elements/scroll-anchor.js +2 -2
  121. package/dist/elements/settings-panel.js +3 -2
  122. package/dist/elements/shared-conversation.js +2 -2
  123. package/dist/elements/sources.js +4 -3
  124. package/dist/elements/speaker-identity.js +1 -1
  125. package/dist/elements/spec-sheet.js +1 -1
  126. package/dist/elements/streaming-text.js +1 -1
  127. package/dist/elements/subagent-list.js +2 -2
  128. package/dist/elements/suggestions.js +1 -1
  129. package/dist/elements/surfaces.d.ts +1 -1
  130. package/dist/elements/surfaces.js +2 -1
  131. package/dist/elements/tail-status.js +1 -1
  132. package/dist/elements/terminal-block.js +1 -1
  133. package/dist/elements/thread-list.js +1 -1
  134. package/dist/elements/thread-search.js +5 -4
  135. package/dist/elements/timeline.js +1 -1
  136. package/dist/elements/todo-list.js +2 -2
  137. package/dist/elements/tool-call.js +4 -3
  138. package/dist/elements/tool-error.js +2 -2
  139. package/dist/elements/tool-group.js +1 -1
  140. package/dist/elements/tool-timeline.js +4 -3
  141. package/dist/elements/trace-waterfall.js +1 -1
  142. package/dist/elements/verdict-row.js +2 -2
  143. package/dist/elements/voice-conversation.js +3 -2
  144. package/dist/elements/web-preview.js +1 -1
  145. package/dist/elements/web-search.js +2 -2
  146. package/dist/elements/work-collapse.js +2 -1
  147. package/dist/flow/node-card.js +3 -2
  148. package/dist/flow/use-flow-theme.js +2 -1
  149. package/dist/forms/_chassis.d.ts +34 -6
  150. package/dist/forms/_chassis.js +44 -9
  151. package/dist/forms/_listbox.js +22 -14
  152. package/dist/forms/checkbox.js +13 -4
  153. package/dist/forms/env-var-input.js +3 -2
  154. package/dist/forms/field.d.ts +2 -1
  155. package/dist/forms/field.js +16 -5
  156. package/dist/forms/file-upload.js +3 -2
  157. package/dist/forms/input-group.js +11 -2
  158. package/dist/forms/multi-select.js +4 -3
  159. package/dist/forms/number-field.js +7 -3
  160. package/dist/forms/otp-field.js +15 -6
  161. package/dist/forms/password-input.js +4 -2
  162. package/dist/forms/radio-group.js +10 -4
  163. package/dist/forms/rating.js +2 -1
  164. package/dist/forms/scrub-input.js +2 -1
  165. package/dist/forms/search-input.js +2 -1
  166. package/dist/forms/select.js +10 -4
  167. package/dist/forms/slider.js +9 -3
  168. package/dist/forms/switch.js +9 -3
  169. package/dist/forms/tags-input.js +4 -3
  170. package/dist/forms/textarea.js +3 -1
  171. package/dist/forms/toggle-group.js +2 -1
  172. package/dist/forms/toggle.js +5 -1
  173. package/dist/index.d.ts +2 -2
  174. package/dist/index.js +2 -2
  175. package/dist/instruments/_data-row.js +2 -1
  176. package/dist/instruments/app-window-frame.js +1 -1
  177. package/dist/instruments/code-block.js +8 -2
  178. package/dist/instruments/group-bar.js +1 -1
  179. package/dist/instruments/ledger.js +6 -2
  180. package/dist/instruments/log-viewer.js +4 -3
  181. package/dist/instruments/meter.js +2 -1
  182. package/dist/instruments/progress.js +9 -3
  183. package/dist/instruments/seam-grid.js +5 -3
  184. package/dist/instruments/stat.js +13 -4
  185. package/dist/instruments/table.js +29 -10
  186. package/dist/instruments/terminal-frame.js +4 -2
  187. package/dist/instruments/usage-chart.js +1 -1
  188. package/dist/layout/_collapse.js +26 -5
  189. package/dist/layout/accordion.js +2 -1
  190. package/dist/layout/bento.js +7 -4
  191. package/dist/layout/breadcrumb.js +10 -5
  192. package/dist/layout/card.js +14 -7
  193. package/dist/layout/carousel.js +3 -2
  194. package/dist/layout/collapsible.js +6 -1
  195. package/dist/layout/container.js +2 -1
  196. package/dist/layout/description-list.js +4 -1
  197. package/dist/layout/frames.js +11 -5
  198. package/dist/layout/item.js +3 -2
  199. package/dist/layout/link.d.ts +30 -0
  200. package/dist/layout/link.js +22 -3
  201. package/dist/layout/pagination.js +8 -8
  202. package/dist/layout/preview.d.ts +32 -12
  203. package/dist/layout/preview.js +149 -40
  204. package/dist/layout/resizable.js +2 -1
  205. package/dist/layout/sidebar.js +11 -3
  206. package/dist/layout/stepper.js +6 -2
  207. package/dist/lib/cn.js +29 -2
  208. package/dist/midi/piano-keyboard.js +3 -2
  209. package/dist/midi/spectrum-visualizer.js +1 -1
  210. package/dist/midi/threshold-rail.js +2 -1
  211. package/dist/midi/timeline-ruler.js +1 -1
  212. package/dist/overlays/_surface.d.ts +74 -14
  213. package/dist/overlays/_surface.js +87 -14
  214. package/dist/overlays/alert-dialog.js +1 -1
  215. package/dist/overlays/command-palette.js +28 -9
  216. package/dist/overlays/dialog.d.ts +5 -0
  217. package/dist/overlays/dialog.js +6 -1
  218. package/dist/overlays/drawer.js +8 -1
  219. package/dist/overlays/hover-card.js +3 -1
  220. package/dist/overlays/info-tip.js +2 -1
  221. package/dist/overlays/menubar.js +3 -1
  222. package/dist/overlays/popover.js +3 -1
  223. package/dist/overlays/toast.js +14 -6
  224. package/dist/overlays/tooltip.js +3 -1
  225. package/dist/primitives/avatar.js +6 -2
  226. package/dist/primitives/button.d.ts +16 -1
  227. package/dist/primitives/button.js +44 -12
  228. package/dist/primitives/chip.d.ts +11 -29
  229. package/dist/primitives/chip.js +40 -50
  230. package/dist/primitives/icon-button.d.ts +1 -1
  231. package/dist/primitives/kbd.d.ts +6 -0
  232. package/dist/primitives/kbd.js +10 -1
  233. package/dist/primitives/skeleton.js +2 -1
  234. package/dist/system/_focus-ring-field.js +29 -0
  235. package/dist/system/_focus-ring.js +125 -0
  236. package/dist/system/_paint-glow.js +22 -3
  237. package/dist/system/_paint-rest-shade.js +32 -0
  238. package/dist/system/_paint-rim.js +22 -4
  239. package/dist/system/_paint-stroke-surface-1.js +1 -1
  240. package/dist/system/_paint-stroke-surface-2.js +14 -1
  241. package/dist/system/_paint-texture.js +5 -2
  242. package/dist/system/_style-accordion-rule.js +32 -0
  243. package/dist/system/_style-app-bar.js +65 -0
  244. package/dist/system/_style-avatar.js +20 -0
  245. package/dist/system/_style-band.js +57 -0
  246. package/dist/system/_style-body-leading.js +19 -0
  247. package/dist/system/_style-body-size.js +30 -0
  248. package/dist/system/_style-body-weight.js +24 -0
  249. package/dist/system/_style-body.js +32 -0
  250. package/dist/system/_style-caption-ink.js +17 -0
  251. package/dist/system/_style-caption-size.js +19 -0
  252. package/dist/system/_style-caption-weight.js +18 -0
  253. package/dist/system/_style-caption.js +19 -0
  254. package/dist/system/_style-card-gap.js +14 -0
  255. package/dist/system/_style-card-pad.js +43 -0
  256. package/dist/system/_style-cell.js +18 -0
  257. package/dist/system/_style-check-glyph.js +14 -0
  258. package/dist/system/_style-check.js +40 -0
  259. package/dist/system/_style-chip.js +143 -0
  260. package/dist/system/_style-choice-gap.js +15 -0
  261. package/dist/system/_style-code.js +13 -0
  262. package/dist/system/_style-collapse.js +94 -0
  263. package/dist/system/_style-control-face.js +29 -0
  264. package/dist/system/_style-control-gap.js +14 -0
  265. package/dist/system/_style-control-label.js +29 -0
  266. package/dist/system/_style-control-step.js +22 -0
  267. package/dist/system/_style-control.js +76 -0
  268. package/dist/system/_style-crumb.js +44 -0
  269. package/dist/system/_style-data-face.js +28 -0
  270. package/dist/system/_style-day.js +25 -0
  271. package/dist/system/_style-description.js +23 -0
  272. package/dist/system/_style-disabled.js +70 -0
  273. package/dist/system/_style-disclosure.js +21 -0
  274. package/dist/system/_style-empty-state.js +42 -0
  275. package/dist/system/_style-eyebrow.js +43 -0
  276. package/dist/system/_style-field-chassis.js +38 -0
  277. package/dist/system/_style-field-gap.js +12 -0
  278. package/dist/system/_style-footer-rule.js +47 -0
  279. package/dist/system/_style-glyph-ink.js +20 -0
  280. package/dist/system/_style-glyph-opacity.js +20 -0
  281. package/dist/system/_style-glyph-size.js +21 -0
  282. package/dist/system/_style-group-gap.js +15 -0
  283. package/dist/system/_style-group-label-pad.js +14 -0
  284. package/dist/system/_style-group-label.js +24 -0
  285. package/dist/system/_style-gutter.js +17 -0
  286. package/dist/system/_style-help-ink.js +14 -0
  287. package/dist/system/_style-help.js +38 -0
  288. package/dist/system/_style-hover-card-width.js +15 -0
  289. package/dist/system/_style-input-face.js +34 -0
  290. package/dist/system/_style-kbd.js +58 -0
  291. package/dist/system/_style-label-case.js +36 -0
  292. package/dist/system/_style-label-face.js +32 -0
  293. package/dist/system/_style-label-ink.js +29 -0
  294. package/dist/system/_style-label-leading.js +14 -0
  295. package/dist/system/_style-label-size.js +36 -0
  296. package/dist/system/_style-label-tracking.js +45 -0
  297. package/dist/system/_style-label-weight.js +40 -0
  298. package/dist/system/_style-lede.js +49 -0
  299. package/dist/system/_style-link.js +58 -0
  300. package/dist/system/_style-menu.js +43 -0
  301. package/dist/system/_style-meter.js +15 -0
  302. package/dist/system/_style-nav-item.js +41 -0
  303. package/dist/system/_style-nav-menu.js +48 -0
  304. package/dist/system/_style-nav-voice.js +43 -0
  305. package/dist/system/_style-option.js +99 -0
  306. package/dist/system/_style-otp.js +15 -0
  307. package/dist/system/_style-outline-hover.js +18 -0
  308. package/dist/system/_style-overlay-title.js +35 -0
  309. package/dist/system/_style-page-title.js +48 -0
  310. package/dist/system/_style-page.js +17 -0
  311. package/dist/system/_style-palette.js +18 -0
  312. package/dist/system/_style-panel.js +21 -0
  313. package/dist/system/_style-popover-pad.js +13 -0
  314. package/dist/system/_style-popover-width.js +15 -0
  315. package/dist/system/_style-quiet-ink.js +13 -0
  316. package/dist/system/_style-radio.js +19 -0
  317. package/dist/system/_style-row-disabled.js +17 -0
  318. package/dist/system/_style-row-pad.js +13 -0
  319. package/dist/system/_style-row.js +30 -0
  320. package/dist/system/_style-scrollbar.js +19 -0
  321. package/dist/system/_style-seam.js +43 -0
  322. package/dist/system/_style-section-rule.js +26 -0
  323. package/dist/system/_style-segment-pad.js +15 -0
  324. package/dist/system/_style-segment.js +30 -0
  325. package/dist/system/_style-segmented-control.js +86 -0
  326. package/dist/system/_style-selected.js +36 -0
  327. package/dist/system/_style-skeleton.js +15 -0
  328. package/dist/system/_style-slider.js +26 -0
  329. package/dist/system/_style-stage-marks.js +26 -0
  330. package/dist/system/_style-stat.js +31 -0
  331. package/dist/system/_style-stepper.js +16 -0
  332. package/dist/system/_style-switch.js +26 -0
  333. package/dist/system/_style-tab-hover.js +15 -0
  334. package/dist/system/_style-tab.js +71 -0
  335. package/dist/system/_style-text-focus.js +26 -0
  336. package/dist/system/_style-textarea.js +21 -0
  337. package/dist/system/_style-title.js +37 -0
  338. package/dist/system/_style-toast.js +22 -0
  339. package/dist/system/_style-toggle.js +50 -0
  340. package/dist/system/_style-toolbar.js +23 -0
  341. package/dist/system/_style-tooltip.js +46 -0
  342. package/dist/system/density.d.ts +15 -5
  343. package/dist/system/density.js +188 -25
  344. package/dist/system/index.d.ts +2 -2
  345. package/dist/system/index.js +2 -2
  346. package/dist/system/overrides.d.ts +1 -0
  347. package/dist/system/overrides.js +151 -3
  348. package/dist/system/portal.d.ts +3 -2
  349. package/dist/system/portal.js +22 -10
  350. package/dist/system/prepaint.d.ts +21 -5
  351. package/dist/system/prepaint.js +3 -1
  352. package/dist/system/published.d.ts +1 -0
  353. package/dist/system/published.js +131 -0
  354. package/dist/system/theme-provider.d.ts +118 -21
  355. package/dist/system/theme-provider.js +362 -73
  356. package/dist/system/theme-registry.d.ts +2 -1
  357. package/dist/system/theme-registry.js +27 -10
  358. package/dist/system/use-density.js +4 -3
  359. package/dist/system/use-theme.d.ts +5 -2
  360. package/dist/system/use-theme.js +7 -4
  361. package/dist/system/vocabulary.js +2 -2
  362. package/dist/theming/create-theme.js +12 -6
  363. package/dist/theming/serialize.d.ts +34 -2
  364. package/dist/theming/serialize.js +86 -4
  365. package/manifest/components/accordion.json +29 -2
  366. package/manifest/components/agent-pile.json +3 -0
  367. package/manifest/components/alert-dialog.json +36 -3
  368. package/manifest/components/app-bar.json +61 -2
  369. package/manifest/components/app-shell.json +5 -0
  370. package/manifest/components/ask-box.json +3 -1
  371. package/manifest/components/autocomplete.json +85 -1
  372. package/manifest/components/avatar-group.json +7 -0
  373. package/manifest/components/avatar.json +7 -0
  374. package/manifest/components/band.json +7 -3
  375. package/manifest/components/bento.json +12 -1
  376. package/manifest/components/breadcrumb.json +12 -0
  377. package/manifest/components/button.json +43 -4
  378. package/manifest/components/calendar.json +13 -0
  379. package/manifest/components/card.json +23 -1
  380. package/manifest/components/carousel.json +4 -1
  381. package/manifest/components/channel-matrix.json +37 -3
  382. package/manifest/components/chart-tooltip-content.json +35 -3
  383. package/manifest/components/chat-empty-state.json +3 -1
  384. package/manifest/components/checkbox-group.json +36 -1
  385. package/manifest/components/checkbox.json +36 -1
  386. package/manifest/components/chip.json +22 -1
  387. package/manifest/components/clamp.json +3 -1
  388. package/manifest/components/code-block.json +10 -1
  389. package/manifest/components/collapsible.json +35 -2
  390. package/manifest/components/color-area.json +4 -2
  391. package/manifest/components/color-field.json +29 -0
  392. package/manifest/components/color-picker.json +29 -0
  393. package/manifest/components/color-slider.json +3 -1
  394. package/manifest/components/colors-section.json +9 -1
  395. package/manifest/components/combobox.json +85 -1
  396. package/manifest/components/command-palette.json +39 -3
  397. package/manifest/components/composer-actions.json +3 -0
  398. package/manifest/components/composer-attach-button.json +3 -0
  399. package/manifest/components/composer-attachment-chip.json +3 -0
  400. package/manifest/components/composer-attachments.json +3 -0
  401. package/manifest/components/composer-bar.json +3 -0
  402. package/manifest/components/composer-command-item.json +3 -0
  403. package/manifest/components/composer-context.json +3 -0
  404. package/manifest/components/composer-input.json +3 -0
  405. package/manifest/components/composer-menu-item.json +3 -0
  406. package/manifest/components/composer-menu.json +3 -0
  407. package/manifest/components/composer-model-item.json +3 -0
  408. package/manifest/components/composer-model-trigger.json +3 -0
  409. package/manifest/components/composer-person-item.json +3 -0
  410. package/manifest/components/composer-send.json +3 -0
  411. package/manifest/components/composer-toolbar.json +3 -0
  412. package/manifest/components/composer-voice-button.json +3 -0
  413. package/manifest/components/composer-voice.json +3 -0
  414. package/manifest/components/composer.json +29 -0
  415. package/manifest/components/confidence-marker.json +3 -1
  416. package/manifest/components/container.json +2 -1
  417. package/manifest/components/context-menu.json +35 -3
  418. package/manifest/components/conversation-search.json +3 -1
  419. package/manifest/components/cue-mark.json +2 -2
  420. package/manifest/components/cue-portal-frame.json +1 -1
  421. package/manifest/components/data-row.json +3 -1
  422. package/manifest/components/data-tree.json +3 -1
  423. package/manifest/components/date-field.json +28 -0
  424. package/manifest/components/date-picker.json +32 -0
  425. package/manifest/components/date-range-picker.json +32 -0
  426. package/manifest/components/delegation-card.json +3 -1
  427. package/manifest/components/density.json +15 -7
  428. package/manifest/components/description-list.json +6 -1
  429. package/manifest/components/dialog.json +37 -3
  430. package/manifest/components/disclosure.json +35 -2
  431. package/manifest/components/dmx-bar.json +34 -3
  432. package/manifest/components/dmx-strip.json +34 -3
  433. package/manifest/components/drawer.json +36 -3
  434. package/manifest/components/dropdown-menu.json +35 -3
  435. package/manifest/components/edit-message.json +3 -1
  436. package/manifest/components/elements-command-palette.json +3 -1
  437. package/manifest/components/elements-composer.json +3 -0
  438. package/manifest/components/empty-state-composer.json +3 -1
  439. package/manifest/components/empty-state-greeting.json +3 -1
  440. package/manifest/components/empty-state-suggestion.json +3 -1
  441. package/manifest/components/empty-state-suggestions.json +3 -1
  442. package/manifest/components/empty-state.json +13 -0
  443. package/manifest/components/env-var-input.json +28 -0
  444. package/manifest/components/export-dialog.json +6 -1
  445. package/manifest/components/eyebrow.json +13 -2
  446. package/manifest/components/feedback-dialog.json +3 -0
  447. package/manifest/components/field-description.json +15 -0
  448. package/manifest/components/field-error.json +15 -0
  449. package/manifest/components/field-label.json +16 -1
  450. package/manifest/components/field.json +15 -0
  451. package/manifest/components/file-upload.json +3 -0
  452. package/manifest/components/footer.json +14 -1
  453. package/manifest/components/frames.json +14 -1
  454. package/manifest/components/hover-card.json +37 -3
  455. package/manifest/components/info-tip.json +3 -0
  456. package/manifest/components/input-group.json +31 -0
  457. package/manifest/components/input.json +29 -0
  458. package/manifest/components/item.json +3 -1
  459. package/manifest/components/kbd.json +12 -1
  460. package/manifest/components/ledger.json +9 -2
  461. package/manifest/components/link.json +33 -0
  462. package/manifest/components/log-viewer.json +3 -0
  463. package/manifest/components/map-answer.json +3 -1
  464. package/manifest/components/markdown-text.json +3 -0
  465. package/manifest/components/menubar.json +38 -4
  466. package/manifest/components/message-list.json +3 -0
  467. package/manifest/components/message.json +6 -1
  468. package/manifest/components/meter.json +1 -0
  469. package/manifest/components/mobile-composer.json +3 -1
  470. package/manifest/components/multi-select.json +86 -1
  471. package/manifest/components/musical-time-input.json +29 -0
  472. package/manifest/components/navigation-menu.json +48 -3
  473. package/manifest/components/node-card.json +3 -0
  474. package/manifest/components/number-field.json +30 -0
  475. package/manifest/components/otp-field.json +29 -0
  476. package/manifest/components/page-shell.json +14 -0
  477. package/manifest/components/pagination.json +22 -0
  478. package/manifest/components/panel-header.json +13 -0
  479. package/manifest/components/panel.json +14 -1
  480. package/manifest/components/password-input.json +28 -0
  481. package/manifest/components/permission-scopes.json +3 -1
  482. package/manifest/components/piano-keyboard.json +3 -0
  483. package/manifest/components/popover.json +37 -3
  484. package/manifest/components/preset-section.json +9 -1
  485. package/manifest/components/preview.json +24 -10
  486. package/manifest/components/progress.json +10 -1
  487. package/manifest/components/prompt-library.json +3 -1
  488. package/manifest/components/queue-dock.json +3 -1
  489. package/manifest/components/radio-group.json +14 -0
  490. package/manifest/components/radio.json +14 -0
  491. package/manifest/components/rating.json +4 -1
  492. package/manifest/components/reasoning-panel.json +3 -1
  493. package/manifest/components/recommendation-card.json +1 -1
  494. package/manifest/components/resizable.json +4 -1
  495. package/manifest/components/revert-dock.json +3 -1
  496. package/manifest/components/row.json +8 -1
  497. package/manifest/components/scroll-area.json +6 -2
  498. package/manifest/components/scrollable-tabs-list.json +21 -0
  499. package/manifest/components/scrub-input.json +28 -0
  500. package/manifest/components/seam-cell.json +1 -0
  501. package/manifest/components/seam-grid.json +1 -0
  502. package/manifest/components/seam-list.json +8 -1
  503. package/manifest/components/search-input.json +28 -0
  504. package/manifest/components/section-header.json +15 -2
  505. package/manifest/components/segmented-control.json +17 -0
  506. package/manifest/components/select.json +42 -0
  507. package/manifest/components/settings-panel.json +3 -0
  508. package/manifest/components/shape-section.json +9 -1
  509. package/manifest/components/sheet.json +35 -3
  510. package/manifest/components/shimmer-label.json +3 -0
  511. package/manifest/components/sidebar.json +19 -2
  512. package/manifest/components/skeleton.json +2 -0
  513. package/manifest/components/slider.json +16 -0
  514. package/manifest/components/sources.json +3 -1
  515. package/manifest/components/stat.json +17 -0
  516. package/manifest/components/status-bar.json +4 -0
  517. package/manifest/components/stepper.json +8 -0
  518. package/manifest/components/swap-label.json +3 -0
  519. package/manifest/components/switch.json +30 -0
  520. package/manifest/components/table-scroll-region.json +22 -2
  521. package/manifest/components/table.json +22 -2
  522. package/manifest/components/tabs.json +22 -1
  523. package/manifest/components/tags-input.json +86 -1
  524. package/manifest/components/terminal-frame.json +3 -0
  525. package/manifest/components/textarea.json +31 -0
  526. package/manifest/components/theme-configurator.json +35 -3
  527. package/manifest/components/theme-provider.json +31 -19
  528. package/manifest/components/thread-search.json +3 -1
  529. package/manifest/components/threshold-rail.json +3 -0
  530. package/manifest/components/time-field.json +28 -0
  531. package/manifest/components/toast.json +39 -2
  532. package/manifest/components/toggle-group.json +2 -1
  533. package/manifest/components/toggle.json +32 -0
  534. package/manifest/components/token-editor.json +6 -1
  535. package/manifest/components/tool-call-card.json +9 -2
  536. package/manifest/components/tool-call.json +3 -1
  537. package/manifest/components/tool-timeline.json +3 -1
  538. package/manifest/components/toolbar.json +22 -1
  539. package/manifest/components/tooltip.json +42 -3
  540. package/manifest/components/tree-visibility-toggle.json +3 -0
  541. package/manifest/components/tree.json +3 -0
  542. package/manifest/components/universe-grid.json +3 -0
  543. package/manifest/components/voice-conversation.json +3 -0
  544. package/manifest/components/work-collapse.json +3 -1
  545. package/manifest/fixtures.json +15 -0
  546. package/manifest/manifest.json +210 -190
  547. package/manifest/tokens.json +395 -4
  548. package/package.json +6 -6
@@ -1,9 +1,10 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { useIsomorphicInsertionEffect, useIsomorphicLayoutEffect } from "./use-isomorphic-layout-effect.js";
4
- import { AmbientThemeContext, DensityContext, PaintContext, StyleSetContext } from "./density.js";
4
+ import { published, usePublish, useRead } from "./published.js";
5
+ import { AmbientThemeContext, DeferRestateContext, DensityContext, PaintContext, RootAxesContext, StyleSetContext, rootAxes, useFollowedAxes, useMountedWhen, useRestateReady } from "./density.js";
5
6
  import { buildRegistry, isPaint, isStyleSet, vocabulary, warnOnce } from "./vocabulary.js";
6
- import { OverridesContext, inlineOverrides, overridesCss, reportOverrides } from "./overrides.js";
7
+ import { OverridesContext, followerColorsCss, inlineOverrides, overridesCss, reportOverrides } from "./overrides.js";
7
8
  import { DEFAULT_STORAGE_KEY } from "./prepaint.js";
8
9
  import { ThemeRegistryContext } from "./theme-registry.js";
9
10
  import * as React from "react";
@@ -45,9 +46,15 @@ const DEFAULT_RESOLVED_MODE = "dark";
45
46
  * Ambient theme state. `null` outside a provider, which is how `useTheme()`
46
47
  * knows to throw and how the portal helpers know to use the defaults.
47
48
  *
49
+ * Carried as a `Published` (see `published.ts`), like every context whose
50
+ * value the root's restore moves: a setter or a prop moves the context, as any
51
+ * context moves, and the restore — which lands while a streamed Suspense
52
+ * boundary below can still be server HTML — is posted beside it instead, so no
53
+ * boundary is told anything changed.
54
+ *
48
55
  * Internal: consumers read it through `useTheme()`.
49
56
  */
50
- const ThemeContext = React.createContext(null);
57
+ const ThemeContext = React.createContext(published(null));
51
58
  /**
52
59
  * The nearest provider's `fontScale`, published on its own so portal roots can
53
60
  * republish it. A portal mounts outside the provider's DOM subtree and so
@@ -60,6 +67,34 @@ const ThemeContext = React.createContext(null);
60
67
  const FontScaleContext = React.createContext(null);
61
68
  /** Effective font-family overrides from the nearest provider chain. */
62
69
  const FontFamiliesContext = React.createContext(null);
70
+ /**
71
+ * The pairing a portal container made right now should wear in place of the
72
+ * one its render read, or `null` for "the one it read".
73
+ *
74
+ * Not `null` under a persisting root until something there is edited, and
75
+ * then it is the visitor's STORED pairing — the one the restore lands on. A
76
+ * container is made and stamped in a layout effect of the very first commit,
77
+ * before the root's restore has run, and re-stamped in the commit after it,
78
+ * before the restore's correction has reached its render; in both, what
79
+ * `useTheme().font` says is the pairing the server rendered. That is right for
80
+ * markup, which has to hydrate against it, and wrong for a container, which is
81
+ * not hydrated and is enough, stamped with the default pairing for one commit,
82
+ * for the engine to start fetching the default's webfont for glyphs nobody
83
+ * sees (see `storedSeed`). After an edit the render's reading is the truth.
84
+ *
85
+ * A function rather than a value, and the same function for the root's whole
86
+ * life, so the context never moves: the restore must not move one (see
87
+ * `published.ts`). A `Preview` stage that names a pairing of its own hands its
88
+ * subtree {@link NO_PAIRING_SEED}; a nested provider passes the root's on.
89
+ *
90
+ * Internal: the portal stamp is the one reader.
91
+ */
92
+ const PairingSeedContext = React.createContext(noPairingSeed);
93
+ function noPairingSeed() {
94
+ return null;
95
+ }
96
+ /** The seed of a subtree whose pairing is named: the one its render read. Internal. */
97
+ const NO_PAIRING_SEED = noPairingSeed;
63
98
  function isOneOf(allowed, value) {
64
99
  return typeof value === "string" && allowed.includes(value);
65
100
  }
@@ -144,21 +179,41 @@ function writePreferences(storageKey, preferences) {
144
179
  *
145
180
  * Rendering: `<div data-cue-root data-theme data-density data-mode style={{ colorScheme, --cue-font-scale }}>`
146
181
  * (or the single child when `asChild`), plus `data-style` when — and only when —
147
- * a style set is in force. The `theme`/`density`/`font`/`mode`/`styleSet` props are
182
+ * a style set is in force, and `data-paint` on the same terms for a pack. The
183
+ * `theme`/`density`/`font`/`mode`/`styleSet`/`paint` props are
148
184
  * *initial* values — the provider holds the state so `setTheme` and friends can
149
185
  * drive it — but a changed prop is adopted after mount, so a controlling parent
150
186
  * still works.
151
187
  *
188
+ * A **nested** provider stamps only what it names. One that names no theme,
189
+ * rung, mode, set or pack follows each of them from around it, live — a
190
+ * preference the root restores after mount, or a setter called at the root,
191
+ * reaches it, its `useTheme()` and its portals — and restates none of them on
192
+ * its element, so inheritance carries the outer attributes through. Naming a
193
+ * theme or a mode stamps theme, rung and mode together (a theme's light block
194
+ * and its rung rules are compound selectors), and restates the set and the pack
195
+ * in force beside them, so their blocks — whose values read the theme — resolve
196
+ * against this element's theme rather than the page's; naming only a rung
197
+ * stamps it as a `<Density>` island does.
198
+ *
152
199
  * The font pairing is the one axis that never lands on this element: it has no
153
200
  * island form, `<html>` is its only home, and restating it here would shadow the
154
201
  * pre-paint stamp for the whole page on the first frame. See the `stamp` object
155
202
  * below.
156
203
  *
204
+ * The other axes wait for the same reason at a root that persists: its server
205
+ * markup, and its first client render, carry `data-cue-root` and no axis
206
+ * attribute or `color-scheme`, so the page inherits the visitor's stored axes
207
+ * from the pre-paint stamp on `<html>`. The restore lands before the first
208
+ * paint, and the element then states what it restored. Read the document's
209
+ * axes off `<html>`, not off this element, before hydration.
210
+ *
157
211
  * Persistence and the pre-paint contract: setters write
158
212
  * `{ theme, density, font, mode }` to `localStorage[storageKey]`, plus a `style`
159
- * key holding the style set when there is one — omitted entirely when there is
160
- * not, so an application that never touches that axis writes the same four-key
161
- * object it always wrote. That is exactly what
213
+ * key holding the style set when there is one and a `paint` key holding the pack
214
+ * when there is one — each omitted entirely when there is not, so an application
215
+ * that never touches either axis writes the same four-key object it always
216
+ * wrote. That is exactly what
162
217
  * {@link prepaintScript} reads to stamp `<html>` before the first paint. The
163
218
  * outermost provider keeps `<html>` in sync while the app runs (and restores the
164
219
  * previous stamp on unmount) so the page ground, UA scrollbars and form controls
@@ -176,13 +231,16 @@ function writePreferences(storageKey, preferences) {
176
231
  * <App />
177
232
  * </ThemeProvider>
178
233
  */
179
- function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityProp, mode: modeProp = DEFAULT_MODE, font: fontProp, styleSet: styleSetProp, paint: paintProp, fontScale = 1, fontFamilies, overrides, storageKey = DEFAULT_STORAGE_KEY, persistPreferences = true, nonce, asChild = false, className, style: styleProp, children }) {
180
- const ambient = React.useContext(ThemeContext);
234
+ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityProp, mode: modeProp, font: fontProp, styleSet: styleSetProp, paint: paintProp, fontScale = 1, fontFamilies, overrides, storageKey = DEFAULT_STORAGE_KEY, persistPreferences = true, nonce, asChild = false, className, style: styleProp, children }) {
235
+ const ambient = useRead(ThemeContext);
181
236
  const isRoot = ambient === null;
182
- const outerStyleSet = React.useContext(StyleSetContext);
183
- const outerPaint = React.useContext(PaintContext);
184
- const ambientRegistry = React.useContext(ThemeRegistryContext);
185
- const themes = themesProp ?? ambientRegistry?.themes ?? EMPTY;
237
+ const outerStyleSet = useRead(StyleSetContext);
238
+ const outerPaint = useRead(PaintContext);
239
+ const outerDensity = useRead(DensityContext);
240
+ const outerDefersRestate = React.useContext(DeferRestateContext);
241
+ const outerRootAxes = React.useContext(RootAxesContext);
242
+ const ambientRegistry = useRead(ThemeRegistryContext);
243
+ const themes = useSameElements(themesProp ?? ambientRegistry?.themes ?? EMPTY);
186
244
  const vocab = React.useMemo(() => vocabulary(themes), [themes]);
187
245
  React.useMemo(() => {
188
246
  if (process.env.NODE_ENV === "production") return;
@@ -205,13 +263,27 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
205
263
  const initialTheme = themeProp ?? (isRoot ? themes[0]?.name : ambient?.theme) ?? DEFAULT_THEME;
206
264
  const initialDensity = densityProp ?? vocab.preferredDensity(initialTheme);
207
265
  const initialFont = fontProp ?? vocab.preferredFont(initialTheme);
208
- const initialStyleSet = styleSetProp ?? (isRoot ? null : outerStyleSet);
209
- const initialPaint = paintProp ?? (isRoot ? null : outerPaint);
210
- const [theme, setThemeState] = React.useState(initialTheme);
211
- const [densityState, setDensityState] = React.useState(initialDensity);
212
- const [mode, setModeState] = React.useState(modeProp);
266
+ const initialStyleSet = styleSetProp ?? null;
267
+ const initialPaint = paintProp ?? null;
268
+ const [themeState, setThemeState] = React.useState(isRoot ? initialTheme : themeProp ?? null);
269
+ const [densityState, setDensityState] = React.useState(isRoot ? initialDensity : densityProp ?? null);
270
+ const [modeState, setModeState] = React.useState(isRoot ? modeProp ?? DEFAULT_MODE : modeProp ?? null);
271
+ const theme = themeState ?? ambient?.theme ?? DEFAULT_THEME;
272
+ const mode = modeState ?? ambient?.mode ?? DEFAULT_MODE;
273
+ const namesColour = themeState !== null || modeState !== null;
213
274
  const [styleSet, setStyleSetState] = React.useState(initialStyleSet);
214
275
  const [paint, setPaintState] = React.useState(initialPaint);
276
+ const [edits, setEdits] = React.useState(0);
277
+ /**
278
+ * The stored pairing, for a portal container made before anything was edited
279
+ * (see `PairingSeedContext`); `null` once something was, or when nothing was
280
+ * stored. Filled in on the first render, below, once the pairing is derived.
281
+ */
282
+ const pairingSeed = React.useRef(void 0);
283
+ const edited = React.useCallback(() => {
284
+ pairingSeed.current = null;
285
+ setEdits((n) => n + 1);
286
+ }, []);
215
287
  const [storedSeed] = React.useState(() => {
216
288
  if (!isRoot || !persistPreferences) return {
217
289
  theme: initialTheme,
@@ -230,14 +302,38 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
230
302
  const [systemMode, setSystemMode] = React.useState(DEFAULT_RESOLVED_MODE);
231
303
  const restoredKey = React.useRef(null);
232
304
  const [restored, setRestored] = React.useState(false);
305
+ const awaitingRestore = isRoot && persistPreferences && !restored;
233
306
  const manifest = React.useMemo(() => themes.find((m) => m.name === theme) ?? null, [themes, theme]);
234
307
  if (vocab.themes !== null && manifest === null) warnOnce(`theme "${theme}" is not registered; useTheme().manifest is null and only the base axes are offered. Add its manifest to ThemeProvider's themes prop.`);
235
- const density = vocab.acceptsDensity(theme, densityState) ? densityState : vocab.preferredDensity(theme);
236
- if (density !== densityState) warnOnce(`density "${densityState}" is not offered by theme "${theme}"; using "${density}"`);
237
- const fontTheme = isRoot && persistPreferences && !restored ? storedSeed.theme : theme;
308
+ const requestedDensity = densityState ?? outerDensity ?? ambient?.density ?? vocab.preferredDensity(theme);
309
+ const density = vocab.acceptsDensity(theme, requestedDensity) ? requestedDensity : vocab.preferredDensity(theme);
310
+ if (density !== requestedDensity && densityState !== null) warnOnce(`density "${densityState}" is not offered by theme "${theme}"; using "${density}"`);
311
+ const stampsRungAlone = !namesColour && (densityState !== null || density !== requestedDensity);
312
+ const stampsComponent = asChild && React.isValidElement(children) && typeof children.type !== "string";
313
+ const stampsOwnAxes = stampsComponent && namesColour;
314
+ const followed = useFollowedAxes(stampsComponent ? {} : {
315
+ theme: !isRoot && themeState === null && (namesColour || stampsRungAlone),
316
+ mode: !isRoot && namesColour && modeState === null,
317
+ density: !isRoot && namesColour && densityState === null
318
+ });
319
+ const fontTheme = awaitingRestore ? storedSeed.theme : theme;
238
320
  const font = vocab.acceptsFont(fontTheme, rawFont) ? rawFont : vocab.preferredFont(fontTheme);
239
321
  if (font !== rawFont) warnOnce(`font "${rawFont}" is not offered by theme "${fontTheme}"; using "${font}"`);
240
- const resolvedMode = manifest?.supportsLight === false ? "dark" : mode === "system" ? systemMode : mode;
322
+ const servedFont = vocab.acceptsFont(initialTheme, initialFont) ? initialFont : vocab.preferredFont(initialTheme);
323
+ if (pairingSeed.current === void 0) pairingSeed.current = awaitingRestore ? font : null;
324
+ const readPairingSeed = React.useCallback(() => pairingSeed.current ?? null, []);
325
+ const outerPairingSeed = React.useContext(PairingSeedContext);
326
+ const nestedPairingSeed = React.useCallback(() => {
327
+ const seed = outerPairingSeed();
328
+ if (seed === null) return null;
329
+ return vocab.acceptsFont(theme, seed) ? seed : vocab.preferredFont(theme);
330
+ }, [
331
+ outerPairingSeed,
332
+ vocab,
333
+ theme
334
+ ]);
335
+ const pairingSeedBelow = isRoot ? readPairingSeed : themeState !== null ? nestedPairingSeed : outerPairingSeed;
336
+ const resolvedMode = !namesColour && ambient !== null ? ambient.resolvedMode : manifest?.supportsLight === false ? "dark" : mode === "system" ? systemMode : mode;
241
337
  useIsomorphicLayoutEffect(() => {
242
338
  if (!isRoot) return;
243
339
  if (!persistPreferences) {
@@ -256,6 +352,7 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
256
352
  styleSet,
257
353
  paint
258
354
  });
355
+ pairingSeed.current = next.font;
259
356
  setThemeState(next.theme);
260
357
  setDensityState(next.density);
261
358
  setRootFontState(next.font);
@@ -286,19 +383,42 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
286
383
  styleSet: styleSetProp,
287
384
  paint: paintProp
288
385
  };
289
- if (previous.theme !== themeProp && themeProp !== void 0) setThemeState(themeProp);
290
- if (previous.density !== densityProp && densityProp !== void 0) setDensityState(densityProp);
291
- if (previous.mode !== modeProp) setModeState(modeProp);
292
- if (previous.font !== fontProp && fontProp !== void 0) setRootFontState(fontProp);
293
- if (previous.styleSet !== styleSetProp && styleSetProp !== void 0) setStyleSetState(styleSetProp);
294
- if (previous.paint !== paintProp && paintProp !== void 0) setPaintState(paintProp);
386
+ let adopted = false;
387
+ if (previous.theme !== themeProp && themeProp !== void 0) {
388
+ setThemeState(themeProp);
389
+ adopted = true;
390
+ }
391
+ if (previous.density !== densityProp && densityProp !== void 0) {
392
+ setDensityState(densityProp);
393
+ adopted = true;
394
+ }
395
+ if (previous.mode !== modeProp) {
396
+ if (modeProp !== void 0) setModeState(modeProp);
397
+ else if (isRoot) setModeState(DEFAULT_MODE);
398
+ adopted = true;
399
+ }
400
+ if (previous.font !== fontProp && fontProp !== void 0) {
401
+ setRootFontState(fontProp);
402
+ adopted = true;
403
+ }
404
+ if (previous.styleSet !== styleSetProp && styleSetProp !== void 0) {
405
+ setStyleSetState(styleSetProp);
406
+ adopted = true;
407
+ }
408
+ if (previous.paint !== paintProp && paintProp !== void 0) {
409
+ setPaintState(paintProp);
410
+ adopted = true;
411
+ }
412
+ if (adopted) edited();
295
413
  }, [
414
+ isRoot,
296
415
  themeProp,
297
416
  densityProp,
298
417
  modeProp,
299
418
  fontProp,
300
419
  styleSetProp,
301
- paintProp
420
+ paintProp,
421
+ edited
302
422
  ]);
303
423
  useIsomorphicLayoutEffect(() => {
304
424
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
@@ -310,7 +430,7 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
310
430
  }, []);
311
431
  const stateRef = React.useRef({
312
432
  theme,
313
- density: densityState,
433
+ density: requestedDensity,
314
434
  mode,
315
435
  font: rawFont,
316
436
  styleSet,
@@ -319,13 +439,40 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
319
439
  useIsomorphicLayoutEffect(() => {
320
440
  stateRef.current = {
321
441
  theme,
322
- density: densityState,
442
+ density: requestedDensity,
323
443
  mode,
324
444
  font: rawFont,
325
445
  styleSet,
326
446
  paint
327
447
  };
328
448
  });
449
+ const heldNow = React.useRef({
450
+ theme: themeState,
451
+ density: densityState,
452
+ mode: modeState,
453
+ font: rootFont,
454
+ styleSet,
455
+ paint
456
+ });
457
+ useIsomorphicLayoutEffect(() => {
458
+ heldNow.current = {
459
+ theme: themeState,
460
+ density: densityState,
461
+ mode: modeState,
462
+ font: rootFont,
463
+ styleSet,
464
+ paint
465
+ };
466
+ });
467
+ /** `true` when `value` is what `axis` holds already; otherwise records it as held and returns `false`. */
468
+ const holds = React.useCallback((axis, value) => {
469
+ if (Object.is(heldNow.current[axis], value)) return true;
470
+ heldNow.current = {
471
+ ...heldNow.current,
472
+ [axis]: value
473
+ };
474
+ return false;
475
+ }, []);
329
476
  const persist = React.useCallback((patch) => {
330
477
  const next = {
331
478
  ...stateRef.current,
@@ -340,31 +487,67 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
340
487
  storageKey
341
488
  ]);
342
489
  const setTheme = React.useCallback((next) => {
490
+ if (holds("theme", next)) return;
343
491
  setThemeState(next);
492
+ edited();
344
493
  persist({ theme: next });
345
- }, [persist]);
494
+ }, [
495
+ persist,
496
+ edited,
497
+ holds
498
+ ]);
346
499
  const setDensity = React.useCallback((next) => {
500
+ if (holds("density", next)) return;
347
501
  setDensityState(next);
502
+ edited();
348
503
  persist({ density: next });
349
- }, [persist]);
504
+ }, [
505
+ persist,
506
+ edited,
507
+ holds
508
+ ]);
350
509
  const setMode = React.useCallback((next) => {
510
+ if (holds("mode", next)) return;
351
511
  setModeState(next);
512
+ edited();
352
513
  persist({ mode: next });
353
- }, [persist]);
514
+ }, [
515
+ persist,
516
+ edited,
517
+ holds
518
+ ]);
354
519
  const rootSetFont = React.useCallback((next) => {
520
+ if (holds("font", next)) return;
355
521
  setRootFontState(next);
522
+ edited();
356
523
  persist({ font: next });
357
- }, [persist]);
524
+ }, [
525
+ persist,
526
+ edited,
527
+ holds
528
+ ]);
358
529
  /** Nested providers hand the axis straight up: one document, one pairing. */
359
530
  const setFont = isRoot ? rootSetFont : ambient.setFont;
360
531
  const setStyleSet = React.useCallback((next) => {
532
+ if (holds("styleSet", next)) return;
361
533
  setStyleSetState(next);
534
+ edited();
362
535
  persist({ styleSet: next });
363
- }, [persist]);
536
+ }, [
537
+ persist,
538
+ edited,
539
+ holds
540
+ ]);
364
541
  const setPaint = React.useCallback((next) => {
542
+ if (holds("paint", next)) return;
365
543
  setPaintState(next);
544
+ edited();
366
545
  persist({ paint: next });
367
- }, [persist]);
546
+ }, [
547
+ persist,
548
+ edited,
549
+ holds
550
+ ]);
368
551
  const originalStamp = React.useRef(null);
369
552
  useIsomorphicInsertionEffect(() => {
370
553
  if (!isRoot || typeof document === "undefined") return;
@@ -385,7 +568,8 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
385
568
  mode: root.getAttribute("data-mode"),
386
569
  style: root.getAttribute("data-style"),
387
570
  paint: root.getAttribute("data-paint"),
388
- colorScheme: root.style.colorScheme
571
+ colorScheme: root.style.colorScheme,
572
+ fontScale: root.style.getPropertyValue("--cue-font-scale")
389
573
  };
390
574
  const write = (name, value) => {
391
575
  if (root.getAttribute(name) !== value) root.setAttribute(name, value);
@@ -402,6 +586,11 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
402
586
  } else write("data-paint", next.paint);
403
587
  const scheme = (themes.find((m) => m.name === next.theme) ?? null)?.supportsLight === false ? "dark" : next.mode === "system" ? "light dark" : next.mode;
404
588
  if (root.style.colorScheme !== scheme) root.style.colorScheme = scheme;
589
+ const scale = fontScale === 1 ? "" : String(fontScale);
590
+ if (root.style.getPropertyValue("--cue-font-scale") !== scale) {
591
+ if (scale === "") root.style.removeProperty("--cue-font-scale");
592
+ else root.style.setProperty("--cue-font-scale", scale);
593
+ }
405
594
  }, [
406
595
  isRoot,
407
596
  restored,
@@ -412,6 +601,8 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
412
601
  font,
413
602
  mode,
414
603
  styleSet,
604
+ paint,
605
+ fontScale,
415
606
  themes,
416
607
  vocab
417
608
  ]);
@@ -431,16 +622,10 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
431
622
  restore("data-style", original.style);
432
623
  restore("data-paint", original.paint);
433
624
  root.style.colorScheme = original.colorScheme;
625
+ if (original.fontScale === "") root.style.removeProperty("--cue-font-scale");
626
+ else root.style.setProperty("--cue-font-scale", original.fontScale);
434
627
  }, []);
435
628
  const effectiveStyleSet = styleSet ?? outerStyleSet;
436
- /**
437
- * The pack in force, for the same reason and with the same caveat: it is what
438
- * `useTheme().paint` reports, and it does NOT feed the `data-paint` stamp.
439
- * That stays on this provider's own `paint` state, so a root that named none
440
- * stamps nothing on itself and nothing on `<html>` however much is stamped
441
- * around it — which keeps a `<Density paint>` island out of the document-wide
442
- * attribute and out of the storage the pre-paint script reads back.
443
- */
444
629
  const effectivePaint = paint ?? outerPaint;
445
630
  const contextValue = React.useMemo(() => ({
446
631
  theme,
@@ -491,8 +676,27 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
491
676
  ]);
492
677
  const overridesKey = JSON.stringify(overrides ?? null);
493
678
  const inline = React.useMemo(() => inlineOverrides(overrides, resolvedMode), [overridesKey, resolvedMode]);
679
+ const colorEdit = Object.values(overrides?.colors?.dark ?? {}).some((value) => value !== void 0) || Object.values(overrides?.colors?.light ?? {}).some((value) => value !== void 0);
680
+ const inheritsRootMode = !isRoot && !namesColour && !stampsComponent && colorEdit && (outerRootAxes.mode || outerRootAxes.theme);
681
+ const inheritedMounted = useMountedWhen(inheritsRootMode);
682
+ const colorsFollowMode = isRoot ? awaitingRestore : namesColour ? followed.mode : inheritsRootMode && !inheritedMounted && outerRootAxes.mode;
683
+ const colorsFollowTheme = isRoot ? awaitingRestore : namesColour ? followed.theme : inheritsRootMode && !inheritedMounted && outerRootAxes.theme;
684
+ const followerColors = React.useMemo(() => colorEdit && (colorsFollowMode || colorsFollowTheme) ? followerColorsCss(overrides, {
685
+ mode: colorsFollowMode ? null : mode,
686
+ supportsLight: colorsFollowTheme ? null : manifest?.supportsLight !== false,
687
+ darkOnly: colorsFollowTheme ? themes.filter((m) => !m.supportsLight).map((m) => m.name) : []
688
+ }) : null, [
689
+ overridesKey,
690
+ colorEdit,
691
+ colorsFollowMode,
692
+ colorsFollowTheme,
693
+ mode,
694
+ manifest?.supportsLight,
695
+ themes
696
+ ]);
697
+ const inlineFonts = React.useMemo(() => inlineOverrides(overrides?.fonts === void 0 ? void 0 : { fonts: overrides.fonts }, "dark"), [overridesKey]);
494
698
  const overridesStyle = React.useMemo(() => overridesCss(overrides), [overridesKey]);
495
- const parentOverrides = React.useContext(OverridesContext);
699
+ const parentOverrides = useRead(OverridesContext);
496
700
  const effectiveOverrides = React.useMemo(() => {
497
701
  const merged = {
498
702
  ...parentOverrides,
@@ -510,28 +714,51 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
510
714
  theme
511
715
  ]);
512
716
  const style = React.useMemo(() => ({
513
- colorScheme: manifest?.supportsLight === false ? "dark" : mode === "system" ? "light dark" : mode,
717
+ ...awaitingRestore || !namesColour || followed.theme || followed.mode && manifest?.supportsLight !== false ? null : { colorScheme: manifest?.supportsLight === false ? "dark" : mode === "system" ? "light dark" : mode },
514
718
  "--cue-font-scale": fontScale,
515
719
  ...fontFamilies?.sans === void 0 ? null : { "--cue-font-sans": fontFamilies.sans },
516
720
  ...fontFamilies?.mono === void 0 ? null : { "--cue-font-mono": fontFamilies.mono },
517
- ...inline,
721
+ ...followerColors === null ? inline : inlineFonts,
518
722
  ...styleProp
519
723
  }), [
724
+ awaitingRestore,
725
+ namesColour,
726
+ followed.mode,
727
+ followed.theme,
520
728
  manifest?.supportsLight,
521
729
  mode,
522
730
  fontScale,
523
731
  fontFamilies?.sans,
524
732
  fontFamilies?.mono,
525
733
  inline,
734
+ inlineFonts,
735
+ followerColors,
526
736
  styleProp
527
737
  ]);
528
- const stamp = {
529
- "data-cue-root": "",
530
- "data-theme": theme,
738
+ const colourStamp = namesColour ? {
739
+ ...followed.theme ? null : { "data-theme": theme },
740
+ ...followed.density ? null : { "data-density": density },
741
+ ...followed.mode ? null : { "data-mode": mode },
742
+ ...followed.marker === null ? null : { "data-cue-follows": followed.marker }
743
+ } : stampsRungAlone ? {
531
744
  "data-density": density,
532
- "data-mode": mode,
533
- ...styleSet === null ? null : { "data-style": styleSet },
534
- ...paint === null ? null : { "data-paint": paint }
745
+ ...followed.theme ? null : { "data-cue-theme": theme },
746
+ ...followed.marker === null ? null : { "data-cue-follows": followed.marker }
747
+ } : null;
748
+ const wantsRestate = !isRoot && namesColour && (effectiveStyleSet !== null || effectivePaint !== null);
749
+ const restates = useRestateReady(wantsRestate) && wantsRestate;
750
+ const stampedStyleSet = restates ? effectiveStyleSet : styleSet;
751
+ const stampedPaint = restates ? effectivePaint : paint;
752
+ const colorsKey = followerColors === null || followerColors.css === "" ? null : { "data-cue-colors": followerColors.key };
753
+ const stamp = awaitingRestore ? {
754
+ "data-cue-root": "",
755
+ ...colorsKey
756
+ } : {
757
+ "data-cue-root": "",
758
+ ...colourStamp,
759
+ ...stampedStyleSet === null ? null : { "data-style": stampedStyleSet },
760
+ ...stampedPaint === null ? null : { "data-paint": stampedPaint },
761
+ ...colorsKey
535
762
  };
536
763
  let root;
537
764
  if (asChild) {
@@ -550,6 +777,11 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
550
777
  style,
551
778
  children
552
779
  });
780
+ const colorLayer = followerColors === null || followerColors.css === "" ? null : /* @__PURE__ */ jsx("style", {
781
+ ...nonce === void 0 ? null : { nonce },
782
+ "data-cue-colors-for": followerColors.key,
783
+ children: followerColors.css
784
+ });
553
785
  const densityLayer = overridesStyle === "" ? null : /* @__PURE__ */ jsx("style", {
554
786
  ...nonce === void 0 ? null : { nonce },
555
787
  "data-cue-overrides": "",
@@ -586,23 +818,68 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
586
818
  nonce,
587
819
  children: tree
588
820
  });
589
- return withCspContext(/* @__PURE__ */ jsx(ThemeRegistryContext.Provider, {
590
- value: registry,
591
- children: /* @__PURE__ */ jsx(ThemeContext.Provider, {
592
- value: contextValue,
593
- children: /* @__PURE__ */ jsx(AmbientThemeContext.Provider, {
594
- value: theme,
595
- children: /* @__PURE__ */ jsx(FontScaleContext.Provider, {
596
- value: fontScale,
597
- children: /* @__PURE__ */ jsx(FontFamiliesContext.Provider, {
598
- value: effectiveFontFamilies,
599
- children: /* @__PURE__ */ jsx(OverridesContext.Provider, {
600
- value: effectiveOverrides,
601
- children: /* @__PURE__ */ jsx(DensityContext.Provider, {
602
- value: density,
603
- children: /* @__PURE__ */ jsxs(StyleSetContext.Provider, {
604
- value: effectiveStyleSet,
605
- children: [root, densityLayer]
821
+ const inputs = [
822
+ edits,
823
+ ...themes,
824
+ themeProp,
825
+ densityProp,
826
+ modeProp,
827
+ fontProp,
828
+ styleSetProp,
829
+ paintProp,
830
+ overridesKey,
831
+ persistPreferences,
832
+ storageKey,
833
+ React.useContext(ThemeContext),
834
+ React.useContext(ThemeRegistryContext),
835
+ React.useContext(OverridesContext),
836
+ React.useContext(DensityContext),
837
+ React.useContext(StyleSetContext),
838
+ React.useContext(PaintContext)
839
+ ];
840
+ const publishedRegistry = usePublish(registry, inputs);
841
+ const publishedTheme = usePublish(contextValue, inputs, isRoot && persistPreferences ? () => servedFont === contextValue.font ? contextValue : {
842
+ ...contextValue,
843
+ font: servedFont
844
+ } : void 0);
845
+ const publishedAmbient = usePublish(theme, inputs);
846
+ const publishedOverrides = usePublish(effectiveOverrides, inputs);
847
+ const publishedDensity = usePublish(density, inputs);
848
+ const publishedStyleSet = usePublish(effectiveStyleSet, inputs);
849
+ const publishedPaint = usePublish(effectivePaint, inputs);
850
+ return withCspContext(/* @__PURE__ */ jsx(DeferRestateContext.Provider, {
851
+ value: isRoot ? persistPreferences : outerDefersRestate,
852
+ children: /* @__PURE__ */ jsx(RootAxesContext.Provider, {
853
+ value: isRoot ? rootAxes(persistPreferences, persistPreferences, persistPreferences) : rootAxes(outerRootAxes.theme && themeState === null && !stampsOwnAxes, outerRootAxes.mode && modeState === null && !stampsOwnAxes, outerRootAxes.density && densityState === null && !stampsOwnAxes),
854
+ children: /* @__PURE__ */ jsx(ThemeRegistryContext.Provider, {
855
+ value: publishedRegistry,
856
+ children: /* @__PURE__ */ jsx(ThemeContext.Provider, {
857
+ value: publishedTheme,
858
+ children: /* @__PURE__ */ jsx(AmbientThemeContext.Provider, {
859
+ value: publishedAmbient,
860
+ children: /* @__PURE__ */ jsx(FontScaleContext.Provider, {
861
+ value: fontScale,
862
+ children: /* @__PURE__ */ jsx(FontFamiliesContext.Provider, {
863
+ value: effectiveFontFamilies,
864
+ children: /* @__PURE__ */ jsx(PairingSeedContext.Provider, {
865
+ value: pairingSeedBelow,
866
+ children: /* @__PURE__ */ jsx(OverridesContext.Provider, {
867
+ value: publishedOverrides,
868
+ children: /* @__PURE__ */ jsx(DensityContext.Provider, {
869
+ value: publishedDensity,
870
+ children: /* @__PURE__ */ jsx(StyleSetContext.Provider, {
871
+ value: publishedStyleSet,
872
+ children: /* @__PURE__ */ jsxs(PaintContext.Provider, {
873
+ value: publishedPaint,
874
+ children: [
875
+ root,
876
+ colorLayer,
877
+ densityLayer
878
+ ]
879
+ })
880
+ })
881
+ })
882
+ })
606
883
  })
607
884
  })
608
885
  })
@@ -612,5 +889,17 @@ function ThemeProvider({ themes: themesProp, theme: themeProp, density: densityP
612
889
  })
613
890
  }));
614
891
  }
892
+ /**
893
+ * `list` itself, or the array this hook returned last time when that one holds
894
+ * the same elements — so a caller that builds an equal array on every render
895
+ * hands on one identity.
896
+ */
897
+ function useSameElements(list) {
898
+ const [kept, setKept] = React.useState(list);
899
+ if (kept === list) return kept;
900
+ if (kept.length === list.length && kept.every((item, i) => Object.is(item, list[i]))) return kept;
901
+ setKept(list);
902
+ return list;
903
+ }
615
904
  //#endregion
616
- export { FontFamiliesContext, FontScaleContext, ThemeContext, ThemeProvider };
905
+ export { FontFamiliesContext, FontScaleContext, NO_PAIRING_SEED, PairingSeedContext, ThemeContext, ThemeProvider };
@@ -1,3 +1,4 @@
1
+ import "./published.js";
1
2
  import { ThemeRegistry } from "./vocabulary.js";
2
3
  import "react";
3
4
  import { DensityEntry, FontEntry, ThemeManifest } from "@cueplusplus/theme-base";
@@ -40,7 +41,7 @@ declare function useThemes(): readonly ThemeManifest[];
40
41
  */
41
42
  declare function useDensities(): readonly DensityEntry[];
42
43
  /**
43
- * The font pairings, by the same rule: the base eight, then the active theme's.
44
+ * The font pairings, by the same rule: the base twelve, then the active theme's.
44
45
  *
45
46
  * @throws If called outside a `<ThemeProvider>`.
46
47
  * @example