@adia-ai/web-components 0.0.28 → 0.0.33

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 (349) hide show
  1. package/README.md +4 -8
  2. package/a2ui/index.js +1 -1
  3. package/components/accordion/accordion.a2ui.json +1 -1
  4. package/components/accordion/accordion.js +6 -6
  5. package/components/accordion/accordion.yaml +1 -1
  6. package/components/action-list/action-list.a2ui.json +1 -1
  7. package/components/action-list/action-list.js +6 -6
  8. package/components/action-list/action-list.yaml +1 -1
  9. package/components/agent-artifact/agent-artifact.a2ui.json +1 -1
  10. package/components/agent-artifact/agent-artifact.js +4 -4
  11. package/components/agent-artifact/agent-artifact.yaml +1 -1
  12. package/components/agent-feedback-bar/agent-feedback-bar.a2ui.json +1 -1
  13. package/components/agent-feedback-bar/agent-feedback-bar.js +4 -4
  14. package/components/agent-feedback-bar/agent-feedback-bar.yaml +1 -1
  15. package/components/agent-questions/agent-questions.a2ui.json +1 -1
  16. package/components/agent-questions/agent-questions.js +4 -4
  17. package/components/agent-questions/agent-questions.yaml +1 -1
  18. package/components/agent-reasoning/agent-reasoning.a2ui.json +3 -3
  19. package/components/agent-reasoning/agent-reasoning.js +4 -4
  20. package/components/agent-reasoning/agent-reasoning.yaml +3 -3
  21. package/components/agent-suggestions/agent-suggestions.a2ui.json +1 -1
  22. package/components/agent-suggestions/agent-suggestions.js +4 -4
  23. package/components/agent-suggestions/agent-suggestions.yaml +1 -1
  24. package/components/agent-trace/agent-trace.a2ui.json +1 -1
  25. package/components/agent-trace/agent-trace.js +4 -4
  26. package/components/agent-trace/agent-trace.yaml +1 -1
  27. package/components/alert/alert.a2ui.json +1 -1
  28. package/components/alert/alert.js +4 -4
  29. package/components/alert/alert.yaml +1 -1
  30. package/components/aside/aside.a2ui.json +1 -1
  31. package/components/aside/aside.yaml +1 -1
  32. package/components/avatar/avatar.a2ui.json +1 -1
  33. package/components/avatar/avatar.js +8 -8
  34. package/components/avatar/avatar.yaml +1 -1
  35. package/components/badge/badge.a2ui.json +1 -1
  36. package/components/badge/badge.js +4 -4
  37. package/components/badge/badge.yaml +1 -1
  38. package/components/block/block.a2ui.json +1 -1
  39. package/components/block/block.js +4 -4
  40. package/components/block/block.yaml +1 -1
  41. package/components/breadcrumb/breadcrumb.a2ui.json +1 -1
  42. package/components/breadcrumb/breadcrumb.js +4 -4
  43. package/components/breadcrumb/breadcrumb.yaml +1 -1
  44. package/components/button/button.a2ui.json +1 -1
  45. package/components/button/button.js +4 -4
  46. package/components/button/button.yaml +1 -1
  47. package/components/calendar-picker/calendar-picker.a2ui.json +1 -1
  48. package/components/calendar-picker/calendar-picker.js +6 -6
  49. package/components/calendar-picker/calendar-picker.yaml +1 -1
  50. package/components/canvas/canvas.a2ui.json +1 -1
  51. package/components/canvas/canvas.js +5 -5
  52. package/components/canvas/canvas.yaml +1 -1
  53. package/components/card/card.a2ui.json +1 -1
  54. package/components/card/card.js +4 -4
  55. package/components/card/card.yaml +1 -1
  56. package/components/chart/chart.a2ui.json +1 -1
  57. package/components/chart/chart.js +5 -5
  58. package/components/chart/chart.yaml +1 -1
  59. package/components/chart-legend/chart-legend.a2ui.json +1 -1
  60. package/components/chart-legend/chart-legend.js +7 -7
  61. package/components/chart-legend/chart-legend.yaml +1 -1
  62. package/components/{chat → chat-thread}/chat-input.js +5 -5
  63. package/components/{chat/chat.a2ui.json → chat-thread/chat-thread.a2ui.json} +6 -6
  64. package/components/{chat/chat.css → chat-thread/chat-thread.css} +2 -2
  65. package/components/{chat/chat.js → chat-thread/chat-thread.js} +7 -7
  66. package/components/{chat/chat.yaml → chat-thread/chat-thread.yaml} +4 -4
  67. package/components/check/check.a2ui.json +1 -1
  68. package/components/check/check.js +5 -5
  69. package/components/check/check.yaml +1 -1
  70. package/components/code/code.a2ui.json +1 -1
  71. package/components/code/code.js +4 -4
  72. package/components/code/code.yaml +1 -1
  73. package/components/col/col.a2ui.json +1 -1
  74. package/components/col/col.js +4 -4
  75. package/components/col/col.yaml +1 -1
  76. package/components/color-picker/color-picker.a2ui.json +1 -1
  77. package/components/color-picker/color-picker.js +6 -6
  78. package/components/color-picker/color-picker.yaml +1 -1
  79. package/components/command/command.a2ui.json +1 -1
  80. package/components/command/command.js +5 -5
  81. package/components/command/command.yaml +1 -1
  82. package/components/description-list/description-list.a2ui.json +1 -1
  83. package/components/description-list/description-list.js +4 -4
  84. package/components/description-list/description-list.yaml +1 -1
  85. package/components/divider/divider.a2ui.json +1 -1
  86. package/components/divider/divider.js +4 -4
  87. package/components/divider/divider.yaml +1 -1
  88. package/components/drawer/drawer.a2ui.json +1 -1
  89. package/components/drawer/drawer.js +4 -4
  90. package/components/drawer/drawer.yaml +1 -1
  91. package/components/embed/embed.a2ui.json +1 -1
  92. package/components/embed/embed.js +4 -4
  93. package/components/embed/embed.yaml +1 -1
  94. package/components/empty-state/empty-state.a2ui.json +1 -1
  95. package/components/empty-state/empty-state.js +4 -4
  96. package/components/empty-state/empty-state.yaml +1 -1
  97. package/components/feed/feed-item.yaml +2 -2
  98. package/components/feed/feed.a2ui.json +2 -2
  99. package/components/feed/feed.css +21 -3
  100. package/components/feed/feed.js +140 -31
  101. package/components/feed/feed.yaml +2 -2
  102. package/components/field/field.a2ui.json +1 -1
  103. package/components/field/field.js +10 -10
  104. package/components/field/field.yaml +2 -2
  105. package/components/footer/footer.a2ui.json +1 -1
  106. package/components/footer/footer.yaml +1 -1
  107. package/components/grid/grid.a2ui.json +1 -1
  108. package/components/grid/grid.js +4 -4
  109. package/components/grid/grid.yaml +1 -1
  110. package/components/header/header.a2ui.json +1 -1
  111. package/components/header/header.yaml +1 -1
  112. package/components/heatmap/heatmap.a2ui.json +1 -1
  113. package/components/heatmap/heatmap.js +4 -4
  114. package/components/heatmap/heatmap.yaml +1 -1
  115. package/components/icon/icon.a2ui.json +1 -1
  116. package/components/icon/icon.js +4 -4
  117. package/components/icon/icon.yaml +1 -1
  118. package/components/image/image.a2ui.json +1 -1
  119. package/components/image/image.js +4 -4
  120. package/components/image/image.yaml +1 -1
  121. package/components/index.js +88 -85
  122. package/components/input/input.a2ui.json +1 -1
  123. package/components/input/input.js +7 -7
  124. package/components/input/input.yaml +1 -1
  125. package/components/inspector/inspector.a2ui.json +1 -1
  126. package/components/inspector/inspector.js +4 -4
  127. package/components/inspector/inspector.yaml +1 -1
  128. package/components/kbd/kbd.a2ui.json +1 -1
  129. package/components/kbd/kbd.js +4 -4
  130. package/components/kbd/kbd.yaml +1 -1
  131. package/components/list/list.a2ui.json +1 -1
  132. package/components/list/list.js +6 -6
  133. package/components/list/list.yaml +1 -1
  134. package/components/menu/menu.a2ui.json +1 -1
  135. package/components/menu/menu.js +8 -8
  136. package/components/menu/menu.yaml +1 -1
  137. package/components/modal/modal.a2ui.json +1 -1
  138. package/components/modal/modal.js +4 -4
  139. package/components/modal/modal.yaml +1 -1
  140. package/components/nav/nav.a2ui.json +98 -0
  141. package/components/nav/nav.css +133 -0
  142. package/components/nav/nav.js +140 -0
  143. package/components/nav/nav.test.js +428 -0
  144. package/components/nav/nav.yaml +114 -0
  145. package/components/nav-group/nav-group.a2ui.json +100 -0
  146. package/{patterns/app-nav-group/app-nav-group.css → components/nav-group/nav-group.css} +71 -18
  147. package/{patterns/app-nav-group/app-nav-group.js → components/nav-group/nav-group.js} +51 -25
  148. package/components/nav-group/nav-group.yaml +69 -0
  149. package/components/nav-item/nav-item.a2ui.json +106 -0
  150. package/{patterns/app-nav-item/app-nav-item.css → components/nav-item/nav-item.css} +42 -10
  151. package/components/nav-item/nav-item.js +76 -0
  152. package/components/nav-item/nav-item.yaml +73 -0
  153. package/components/noodles/noodles.a2ui.json +1 -1
  154. package/components/noodles/noodles.js +4 -4
  155. package/components/noodles/noodles.yaml +1 -1
  156. package/components/option-card/option-card.a2ui.json +1 -1
  157. package/components/option-card/option-card.js +6 -6
  158. package/components/option-card/option-card.yaml +1 -1
  159. package/components/otp-input/otp-input.a2ui.json +1 -1
  160. package/components/otp-input/otp-input.js +5 -5
  161. package/components/otp-input/otp-input.yaml +1 -1
  162. package/components/page/page.a2ui.json +3 -3
  163. package/components/page/page.js +4 -4
  164. package/components/page/page.yaml +3 -3
  165. package/components/pagination/pagination.a2ui.json +1 -1
  166. package/components/pagination/pagination.js +4 -4
  167. package/components/pagination/pagination.yaml +1 -1
  168. package/components/pane/pane.a2ui.json +1 -1
  169. package/components/pane/pane.js +4 -4
  170. package/components/pane/pane.yaml +1 -1
  171. package/components/pipeline-status/pipeline-status.a2ui.json +1 -1
  172. package/components/pipeline-status/pipeline-status.js +4 -4
  173. package/components/pipeline-status/pipeline-status.yaml +1 -1
  174. package/components/popover/popover.a2ui.json +1 -1
  175. package/components/popover/popover.js +4 -4
  176. package/components/popover/popover.yaml +1 -1
  177. package/components/progress/progress.a2ui.json +1 -1
  178. package/components/progress/progress.js +4 -4
  179. package/components/progress/progress.yaml +1 -1
  180. package/components/progress-row/progress-row.a2ui.json +1 -1
  181. package/components/progress-row/progress-row.js +4 -4
  182. package/components/progress-row/progress-row.yaml +1 -1
  183. package/components/radio/radio.a2ui.json +1 -1
  184. package/components/radio/radio.js +5 -5
  185. package/components/radio/radio.yaml +1 -1
  186. package/components/range/range.a2ui.json +1 -1
  187. package/components/range/range.js +7 -7
  188. package/components/range/range.yaml +1 -1
  189. package/components/rating/rating.a2ui.json +1 -1
  190. package/components/rating/rating.js +6 -6
  191. package/components/rating/rating.yaml +1 -1
  192. package/components/richtext/richtext.a2ui.json +1 -1
  193. package/components/richtext/richtext.js +4 -4
  194. package/components/richtext/richtext.yaml +1 -1
  195. package/components/row/row.a2ui.json +1 -1
  196. package/components/row/row.js +4 -4
  197. package/components/row/row.yaml +1 -1
  198. package/components/search/search.a2ui.json +1 -1
  199. package/components/search/search.js +5 -5
  200. package/components/search/search.yaml +1 -1
  201. package/components/section/section.a2ui.json +1 -1
  202. package/components/section/section.yaml +1 -1
  203. package/components/segment/segment.a2ui.json +1 -1
  204. package/components/segment/segment.js +4 -4
  205. package/components/segment/segment.yaml +1 -1
  206. package/components/segmented/segmented.a2ui.json +1 -1
  207. package/components/segmented/segmented.css +6 -0
  208. package/components/segmented/segmented.js +7 -7
  209. package/components/segmented/segmented.yaml +1 -1
  210. package/components/select/select.a2ui.json +1 -1
  211. package/components/select/select.js +5 -5
  212. package/components/select/select.yaml +1 -1
  213. package/components/skeleton/skeleton.a2ui.json +1 -1
  214. package/components/skeleton/skeleton.js +4 -4
  215. package/components/skeleton/skeleton.yaml +1 -1
  216. package/components/slider/slider.a2ui.json +1 -1
  217. package/components/slider/slider.js +7 -7
  218. package/components/slider/slider.yaml +1 -1
  219. package/components/stack/stack.a2ui.json +1 -1
  220. package/components/stack/stack.js +4 -4
  221. package/components/stack/stack.yaml +1 -1
  222. package/components/stat/stat.a2ui.json +1 -1
  223. package/components/stat/stat.js +4 -4
  224. package/components/stat/stat.yaml +1 -1
  225. package/components/stepper/stepper.a2ui.json +1 -1
  226. package/components/stepper/stepper.js +6 -6
  227. package/components/stepper/stepper.yaml +1 -1
  228. package/components/stream/stream.a2ui.json +1 -1
  229. package/components/stream/stream.js +4 -4
  230. package/components/stream/stream.yaml +1 -1
  231. package/components/swatch/swatch.a2ui.json +1 -1
  232. package/components/swatch/swatch.js +4 -4
  233. package/components/swatch/swatch.yaml +1 -1
  234. package/components/swiper/swiper.a2ui.json +1 -1
  235. package/components/swiper/swiper.js +4 -4
  236. package/components/swiper/swiper.yaml +1 -1
  237. package/components/switch/switch.a2ui.json +1 -1
  238. package/components/switch/switch.js +5 -5
  239. package/components/switch/switch.yaml +1 -1
  240. package/components/table/table.a2ui.json +1 -1
  241. package/components/table/table.js +4 -4
  242. package/components/table/table.yaml +1 -1
  243. package/components/table-toolbar/table-toolbar.a2ui.json +1 -1
  244. package/components/table-toolbar/table-toolbar.js +4 -4
  245. package/components/table-toolbar/table-toolbar.yaml +1 -1
  246. package/components/tabs/tab.js +4 -4
  247. package/components/tabs/tabs.a2ui.json +1 -1
  248. package/components/tabs/tabs.js +5 -5
  249. package/components/tabs/tabs.yaml +1 -1
  250. package/components/tag/tag.a2ui.json +1 -1
  251. package/components/tag/tag.js +4 -4
  252. package/components/tag/tag.yaml +1 -1
  253. package/components/text/text.a2ui.json +1 -1
  254. package/components/text/text.js +4 -4
  255. package/components/text/text.yaml +1 -1
  256. package/components/textarea/textarea.a2ui.json +1 -1
  257. package/components/textarea/textarea.js +5 -5
  258. package/components/textarea/textarea.yaml +1 -1
  259. package/components/timeline/timeline.a2ui.json +1 -1
  260. package/components/timeline/timeline.js +6 -6
  261. package/components/timeline/timeline.yaml +1 -1
  262. package/components/toast/toast.a2ui.json +1 -1
  263. package/components/toast/toast.js +54 -184
  264. package/components/toast/toast.yaml +1 -1
  265. package/components/toggle-group/toggle-group.a2ui.json +1 -1
  266. package/components/toggle-group/toggle-group.js +6 -6
  267. package/components/toggle-group/toggle-group.yaml +1 -1
  268. package/components/toolbar/toolbar.a2ui.json +1 -1
  269. package/components/toolbar/toolbar.js +6 -6
  270. package/components/toolbar/toolbar.yaml +1 -1
  271. package/components/tooltip/tooltip.a2ui.json +1 -1
  272. package/components/tooltip/tooltip.js +7 -7
  273. package/components/tooltip/tooltip.yaml +1 -1
  274. package/components/tree/tree.a2ui.json +1 -1
  275. package/components/tree/tree.js +6 -6
  276. package/components/tree/tree.yaml +1 -1
  277. package/components/upload/upload.a2ui.json +1 -1
  278. package/components/upload/upload.js +6 -6
  279. package/components/upload/upload.yaml +1 -1
  280. package/core/element.js +4 -4
  281. package/core/element.test.js +18 -18
  282. package/core/form.js +9 -9
  283. package/core/index.js +2 -2
  284. package/core/provider.js +7 -7
  285. package/core/template.js +1 -1
  286. package/index.css +3 -2
  287. package/index.js +17 -7
  288. package/package.json +1 -5
  289. package/styles/components.css +10 -6
  290. package/styles/resets.css +1 -1
  291. package/traits/define.js +2 -2
  292. package/patterns/a2ui-root/a2ui-root.a2ui.json +0 -125
  293. package/patterns/a2ui-root/a2ui-root.js +0 -191
  294. package/patterns/a2ui-root/a2ui-root.yaml +0 -87
  295. package/patterns/adia-chat/adia-chat.a2ui.json +0 -149
  296. package/patterns/adia-chat/adia-chat.css +0 -10
  297. package/patterns/adia-chat/adia-chat.js +0 -297
  298. package/patterns/adia-chat/adia-chat.yaml +0 -118
  299. package/patterns/adia-chat/css/adia-chat.empty.css +0 -12
  300. package/patterns/adia-chat/css/adia-chat.layout.css +0 -60
  301. package/patterns/adia-chat/css/adia-chat.markdown.css +0 -74
  302. package/patterns/adia-chat/css/adia-chat.messages.css +0 -87
  303. package/patterns/adia-chat/css/adia-chat.streaming.css +0 -30
  304. package/patterns/adia-chat/css/adia-chat.tokens.css +0 -95
  305. package/patterns/adia-editor/adia-editor.a2ui.json +0 -73
  306. package/patterns/adia-editor/adia-editor.css +0 -6
  307. package/patterns/adia-editor/adia-editor.js +0 -56
  308. package/patterns/adia-editor/adia-editor.yaml +0 -59
  309. package/patterns/adia-editor/css/adia-editor.layout.css +0 -171
  310. package/patterns/adia-editor/css/adia-editor.tokens.css +0 -28
  311. package/patterns/app-nav/app-nav.a2ui.json +0 -89
  312. package/patterns/app-nav/app-nav.css +0 -92
  313. package/patterns/app-nav/app-nav.js +0 -112
  314. package/patterns/app-nav/app-nav.yaml +0 -54
  315. package/patterns/app-nav-group/app-nav-group.a2ui.json +0 -82
  316. package/patterns/app-nav-group/app-nav-group.yaml +0 -59
  317. package/patterns/app-nav-item/app-nav-item.a2ui.json +0 -83
  318. package/patterns/app-nav-item/app-nav-item.js +0 -42
  319. package/patterns/app-nav-item/app-nav-item.yaml +0 -62
  320. package/patterns/app-shell/app-shell.a2ui.json +0 -129
  321. package/patterns/app-shell/app-shell.css +0 -14
  322. package/patterns/app-shell/app-shell.js +0 -251
  323. package/patterns/app-shell/app-shell.yaml +0 -89
  324. package/patterns/app-shell/css/app-shell.collapsed.css +0 -86
  325. package/patterns/app-shell/css/app-shell.helpers.css +0 -42
  326. package/patterns/app-shell/css/app-shell.main.css +0 -172
  327. package/patterns/app-shell/css/app-shell.shell.css +0 -44
  328. package/patterns/app-shell/css/app-shell.sidebar.css +0 -161
  329. package/patterns/app-shell/css/app-shell.templates.css +0 -214
  330. package/patterns/app-shell/css/app-shell.tokens.css +0 -119
  331. package/patterns/gen-ui/gen-ui.a2ui.json +0 -72
  332. package/patterns/gen-ui/gen-ui.css +0 -83
  333. package/patterns/gen-ui/gen-ui.js +0 -136
  334. package/patterns/gen-ui/gen-ui.yaml +0 -43
  335. package/patterns/index.js +0 -11
  336. package/patterns/section-nav/section-nav.a2ui.json +0 -91
  337. package/patterns/section-nav/section-nav.css +0 -60
  338. package/patterns/section-nav/section-nav.js +0 -42
  339. package/patterns/section-nav/section-nav.yaml +0 -58
  340. package/patterns/section-nav-group/section-nav-group.a2ui.json +0 -95
  341. package/patterns/section-nav-group/section-nav-group.css +0 -74
  342. package/patterns/section-nav-group/section-nav-group.js +0 -84
  343. package/patterns/section-nav-group/section-nav-group.yaml +0 -66
  344. package/patterns/section-nav-item/section-nav-item.a2ui.json +0 -97
  345. package/patterns/section-nav-item/section-nav-item.css +0 -106
  346. package/patterns/section-nav-item/section-nav-item.js +0 -66
  347. package/patterns/section-nav-item/section-nav-item.yaml +0 -70
  348. package/styles/layouts/admin.css +0 -7
  349. /package/components/{chat → chat-thread}/chat-input.css +0 -0
@@ -1,297 +0,0 @@
1
- import { AdiaElement } from '../../core/element.js';
2
- import { renderMarkdown } from '../../core/markdown.js';
3
- import { streamChat } from '../../../a2ui/compose/llm/adapters/index.js';
4
-
5
- function escapeHTML(s) {
6
- return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
7
- }
8
-
9
- let msgId = 0;
10
-
11
- /**
12
- * <adia-chat-ui> — Chat pattern component.
13
- *
14
- * Behavior-only orchestrator: stamps no HTML of its own.
15
- * The author writes the structure; adia-chat wires the behaviors.
16
- *
17
- * Structure:
18
- * <adia-chat-ui proxy-url="/api/chat" model="claude-sonnet-4-20250514">
19
- * <header>
20
- * <span data-chat-name>Claude</span>
21
- * <span data-chat-status></span>
22
- * </header>
23
- * <section data-chat-messages>
24
- * <empty-state-ui data-chat-empty icon="chat-circle"
25
- * heading="Hello!" description="Ask me anything.">
26
- * </empty-state-ui>
27
- * </section>
28
- * <footer>
29
- * <chat-input-ui data-chat-input placeholder="Message..."></chat-input-ui>
30
- * </footer>
31
- * </adia-chat-ui>
32
- *
33
- * Two modes:
34
- * 1. Built-in: set proxy-url + model, adia-chat streams via LLM adapters
35
- * 2. External: listen for 'submit', call your API, use appendChunk() etc.
36
- *
37
- * Events: submit, chunk, thinking, done, error, abort, clear
38
- */
39
- class AdiaChatElement extends AdiaElement {
40
- static properties = {
41
- streaming: { type: Boolean, default: false, reflect: true },
42
- provider: { type: String, default: '', reflect: true },
43
- model: { type: String, default: '', reflect: true },
44
- system: { type: String, default: '', reflect: true },
45
- proxyUrl: { type: String, default: '', attribute: 'proxy-url', reflect: true },
46
- thinking: { type: Boolean, default: false, reflect: true },
47
- };
48
-
49
- static template = () => null;
50
-
51
- #messages = [];
52
- #abortController = null;
53
- #messagesEl = null;
54
- #inputEl = null;
55
- #emptyEl = null;
56
- #statusEl = null;
57
- #apiKey = '';
58
-
59
- // ── Accessors ──
60
-
61
- get messages() { return [...this.#messages]; }
62
-
63
- get conversation() {
64
- return this.#messages
65
- .filter(m => m.role === 'user' || m.role === 'assistant')
66
- .map(m => ({ role: m.role, content: m.content }));
67
- }
68
-
69
- set conversation(msgs) {
70
- this.clear();
71
- for (const m of msgs) {
72
- this.appendMessage({ role: m.role, content: m.content, render: true });
73
- }
74
- }
75
-
76
- set apiKey(key) { this.#apiKey = key; }
77
-
78
- // ── Lifecycle ──
79
-
80
- connected() {
81
- this.#messagesEl = this.querySelector('[data-chat-messages]') || this.querySelector('section');
82
- this.#inputEl = this.querySelector('[data-chat-input]') || this.querySelector('chat-input-ui');
83
- this.#emptyEl = this.querySelector('[data-chat-empty]');
84
- this.#statusEl = this.querySelector('[data-chat-status]');
85
-
86
- this.#inputEl?.addEventListener('submit', this.#onSubmit);
87
- }
88
-
89
- disconnected() {
90
- this.#inputEl?.removeEventListener('submit', this.#onSubmit);
91
- this.abort();
92
- }
93
-
94
- // ── Events ──
95
-
96
- #emit(name, detail) {
97
- this.dispatchEvent(new CustomEvent(name, { bubbles: true, detail }));
98
- }
99
-
100
- #onSubmit = (e) => {
101
- if (this.streaming) return;
102
- const { text, model } = e.detail || {};
103
- if (!text) return;
104
- this.#inputEl.clear();
105
-
106
- this.#emit('submit', { text, model });
107
-
108
- // If proxy-url or apiKey is set, auto-send
109
- if (this.proxyUrl || this.#apiKey) {
110
- this.send(text, model ? { model } : {});
111
- }
112
- };
113
-
114
- // ── Message management ──
115
-
116
- appendMessage({ role, content = '', render: renderMd = false }) {
117
- const id = `msg_${++msgId}`;
118
- this.#messages.push({ id, role, content });
119
-
120
- const el = document.createElement('div');
121
- el.setAttribute('data-role', role);
122
- el.setAttribute('data-id', id);
123
-
124
- if (role === 'user') {
125
- el.innerHTML = `<div data-bubble>${escapeHTML(content)}</div>`;
126
- } else if (role === 'assistant') {
127
- const rendered = renderMd && content ? renderMarkdown(content) : escapeHTML(content);
128
- el.innerHTML = `
129
- <span data-avatar>AI</span>
130
- <div data-bubble><div data-content>${rendered}</div>${!renderMd ? '<span data-cursor></span>' : ''}</div>
131
- `;
132
- } else if (role === 'error') {
133
- el.innerHTML = `<icon-ui name="warning"></icon-ui><span>${escapeHTML(content)}</span>`;
134
- }
135
-
136
- this.#messagesEl?.appendChild(el);
137
- this.#scrollToBottom();
138
- this.#emit('message', { id, role, content });
139
- return el;
140
- }
141
-
142
- appendChunk(text) {
143
- const last = this.#messages[this.#messages.length - 1];
144
- if (!last || last.role !== 'assistant') return;
145
- last.content += text;
146
-
147
- const contentEl = this.#messagesEl?.querySelector('[data-role]:last-child [data-content]');
148
- if (contentEl) {
149
- contentEl.insertAdjacentText('beforeend', text);
150
- }
151
- this.#scrollToBottom();
152
- }
153
-
154
- deleteMessage(id) {
155
- const idx = this.#messages.findIndex(m => m.id === id);
156
- if (idx === -1) return;
157
- this.#messages.splice(idx, 1);
158
- this.#messagesEl?.querySelector(`[data-id="${id}"]`)?.remove();
159
- }
160
-
161
- clear() {
162
- this.#messages.length = 0;
163
- if (this.#messagesEl) {
164
- // Preserve empty state element
165
- const empty = this.#emptyEl;
166
- this.#messagesEl.innerHTML = '';
167
- if (empty) this.#messagesEl.appendChild(empty);
168
- }
169
- this.#emit('clear');
170
- }
171
-
172
- // ── Streaming control ──
173
-
174
- startStreaming() {
175
- this.streaming = true;
176
- if (this.#inputEl) this.#inputEl.disabled = true;
177
- if (this.#statusEl) this.#statusEl.textContent = 'Typing...';
178
- }
179
-
180
- stopStreaming() {
181
- this.streaming = false;
182
- if (this.#inputEl) this.#inputEl.disabled = false;
183
- if (this.#statusEl) this.#statusEl.textContent = '';
184
-
185
- // Remove cursor
186
- this.#messagesEl?.querySelector('[data-role]:last-child [data-cursor]')?.remove();
187
-
188
- // Render markdown in last assistant bubble
189
- const last = this.#messages[this.#messages.length - 1];
190
- if (last?.role === 'assistant' && last.content) {
191
- const contentEl = this.#messagesEl?.querySelector('[data-role]:last-child [data-content]');
192
- if (contentEl) {
193
- contentEl.innerHTML = renderMarkdown(last.content);
194
- // Upgrade code blocks to code-ui
195
- this.#upgradeCodeBlocks(contentEl);
196
- }
197
- }
198
-
199
- this.#inputEl?.focus();
200
- }
201
-
202
- abort() {
203
- if (this.#abortController) {
204
- this.#abortController.abort();
205
- this.#abortController = null;
206
- this.#emit('abort');
207
- }
208
- if (this.streaming) this.stopStreaming();
209
- }
210
-
211
- // ── LLM send ──
212
-
213
- async send(text, opts = {}) {
214
- const model = opts.model || this.model || this.#inputEl?.model;
215
- if (!model) throw new Error('No model specified');
216
-
217
- this.appendMessage({ role: 'user', content: text });
218
- this.appendMessage({ role: 'assistant', content: '' });
219
- this.startStreaming();
220
-
221
- this.#abortController = new AbortController();
222
-
223
- try {
224
- const streamOpts = {
225
- provider: this.provider || undefined,
226
- apiKey: this.#apiKey || undefined,
227
- model,
228
- system: this.system || undefined,
229
- proxyUrl: this.proxyUrl || undefined,
230
- thinking: this.thinking || undefined,
231
- messages: this.conversation.slice(0, -1), // exclude empty assistant
232
- signal: this.#abortController.signal,
233
- ...opts,
234
- };
235
-
236
- for await (const chunk of streamChat(streamOpts)) {
237
- if (chunk.type === 'text') {
238
- this.appendChunk(chunk.text);
239
- this.#emit('chunk', { text: chunk.text, snapshot: chunk.snapshot });
240
- } else if (chunk.type === 'thinking') {
241
- this.#emit('thinking', { text: chunk.text });
242
- } else if (chunk.type === 'done') {
243
- this.#emit('done', { text: chunk.text, usage: chunk.usage, stopReason: chunk.stopReason });
244
- } else if (chunk.type === 'error') {
245
- this.appendMessage({ role: 'error', content: chunk.error.message });
246
- this.#emit('error', { error: chunk.error });
247
- }
248
- }
249
- } catch (err) {
250
- if (err.name !== 'AbortError') {
251
- this.appendMessage({ role: 'error', content: err.message });
252
- this.#emit('error', { error: err });
253
- }
254
- }
255
-
256
- this.#abortController = null;
257
- this.stopStreaming();
258
- }
259
-
260
- // ── Export / import ──
261
-
262
- export() {
263
- return {
264
- messages: this.#messages.map(m => ({ role: m.role, content: m.content })),
265
- model: this.model,
266
- system: this.system,
267
- };
268
- }
269
-
270
- import(data) {
271
- if (data.model) this.model = data.model;
272
- if (data.system) this.system = data.system;
273
- if (data.messages) this.conversation = data.messages;
274
- }
275
-
276
- // ── Private ──
277
-
278
- #scrollToBottom() {
279
- const el = this.#messagesEl;
280
- if (el) requestAnimationFrame(() => { el.scrollTop = el.scrollHeight; });
281
- }
282
-
283
- #upgradeCodeBlocks(container) {
284
- for (const pre of container.querySelectorAll('pre')) {
285
- const code = pre.querySelector('code');
286
- if (!code) continue;
287
- const lang = code.getAttribute('data-lang') || '';
288
- const codeN = document.createElement('code-ui');
289
- if (lang) codeN.setAttribute('language', lang);
290
- codeN.textContent = code.textContent;
291
- pre.replaceWith(codeN);
292
- }
293
- }
294
- }
295
-
296
- customElements.define('adia-chat-ui', AdiaChatElement);
297
- export { AdiaChatElement };
@@ -1,118 +0,0 @@
1
- $schema: ../../../../scripts/schemas/component.yaml.schema.json
2
- name: AdiaChatElement
3
- tag: adia-chat-ui
4
- component: Chat
5
- category: container
6
- version: 1
7
- description: |
8
- Behavior-only chat orchestrator. Author supplies the DOM structure via
9
- [data-chat-messages], [data-chat-input], [data-chat-empty], [data-chat-status]
10
- elements; adia-chat wires message streaming, markdown rendering, code-block
11
- upgrades, and an LLM integration path via proxy-url (or via external submit).
12
-
13
- props:
14
- streaming:
15
- type: boolean
16
- default: false
17
- reflect: true
18
- description: Active streaming indicator; toggled while a response is being received.
19
-
20
- provider:
21
- type: string
22
- default: ""
23
- reflect: true
24
- description: LLM provider name (anthropic | openai | google | stub).
25
-
26
- model:
27
- type: string
28
- default: ""
29
- reflect: true
30
- description: Model identifier.
31
-
32
- system:
33
- type: string
34
- default: ""
35
- reflect: true
36
- description: System prompt prepended to conversations.
37
-
38
- proxyUrl:
39
- type: string
40
- default: ""
41
- reflect: true
42
- attribute: proxy-url
43
- description: API proxy endpoint for LLM calls; enables self-contained chat without external wiring.
44
-
45
- thinking:
46
- type: boolean
47
- default: false
48
- reflect: true
49
- description: Enable Anthropic extended-thinking mode.
50
-
51
- events:
52
- submit:
53
- description: Fired on user message submit (before LLM call begins).
54
- detail:
55
- text: string
56
- model: string
57
-
58
- chunk:
59
- description: Fired for each streaming chunk.
60
- detail:
61
- text: string
62
- snapshot: string
63
-
64
- thinking:
65
- description: Fired when the model emits extended-thinking content.
66
- detail:
67
- text: string
68
-
69
- done:
70
- description: Fired when a response completes.
71
- detail:
72
- text: string
73
- usage: object
74
- stopReason: string
75
-
76
- error:
77
- description: Fired on any LLM / network error.
78
- detail:
79
- error: Error
80
-
81
- abort:
82
- description: Fired when the user aborts an in-flight request.
83
-
84
- clear:
85
- description: Fired when the conversation is cleared.
86
-
87
- message:
88
- description: Fired after each message (user or assistant) is appended.
89
- detail:
90
- id: string
91
- role: string
92
- content: string
93
-
94
- slots:
95
- default:
96
- description: >-
97
- Author provides the structural DOM. Expected markers —
98
- [data-chat-messages] (message list), [data-chat-input] (input surface),
99
- [data-chat-empty] (empty state), [data-chat-status] (streaming indicator).
100
-
101
- states:
102
- - name: idle
103
- description: No active request.
104
- - name: streaming
105
- attribute: streaming
106
- description: An LLM request is in-flight; [data-chat-status] visible.
107
-
108
- traits: []
109
-
110
- a2ui:
111
- rules:
112
- - adia-chat is a behavior wrapper; don't nest col-ui/row-ui inside it directly —
113
- author the structural DOM using [data-chat-*] markers instead.
114
-
115
- keywords: [adia-chat, chat, llm, streaming, conversation, agent]
116
- synonyms:
117
- chat: [conversation, messages, thread]
118
- related: [ChatInput, Code]
@@ -1,12 +0,0 @@
1
- /* ═══════════════════════════════════════════════════════════════
2
- adia-chat-ui — Empty state
3
- ═══════════════════════════════════════════════════════════════ */
4
-
5
- adia-chat-ui [data-chat-empty] {
6
- margin: auto;
7
- }
8
-
9
- adia-chat-ui[streaming] [data-chat-empty],
10
- adia-chat-ui:has([data-role]) [data-chat-empty] {
11
- display: none;
12
- }
@@ -1,60 +0,0 @@
1
- /* ═══════════════════════════════════════════════════════════════
2
- adia-chat-ui — Root layout
3
- ═══════════════════════════════════════════════════════════════ */
4
-
5
- adia-chat-ui {
6
- box-sizing: border-box;
7
- display: flex;
8
- flex-direction: column;
9
- height: 100%;
10
- overflow: hidden;
11
- border: var(--chat-border);
12
- border-radius: var(--chat-radius);
13
- background: var(--chat-bg);
14
- }
15
-
16
- /* Header */
17
- adia-chat-ui > header {
18
- display: flex;
19
- align-items: center;
20
- gap: var(--chat-header-gap);
21
- min-height: var(--chat-header-height);
22
- padding: 0 var(--chat-header-px);
23
- border-bottom: var(--chat-header-border);
24
- flex-shrink: 0;
25
- }
26
-
27
- adia-chat-ui > header [data-chat-name] {
28
- font-weight: var(--chat-weight-semibold);
29
- font-size: var(--chat-header-name-font);
30
- }
31
-
32
- adia-chat-ui > header [data-chat-status] {
33
- font-size: var(--chat-header-status-font);
34
- color: var(--chat-header-status-fg);
35
- margin-inline-start: auto;
36
- }
37
-
38
- /* Messages scroll container */
39
- adia-chat-ui > [data-chat-messages],
40
- adia-chat-ui > section {
41
- flex: 1;
42
- overflow-y: auto;
43
- padding: var(--chat-messages-py) var(--chat-messages-px);
44
- display: flex;
45
- flex-direction: column;
46
- gap: var(--chat-messages-gap);
47
- min-height: 0;
48
- }
49
-
50
- /* Footer */
51
- adia-chat-ui > footer {
52
- flex-shrink: 0;
53
- display: flex;
54
- align-items: center;
55
- padding: var(--chat-footer-py) var(--chat-footer-px);
56
- }
57
-
58
- adia-chat-ui > footer chat-input-ui {
59
- flex: 1;
60
- }
@@ -1,74 +0,0 @@
1
- /* ═══════════════════════════════════════════════════════════════
2
- adia-chat-ui — Markdown prose inside bubbles
3
- ═══════════════════════════════════════════════════════════════ */
4
-
5
- adia-chat-ui [data-bubble] [data-content] {
6
- white-space: normal;
7
- }
8
-
9
- adia-chat-ui [data-bubble] [data-content] p {
10
- margin: 0 0 0.5em;
11
- }
12
-
13
- adia-chat-ui [data-bubble] [data-content] p:last-child {
14
- margin-bottom: 0;
15
- }
16
-
17
- adia-chat-ui [data-bubble] [data-content] strong {
18
- font-weight: var(--chat-weight-semibold);
19
- }
20
-
21
- adia-chat-ui [data-bubble] [data-content] code {
22
- background: var(--chat-code-bg);
23
- padding: 0.1em 0.15em;
24
- border-radius: var(--chat-code-inline-radius);
25
- font-family: var(--chat-code-inline-family);
26
- font-size: 0.875em;
27
- }
28
-
29
- adia-chat-ui [data-bubble] [data-content] pre {
30
- background: var(--chat-code-bg);
31
- border-radius: var(--chat-code-radius);
32
- padding: var(--chat-code-block-px);
33
- overflow-x: auto;
34
- margin: var(--chat-code-block-my) 0;
35
- font-size: var(--chat-code-block-font);
36
- line-height: 1.5;
37
- }
38
-
39
- adia-chat-ui [data-bubble] [data-content] pre code {
40
- background: none;
41
- padding: 0;
42
- border-radius: 0;
43
- font-size: inherit;
44
- }
45
-
46
- adia-chat-ui [data-bubble] [data-content] ul,
47
- adia-chat-ui [data-bubble] [data-content] ol {
48
- margin: 0.25em 0;
49
- padding-inline-start: 1.25em;
50
- }
51
-
52
- adia-chat-ui [data-bubble] [data-content] li {
53
- margin-bottom: 0.15em;
54
- }
55
-
56
- adia-chat-ui [data-bubble] [data-content] a {
57
- color: inherit;
58
- text-decoration: underline;
59
- text-underline-offset: 2px;
60
- }
61
-
62
- adia-chat-ui [data-bubble] [data-content] h1,
63
- adia-chat-ui [data-bubble] [data-content] h2,
64
- adia-chat-ui [data-bubble] [data-content] h3,
65
- adia-chat-ui [data-bubble] [data-content] h4 {
66
- font-weight: var(--chat-weight-semibold);
67
- margin: 0.75em 0 0.25em;
68
- }
69
-
70
- adia-chat-ui [data-bubble] [data-content] h1:first-child,
71
- adia-chat-ui [data-bubble] [data-content] h2:first-child,
72
- adia-chat-ui [data-bubble] [data-content] h3:first-child {
73
- margin-top: 0;
74
- }
@@ -1,87 +0,0 @@
1
- /* ═══════════════════════════════════════════════════════════════
2
- adia-chat-ui — Message bubbles
3
- ═══════════════════════════════════════════════════════════════ */
4
-
5
- /* Message row */
6
- adia-chat-ui [data-role] {
7
- display: flex;
8
- gap: var(--chat-header-gap);
9
- align-items: flex-end;
10
- max-width: var(--chat-message-max-width);
11
- }
12
-
13
- adia-chat-ui [data-role="user"] {
14
- align-self: flex-end;
15
- flex-direction: row-reverse;
16
- }
17
-
18
- adia-chat-ui [data-role="assistant"] {
19
- align-self: flex-start;
20
- }
21
-
22
- /* Avatar */
23
- adia-chat-ui [data-role] [data-avatar] {
24
- width: var(--chat-avatar-size);
25
- height: var(--chat-avatar-size);
26
- border-radius: var(--chat-avatar-radius);
27
- background: var(--chat-avatar-bg);
28
- color: var(--chat-avatar-fg);
29
- display: flex;
30
- align-items: center;
31
- justify-content: center;
32
- font-size: var(--chat-avatar-font);
33
- font-weight: var(--chat-avatar-weight);
34
- flex-shrink: 0;
35
- }
36
-
37
- /* Bubble */
38
- adia-chat-ui [data-role] [data-bubble] {
39
- padding: var(--chat-assistant-py) var(--chat-assistant-px);
40
- border-radius: var(--chat-assistant-radius);
41
- font-size: var(--chat-font-size);
42
- line-height: var(--chat-line-height);
43
- white-space: pre-wrap;
44
- word-break: break-word;
45
- }
46
-
47
- adia-chat-ui [data-role] [data-bubble] > :first-child { margin-block-start: 0; }
48
- adia-chat-ui [data-role] [data-bubble] > :last-child { margin-block-end: 0; }
49
-
50
- /* User bubble */
51
- adia-chat-ui [data-role="user"] [data-bubble] {
52
- background: var(--chat-user-bg);
53
- color: var(--chat-user-fg);
54
- padding: var(--chat-user-py) var(--chat-user-px);
55
- border-radius: var(--chat-user-radius);
56
- border-bottom-right-radius: var(--chat-user-tail-radius);
57
- }
58
-
59
- /* Assistant bubble */
60
- adia-chat-ui [data-role="assistant"] [data-bubble] {
61
- background: var(--chat-assistant-bg);
62
- color: var(--chat-assistant-fg);
63
- border-bottom-left-radius: var(--chat-assistant-tail-radius);
64
- }
65
-
66
- /* Error message */
67
- adia-chat-ui [data-role="error"] {
68
- align-self: center;
69
- max-width: none;
70
- display: flex;
71
- align-items: center;
72
- gap: var(--chat-error-gap);
73
- color: var(--chat-error-fg);
74
- font-size: var(--chat-error-font);
75
- }
76
-
77
- /* Message actions (copy, regenerate) */
78
- adia-chat-ui [data-role] [data-actions] {
79
- display: flex;
80
- gap: var(--chat-actions-gap);
81
- opacity: 0;
82
- transition: opacity var(--chat-actions-duration) var(--chat-actions-easing);
83
- }
84
-
85
- adia-chat-ui [data-role]:hover [data-actions] {
86
- opacity: 1;
87
- }
@@ -1,30 +0,0 @@
1
- /* ═══════════════════════════════════════════════════════════════
2
- adia-chat-ui — Streaming states (cursor, thinking)
3
- ═══════════════════════════════════════════════════════════════ */
4
-
5
- /* Blinking cursor during streaming */
6
- adia-chat-ui [data-cursor] {
7
- display: inline-block;
8
- width: var(--chat-cursor-width);
9
- height: 1em;
10
- background: var(--chat-cursor-color);
11
- margin-inline-start: 1px;
12
- vertical-align: text-bottom;
13
- animation: adia-chat-blink var(--chat-cursor-speed) step-end infinite;
14
- }
15
-
16
- @keyframes adia-chat-blink {
17
- 50% { opacity: 0; }
18
- }
19
-
20
- @media (prefers-reduced-motion: reduce) {
21
- adia-chat-ui [data-cursor] {
22
- animation: none;
23
- opacity: 0.7;
24
- }
25
- }
26
-
27
- /* Thinking indicator */
28
- adia-chat-ui [data-role="assistant"][data-thinking] [data-bubble] {
29
- color: var(--chat-thinking-fg);
30
- }