@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,364 @@
1
+ /**
2
+ * Non-side-effect class export for `<command-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/command`
9
+ * (which imports this file + calls `defineIfFree()`).
10
+ *
11
+ * @see ../../USAGE.md#registration--auto-vs-explicit
12
+ */
13
+
14
+ import { UIElement } from '../../core/element.js';
15
+
16
+ /**
17
+ * <command-ui> — Searchable command palette.
18
+ *
19
+ * Usage:
20
+ * <command-ui placeholder="Search...">
21
+ * <optgroup label="Navigation">
22
+ * <option value="home" data-icon="home" data-shortcut="⌘H">Go Home</option>
23
+ * </optgroup>
24
+ * </command-ui>
25
+ *
26
+ * Attributes on <option>:
27
+ * data-icon — icon name (renders icon-ui)
28
+ * data-shortcut — keyboard shortcut hint
29
+ * data-keywords — extra searchable text
30
+ * disabled — skips in navigation
31
+ *
32
+ * Events:
33
+ * select — { detail: { value, label } }
34
+ * dismiss — Escape pressed
35
+ */
36
+ export class UICommand extends UIElement {
37
+ static properties = {
38
+ placeholder: { type: String, default: 'Type a command...', reflect: true },
39
+ open: { type: Boolean, default: false, reflect: true },
40
+ };
41
+
42
+ static template = () => null;
43
+
44
+ #items = [];
45
+ #recents = [];
46
+ #activeIdx = -1;
47
+ #inputEl = null;
48
+ #listEl = null;
49
+ #focusRaf = null;
50
+ #footerEl = null;
51
+ #bound = false;
52
+ #itemByEl = new WeakMap();
53
+
54
+ static #RECENTS_MAX = 3;
55
+
56
+ #onListClick = (e) => {
57
+ const el = e.target instanceof Element ? e.target.closest('[role="option"]:not([aria-disabled])') : null;
58
+ if (!el) return;
59
+ const item = this.#itemByEl.get(el);
60
+ if (item) this.#select(item);
61
+ };
62
+
63
+ #onListPointerOver = (e) => {
64
+ const el = e.target instanceof Element ? e.target.closest('[role="option"]:not([aria-disabled])') : null;
65
+ if (!el) return;
66
+ const idx = parseInt(el.dataset.idx);
67
+ if (Number.isFinite(idx) && idx !== this.#activeIdx) this.#activate(idx);
68
+ };
69
+
70
+ connected() {
71
+ if (!this.#bound) {
72
+ this.#bound = true;
73
+ this.addEventListener('keydown', this.#onKeydown);
74
+ }
75
+ }
76
+
77
+ render() {
78
+ // Stamp internal structure once
79
+ if (!this.#inputEl) {
80
+ // Parse options from declarative children before replacing innerHTML
81
+ this.#parseOptions();
82
+
83
+ this.innerHTML = `
84
+ <header>
85
+ <icon-ui name="magnifying-glass" slot="icon"></icon-ui>
86
+ <input type="text" placeholder="${this.placeholder}" slot="input" />
87
+ </header>
88
+ <section slot="list"></section>
89
+ <footer>
90
+ <span data-hint><kbd>↑</kbd><kbd>↓</kbd> Navigate</span>
91
+ <span data-hint><kbd>↵</kbd> Select</span>
92
+ <span data-hint><kbd>⎋</kbd> Close</span>
93
+ </footer>
94
+ `;
95
+
96
+ this.#inputEl = this.querySelector('input');
97
+ this.#listEl = this.querySelector('[slot="list"]');
98
+ this.#footerEl = this.querySelector('footer');
99
+
100
+ this.#inputEl.addEventListener('input', this.#onInput);
101
+ // Delegated item handlers — handler identity is stable so teardown is symmetric.
102
+ this.#listEl.addEventListener('click', this.#onListClick);
103
+ this.#listEl.addEventListener('pointerover', this.#onListPointerOver);
104
+ this.#renderItems();
105
+ }
106
+
107
+ if (this.open) {
108
+ this.#focusRaf = requestAnimationFrame(() => {
109
+ this.#focusRaf = null;
110
+ this.#inputEl?.focus();
111
+ });
112
+ }
113
+ }
114
+
115
+ // ── Public API ──
116
+
117
+ get value() { return this.#inputEl?.value || ''; }
118
+ set value(v) {
119
+ if (!this.#inputEl) return;
120
+ const next = v ?? '';
121
+ this.#inputEl.value = next;
122
+ // Keep the rendered list in sync with the visible input — the host
123
+ // commonly clears value on (re)open, and consumers expect to see the
124
+ // full list (plus recents) rather than the previous filter's residue.
125
+ this.#renderItems(next);
126
+ }
127
+
128
+ focus() { this.#inputEl?.focus(); }
129
+
130
+ setItems(items) {
131
+ this.#items = items;
132
+ this.#renderItems();
133
+ }
134
+
135
+ // ── Parse declarative <option>/<optgroup> ──
136
+
137
+ #parseOptions() {
138
+ const items = [];
139
+ for (const child of this.children) {
140
+ if (child.tagName === 'OPTGROUP') {
141
+ const group = { label: child.label, items: [] };
142
+ for (const opt of child.querySelectorAll('option')) {
143
+ group.items.push(this.#optionToItem(opt));
144
+ }
145
+ items.push(group);
146
+ } else if (child.tagName === 'OPTION') {
147
+ items.push(this.#optionToItem(child));
148
+ }
149
+ }
150
+ this.#items = items;
151
+ }
152
+
153
+ #optionToItem(opt) {
154
+ return {
155
+ value: opt.value,
156
+ label: opt.textContent.trim(),
157
+ icon: opt.dataset.icon || '',
158
+ shortcut: opt.dataset.shortcut || '',
159
+ keywords: opt.dataset.keywords || '',
160
+ disabled: opt.disabled,
161
+ };
162
+ }
163
+
164
+ // ── Render ──
165
+
166
+ #renderItems(filter = '') {
167
+ if (!this.#listEl) return;
168
+ this.#listEl.innerHTML = '';
169
+ this.#activeIdx = -1;
170
+ const q = filter.toLowerCase();
171
+
172
+ const flat = this.#items;
173
+ let visibleCount = 0;
174
+
175
+ // Recents — only when no filter is applied. Resolved against the
176
+ // current item set so a stale recent (item removed via setItems)
177
+ // is silently dropped.
178
+ if (!q && this.#recents.length) {
179
+ const resolved = this.#recents
180
+ .map(v => this.#findItem(v))
181
+ .filter(it => it && !it.disabled);
182
+ if (resolved.length) {
183
+ const groupEl = document.createElement('div');
184
+ groupEl.setAttribute('data-group', '');
185
+ groupEl.setAttribute('data-recent', '');
186
+ groupEl.innerHTML = `<div data-group-label>Recent</div>`;
187
+ for (const item of resolved) {
188
+ groupEl.appendChild(this.#createItemEl(item, visibleCount));
189
+ visibleCount++;
190
+ }
191
+ this.#listEl.appendChild(groupEl);
192
+ }
193
+ }
194
+
195
+ for (const entry of flat) {
196
+ if (entry.items) {
197
+ // Group
198
+ const filtered = entry.items.filter(i => this.#matches(i, q));
199
+ if (!filtered.length) continue;
200
+
201
+ const groupEl = document.createElement('div');
202
+ groupEl.setAttribute('data-group', '');
203
+ groupEl.innerHTML = `<div data-group-label>${entry.label}</div>`;
204
+
205
+ for (const item of filtered) {
206
+ groupEl.appendChild(this.#createItemEl(item, visibleCount));
207
+ visibleCount++;
208
+ }
209
+ this.#listEl.appendChild(groupEl);
210
+ } else {
211
+ if (!this.#matches(entry, q)) continue;
212
+ this.#listEl.appendChild(this.#createItemEl(entry, visibleCount));
213
+ visibleCount++;
214
+ }
215
+ }
216
+
217
+ // Empty state
218
+ if (!visibleCount) {
219
+ const empty = document.createElement('div');
220
+ empty.setAttribute('data-empty', '');
221
+ empty.textContent = 'No results found.';
222
+ this.#listEl.appendChild(empty);
223
+ }
224
+
225
+ // Activate first non-disabled
226
+ if (visibleCount > 0) this.#activate(0);
227
+ }
228
+
229
+ #findItem(value) {
230
+ for (const entry of this.#items) {
231
+ if (entry.items) {
232
+ const hit = entry.items.find(i => i.value === value);
233
+ if (hit) return hit;
234
+ } else if (entry.value === value) {
235
+ return entry;
236
+ }
237
+ }
238
+ return null;
239
+ }
240
+
241
+ #pushRecent(value) {
242
+ if (!value) return;
243
+ this.#recents = [value, ...this.#recents.filter(v => v !== value)]
244
+ .slice(0, UICommand.#RECENTS_MAX);
245
+ }
246
+
247
+ #createItemEl(item, idx) {
248
+ const el = document.createElement('div');
249
+ el.setAttribute('role', 'option');
250
+ el.setAttribute('data-value', item.value);
251
+ el.setAttribute('data-idx', idx);
252
+ if (item.disabled) el.setAttribute('aria-disabled', 'true');
253
+
254
+ el.innerHTML = `
255
+ ${item.icon ? `<icon-ui name="${item.icon}"></icon-ui>` : ''}
256
+ <span data-text>${item.label}</span>
257
+ ${item.shortcut ? `<span data-shortcut>${item.shortcut}</span>` : ''}
258
+ `;
259
+
260
+ this.#itemByEl.set(el, item);
261
+ return el;
262
+ }
263
+
264
+ #matches(item, q) {
265
+ if (!q) return true;
266
+ return (item.label || '').toLowerCase().includes(q) ||
267
+ (item.value || '').toLowerCase().includes(q) ||
268
+ (item.keywords || '').toLowerCase().includes(q);
269
+ }
270
+
271
+ // ── Navigation ──
272
+
273
+ #activate(idx) {
274
+ const options = this.#listEl.querySelectorAll('[role="option"]:not([aria-disabled])');
275
+ const prev = this.#listEl.querySelector('[data-active]');
276
+ if (prev) prev.removeAttribute('data-active');
277
+
278
+ const target = [...options].find(el => parseInt(el.dataset.idx) === idx);
279
+ if (target) {
280
+ target.setAttribute('data-active', '');
281
+ target.scrollIntoView({ block: 'nearest' });
282
+ this.#activeIdx = idx;
283
+ }
284
+ }
285
+
286
+ #moveActive(dir) {
287
+ const options = [...this.#listEl.querySelectorAll('[role="option"]:not([aria-disabled])')];
288
+ if (!options.length) return;
289
+
290
+ const currentEl = this.#listEl.querySelector('[data-active]');
291
+ const currentPos = currentEl ? options.indexOf(currentEl) : -1;
292
+ let next = currentPos + dir;
293
+ if (next < 0) next = options.length - 1;
294
+ if (next >= options.length) next = 0;
295
+
296
+ this.#activate(parseInt(options[next].dataset.idx));
297
+ }
298
+
299
+ #select(item) {
300
+ this.#pushRecent(item.value);
301
+ this.dispatchEvent(new CustomEvent('select', {
302
+ bubbles: true,
303
+ detail: { value: item.value, label: item.label },
304
+ }));
305
+ }
306
+
307
+ #selectActive() {
308
+ const active = this.#listEl.querySelector('[data-active]');
309
+ if (!active) return;
310
+ const value = active.dataset.value;
311
+ const label = active.querySelector('[data-text]')?.textContent || '';
312
+ this.#pushRecent(value);
313
+ this.dispatchEvent(new CustomEvent('select', {
314
+ bubbles: true,
315
+ detail: { value, label },
316
+ }));
317
+ }
318
+
319
+ // ── Events ──
320
+
321
+ #onInput = () => {
322
+ this.#renderItems(this.#inputEl.value);
323
+ };
324
+
325
+ #onKeydown = (e) => {
326
+ switch (e.key) {
327
+ case 'ArrowDown':
328
+ e.preventDefault();
329
+ this.#moveActive(1);
330
+ break;
331
+ case 'ArrowUp':
332
+ e.preventDefault();
333
+ this.#moveActive(-1);
334
+ break;
335
+ case 'Enter':
336
+ e.preventDefault();
337
+ this.#selectActive();
338
+ break;
339
+ case 'Tab':
340
+ e.preventDefault();
341
+ this.#selectActive();
342
+ break;
343
+ case 'Escape':
344
+ e.preventDefault();
345
+ this.dispatchEvent(new Event('dismiss', { bubbles: true }));
346
+ break;
347
+ }
348
+ };
349
+
350
+ disconnected() {
351
+ if (this.#focusRaf != null) {
352
+ cancelAnimationFrame(this.#focusRaf);
353
+ this.#focusRaf = null;
354
+ }
355
+ this.removeEventListener('keydown', this.#onKeydown);
356
+ this.#inputEl?.removeEventListener('input', this.#onInput);
357
+ this.#listEl?.removeEventListener('click', this.#onListClick);
358
+ this.#listEl?.removeEventListener('pointerover', this.#onListPointerOver);
359
+ this.#inputEl = null;
360
+ this.#listEl = null;
361
+ this.#footerEl = null;
362
+ this.#bound = false;
363
+ }
364
+ }
@@ -34,6 +34,7 @@
34
34
  "x-adiaui": {
35
35
  "anti_patterns": [],
36
36
  "category": "container",
37
+ "composes": [],
37
38
  "events": {
38
39
  "dismiss": {
39
40
  "description": "Fired when Escape is pressed"
@@ -202,6 +203,9 @@
202
203
  "palette",
203
204
  "search"
204
205
  ],
206
+ "tags": [
207
+ "CommandPalette"
208
+ ],
205
209
  "terminal": [
206
210
  "code",
207
211
  "block",
@@ -0,0 +1,31 @@
1
+ /**
2
+ * `<command-ui>` — Searchable command palette with keyboard navigation.
3
+ *
4
+ * @see https://ui-kit.exe.xyz/site/components/command
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 CommandDismissEvent = CustomEvent<unknown>;
16
+ export type CommandSelectEvent = CustomEvent<unknown>;
17
+
18
+ export class UICommand extends UIElement {
19
+ /** Whether the command palette is visible */
20
+ open: boolean;
21
+ /** Placeholder text for the search input */
22
+ placeholder: string;
23
+
24
+ addEventListener<K extends keyof HTMLElementEventMap>(
25
+ type: K,
26
+ listener: (this: UICommand, ev: HTMLElementEventMap[K]) => unknown,
27
+ options?: boolean | AddEventListenerOptions,
28
+ ): void;
29
+ addEventListener(type: 'dismiss', listener: (ev: CommandDismissEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
30
+ addEventListener(type: 'select', listener: (ev: CommandSelectEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
31
+ }