@adia-ai/web-components 0.4.6 → 0.4.8

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 (399) hide show
  1. package/README.md +39 -0
  2. package/USAGE.md +29 -9
  3. package/components/accordion/accordion.a2ui.json +3 -0
  4. package/components/accordion/accordion.d.ts +27 -0
  5. package/components/accordion/accordion.js +10 -117
  6. package/components/accordion/accordion.yaml +4 -0
  7. package/components/accordion/class.js +132 -0
  8. package/components/action-list/action-list.a2ui.json +3 -0
  9. package/components/action-list/action-list.d.ts +25 -0
  10. package/components/action-list/action-list.js +9 -140
  11. package/components/action-list/action-list.yaml +4 -0
  12. package/components/action-list/class.js +156 -0
  13. package/components/agent-artifact/agent-artifact.a2ui.json +4 -0
  14. package/components/agent-artifact/agent-artifact.d.ts +35 -0
  15. package/components/agent-artifact/agent-artifact.js +8 -181
  16. package/components/agent-artifact/agent-artifact.yaml +5 -0
  17. package/components/agent-artifact/class.js +200 -0
  18. package/components/agent-feedback-bar/agent-feedback-bar.a2ui.json +3 -0
  19. package/components/agent-feedback-bar/agent-feedback-bar.d.ts +33 -0
  20. package/components/agent-feedback-bar/agent-feedback-bar.js +8 -143
  21. package/components/agent-feedback-bar/agent-feedback-bar.yaml +4 -0
  22. package/components/agent-feedback-bar/class.js +162 -0
  23. package/components/agent-questions/agent-questions.a2ui.json +3 -0
  24. package/components/agent-questions/agent-questions.d.ts +33 -0
  25. package/components/agent-questions/agent-questions.js +8 -180
  26. package/components/agent-questions/agent-questions.yaml +4 -0
  27. package/components/agent-questions/class.js +199 -0
  28. package/components/agent-reasoning/agent-reasoning.a2ui.json +4 -0
  29. package/components/agent-reasoning/agent-reasoning.d.ts +37 -0
  30. package/components/agent-reasoning/agent-reasoning.js +8 -494
  31. package/components/agent-reasoning/agent-reasoning.yaml +5 -0
  32. package/components/agent-reasoning/class.js +513 -0
  33. package/components/agent-suggestions/agent-suggestions.a2ui.json +3 -0
  34. package/components/agent-suggestions/agent-suggestions.d.ts +31 -0
  35. package/components/agent-suggestions/agent-suggestions.js +8 -78
  36. package/components/agent-suggestions/agent-suggestions.yaml +4 -0
  37. package/components/agent-suggestions/class.js +97 -0
  38. package/components/agent-trace/agent-trace.a2ui.json +1 -0
  39. package/components/agent-trace/agent-trace.d.ts +29 -0
  40. package/components/alert/alert.a2ui.json +1 -0
  41. package/components/alert/alert.d.ts +39 -0
  42. package/components/alert/alert.js +8 -175
  43. package/components/alert/class.js +194 -0
  44. package/components/aside/aside.a2ui.json +1 -0
  45. package/components/avatar/avatar.a2ui.json +3 -0
  46. package/components/avatar/avatar.d.ts +28 -0
  47. package/components/avatar/avatar.js +9 -159
  48. package/components/avatar/avatar.yaml +4 -0
  49. package/components/avatar/class.js +173 -0
  50. package/components/badge/badge.a2ui.json +3 -0
  51. package/components/badge/badge.d.ts +28 -0
  52. package/components/badge/badge.js +9 -75
  53. package/components/badge/badge.yaml +4 -0
  54. package/components/badge/class.js +93 -0
  55. package/components/block/block.a2ui.json +1 -0
  56. package/components/block/block.d.ts +20 -0
  57. package/components/block/block.js +9 -15
  58. package/components/block/class.js +33 -0
  59. package/components/breadcrumb/breadcrumb.a2ui.json +5 -0
  60. package/components/breadcrumb/breadcrumb.d.ts +24 -0
  61. package/components/breadcrumb/breadcrumb.js +8 -113
  62. package/components/breadcrumb/breadcrumb.yaml +6 -0
  63. package/components/breadcrumb/class.js +132 -0
  64. package/components/button/button.a2ui.json +3 -0
  65. package/components/button/button.d.ts +44 -0
  66. package/components/button/button.js +15 -66
  67. package/components/button/button.yaml +5 -0
  68. package/components/button/class.js +80 -0
  69. package/components/calendar-picker/calendar-picker.a2ui.json +7 -1
  70. package/components/calendar-picker/calendar-picker.js +8 -332
  71. package/components/calendar-picker/calendar-picker.yaml +51 -177
  72. package/components/calendar-picker/class.js +351 -0
  73. package/components/canvas/canvas.a2ui.json +7 -1
  74. package/components/canvas/canvas.d.ts +33 -0
  75. package/components/canvas/canvas.yaml +29 -36
  76. package/components/card/card.a2ui.json +4 -0
  77. package/components/card/card.d.ts +37 -0
  78. package/components/card/card.js +9 -50
  79. package/components/card/card.yaml +171 -433
  80. package/components/card/class.js +68 -0
  81. package/components/chart/chart.a2ui.json +1 -0
  82. package/components/chart/chart.d.ts +55 -0
  83. package/components/chart/chart.js +8 -2131
  84. package/components/chart/class.js +2150 -0
  85. package/components/chart-legend/chart-legend.a2ui.json +4 -0
  86. package/components/chart-legend/chart-legend.d.ts +37 -0
  87. package/components/chart-legend/chart-legend.js +8 -197
  88. package/components/chart-legend/chart-legend.yaml +5 -0
  89. package/components/chart-legend/class.js +215 -0
  90. package/components/chat-thread/chat-thread.a2ui.json +1 -0
  91. package/components/chat-thread/chat-thread.d.ts +27 -0
  92. package/components/chat-thread/chat-thread.js +8 -157
  93. package/components/chat-thread/class.js +176 -0
  94. package/components/check/check.a2ui.json +1 -0
  95. package/components/check/check.js +11 -52
  96. package/components/check/class.js +68 -0
  97. package/components/code/class.js +501 -0
  98. package/components/code/code.a2ui.json +1 -0
  99. package/components/code/code.js +8 -482
  100. package/components/col/class.js +30 -0
  101. package/components/col/col.a2ui.json +1 -0
  102. package/components/col/col.d.ts +24 -0
  103. package/components/col/col.js +10 -13
  104. package/components/color-picker/class.js +550 -0
  105. package/components/color-picker/color-picker.a2ui.json +3 -0
  106. package/components/color-picker/color-picker.js +8 -531
  107. package/components/color-picker/color-picker.yaml +4 -0
  108. package/components/command/class.js +364 -0
  109. package/components/command/command.a2ui.json +4 -0
  110. package/components/command/command.d.ts +31 -0
  111. package/components/command/command.js +8 -345
  112. package/components/command/command.yaml +105 -124
  113. package/components/demo-toggle/class.js +153 -0
  114. package/components/demo-toggle/demo-toggle.a2ui.json +1 -0
  115. package/components/demo-toggle/demo-toggle.d.ts +33 -0
  116. package/components/demo-toggle/demo-toggle.js +8 -135
  117. package/components/description-list/class.js +86 -0
  118. package/components/description-list/description-list.a2ui.json +1 -0
  119. package/components/description-list/description-list.d.ts +22 -0
  120. package/components/description-list/description-list.js +8 -67
  121. package/components/divider/class.js +57 -0
  122. package/components/divider/divider.a2ui.json +1 -0
  123. package/components/divider/divider.d.ts +20 -0
  124. package/components/divider/divider.js +10 -40
  125. package/components/drawer/class.js +306 -0
  126. package/components/drawer/drawer.a2ui.json +1 -0
  127. package/components/drawer/drawer.d.ts +35 -0
  128. package/components/drawer/drawer.js +8 -287
  129. package/components/embed/class.js +73 -0
  130. package/components/embed/embed.a2ui.json +1 -0
  131. package/components/embed/embed.d.ts +24 -0
  132. package/components/embed/embed.js +9 -55
  133. package/components/empty-state/class.js +108 -0
  134. package/components/empty-state/empty-state.a2ui.json +3 -0
  135. package/components/empty-state/empty-state.d.ts +22 -0
  136. package/components/empty-state/empty-state.js +9 -90
  137. package/components/empty-state/empty-state.yaml +4 -0
  138. package/components/feed/class.js +381 -0
  139. package/components/feed/feed.a2ui.json +9 -1
  140. package/components/feed/feed.d.ts +29 -0
  141. package/components/feed/feed.js +9 -367
  142. package/components/feed/feed.yaml +8 -1
  143. package/components/field/class.js +266 -0
  144. package/components/field/field.a2ui.json +1 -0
  145. package/components/field/field.d.ts +24 -0
  146. package/components/field/field.js +8 -247
  147. package/components/fields/class.js +106 -0
  148. package/components/fields/fields.a2ui.json +1 -0
  149. package/components/fields/fields.d.ts +20 -0
  150. package/components/fields/fields.js +8 -87
  151. package/components/footer/footer.a2ui.json +1 -0
  152. package/components/grid/class.js +31 -0
  153. package/components/grid/grid.a2ui.json +1 -0
  154. package/components/grid/grid.d.ts +24 -0
  155. package/components/grid/grid.js +10 -14
  156. package/components/header/header.a2ui.json +1 -0
  157. package/components/heatmap/class.js +305 -0
  158. package/components/heatmap/heatmap.a2ui.json +1 -0
  159. package/components/heatmap/heatmap.d.ts +43 -0
  160. package/components/heatmap/heatmap.js +8 -286
  161. package/components/icon/class.js +54 -0
  162. package/components/icon/icon.a2ui.json +1 -0
  163. package/components/icon/icon.d.ts +24 -0
  164. package/components/icon/icon.js +13 -40
  165. package/components/image/class.js +112 -0
  166. package/components/image/image.a2ui.json +3 -0
  167. package/components/image/image.d.ts +34 -0
  168. package/components/image/image.js +9 -94
  169. package/components/image/image.yaml +4 -0
  170. package/components/index.js +8 -0
  171. package/components/input/class.js +773 -0
  172. package/components/input/input.a2ui.json +7 -0
  173. package/components/input/input.js +8 -755
  174. package/components/input/input.yaml +177 -442
  175. package/components/inspector/class.js +142 -0
  176. package/components/inspector/inspector.a2ui.json +13 -1
  177. package/components/inspector/inspector.d.ts +18 -0
  178. package/components/inspector/inspector.js +8 -124
  179. package/components/inspector/inspector.yaml +21 -30
  180. package/components/kbd/class.js +34 -0
  181. package/components/kbd/kbd.a2ui.json +4 -0
  182. package/components/kbd/kbd.d.ts +18 -0
  183. package/components/kbd/kbd.js +10 -17
  184. package/components/kbd/kbd.yaml +54 -185
  185. package/components/link/class.js +187 -0
  186. package/components/link/link.a2ui.json +1 -0
  187. package/components/link/link.d.ts +65 -0
  188. package/components/link/link.js +8 -168
  189. package/components/list/class.js +249 -0
  190. package/components/list/list.a2ui.json +3 -0
  191. package/components/list/list.d.ts +33 -0
  192. package/components/list/list.js +9 -231
  193. package/components/list/list.yaml +4 -0
  194. package/components/menu/class.js +332 -0
  195. package/components/menu/menu.a2ui.json +3 -0
  196. package/components/menu/menu.d.ts +31 -0
  197. package/components/menu/menu.js +11 -316
  198. package/components/menu/menu.yaml +4 -0
  199. package/components/modal/class.js +231 -0
  200. package/components/modal/modal.a2ui.json +6 -1
  201. package/components/modal/modal.d.ts +33 -0
  202. package/components/modal/modal.js +8 -212
  203. package/components/modal/modal.yaml +19 -39
  204. package/components/nav/class.js +150 -0
  205. package/components/nav/nav.a2ui.json +1 -0
  206. package/components/nav/nav.d.ts +41 -0
  207. package/components/nav/nav.js +8 -131
  208. package/components/nav-group/class.js +152 -0
  209. package/components/nav-group/nav-group.a2ui.json +1 -0
  210. package/components/nav-group/nav-group.d.ts +45 -0
  211. package/components/nav-group/nav-group.js +9 -134
  212. package/components/nav-item/class.js +86 -0
  213. package/components/nav-item/nav-item.a2ui.json +1 -0
  214. package/components/nav-item/nav-item.d.ts +47 -0
  215. package/components/nav-item/nav-item.js +10 -69
  216. package/components/noodles/class.js +510 -0
  217. package/components/noodles/noodles.a2ui.json +1 -0
  218. package/components/noodles/noodles.d.ts +47 -0
  219. package/components/noodles/noodles.js +9 -493
  220. package/components/option-card/class.js +167 -0
  221. package/components/option-card/option-card.a2ui.json +3 -0
  222. package/components/option-card/option-card.js +8 -149
  223. package/components/option-card/option-card.yaml +4 -0
  224. package/components/otp-input/class.js +180 -0
  225. package/components/otp-input/otp-input.a2ui.json +6 -1
  226. package/components/otp-input/otp-input.js +9 -162
  227. package/components/otp-input/otp-input.yaml +45 -174
  228. package/components/page/class.js +97 -0
  229. package/components/page/page.a2ui.json +1 -0
  230. package/components/page/page.d.ts +47 -0
  231. package/components/page/page.js +8 -79
  232. package/components/pagination/class.js +195 -0
  233. package/components/pagination/pagination.a2ui.json +1 -0
  234. package/components/pagination/pagination.d.ts +33 -0
  235. package/components/pagination/pagination.js +9 -177
  236. package/components/pane/class.js +186 -0
  237. package/components/pane/pane.a2ui.json +20 -2
  238. package/components/pane/pane.d.ts +41 -0
  239. package/components/pane/pane.js +8 -167
  240. package/components/pane/pane.yaml +64 -158
  241. package/components/pipeline-status/class.js +189 -0
  242. package/components/pipeline-status/pipeline-status.a2ui.json +8 -1
  243. package/components/pipeline-status/pipeline-status.d.ts +22 -0
  244. package/components/pipeline-status/pipeline-status.js +9 -172
  245. package/components/pipeline-status/pipeline-status.yaml +34 -72
  246. package/components/popover/class.js +194 -0
  247. package/components/popover/popover.a2ui.json +1 -0
  248. package/components/popover/popover.d.ts +24 -0
  249. package/components/popover/popover.js +9 -176
  250. package/components/progress/class.js +74 -0
  251. package/components/progress/progress.a2ui.json +4 -0
  252. package/components/progress/progress.d.ts +20 -0
  253. package/components/progress/progress.js +10 -57
  254. package/components/progress/progress.yaml +124 -287
  255. package/components/progress-row/class.js +110 -0
  256. package/components/progress-row/progress-row.a2ui.json +3 -0
  257. package/components/progress-row/progress-row.d.ts +24 -0
  258. package/components/progress-row/progress-row.js +8 -92
  259. package/components/progress-row/progress-row.yaml +4 -0
  260. package/components/radio/class.js +83 -0
  261. package/components/radio/radio.a2ui.json +1 -0
  262. package/components/radio/radio.js +11 -67
  263. package/components/range/class.js +194 -0
  264. package/components/range/range.a2ui.json +1 -0
  265. package/components/range/range.js +9 -176
  266. package/components/rating/class.js +148 -0
  267. package/components/rating/rating.a2ui.json +1 -0
  268. package/components/rating/rating.js +9 -130
  269. package/components/richtext/class.js +87 -0
  270. package/components/richtext/richtext.a2ui.json +8 -1
  271. package/components/richtext/richtext.d.ts +20 -0
  272. package/components/richtext/richtext.js +8 -68
  273. package/components/richtext/richtext.yaml +30 -65
  274. package/components/row/class.js +50 -0
  275. package/components/row/row.a2ui.json +1 -0
  276. package/components/row/row.d.ts +37 -0
  277. package/components/row/row.js +10 -33
  278. package/components/search/class.js +134 -0
  279. package/components/search/search.a2ui.json +1 -0
  280. package/components/search/search.js +10 -117
  281. package/components/section/section.a2ui.json +1 -0
  282. package/components/segment/class.js +62 -0
  283. package/components/segment/segment.a2ui.json +3 -0
  284. package/components/segment/segment.d.ts +26 -0
  285. package/components/segment/segment.js +10 -45
  286. package/components/segment/segment.yaml +4 -0
  287. package/components/segmented/class.js +165 -0
  288. package/components/segmented/segmented.a2ui.json +5 -0
  289. package/components/segmented/segmented.js +10 -148
  290. package/components/segmented/segmented.yaml +41 -59
  291. package/components/select/class.js +408 -0
  292. package/components/select/select.a2ui.json +3 -0
  293. package/components/select/select.js +15 -396
  294. package/components/select/select.yaml +4 -0
  295. package/components/skeleton/class.js +52 -0
  296. package/components/skeleton/skeleton.a2ui.json +1 -0
  297. package/components/skeleton/skeleton.d.ts +24 -0
  298. package/components/skeleton/skeleton.js +8 -34
  299. package/components/slider/class.js +184 -0
  300. package/components/slider/slider.a2ui.json +1 -0
  301. package/components/slider/slider.js +9 -166
  302. package/components/stack/class.js +28 -0
  303. package/components/stack/stack.a2ui.json +1 -0
  304. package/components/stack/stack.d.ts +18 -0
  305. package/components/stack/stack.js +10 -11
  306. package/components/stat/stat.a2ui.json +1 -0
  307. package/components/step-progress/class.js +98 -0
  308. package/components/step-progress/step-progress.a2ui.json +1 -0
  309. package/components/step-progress/step-progress.d.ts +28 -0
  310. package/components/step-progress/step-progress.js +8 -79
  311. package/components/stepper/class.js +126 -0
  312. package/components/stepper/stepper.a2ui.json +3 -0
  313. package/components/stepper/stepper.d.ts +20 -0
  314. package/components/stepper/stepper.js +9 -112
  315. package/components/stepper/stepper.yaml +4 -0
  316. package/components/stream/class.js +109 -0
  317. package/components/stream/stream.a2ui.json +1 -0
  318. package/components/stream/stream.d.ts +33 -0
  319. package/components/stream/stream.js +8 -90
  320. package/components/swatch/class.js +131 -0
  321. package/components/swatch/swatch.a2ui.json +1 -0
  322. package/components/swatch/swatch.d.ts +29 -0
  323. package/components/swatch/swatch.js +8 -112
  324. package/components/swiper/class.js +373 -0
  325. package/components/swiper/swiper.a2ui.json +7 -0
  326. package/components/swiper/swiper.d.ts +45 -0
  327. package/components/swiper/swiper.js +8 -354
  328. package/components/swiper/swiper.yaml +72 -212
  329. package/components/switch/class.js +63 -0
  330. package/components/switch/switch.a2ui.json +7 -1
  331. package/components/switch/switch.js +11 -47
  332. package/components/switch/switch.yaml +70 -265
  333. package/components/table/class.js +1453 -0
  334. package/components/table/table.a2ui.json +7 -0
  335. package/components/table/table.d.ts +55 -0
  336. package/components/table/table.js +8 -1435
  337. package/components/table/table.yaml +8 -0
  338. package/components/table-toolbar/class.js +680 -0
  339. package/components/table-toolbar/table-toolbar.a2ui.json +12 -0
  340. package/components/table-toolbar/table-toolbar.d.ts +49 -0
  341. package/components/table-toolbar/table-toolbar.js +8 -689
  342. package/components/table-toolbar/table-toolbar.yaml +13 -0
  343. package/components/tabs/class.js +242 -0
  344. package/components/tabs/tabs.a2ui.json +3 -0
  345. package/components/tabs/tabs.d.ts +31 -0
  346. package/components/tabs/tabs.js +8 -223
  347. package/components/tabs/tabs.yaml +4 -0
  348. package/components/tag/class.js +99 -0
  349. package/components/tag/tag.a2ui.json +1 -0
  350. package/components/tag/tag.d.ts +37 -0
  351. package/components/tag/tag.js +8 -80
  352. package/components/text/class.js +46 -0
  353. package/components/text/text.a2ui.json +1 -0
  354. package/components/text/text.d.ts +26 -0
  355. package/components/text/text.js +9 -28
  356. package/components/textarea/class.js +134 -0
  357. package/components/textarea/textarea.a2ui.json +1 -0
  358. package/components/textarea/textarea.js +11 -118
  359. package/components/timeline/class.js +176 -0
  360. package/components/timeline/timeline.a2ui.json +18 -1
  361. package/components/timeline/timeline.d.ts +36 -0
  362. package/components/timeline/timeline.js +9 -162
  363. package/components/timeline/timeline.yaml +14 -1
  364. package/components/toast/class.js +92 -0
  365. package/components/toast/toast.a2ui.json +1 -0
  366. package/components/toast/toast.d.ts +33 -0
  367. package/components/toast/toast.js +9 -76
  368. package/components/toggle-group/class.js +154 -0
  369. package/components/toggle-group/toggle-group.a2ui.json +1 -0
  370. package/components/toggle-group/toggle-group.d.ts +29 -0
  371. package/components/toggle-group/toggle-group.js +11 -140
  372. package/components/toggle-scheme/class.js +286 -0
  373. package/components/toggle-scheme/toggle-scheme.a2ui.json +3 -0
  374. package/components/toggle-scheme/toggle-scheme.d.ts +51 -0
  375. package/components/toggle-scheme/toggle-scheme.js +8 -268
  376. package/components/toggle-scheme/toggle-scheme.yaml +4 -0
  377. package/components/toolbar/class.js +388 -0
  378. package/components/toolbar/toolbar.a2ui.json +3 -0
  379. package/components/toolbar/toolbar.d.ts +24 -0
  380. package/components/toolbar/toolbar.js +10 -376
  381. package/components/toolbar/toolbar.yaml +4 -0
  382. package/components/tooltip/class.js +299 -0
  383. package/components/tooltip/tooltip.a2ui.json +1 -0
  384. package/components/tooltip/tooltip.d.ts +28 -0
  385. package/components/tooltip/tooltip.js +8 -280
  386. package/components/tree/class.js +245 -0
  387. package/components/tree/tree.a2ui.json +3 -0
  388. package/components/tree/tree.d.ts +25 -0
  389. package/components/tree/tree.js +9 -244
  390. package/components/tree/tree.yaml +4 -0
  391. package/components/upload/class.js +199 -0
  392. package/components/upload/upload.a2ui.json +1 -0
  393. package/components/upload/upload.js +11 -183
  394. package/core/icons-phosphor.js +93 -0
  395. package/core/icons.js +92 -90
  396. package/core/index.js +5 -0
  397. package/index.d.ts +160 -5
  398. package/index.js +7 -0
  399. package/package.json +7 -2
@@ -0,0 +1,286 @@
1
+ /**
2
+ * Non-side-effect class export for `<toggle-scheme-ui>`.
3
+ *
4
+ * Importing this file gives you the class(es) without auto-registering the tag.
5
+ * Useful for test isolation, subclassing with tag-name override, or selective
6
+ * composition.
7
+ *
8
+ * The auto-register path stays at `@adia-ai/web-components/components/toggle-scheme`
9
+ * (which imports this file + calls `defineIfFree()`).
10
+ *
11
+ * @see ../../USAGE.md#registration--auto-vs-explicit
12
+ */
13
+
14
+ /**
15
+ * <toggle-scheme-ui>
16
+ *
17
+ * Icon-button primitive that toggles `color-scheme` between light and dark
18
+ * on a target element (default `:root`). Replaces the hand-wired
19
+ * `<button-ui id="theme-toggle"> + applyScheme()` boilerplate previously
20
+ * duplicated across apps/genui, apps/construct-canvas, playgrounds/chat.
21
+ *
22
+ * Composition: light-DOM host, internally stamps a single <button-ui>.
23
+ *
24
+ * Authoring API:
25
+ * [scheme="auto"|"light"|"dark"] initial scheme (default "auto")
26
+ * [target=":root"] CSS selector for target element
27
+ * [persist] write selection to localStorage
28
+ * [storage-prefix="adia-theme-"] LS key namespace (matches theme-panel)
29
+ * [icon-light="sun"] icon shown when active-scheme is light
30
+ * [icon-dark="moon"] icon shown when active-scheme is dark
31
+ * [label-light] aria-label / title in light mode
32
+ * [label-dark] aria-label / title in dark mode
33
+ * [size="md"] forwarded to internal <button-ui>
34
+ * [variant="ghost"] forwarded to internal <button-ui>
35
+ * [color=""] forwarded to internal <button-ui>
36
+ * [disabled] forwarded to internal <button-ui>
37
+ *
38
+ * Reflected state (read-only externally; use .setScheme() to mutate):
39
+ * [active-scheme] resolved scheme ("light" | "dark")
40
+ *
41
+ * Events:
42
+ * scheme-change — bubbles. detail: { scheme, source }
43
+ * source ∈ "press" | "media" | "programmatic"
44
+ *
45
+ * Public methods:
46
+ * .toggle() flip between light and dark (defeats auto)
47
+ * .setScheme(s) "light" | "dark" | "auto"; programmatic write
48
+ */
49
+
50
+ import { UIElement } from '../../core/element.js';
51
+ import '../button/button.js';
52
+
53
+ const LIGHT = 'light';
54
+ const DARK = 'dark';
55
+ const AUTO = 'auto';
56
+
57
+ export class UIToggleScheme extends UIElement {
58
+ static properties = {
59
+ scheme: { type: String, default: AUTO, reflect: true },
60
+ target: { type: String, default: ':root', reflect: true },
61
+ persist: { type: Boolean, default: false, reflect: true },
62
+ storagePrefix: { type: String, default: 'adia-theme-', reflect: true, attribute: 'storage-prefix' },
63
+ iconLight: { type: String, default: 'sun', reflect: true, attribute: 'icon-light' },
64
+ iconDark: { type: String, default: 'moon', reflect: true, attribute: 'icon-dark' },
65
+ labelLight: { type: String, default: 'Switch to dark mode', reflect: true, attribute: 'label-light' },
66
+ labelDark: { type: String, default: 'Switch to light mode', reflect: true, attribute: 'label-dark' },
67
+ size: { type: String, default: 'md', reflect: true },
68
+ variant: { type: String, default: 'ghost', reflect: true },
69
+ color: { type: String, default: '', reflect: true },
70
+ disabled: { type: Boolean, default: false, reflect: true },
71
+ activeScheme: { type: String, default: '', reflect: true, attribute: 'active-scheme' },
72
+ };
73
+
74
+ static template = () => null;
75
+
76
+ #button = null;
77
+ #mql = null;
78
+ #mqlHandler = null;
79
+ #onPress = null;
80
+ #stamped = false;
81
+
82
+ connected() {
83
+ if (!this.#stamped) {
84
+ this.#stamp();
85
+ this.#stamped = true;
86
+ }
87
+ this.#initState();
88
+ }
89
+
90
+ disconnected() {
91
+ if (this.#button && this.#onPress) {
92
+ this.#button.removeEventListener('press', this.#onPress);
93
+ }
94
+ this.#detachPcm();
95
+ }
96
+
97
+ // ── Public API ──────────────────────────────────────────────────────
98
+
99
+ /** Flip between light and dark — defeats auto. */
100
+ toggle() {
101
+ const next = this.activeScheme === DARK ? LIGHT : DARK;
102
+ this.#apply(next, 'programmatic');
103
+ }
104
+
105
+ /**
106
+ * @param {"light"|"dark"|"auto"} s
107
+ */
108
+ setScheme(s) {
109
+ if (s === AUTO) {
110
+ this.#clearTargetOverride();
111
+ const resolved = this.#resolvePrefersScheme();
112
+ this.activeScheme = resolved;
113
+ this.#syncButton();
114
+ this.#attachPcm();
115
+ this.#emit('programmatic');
116
+ } else if (s === LIGHT || s === DARK) {
117
+ this.#apply(s, 'programmatic');
118
+ }
119
+ }
120
+
121
+ // ── Internal — stamping ─────────────────────────────────────────────
122
+
123
+ #stamp() {
124
+ const btn = document.createElement('button-ui');
125
+ btn.setAttribute('part', 'button');
126
+ btn.setAttribute('variant', this.variant || 'ghost');
127
+ btn.setAttribute('size', this.size || 'md');
128
+ if (this.color) btn.setAttribute('color', this.color);
129
+ if (this.disabled) btn.setAttribute('disabled', '');
130
+ this.appendChild(btn);
131
+
132
+ this.#button = btn;
133
+ this.#onPress = (e) => {
134
+ // Internal button bubbles 'press'; we re-emit our own 'scheme-change'
135
+ // so consumers see one semantic event, not the inner button's.
136
+ e.stopPropagation();
137
+ if (this.disabled) return;
138
+ const next = this.activeScheme === DARK ? LIGHT : DARK;
139
+ this.#apply(next, 'press');
140
+ };
141
+ btn.addEventListener('press', this.#onPress);
142
+ }
143
+
144
+ // ── Internal — initial state ────────────────────────────────────────
145
+
146
+ #initState() {
147
+ // Priority: persisted > [scheme] attr > auto
148
+ let initial = null;
149
+ if (this.persist) {
150
+ try {
151
+ const v = localStorage.getItem(`${this.storagePrefix}scheme`);
152
+ if (v === LIGHT || v === DARK) initial = v;
153
+ } catch {}
154
+ }
155
+ if (initial === null) {
156
+ const attr = (this.scheme || AUTO);
157
+ if (attr === LIGHT || attr === DARK) initial = attr;
158
+ }
159
+
160
+ if (initial === LIGHT || initial === DARK) {
161
+ // Explicit choice — write to target, no MQL listening
162
+ this.#writeTarget(initial);
163
+ this.activeScheme = initial;
164
+ } else {
165
+ // Auto — follow prefers-color-scheme, attach listener
166
+ this.activeScheme = this.#resolvePrefersScheme();
167
+ this.#attachPcm();
168
+ }
169
+ this.#syncButton();
170
+ }
171
+
172
+ // ── Internal — mutation (single path) ───────────────────────────────
173
+
174
+ #apply(next, source) {
175
+ if (next !== LIGHT && next !== DARK) return;
176
+ this.#writeTarget(next);
177
+ this.activeScheme = next;
178
+ if (this.persist) {
179
+ try { localStorage.setItem(`${this.storagePrefix}scheme`, next); } catch {}
180
+ }
181
+ // User picked explicitly — stop tracking OS preference
182
+ this.#detachPcm();
183
+ this.#syncButton();
184
+ this.#emit(source);
185
+ }
186
+
187
+ #syncButton() {
188
+ if (!this.#button) return;
189
+ const dark = this.activeScheme === DARK;
190
+ const icon = dark ? this.iconDark : this.iconLight;
191
+ const label = dark ? this.labelDark : this.labelLight;
192
+ if (this.#button.getAttribute('icon') !== icon) {
193
+ this.#button.setAttribute('icon', icon);
194
+ }
195
+ this.#button.setAttribute('aria-label', label);
196
+ this.#button.setAttribute('title', label);
197
+ // Forward style passthrough so authors can change variant/size/color
198
+ // at runtime and the internal button reflects it.
199
+ if (this.#button.getAttribute('variant') !== this.variant) {
200
+ this.#button.setAttribute('variant', this.variant || 'ghost');
201
+ }
202
+ if (this.#button.getAttribute('size') !== this.size) {
203
+ this.#button.setAttribute('size', this.size || 'md');
204
+ }
205
+ if (this.color) {
206
+ this.#button.setAttribute('color', this.color);
207
+ } else {
208
+ this.#button.removeAttribute('color');
209
+ }
210
+ if (this.disabled) {
211
+ this.#button.setAttribute('disabled', '');
212
+ } else {
213
+ this.#button.removeAttribute('disabled');
214
+ }
215
+ }
216
+
217
+ render() {
218
+ // Property writes after connect (e.g. el.size = 'sm') route through here.
219
+ this.#syncButton();
220
+ }
221
+
222
+ #emit(source) {
223
+ this.dispatchEvent(new CustomEvent('scheme-change', {
224
+ bubbles: true,
225
+ detail: { scheme: this.activeScheme, source },
226
+ }));
227
+ }
228
+
229
+ // ── Internal — target resolution + write ────────────────────────────
230
+
231
+ #resolveTarget() {
232
+ const sel = this.target || ':root';
233
+ if (sel === ':root') return document.documentElement;
234
+ try {
235
+ return document.querySelector(sel) ?? document.documentElement;
236
+ } catch {
237
+ return document.documentElement;
238
+ }
239
+ }
240
+
241
+ #writeTarget(scheme) {
242
+ const t = this.#resolveTarget();
243
+ t.style.setProperty('color-scheme', scheme);
244
+ }
245
+
246
+ #clearTargetOverride() {
247
+ const t = this.#resolveTarget();
248
+ t.style.removeProperty('color-scheme');
249
+ if (this.persist) {
250
+ try { localStorage.removeItem(`${this.storagePrefix}scheme`); } catch {}
251
+ }
252
+ }
253
+
254
+ // ── Internal — prefers-color-scheme ─────────────────────────────────
255
+
256
+ #resolvePrefersScheme() {
257
+ try {
258
+ if (typeof matchMedia === 'function' &&
259
+ matchMedia('(prefers-color-scheme: dark)').matches) return DARK;
260
+ } catch {}
261
+ return LIGHT;
262
+ }
263
+
264
+ #attachPcm() {
265
+ if (this.#mql || typeof matchMedia !== 'function') return;
266
+ try {
267
+ this.#mql = matchMedia('(prefers-color-scheme: dark)');
268
+ this.#mqlHandler = () => {
269
+ const resolved = this.#mql.matches ? DARK : LIGHT;
270
+ if (resolved === this.activeScheme) return;
271
+ this.activeScheme = resolved;
272
+ this.#syncButton();
273
+ this.#emit('media');
274
+ };
275
+ this.#mql.addEventListener('change', this.#mqlHandler);
276
+ } catch {}
277
+ }
278
+
279
+ #detachPcm() {
280
+ if (this.#mql && this.#mqlHandler) {
281
+ try { this.#mql.removeEventListener('change', this.#mqlHandler); } catch {}
282
+ }
283
+ this.#mql = null;
284
+ this.#mqlHandler = null;
285
+ }
286
+ }
@@ -124,6 +124,9 @@
124
124
  "x-adiaui": {
125
125
  "anti_patterns": [],
126
126
  "category": "control",
127
+ "composes": [
128
+ "button-ui"
129
+ ],
127
130
  "events": {
128
131
  "scheme-change": {
129
132
  "description": "Fired when the active scheme changes. detail contains { scheme: \"light\" | \"dark\", source: \"press\" | \"media\" | \"programmatic\" }."
@@ -0,0 +1,51 @@
1
+ /**
2
+ * `<toggle-scheme-ui>` — Icon-button primitive that toggles `color-scheme` between light and dark on a target element (default `:root`). Encapsulates the prefers-color-scheme initial-resolution, the inline-style write to the target, optional localStorage persistence (sharing the `adia-theme-` namespace with <theme-panel>), and the moon/sun icon swap. Replaces the hand-wired `<button-ui id="theme-toggle">` + `applyScheme()` pattern previously duplicated across apps/genui, apps/construct-canvas, playgrounds/chat.
3
+ *
4
+ * @see https://ui-kit.exe.xyz/site/components/toggle-scheme
5
+ *
6
+ * Type declarations generated by scripts/build/dts-codegen.mjs from
7
+ * the component's `.a2ui.json` sidecar. Edit the source `.yaml`,
8
+ * run `npm run build:components`, then `npm run codegen:dts` to
9
+ * regenerate; or hand-author this file fully if rich event types are
10
+ * needed beyond what the yaml `events:` block can express.
11
+ */
12
+
13
+ import { UIElement } from '../../core/element.js';
14
+
15
+ export type ToggleSchemeSchemeChangeEvent = CustomEvent<unknown>;
16
+
17
+ export class UIToggleScheme extends UIElement {
18
+ /** Resolved scheme ("light" | "dark"). Read-only; mutate via .setScheme() or .toggle(). */
19
+ activeScheme: '' | 'light' | 'dark';
20
+ /** Semantic intent forwarded to the internal <button-ui>. */
21
+ color: '' | 'default' | 'accent' | 'info' | 'success' | 'warning' | 'danger';
22
+ /** Disables the internal button. */
23
+ disabled: boolean;
24
+ /** Phosphor icon shown when active-scheme is "dark" (clicking switches to light). */
25
+ iconDark: string;
26
+ /** Phosphor icon shown when active-scheme is "light" (clicking switches to dark). */
27
+ iconLight: string;
28
+ /** aria-label / title applied to the internal button when active-scheme is "dark". */
29
+ labelDark: string;
30
+ /** aria-label / title applied to the internal button when active-scheme is "light". */
31
+ labelLight: string;
32
+ /** Persist the user's choice to localStorage under `${storage-prefix}scheme`. */
33
+ persist: boolean;
34
+ /** Initial scheme — "auto" follows prefers-color-scheme; "light" / "dark" force. */
35
+ scheme: 'auto' | 'light' | 'dark';
36
+ /** Sizing scale forwarded to the internal <button-ui>. */
37
+ size: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
38
+ /** LocalStorage key prefix; default matches <theme-panel> for cross-element interop. */
39
+ storagePrefix: string;
40
+ /** CSS selector for the element receiving `color-scheme`. ":root" → <html>. */
41
+ target: string;
42
+ /** Visual style forwarded to the internal <button-ui>. Defaults to "ghost" (matches app practice). */
43
+ variant: 'default' | 'solid' | 'outline' | 'ghost' | 'primary' | 'secondary' | 'soft';
44
+
45
+ addEventListener<K extends keyof HTMLElementEventMap>(
46
+ type: K,
47
+ listener: (this: UIToggleScheme, ev: HTMLElementEventMap[K]) => unknown,
48
+ options?: boolean | AddEventListenerOptions,
49
+ ): void;
50
+ addEventListener(type: 'scheme-change', listener: (ev: ToggleSchemeSchemeChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
51
+ }
@@ -1,277 +1,17 @@
1
1
  /**
2
- * <toggle-scheme-ui>
2
+ * `<toggle-scheme-ui>` — auto-registers the tag on import.
3
3
  *
4
- * Icon-button primitive that toggles `color-scheme` between light and dark
5
- * on a target element (default `:root`). Replaces the hand-wired
6
- * `<button-ui id="theme-toggle"> + applyScheme()` boilerplate previously
7
- * duplicated across apps/genui, apps/construct-canvas, playgrounds/chat.
4
+ * For non-side-effect class import (test isolation, tag override), use
5
+ * the `class` subpath:
8
6
  *
9
- * Composition: light-DOM host, internally stamps a single <button-ui>.
7
+ * import { UIToggleScheme } from '@adia-ai/web-components/components/toggle-scheme/class';
10
8
  *
11
- * Authoring API:
12
- * [scheme="auto"|"light"|"dark"] initial scheme (default "auto")
13
- * [target=":root"] CSS selector for target element
14
- * [persist] write selection to localStorage
15
- * [storage-prefix="adia-theme-"] LS key namespace (matches theme-panel)
16
- * [icon-light="sun"] icon shown when active-scheme is light
17
- * [icon-dark="moon"] icon shown when active-scheme is dark
18
- * [label-light] aria-label / title in light mode
19
- * [label-dark] aria-label / title in dark mode
20
- * [size="md"] forwarded to internal <button-ui>
21
- * [variant="ghost"] forwarded to internal <button-ui>
22
- * [color=""] forwarded to internal <button-ui>
23
- * [disabled] forwarded to internal <button-ui>
24
- *
25
- * Reflected state (read-only externally; use .setScheme() to mutate):
26
- * [active-scheme] resolved scheme ("light" | "dark")
27
- *
28
- * Events:
29
- * scheme-change — bubbles. detail: { scheme, source }
30
- * source ∈ "press" | "media" | "programmatic"
31
- *
32
- * Public methods:
33
- * .toggle() flip between light and dark (defeats auto)
34
- * .setScheme(s) "light" | "dark" | "auto"; programmatic write
9
+ * @see ../../USAGE.md#registration--auto-vs-explicit
35
10
  */
36
11
 
37
- import { UIElement } from '../../core/element.js';
38
- import '../button/button.js';
39
-
40
- const LIGHT = 'light';
41
- const DARK = 'dark';
42
- const AUTO = 'auto';
43
-
44
- class UIToggleScheme extends UIElement {
45
- static properties = {
46
- scheme: { type: String, default: AUTO, reflect: true },
47
- target: { type: String, default: ':root', reflect: true },
48
- persist: { type: Boolean, default: false, reflect: true },
49
- storagePrefix: { type: String, default: 'adia-theme-', reflect: true, attribute: 'storage-prefix' },
50
- iconLight: { type: String, default: 'sun', reflect: true, attribute: 'icon-light' },
51
- iconDark: { type: String, default: 'moon', reflect: true, attribute: 'icon-dark' },
52
- labelLight: { type: String, default: 'Switch to dark mode', reflect: true, attribute: 'label-light' },
53
- labelDark: { type: String, default: 'Switch to light mode', reflect: true, attribute: 'label-dark' },
54
- size: { type: String, default: 'md', reflect: true },
55
- variant: { type: String, default: 'ghost', reflect: true },
56
- color: { type: String, default: '', reflect: true },
57
- disabled: { type: Boolean, default: false, reflect: true },
58
- activeScheme: { type: String, default: '', reflect: true, attribute: 'active-scheme' },
59
- };
60
-
61
- static template = () => null;
62
-
63
- #button = null;
64
- #mql = null;
65
- #mqlHandler = null;
66
- #onPress = null;
67
- #stamped = false;
68
-
69
- connected() {
70
- if (!this.#stamped) {
71
- this.#stamp();
72
- this.#stamped = true;
73
- }
74
- this.#initState();
75
- }
76
-
77
- disconnected() {
78
- if (this.#button && this.#onPress) {
79
- this.#button.removeEventListener('press', this.#onPress);
80
- }
81
- this.#detachPcm();
82
- }
83
-
84
- // ── Public API ──────────────────────────────────────────────────────
85
-
86
- /** Flip between light and dark — defeats auto. */
87
- toggle() {
88
- const next = this.activeScheme === DARK ? LIGHT : DARK;
89
- this.#apply(next, 'programmatic');
90
- }
91
-
92
- /**
93
- * @param {"light"|"dark"|"auto"} s
94
- */
95
- setScheme(s) {
96
- if (s === AUTO) {
97
- this.#clearTargetOverride();
98
- const resolved = this.#resolvePrefersScheme();
99
- this.activeScheme = resolved;
100
- this.#syncButton();
101
- this.#attachPcm();
102
- this.#emit('programmatic');
103
- } else if (s === LIGHT || s === DARK) {
104
- this.#apply(s, 'programmatic');
105
- }
106
- }
107
-
108
- // ── Internal — stamping ─────────────────────────────────────────────
109
-
110
- #stamp() {
111
- const btn = document.createElement('button-ui');
112
- btn.setAttribute('part', 'button');
113
- btn.setAttribute('variant', this.variant || 'ghost');
114
- btn.setAttribute('size', this.size || 'md');
115
- if (this.color) btn.setAttribute('color', this.color);
116
- if (this.disabled) btn.setAttribute('disabled', '');
117
- this.appendChild(btn);
118
-
119
- this.#button = btn;
120
- this.#onPress = (e) => {
121
- // Internal button bubbles 'press'; we re-emit our own 'scheme-change'
122
- // so consumers see one semantic event, not the inner button's.
123
- e.stopPropagation();
124
- if (this.disabled) return;
125
- const next = this.activeScheme === DARK ? LIGHT : DARK;
126
- this.#apply(next, 'press');
127
- };
128
- btn.addEventListener('press', this.#onPress);
129
- }
130
-
131
- // ── Internal — initial state ────────────────────────────────────────
132
-
133
- #initState() {
134
- // Priority: persisted > [scheme] attr > auto
135
- let initial = null;
136
- if (this.persist) {
137
- try {
138
- const v = localStorage.getItem(`${this.storagePrefix}scheme`);
139
- if (v === LIGHT || v === DARK) initial = v;
140
- } catch {}
141
- }
142
- if (initial === null) {
143
- const attr = (this.scheme || AUTO);
144
- if (attr === LIGHT || attr === DARK) initial = attr;
145
- }
146
-
147
- if (initial === LIGHT || initial === DARK) {
148
- // Explicit choice — write to target, no MQL listening
149
- this.#writeTarget(initial);
150
- this.activeScheme = initial;
151
- } else {
152
- // Auto — follow prefers-color-scheme, attach listener
153
- this.activeScheme = this.#resolvePrefersScheme();
154
- this.#attachPcm();
155
- }
156
- this.#syncButton();
157
- }
158
-
159
- // ── Internal — mutation (single path) ───────────────────────────────
160
-
161
- #apply(next, source) {
162
- if (next !== LIGHT && next !== DARK) return;
163
- this.#writeTarget(next);
164
- this.activeScheme = next;
165
- if (this.persist) {
166
- try { localStorage.setItem(`${this.storagePrefix}scheme`, next); } catch {}
167
- }
168
- // User picked explicitly — stop tracking OS preference
169
- this.#detachPcm();
170
- this.#syncButton();
171
- this.#emit(source);
172
- }
173
-
174
- #syncButton() {
175
- if (!this.#button) return;
176
- const dark = this.activeScheme === DARK;
177
- const icon = dark ? this.iconDark : this.iconLight;
178
- const label = dark ? this.labelDark : this.labelLight;
179
- if (this.#button.getAttribute('icon') !== icon) {
180
- this.#button.setAttribute('icon', icon);
181
- }
182
- this.#button.setAttribute('aria-label', label);
183
- this.#button.setAttribute('title', label);
184
- // Forward style passthrough so authors can change variant/size/color
185
- // at runtime and the internal button reflects it.
186
- if (this.#button.getAttribute('variant') !== this.variant) {
187
- this.#button.setAttribute('variant', this.variant || 'ghost');
188
- }
189
- if (this.#button.getAttribute('size') !== this.size) {
190
- this.#button.setAttribute('size', this.size || 'md');
191
- }
192
- if (this.color) {
193
- this.#button.setAttribute('color', this.color);
194
- } else {
195
- this.#button.removeAttribute('color');
196
- }
197
- if (this.disabled) {
198
- this.#button.setAttribute('disabled', '');
199
- } else {
200
- this.#button.removeAttribute('disabled');
201
- }
202
- }
203
-
204
- render() {
205
- // Property writes after connect (e.g. el.size = 'sm') route through here.
206
- this.#syncButton();
207
- }
208
-
209
- #emit(source) {
210
- this.dispatchEvent(new CustomEvent('scheme-change', {
211
- bubbles: true,
212
- detail: { scheme: this.activeScheme, source },
213
- }));
214
- }
215
-
216
- // ── Internal — target resolution + write ────────────────────────────
217
-
218
- #resolveTarget() {
219
- const sel = this.target || ':root';
220
- if (sel === ':root') return document.documentElement;
221
- try {
222
- return document.querySelector(sel) ?? document.documentElement;
223
- } catch {
224
- return document.documentElement;
225
- }
226
- }
227
-
228
- #writeTarget(scheme) {
229
- const t = this.#resolveTarget();
230
- t.style.setProperty('color-scheme', scheme);
231
- }
232
-
233
- #clearTargetOverride() {
234
- const t = this.#resolveTarget();
235
- t.style.removeProperty('color-scheme');
236
- if (this.persist) {
237
- try { localStorage.removeItem(`${this.storagePrefix}scheme`); } catch {}
238
- }
239
- }
240
-
241
- // ── Internal — prefers-color-scheme ─────────────────────────────────
242
-
243
- #resolvePrefersScheme() {
244
- try {
245
- if (typeof matchMedia === 'function' &&
246
- matchMedia('(prefers-color-scheme: dark)').matches) return DARK;
247
- } catch {}
248
- return LIGHT;
249
- }
250
-
251
- #attachPcm() {
252
- if (this.#mql || typeof matchMedia !== 'function') return;
253
- try {
254
- this.#mql = matchMedia('(prefers-color-scheme: dark)');
255
- this.#mqlHandler = () => {
256
- const resolved = this.#mql.matches ? DARK : LIGHT;
257
- if (resolved === this.activeScheme) return;
258
- this.activeScheme = resolved;
259
- this.#syncButton();
260
- this.#emit('media');
261
- };
262
- this.#mql.addEventListener('change', this.#mqlHandler);
263
- } catch {}
264
- }
265
-
266
- #detachPcm() {
267
- if (this.#mql && this.#mqlHandler) {
268
- try { this.#mql.removeEventListener('change', this.#mqlHandler); } catch {}
269
- }
270
- this.#mql = null;
271
- this.#mqlHandler = null;
272
- }
273
- }
12
+ import { defineIfFree } from '../../core/register.js';
13
+ import { UIToggleScheme } from './class.js';
274
14
 
275
- customElements.define('toggle-scheme-ui', UIToggleScheme);
15
+ defineIfFree('toggle-scheme-ui', UIToggleScheme);
276
16
 
277
17
  export { UIToggleScheme };
@@ -13,6 +13,10 @@ description: >-
13
13
  <theme-panel>), and the moon/sun icon swap. Replaces the hand-wired
14
14
  `<button-ui id="theme-toggle">` + `applyScheme()` pattern previously
15
15
  duplicated across apps/genui, apps/construct-canvas, playgrounds/chat.
16
+ # Per ADR-0027 — primitives that programmatically create other primitives
17
+ # do NOT auto-import them. Consumer (or demo shell) must explicitly import.
18
+ composes:
19
+ - button-ui
16
20
  props:
17
21
  scheme:
18
22
  description: Initial scheme — "auto" follows prefers-color-scheme; "light" / "dark" force.