@kitn.ai/ui 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (493) hide show
  1. package/README.md +55 -17
  2. package/dist/components/artifact.d.ts +39 -1
  3. package/dist/components/attachment-types.d.ts +12 -0
  4. package/dist/components/attachments.d.ts +2 -10
  5. package/dist/components/card.d.ts +27 -0
  6. package/dist/components/chain-of-thought.d.ts +78 -2
  7. package/dist/components/chat-scope-picker.d.ts +7 -0
  8. package/dist/components/chat-thread.d.ts +39 -16
  9. package/dist/components/choice-card.d.ts +27 -0
  10. package/dist/components/coachmark.d.ts +49 -0
  11. package/dist/components/composer-dom.d.ts +35 -0
  12. package/dist/components/composer-highlight.d.ts +48 -0
  13. package/dist/components/composer-history.d.ts +34 -0
  14. package/dist/components/composer.d.ts +86 -0
  15. package/dist/components/confirm-card.d.ts +17 -0
  16. package/dist/components/conversation-item.d.ts +9 -0
  17. package/dist/components/conversation-list.d.ts +36 -1
  18. package/dist/components/dismissed-stub.d.ts +22 -0
  19. package/dist/components/file-tree.d.ts +15 -0
  20. package/dist/components/form.d.ts +34 -0
  21. package/dist/components/markdown.d.ts +3 -0
  22. package/dist/components/message.d.ts +71 -2
  23. package/dist/components/model-switcher.d.ts +7 -0
  24. package/dist/components/prompt-input.d.ts +13 -4
  25. package/dist/components/prompt-suggestion.d.ts +9 -1
  26. package/dist/components/reasoning.d.ts +14 -1
  27. package/dist/components/response-compare-types.d.ts +66 -0
  28. package/dist/components/response-compare.d.ts +65 -0
  29. package/dist/components/screen.d.ts +46 -0
  30. package/dist/components/tasks-card.d.ts +50 -1
  31. package/dist/components/toast.d.ts +58 -0
  32. package/dist/components/tool-types.d.ts +10 -0
  33. package/dist/components/tool.d.ts +8 -8
  34. package/dist/components/use-card-resolution.d.ts +10 -6
  35. package/dist/components/voice-input.d.ts +27 -0
  36. package/dist/components/voice-output.d.ts +33 -0
  37. package/dist/core-C8fzo39E.js +12 -0
  38. package/dist/custom-elements.json +8472 -1691
  39. package/dist/elements/agent-card.d.ts +1 -0
  40. package/dist/elements/agent-card.js +1 -0
  41. package/dist/elements/artifact.js +1 -0
  42. package/dist/elements/attachments.js +1 -0
  43. package/dist/elements/autoloader.d.ts +2 -0
  44. package/dist/elements/autoloader.js +1 -0
  45. package/dist/elements/avatar.d.ts +1 -0
  46. package/dist/elements/avatar.js +1 -0
  47. package/dist/elements/badge.d.ts +1 -0
  48. package/dist/elements/badge.js +1 -0
  49. package/dist/elements/button.d.ts +1 -0
  50. package/dist/elements/button.js +1 -0
  51. package/dist/elements/card.js +1 -0
  52. package/dist/elements/cards.d.ts +1 -0
  53. package/dist/elements/cards.js +1 -0
  54. package/dist/elements/chain-of-thought.d.ts +0 -12
  55. package/dist/elements/chain-of-thought.js +1 -0
  56. package/dist/elements/chat-scope-picker.js +1 -0
  57. package/dist/elements/chat-types.d.ts +8 -2
  58. package/dist/elements/chat-workspace.js +1 -0
  59. package/dist/elements/chat.js +1 -0
  60. package/dist/elements/checkpoint.js +1 -0
  61. package/dist/elements/choice.js +1 -0
  62. package/dist/elements/chunks/Icon-DLLBeLG5.js +1 -0
  63. package/dist/elements/chunks/action-icons-UB4V5FNq.js +1 -0
  64. package/dist/elements/chunks/arrow-left-C-gwlUmx.js +1 -0
  65. package/dist/elements/chunks/attachments-CgbErf1r.js +1 -0
  66. package/dist/elements/chunks/badge-DTQpgB6N.js +1 -0
  67. package/dist/elements/chunks/bash-InADTalH.js +1 -0
  68. package/dist/elements/chunks/button-XDUM6lXs.js +1 -0
  69. package/dist/elements/chunks/card-CBlFZ-7I.js +1 -0
  70. package/dist/elements/chunks/card-routing-C986KuUA.js +1 -0
  71. package/dist/elements/chunks/chat-thread-BIhmqwNL.js +1 -0
  72. package/dist/elements/chunks/check-hGUoVIKb.js +1 -0
  73. package/dist/elements/chunks/chevron-down-DDoaSUtO.js +1 -0
  74. package/dist/elements/chunks/chevron-right-CdGEUakB.js +1 -0
  75. package/dist/elements/chunks/circle-BKAZdmzb.js +1 -0
  76. package/dist/elements/chunks/circle-check-CmYG-y3I.js +1 -0
  77. package/dist/elements/chunks/circle-x-DewgAEym.js +1 -0
  78. package/dist/elements/chunks/cn-CU7UAWzk.js +1 -0
  79. package/dist/elements/chunks/code-block-DedwxwFI.js +1 -0
  80. package/dist/elements/chunks/collapsible-FfgmTHtM.js +1 -0
  81. package/dist/elements/chunks/composer-Cfbw5HKT.js +65 -0
  82. package/dist/elements/chunks/context-DwJmxlRE.js +1 -0
  83. package/dist/elements/chunks/conversation-list-DsCQMfPq.js +1 -0
  84. package/dist/elements/chunks/core-AYMC6_lb.js +12 -0
  85. package/dist/elements/chunks/css-M7EaDHN_.js +1 -0
  86. package/dist/elements/chunks/default-input-BuqsoENC.js +1 -0
  87. package/dist/elements/chunks/define-rGsaWsLL.js +1 -0
  88. package/dist/elements/chunks/disclosure-CwoAkpMH.js +1 -0
  89. package/dist/elements/chunks/download-DJ06G3Bz.js +1 -0
  90. package/dist/elements/chunks/dropdown-BFg8ri_R.js +1 -0
  91. package/dist/elements/chunks/ellipsis-dlN6YvGw.js +1 -0
  92. package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +141 -0
  93. package/dist/elements/chunks/external-link-DBX2lc_R.js +1 -0
  94. package/dist/elements/chunks/file-text-HfwUx4F9.js +1 -0
  95. package/dist/elements/chunks/file-tree-C6Toj71u.js +1 -0
  96. package/dist/elements/chunks/folder-MYuqa9Xp.js +1 -0
  97. package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +1 -0
  98. package/dist/elements/chunks/github-light-JYsPkUQd.js +1 -0
  99. package/dist/elements/chunks/hover-card-gE7iyXdW.js +1 -0
  100. package/dist/elements/chunks/html-CPZ3oZQ7.js +1 -0
  101. package/dist/elements/chunks/icon-Vqz4ivrY.js +1 -0
  102. package/dist/elements/chunks/index-BCRhi84a.js +1 -0
  103. package/dist/elements/chunks/info-B_toFS0l.js +1 -0
  104. package/dist/elements/chunks/input-gzbHYZvQ.js +1 -0
  105. package/dist/elements/chunks/javascript-C25yR2R2.js +1 -0
  106. package/dist/elements/chunks/json-DxJze_jm.js +1 -0
  107. package/dist/elements/chunks/kbd-n49c4KZm.js +1 -0
  108. package/dist/elements/chunks/link-CKPs9yM0.js +1 -0
  109. package/dist/elements/chunks/loader-q6MamGus.js +1 -0
  110. package/dist/elements/chunks/markdown-DBrcqq4S.js +64 -0
  111. package/dist/elements/chunks/message-CTqaYI0s.js +1 -0
  112. package/dist/elements/chunks/message-feedback-Cvzm03w0.js +1 -0
  113. package/dist/elements/chunks/message-square-CUg9eRCi.js +1 -0
  114. package/dist/elements/chunks/minimize-2-l2klxP6K.js +1 -0
  115. package/dist/elements/chunks/model-switcher-CmyjiHO1.js +1 -0
  116. package/dist/elements/chunks/overlay-C8sOYqjT.js +1 -0
  117. package/dist/elements/chunks/paperclip-42Ia7xHD.js +1 -0
  118. package/dist/elements/chunks/progress-bar-tzKMWAwO.js +1 -0
  119. package/dist/elements/chunks/prompt-suggestion-D3F6vP_A.js +1 -0
  120. package/dist/elements/chunks/reasoning-BJNmmyov.js +1 -0
  121. package/dist/elements/chunks/resizable-BRsk19qI.js +1 -0
  122. package/dist/elements/chunks/rotate-cw-BgcggLHC.js +1 -0
  123. package/dist/elements/chunks/scroll-area-CgGbFFbT.js +1 -0
  124. package/dist/elements/chunks/separator-8hM4GdHE.js +1 -0
  125. package/dist/elements/chunks/settings-CaUIYOg-.js +1 -0
  126. package/dist/elements/chunks/settings-group-CYjOVIZQ.js +1 -0
  127. package/dist/elements/chunks/share-BTYM3Ddt.js +1 -0
  128. package/dist/elements/chunks/skeleton-DsTYrPUe.js +1 -0
  129. package/dist/elements/chunks/slots-DkZ-Cmha.js +1 -0
  130. package/dist/elements/chunks/star-9R3LBQ9n.js +1 -0
  131. package/dist/elements/chunks/store-CYl5Y0_u.js +1 -0
  132. package/dist/elements/chunks/svelte--5p79yCD.js +1 -0
  133. package/dist/elements/chunks/text-shimmer-CaYGv8Se.js +1 -0
  134. package/dist/elements/chunks/textarea-NEr2SLcD.js +1 -0
  135. package/dist/elements/chunks/thumbs-up-DZYZkFfc.js +1 -0
  136. package/dist/elements/chunks/toast-store-ClxVZRcc.js +1 -0
  137. package/dist/elements/chunks/tool-CHZOmoe9.js +1 -0
  138. package/dist/elements/chunks/tooltip-WpHElELC.js +1 -0
  139. package/dist/elements/chunks/triangle-alert-BlS80PUg.js +1 -0
  140. package/dist/elements/chunks/tsx-B8rCNbgL.js +1 -0
  141. package/dist/elements/chunks/typescript-RycA9KXf.js +1 -0
  142. package/dist/elements/chunks/use-card-resolution-VSVoxDeJ.js +1 -0
  143. package/dist/elements/chunks/video-DxTPZqT8.js +1 -0
  144. package/dist/elements/chunks/vue-BmIZj4XD.js +1 -0
  145. package/dist/elements/chunks/x-C1qtndxn.js +1 -0
  146. package/dist/elements/coachmark.d.ts +1 -0
  147. package/dist/elements/coachmark.js +1 -0
  148. package/dist/elements/code-block.js +1 -0
  149. package/dist/elements/command.d.ts +1 -0
  150. package/dist/elements/command.js +1 -0
  151. package/dist/elements/compare.d.ts +1 -0
  152. package/dist/elements/compare.js +1 -0
  153. package/dist/elements/composer.d.ts +1 -0
  154. package/dist/elements/composer.js +1 -0
  155. package/dist/elements/confirm-card.js +1 -0
  156. package/dist/elements/context-meter.js +1 -0
  157. package/dist/elements/conversation-list.d.ts +1 -11
  158. package/dist/elements/conversation-list.js +1 -0
  159. package/dist/elements/default-input.d.ts +20 -9
  160. package/dist/elements/define.d.ts +11 -0
  161. package/dist/elements/dialog.d.ts +1 -0
  162. package/dist/elements/dialog.js +1 -0
  163. package/dist/elements/disclosure.d.ts +37 -0
  164. package/dist/elements/editable-label.d.ts +1 -0
  165. package/dist/elements/editable-label.js +1 -0
  166. package/dist/elements/embed.js +1 -0
  167. package/dist/elements/empty.js +1 -0
  168. package/dist/elements/feedback-bar.js +1 -0
  169. package/dist/elements/file-tree.js +1 -0
  170. package/dist/elements/file-upload.js +1 -0
  171. package/dist/elements/form.js +1 -0
  172. package/dist/elements/hover-card.d.ts +1 -0
  173. package/dist/elements/hover-card.js +1 -0
  174. package/dist/elements/icon.d.ts +1 -0
  175. package/dist/elements/icon.js +1 -0
  176. package/dist/elements/image.js +1 -0
  177. package/dist/elements/input.d.ts +1 -0
  178. package/dist/elements/input.js +1 -0
  179. package/dist/elements/kbd.d.ts +1 -0
  180. package/dist/elements/kbd.js +1 -0
  181. package/dist/elements/link-preview.js +1 -0
  182. package/dist/elements/loader.js +1 -0
  183. package/dist/elements/markdown.js +1 -0
  184. package/dist/elements/menu.d.ts +1 -0
  185. package/dist/elements/menu.js +1 -0
  186. package/dist/elements/message-skills.d.ts +0 -16
  187. package/dist/elements/message-skills.js +1 -0
  188. package/dist/elements/message.js +1 -0
  189. package/dist/elements/model-switcher.d.ts +1 -11
  190. package/dist/elements/model-switcher.js +1 -0
  191. package/dist/elements/nav.d.ts +1 -0
  192. package/dist/elements/nav.js +1 -0
  193. package/dist/elements/notice.d.ts +1 -0
  194. package/dist/elements/notice.js +1 -0
  195. package/dist/elements/pane-group.d.ts +1 -0
  196. package/dist/elements/pane-group.js +1 -0
  197. package/dist/elements/pane.d.ts +1 -0
  198. package/dist/elements/pane.js +1 -0
  199. package/dist/elements/popover.js +1 -0
  200. package/dist/elements/progress-bar.d.ts +1 -0
  201. package/dist/elements/progress-bar.js +1 -0
  202. package/dist/elements/prompt-dock.d.ts +1 -0
  203. package/dist/elements/prompt-dock.js +1 -0
  204. package/dist/elements/prompt-input.d.ts +1 -9
  205. package/dist/elements/prompt-input.js +1 -0
  206. package/dist/elements/prompt-suggestions.d.ts +0 -6
  207. package/dist/elements/prompt-suggestions.js +1 -0
  208. package/dist/elements/reasoning.js +1 -0
  209. package/dist/elements/register.d.ts +10 -0
  210. package/dist/elements/remote.js +1 -0
  211. package/dist/elements/resizable.d.ts +1 -17
  212. package/dist/elements/resizable.js +1 -0
  213. package/dist/elements/response-stream.js +14 -0
  214. package/dist/elements/screen.d.ts +1 -0
  215. package/dist/elements/screen.js +1 -0
  216. package/dist/elements/scroll-area.d.ts +1 -0
  217. package/dist/elements/scroll-area.js +1 -0
  218. package/dist/elements/scroll-button.js +1 -0
  219. package/dist/elements/search.d.ts +1 -0
  220. package/dist/elements/search.js +1 -0
  221. package/dist/elements/segmented.d.ts +1 -0
  222. package/dist/elements/segmented.js +1 -0
  223. package/dist/elements/separator.d.ts +1 -0
  224. package/dist/elements/separator.js +1 -0
  225. package/dist/elements/setting-item.d.ts +1 -0
  226. package/dist/elements/setting-item.js +1 -0
  227. package/dist/elements/settings-group.d.ts +1 -0
  228. package/dist/elements/settings-group.js +1 -0
  229. package/dist/elements/skeleton.d.ts +1 -0
  230. package/dist/elements/skeleton.js +1 -0
  231. package/dist/elements/slots.d.ts +176 -0
  232. package/dist/elements/source.d.ts +0 -17
  233. package/dist/elements/source.js +1 -0
  234. package/dist/elements/status.d.ts +1 -0
  235. package/dist/elements/status.js +1 -0
  236. package/dist/elements/switch.js +1 -0
  237. package/dist/elements/tabs.d.ts +1 -0
  238. package/dist/elements/tabs.js +1 -0
  239. package/dist/elements/tasks.js +1 -0
  240. package/dist/elements/text-shimmer.js +1 -0
  241. package/dist/elements/thinking-bar.js +1 -0
  242. package/dist/elements/toast.d.ts +1 -0
  243. package/dist/elements/toast.js +1 -0
  244. package/dist/elements/tool.js +1 -0
  245. package/dist/elements/tooltip.d.ts +1 -0
  246. package/dist/elements/tooltip.js +1 -0
  247. package/dist/elements/voice-input.js +1 -0
  248. package/dist/elements/voice-output.d.ts +1 -0
  249. package/dist/elements/voice-output.js +1 -0
  250. package/dist/elements.d.ts +772 -61
  251. package/dist/engine-javascript-C1x7zo1_.js +141 -0
  252. package/dist/index.d.ts +15 -2
  253. package/dist/index.js +14405 -9810
  254. package/dist/kai.es.js +1 -0
  255. package/dist/llms/llms-full.txt +1234 -107
  256. package/dist/llms/llms.txt +4 -4
  257. package/dist/mcp.es.js +217 -6
  258. package/dist/primitives/card-contract.d.ts +20 -4
  259. package/dist/primitives/card-recovery.d.ts +55 -0
  260. package/dist/primitives/composer-model.d.ts +22 -0
  261. package/dist/primitives/composer-triggers.d.ts +19 -0
  262. package/dist/primitives/create-kai-chat.d.ts +38 -0
  263. package/dist/primitives/message-feedback.d.ts +35 -0
  264. package/dist/primitives/toast-store.d.ts +118 -0
  265. package/dist/primitives/use-speech-recognition.d.ts +26 -0
  266. package/dist/react/index.d.ts +1166 -98
  267. package/dist/react/runtime.d.ts +9 -2
  268. package/dist/react/use-kai-chat.d.ts +41 -0
  269. package/dist/react.js +575 -186
  270. package/dist/register-impl-CYWGkgbI.js +141 -0
  271. package/dist/schemas/choice.schema.json +5 -0
  272. package/dist/schemas/tasks.schema.json +7 -2
  273. package/dist/state/index.d.ts +4 -0
  274. package/dist/state/messages.d.ts +11 -0
  275. package/dist/state/stream.d.ts +22 -0
  276. package/dist/state/suggestions.d.ts +4 -0
  277. package/dist/state.js +117 -0
  278. package/dist/theme.tokens.css +87 -0
  279. package/dist/types.d.ts +4 -0
  280. package/dist/ui/agent-card.d.ts +61 -0
  281. package/dist/ui/button.d.ts +5 -2
  282. package/dist/ui/card.d.ts +61 -0
  283. package/dist/ui/collapsible.d.ts +15 -1
  284. package/dist/ui/command.d.ts +33 -0
  285. package/dist/ui/dialog.d.ts +42 -0
  286. package/dist/ui/dropdown.d.ts +95 -1
  287. package/dist/ui/editable-label.d.ts +26 -0
  288. package/dist/ui/hover-card.d.ts +13 -1
  289. package/dist/ui/icon.d.ts +18 -0
  290. package/dist/ui/input.d.ts +33 -0
  291. package/dist/ui/kbd.d.ts +21 -0
  292. package/dist/ui/nav.d.ts +62 -0
  293. package/dist/ui/notice.d.ts +31 -0
  294. package/dist/ui/overlay.d.ts +12 -0
  295. package/dist/ui/pane-grid.d.ts +58 -0
  296. package/dist/ui/pane-group.d.ts +75 -0
  297. package/dist/ui/pane.d.ts +78 -0
  298. package/dist/ui/popover.d.ts +11 -1
  299. package/dist/ui/progress-bar.d.ts +23 -0
  300. package/dist/ui/prompt-dock.d.ts +96 -0
  301. package/dist/ui/resizable.d.ts +12 -0
  302. package/dist/ui/scroll-area.d.ts +4 -0
  303. package/dist/ui/segmented.d.ts +28 -0
  304. package/dist/ui/settings-group.d.ts +32 -0
  305. package/dist/ui/skeleton.d.ts +12 -0
  306. package/dist/ui/stat.d.ts +16 -0
  307. package/dist/ui/status.d.ts +13 -0
  308. package/dist/ui/switch.d.ts +8 -1
  309. package/dist/ui/tabs.d.ts +35 -0
  310. package/dist/ui/tooltip.d.ts +20 -1
  311. package/frameworks/react/index.tsx +1100 -163
  312. package/frameworks/react/runtime.tsx +30 -1
  313. package/frameworks/react/use-kai-chat.tsx +87 -0
  314. package/llms-full.txt +1234 -107
  315. package/llms.txt +4 -4
  316. package/package.json +36 -12
  317. package/src/agent-tooling/mcp/manifest.ts +14 -0
  318. package/src/agent-tooling/mcp/tools/debug.ts +194 -6
  319. package/src/agent-tooling/mcp/tools/reference.ts +32 -0
  320. package/src/agent-tooling/mcp/tools/scaffold.ts +162 -1
  321. package/src/components/artifact.tsx +98 -13
  322. package/src/components/attachment-types.ts +13 -0
  323. package/src/components/attachments.tsx +4 -14
  324. package/src/components/card.tsx +109 -15
  325. package/src/components/chain-of-thought.tsx +210 -1
  326. package/src/components/chat-scope-picker.tsx +13 -3
  327. package/src/components/chat-thread.tsx +238 -137
  328. package/src/components/choice-card.tsx +136 -15
  329. package/src/components/coachmark.tsx +245 -0
  330. package/src/components/component-meta.json +921 -108
  331. package/src/components/composer-dom.ts +159 -0
  332. package/src/components/composer-highlight.ts +242 -0
  333. package/src/components/composer-history.ts +82 -0
  334. package/src/components/composer.tsx +979 -0
  335. package/src/components/confirm-card.tsx +69 -2
  336. package/src/components/conversation-item.tsx +69 -7
  337. package/src/components/conversation-list.tsx +134 -37
  338. package/src/components/dismissed-stub.tsx +80 -0
  339. package/src/components/file-tree.tsx +197 -47
  340. package/src/components/form-widgets.tsx +9 -7
  341. package/src/components/form.tsx +161 -20
  342. package/src/components/image.tsx +3 -5
  343. package/src/components/link-preview.tsx +5 -4
  344. package/src/components/markdown.tsx +5 -2
  345. package/src/components/message.tsx +174 -14
  346. package/src/components/model-switcher.tsx +19 -4
  347. package/src/components/prompt-input.tsx +46 -75
  348. package/src/components/prompt-suggestion.tsx +48 -16
  349. package/src/components/reasoning.tsx +29 -6
  350. package/src/components/response-compare-types.ts +127 -0
  351. package/src/components/response-compare.tsx +460 -0
  352. package/src/components/screen.tsx +176 -0
  353. package/src/components/tasks-card.tsx +374 -23
  354. package/src/components/toast.tsx +486 -0
  355. package/src/components/tool-types.ts +10 -0
  356. package/src/components/tool.tsx +22 -16
  357. package/src/components/use-card-resolution.ts +24 -8
  358. package/src/components/voice-input.tsx +102 -19
  359. package/src/components/voice-output.tsx +202 -0
  360. package/src/elements/agent-card.tsx +67 -0
  361. package/src/elements/artifact.tsx +53 -4
  362. package/src/elements/attachments.tsx +1 -0
  363. package/src/elements/autoloader.ts +89 -0
  364. package/src/elements/avatar.tsx +33 -0
  365. package/src/elements/badge.tsx +32 -0
  366. package/src/elements/button.tsx +126 -0
  367. package/src/elements/card-media.jpg +0 -0
  368. package/src/elements/card.tsx +124 -31
  369. package/src/elements/cards.tsx +81 -7
  370. package/src/elements/chain-of-thought.tsx +77 -32
  371. package/src/elements/chat-scope-picker.tsx +35 -8
  372. package/src/elements/chat-types.ts +9 -2
  373. package/src/elements/chat-workspace.tsx +157 -43
  374. package/src/elements/chat.tsx +49 -25
  375. package/src/elements/choice.tsx +71 -19
  376. package/src/elements/coachmark.tsx +90 -0
  377. package/src/elements/command.tsx +209 -0
  378. package/src/elements/compare.tsx +110 -0
  379. package/src/elements/compiled.css +1 -1
  380. package/src/elements/composer.tsx +151 -0
  381. package/src/elements/confirm-card.tsx +36 -11
  382. package/src/elements/conversation-list.tsx +80 -11
  383. package/src/elements/default-input.tsx +75 -53
  384. package/src/elements/define.tsx +47 -6
  385. package/src/elements/dialog.tsx +98 -0
  386. package/src/elements/disclosure.ts +73 -0
  387. package/src/elements/editable-label.tsx +125 -0
  388. package/src/elements/element-manifest.json +310 -0
  389. package/src/elements/element-meta.json +5954 -1605
  390. package/src/elements/element-types.d.ts +771 -60
  391. package/src/elements/file-tree.tsx +12 -2
  392. package/src/elements/file-upload.tsx +1 -1
  393. package/src/elements/form.tsx +54 -11
  394. package/src/elements/hover-card.tsx +80 -0
  395. package/src/elements/icon-names.json +48 -0
  396. package/src/elements/icon.tsx +41 -0
  397. package/src/elements/input.tsx +203 -0
  398. package/src/elements/kbd.tsx +45 -0
  399. package/src/elements/menu.tsx +217 -0
  400. package/src/elements/message.tsx +84 -55
  401. package/src/elements/model-switcher.tsx +27 -1
  402. package/src/elements/nav.tsx +87 -0
  403. package/src/elements/notice.tsx +53 -0
  404. package/src/elements/pane-group.tsx +119 -0
  405. package/src/elements/pane.tsx +129 -0
  406. package/src/elements/popover.tsx +39 -17
  407. package/src/elements/progress-bar.tsx +39 -0
  408. package/src/elements/prompt-dock.tsx +81 -0
  409. package/src/elements/prompt-input.tsx +112 -63
  410. package/src/elements/prompt-suggestions.tsx +25 -9
  411. package/src/elements/reasoning.tsx +30 -9
  412. package/src/elements/register-impl.ts +41 -3
  413. package/src/elements/register.ts +20 -3
  414. package/src/elements/remote.tsx +4 -0
  415. package/src/elements/resizable.tsx +48 -11
  416. package/src/elements/screen.tsx +90 -0
  417. package/src/elements/scroll-area.tsx +33 -0
  418. package/src/elements/search.tsx +180 -0
  419. package/src/elements/segmented.tsx +135 -0
  420. package/src/elements/separator.tsx +36 -0
  421. package/src/elements/setting-item.tsx +50 -0
  422. package/src/elements/settings-group.tsx +37 -0
  423. package/src/elements/skeleton.tsx +45 -0
  424. package/src/elements/slots.ts +607 -0
  425. package/src/elements/source.tsx +13 -6
  426. package/src/elements/status.tsx +42 -0
  427. package/src/elements/styles.css +19 -0
  428. package/src/elements/switch.tsx +89 -14
  429. package/src/elements/tabs.tsx +95 -0
  430. package/src/elements/tasks.tsx +70 -14
  431. package/src/elements/toast.tsx +89 -0
  432. package/src/elements/tool.tsx +43 -9
  433. package/src/elements/tooltip.tsx +85 -0
  434. package/src/elements/video-poster.jpg +0 -0
  435. package/src/elements/voice-input.tsx +66 -16
  436. package/src/elements/voice-output.tsx +69 -0
  437. package/src/index.ts +35 -2
  438. package/src/primitives/card-contract.ts +14 -5
  439. package/src/primitives/card-recovery.ts +149 -0
  440. package/src/primitives/card-routing.ts +3 -0
  441. package/src/primitives/card-schemas/choice.schema.json +5 -0
  442. package/src/primitives/card-schemas/tasks.schema.json +7 -2
  443. package/src/primitives/composer-model.ts +49 -0
  444. package/src/primitives/composer-triggers.ts +35 -0
  445. package/src/primitives/create-kai-chat.ts +66 -0
  446. package/src/primitives/message-feedback.ts +123 -0
  447. package/src/primitives/toast-store.ts +276 -0
  448. package/src/primitives/use-speech-recognition.ts +135 -0
  449. package/src/state/index.ts +6 -0
  450. package/src/state/messages.ts +36 -0
  451. package/src/state/stream.ts +92 -0
  452. package/src/state/suggestions.ts +9 -0
  453. package/src/types.ts +4 -0
  454. package/src/ui/agent-card.tsx +212 -0
  455. package/src/ui/button.tsx +16 -5
  456. package/src/ui/card.tsx +245 -0
  457. package/src/ui/collapsible.tsx +30 -4
  458. package/src/ui/command.tsx +99 -0
  459. package/src/ui/dialog.tsx +217 -0
  460. package/src/ui/dropdown.tsx +375 -13
  461. package/src/ui/editable-label.tsx +112 -0
  462. package/src/ui/hover-card.tsx +28 -5
  463. package/src/ui/icon.tsx +110 -0
  464. package/src/ui/input.tsx +132 -0
  465. package/src/ui/kbd.tsx +118 -0
  466. package/src/ui/nav.tsx +282 -0
  467. package/src/ui/notice.tsx +84 -0
  468. package/src/ui/overlay.tsx +108 -2
  469. package/src/ui/pane-grid.tsx +116 -0
  470. package/src/ui/pane-group.tsx +280 -0
  471. package/src/ui/pane.tsx +193 -0
  472. package/src/ui/popover.tsx +16 -2
  473. package/src/ui/progress-bar.tsx +83 -0
  474. package/src/ui/prompt-dock.tsx +145 -0
  475. package/src/ui/resizable.tsx +69 -1
  476. package/src/ui/scroll-area.tsx +14 -3
  477. package/src/ui/segmented.tsx +109 -0
  478. package/src/ui/settings-group.tsx +67 -0
  479. package/src/ui/skeleton.tsx +62 -5
  480. package/src/ui/stat.tsx +41 -0
  481. package/src/ui/status.tsx +48 -0
  482. package/src/ui/switch.tsx +49 -23
  483. package/src/ui/tabs.tsx +168 -0
  484. package/src/ui/tooltip.tsx +57 -7
  485. package/theme.css +113 -0
  486. package/dist/components/slash-command.d.ts +0 -15
  487. package/dist/kitn-chat.es.js +0 -1
  488. package/dist/register-impl-wCsFPoh9.js +0 -77
  489. package/dist/register-ujhr1nBS.js +0 -1
  490. package/src/components/slash-command.tsx +0 -232
  491. package/src/elements/framework-usage.json +0 -563
  492. /package/dist/{kitn-chat-provider.d.ts → kai-provider.d.ts} +0 -0
  493. /package/dist/{kitn-chat-provider.es.js → kai-provider.es.js} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { splitProps, Show, For } from 'solid-js';
2
2
  import { cn } from '../utils/cn';
3
- import { Dropdown, DropdownTrigger, DropdownContent, DropdownItem } from '../ui/dropdown';
3
+ import { Dropdown, DropdownTrigger, DropdownContent, DropdownItem, type DropdownController } from '../ui/dropdown';
4
4
  import { Button } from '../ui/button';
5
5
  import type { SearchFilters } from '../types';
6
6
 
@@ -10,12 +10,22 @@ export interface ChatScopePickerProps {
10
10
  availableAuthors?: string[];
11
11
  availableTags?: string[];
12
12
  class?: string;
13
+ /** Initial open state of the dropdown (uncontrolled seed). */
14
+ defaultOpen?: boolean;
15
+ /** Disable the trigger — click/keyboard no longer open the dropdown. */
16
+ disabled?: boolean;
17
+ /** Receive the dropdown's open controller (forwarded from the inner Dropdown). */
18
+ controllerRef?: (api: DropdownController) => void;
13
19
  }
14
20
 
15
21
  export function ChatScopePicker(props: ChatScopePickerProps) {
16
- const [local] = splitProps(props, ['currentLabel', 'onScopeChange', 'availableAuthors', 'availableTags', 'class']);
22
+ const [local] = splitProps(props, ['currentLabel', 'onScopeChange', 'availableAuthors', 'availableTags', 'class', 'defaultOpen', 'disabled', 'controllerRef']);
17
23
  return (
18
- <Dropdown>
24
+ <Dropdown
25
+ defaultOpen={local.defaultOpen}
26
+ disabled={local.disabled}
27
+ controllerRef={local.controllerRef}
28
+ >
19
29
  <DropdownTrigger as={(triggerProps: any) => (
20
30
  <Button variant="ghost" size="sm" class={cn('gap-1 text-xs', local.class)} {...triggerProps}>
21
31
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/></svg>
@@ -1,10 +1,10 @@
1
- import { createSignal, For, Show } from 'solid-js';
1
+ import { createSignal, createEffect, For, Show, onMount } from 'solid-js';
2
2
  import { ChatConfig, useChatConfig } from '../primitives/chat-config';
3
+ import { type ComposerDoc, normalizeValue, serializeToText } from '../primitives/composer-model';
3
4
  import { ChatContainer, ChatContainerContent, ChatContainerScrollAnchor } from './chat-container';
4
- import { Message, MessageAvatar, MessageContent, MessageActionBar } from './message';
5
- import { Reasoning, ReasoningTrigger, ReasoningContent } from './reasoning';
6
- import { Tool } from './tool';
7
- import { Attachments, Attachment, AttachmentPreview, AttachmentInfo, type AttachmentData } from './attachments';
5
+ import { Message, MessageAvatar, MessageBody } from './message';
6
+ import { type AttachmentData } from './attachments';
7
+ import { createMessageFeedback, type MessageActionDetail } from '../primitives/message-feedback';
8
8
  import { ModelSwitcher } from './model-switcher';
9
9
  import { ScrollButton } from './scroll-button';
10
10
  import {
@@ -12,7 +12,7 @@ import {
12
12
  ContextContentBody, ContextContentFooter, ContextInputUsage, ContextOutputUsage,
13
13
  } from './context';
14
14
  import { DefaultPromptInput } from '../elements/default-input';
15
- import type { SlashCommandItem } from './slash-command';
15
+ import type { TriggerDef } from './composer';
16
16
  import type { ChatMessage } from '../elements/chat-types';
17
17
  import type { ProseSize } from '../primitives/chat-config';
18
18
  import type { ModelOption } from '../types';
@@ -32,9 +32,10 @@ export interface ChatThreadProps {
32
32
  * content, and optional reasoning/tools/attachments/actions. Set as a JS
33
33
  * property (`el.messages = [...]`). */
34
34
  messages: ChatMessage[];
35
- /** Controlled value of the input. When set, the host owns the input text and
36
- * must update it on `kai-value-change`; leave unset for uncontrolled behavior. */
37
- value?: string;
35
+ /** Value of the input. A **string** is controlled (the host owns the text and
36
+ * updates it on `kai-value-change`). A **ComposerDoc** is a one-time seed that
37
+ * pre-populates pills; the user then edits freely. Leave unset for uncontrolled. */
38
+ value?: string | ComposerDoc;
38
39
  /** Placeholder text shown in the empty input. */
39
40
  placeholder?: string;
40
41
  /** When true, shows the loading/streaming state and disables submit (use while
@@ -76,42 +77,97 @@ export interface ChatThreadProps {
76
77
  headerStart?: boolean;
77
78
  /** Whether the host has `slot="header-end"` content (right of the controls). */
78
79
  headerEnd?: boolean;
80
+ // ── Composition slots ─────────────────────────────────────────────────────
81
+ // Each flag below is set by the `<kai-chat>` facade when matching light-DOM
82
+ // `slot="…"` content is projected, and gates one composition slot. Two kinds:
83
+ // • INJECT — additive: project YOUR markup into a region (sidebar, footer,
84
+ // composer-actions, header-start/-end).
85
+ // • REPLACE — substitutive: your markup stands in for a whole region
86
+ // (header, empty, composer). A replaced region's projected
87
+ // content owns its own data/events — a slotted (light-DOM) node
88
+ // can't read this component's reactive state. That boundary is
89
+ // the whole reason `messages` stays a data prop, not a slot.
90
+ /** REPLACE — full custom header in place of the built-in title/model/context bar. */
91
+ headerFull?: boolean;
92
+ /** INJECT — left sidebar column (e.g. a conversation list / your own nav). */
93
+ sidebar?: boolean;
94
+ /** REPLACE — custom zero-state rendered in the message area while the thread is empty (replaces the empty message list only; the composer and its suggestions still render). */
95
+ empty?: boolean;
96
+ /** REPLACE — full custom composer in place of the built-in prompt input. The
97
+ * projected content wires its own submit (the data-flow boundary). */
98
+ composer?: boolean;
99
+ /** INJECT — accessory row just above the composer (e.g. extra actions). */
100
+ composerActions?: boolean;
101
+ /** INJECT — footer row below the composer (disclaimers, token meter, …). */
102
+ footer?: boolean;
79
103
  /** Show a Search (Globe) button in the input toolbar; fires a `search` event. */
80
104
  search?: boolean;
81
105
  /** Show a Voice (Mic) button in the input toolbar; fires a `voice` event. */
82
106
  voice?: boolean;
83
- /** Slash commandswhen set, typing `/` in the input opens the command
84
- * palette and fires `kai-slash-select`. Set as a JS property. */
85
- slashCommands?: SlashCommandItem[];
86
- /** Command ids to highlight as active in the palette. */
87
- slashActiveIds?: string[];
88
- /** Single-line palette rows. */
89
- slashCompact?: boolean;
107
+ /** Rich entity triggers each `{ char, kind, items }` opens a caret-anchored
108
+ * menu that inserts an atomic pill (`/` skills, `@` agents/plugins). Set as a
109
+ * JS property; forwarded to the input. */
110
+ triggers?: TriggerDef[];
111
+ /** Default icon per entity kind (kind → image src) for pills/menu items. */
112
+ kindIcons?: Record<string, string>;
90
113
  /** Whether each message's action bar is always visible (`'always'`, default)
91
114
  * or only revealed on hover of that message row (`'hover'`). */
92
115
  actionsReveal?: 'always' | 'hover';
93
116
  // callbacks (the facade maps these to dispatch())
94
117
  onValueChange?: (value: string) => void;
95
118
  onSubmit?: (detail: { value: string; attachments: AttachmentData[] }) => void;
119
+ onAttachmentsChange?: (attachments: AttachmentData[]) => void;
96
120
  onSuggestionClick?: (value: string) => void;
97
121
  onModelChange?: (modelId: string) => void;
98
- onMessageAction?: (detail: { messageId: string; action: string }) => void;
122
+ onMessageAction?: (detail: MessageActionDetail) => void;
99
123
  onSearch?: () => void;
100
124
  onVoice?: () => void;
101
- onSlashSelect?: (command: SlashCommandItem) => void;
125
+ /** Receive the imperative controller once mounted. The kai-chat facade forwards
126
+ * these as element methods (focus/clear/send/scrollToBottom). */
127
+ controllerRef?: (controller: ChatThreadController) => void;
128
+ }
129
+
130
+ /** Imperative handle exposed via `controllerRef` — the input half of the chat's
131
+ * interaction surface, forwarded onto `<kai-chat>` as instance methods. */
132
+ export interface ChatThreadController {
133
+ focus(options?: FocusOptions): void;
134
+ clear(): void;
135
+ send(): void;
136
+ scrollToBottom(behavior?: ScrollBehavior): void;
102
137
  }
103
138
 
104
139
  export function ChatThread(props: ChatThreadProps) {
105
140
  const outer = useChatConfig();
106
141
  const reveal = () => (props.actionsReveal === 'hover' ? 'hover' : 'always');
107
- const [internal, setInternal] = createSignal(props.value ?? '');
142
+ // Feedback (copy + vote) state lives ABOVE the per-message <For>, so streaming
143
+ // re-renders (a fresh `messages` array ref per chunk) don't wipe it.
144
+ // The copy/feedback toasts scope to the chat (this thread's root) so they appear
145
+ // in-chat rather than at the page top.
146
+ let rootEl: HTMLElement | undefined;
147
+ const feedback = createMessageFeedback({
148
+ emit: (detail) => props.onMessageAction?.(detail),
149
+ target: () => rootEl,
150
+ });
151
+ const [internal, setInternal] = createSignal<string | ComposerDoc>(props.value ?? '');
108
152
  const [attachments, setAttachments] = createSignal<AttachmentData[]>([]);
109
- const current = () => props.value ?? internal();
153
+ // A string `value` is controlled; a ComposerDoc `value` is a one-time seed that
154
+ // lives in `internal` so the user's (string) edits replace it without a fight.
155
+ const current = (): string | ComposerDoc =>
156
+ typeof props.value === 'string' ? props.value : internal();
157
+ createEffect(() => {
158
+ const v = props.value;
159
+ if (v != null && typeof v !== 'string') setInternal(v);
160
+ });
110
161
  const handleChange = (v: string) => { setInternal(v); props.onValueChange?.(v); };
111
- const handleSubmit = () => { props.onSubmit?.({ value: current(), attachments: attachments() }); setAttachments([]); };
162
+ // After a send, reset the composer. Clear the internal draft ONLY when the value is
163
+ // uncontrolled (props.value === undefined) — a controlled host owns its own value and
164
+ // clears it itself. This lets the batteries-included hooks (useKaiChat/createKaiChat),
165
+ // whose `bind` does not control `value`, get a clean composer after each submit.
166
+ const afterSubmit = () => { setAttachments([]); if (props.value === undefined) setInternal(''); };
167
+ const handleSubmit = () => { props.onSubmit?.({ value: serializeToText(normalizeValue(current())), attachments: attachments() }); afterSubmit(); };
112
168
  const handleSuggestionClick = (v: string) => {
113
169
  if ((props.suggestionMode ?? 'submit') === 'fill') { handleChange(v); props.onSuggestionClick?.(v); }
114
- else { props.onSubmit?.({ value: v, attachments: attachments() }); setAttachments([]); }
170
+ else { props.onSubmit?.({ value: v, attachments: attachments() }); afterSubmit(); }
115
171
  };
116
172
  const showHeader = () => !!(props.chatTitle || props.models || props.context || props.headerStart || props.headerEnd);
117
173
  // Suggestions are conversation starters: show only on an empty thread unless
@@ -120,128 +176,173 @@ export function ChatThread(props: ChatThreadProps) {
120
176
  props.persistSuggestions || props.messages.length === 0 ? props.suggestions : undefined;
121
177
  const showScrollButton = () => props.scrollButton !== false;
122
178
 
179
+ // Hand the imperative controller to the facade once mounted (rootEl is set).
180
+ onMount(() => {
181
+ props.controllerRef?.({
182
+ focus: (options) =>
183
+ rootEl
184
+ ?.querySelector<HTMLElement>('[contenteditable]:not([contenteditable="false"]), textarea')
185
+ ?.focus(options),
186
+ clear: () => { setInternal(''); setAttachments([]); props.onValueChange?.(''); },
187
+ send: () => handleSubmit(),
188
+ scrollToBottom: (behavior) => {
189
+ const vp = rootEl?.querySelector<HTMLElement>('.overflow-y-auto');
190
+ vp?.scrollTo({ top: vp.scrollHeight, behavior: behavior ?? 'smooth' });
191
+ },
192
+ });
193
+ });
194
+
123
195
  return (
124
196
  <ChatConfig proseSize={props.proseSize} codeTheme={props.codeTheme} codeHighlight={props.codeHighlight !== false} portalMount={outer.portalMount()}>
125
- <div class={`flex h-full flex-col bg-background ${props.class ?? ''}`}>
126
- <Show when={showHeader()}>
127
- <header class="flex h-14 shrink-0 items-center justify-between border-b border-border px-5">
128
- <div class="flex items-center gap-2">
129
- {/* Consumer-injected leading controls (sidebar-toggle, compose, a
130
- popover title-button). Projects light-DOM `slot="header-start"`
131
- children of <kai-chat>; inert outside a shadow root. */}
132
- <slot name="header-start" />
133
- <Show when={props.chatTitle}>
134
- <div class="text-sm font-semibold text-foreground">{props.chatTitle}</div>
135
- </Show>
136
- </div>
137
- <div class="flex items-center gap-2">
138
- <Show when={props.models}>
139
- <ModelSwitcher
140
- models={props.models!}
141
- currentModelId={props.currentModel ?? props.models![0]?.id ?? ''}
142
- onModelChange={(modelId) => props.onModelChange?.(modelId)}
143
- />
144
- </Show>
145
- <Show when={props.context}>
146
- <Context
147
- usedTokens={props.context!.usedTokens} maxTokens={props.context!.maxTokens}
148
- inputTokens={props.context!.inputTokens} outputTokens={props.context!.outputTokens}
149
- estimatedCost={props.context!.estimatedCost}
150
- >
151
- <ContextTrigger />
152
- <ContextContent>
153
- <ContextContentHeader />
154
- <ContextContentBody><div class="space-y-1.5"><ContextInputUsage /><ContextOutputUsage /></div></ContextContentBody>
155
- <ContextContentFooter />
156
- </ContextContent>
157
- </Context>
158
- </Show>
159
- {/* Consumer-injected trailing controls (share, settings, …).
160
- Projects light-DOM `slot="header-end"` children of <kai-chat>. */}
161
- <slot name="header-end" />
162
- </div>
163
- </header>
197
+ {/* The root is a ROW so a `sidebar` slot can sit beside the main column.
198
+ With no sidebar projected it collapses to the original column. */}
199
+ <div ref={(e) => (rootEl = e as HTMLElement)} class={`flex h-full bg-background ${props.class ?? ''}`}>
200
+ <Show when={props.sidebar}>
201
+ <aside part="sidebar" class="flex w-64 shrink-0 flex-col overflow-hidden border-r border-border">
202
+ <slot name="sidebar" />
203
+ </aside>
164
204
  </Show>
165
- <div class="relative flex-1 overflow-hidden">
166
- <ChatContainer class="h-full px-4 py-3">
167
- <ChatContainerContent class="mx-auto w-full max-w-3xl space-y-4">
168
- <For each={props.messages}>
169
- {(m) => {
170
- const body = (
171
- <>
172
- <Show when={m.reasoning}>
173
- <Reasoning class="mb-2 w-full">
174
- <ReasoningTrigger>{m.reasoning!.label ?? 'Reasoning'}</ReasoningTrigger>
175
- <ReasoningContent markdown>{m.reasoning!.text}</ReasoningContent>
176
- </Reasoning>
177
- </Show>
178
- <For each={m.tools ?? []}>{(tp) => <Tool toolPart={tp} class="mb-2 w-full" />}</For>
179
- <Show when={m.attachments?.length}>
180
- <Attachments variant="inline" class={m.role === 'user' ? 'mb-2 justify-end' : 'mb-2'}>
181
- <For each={m.attachments!}>
182
- {(att) => (<Attachment data={att}><AttachmentPreview /><AttachmentInfo /></Attachment>)}
183
- </For>
184
- </Attachments>
185
- </Show>
186
- <MessageContent
205
+ <div class="flex h-full min-w-0 flex-1 flex-col">
206
+ {/* Header: a full `header` slot REPLACES the built-in bar; otherwise the
207
+ built-in header renders, itself carrying the header-start/header-end
208
+ INJECT slots. */}
209
+ <Show
210
+ when={props.headerFull}
211
+ fallback={
212
+ <Show when={showHeader()}>
213
+ <header part="header-bar" class="flex h-14 shrink-0 items-center justify-between border-b border-border px-5">
214
+ <div class="flex items-center gap-2">
215
+ {/* Consumer-injected leading controls (sidebar-toggle, compose, a
216
+ popover title-button). Projects light-DOM `slot="header-start"`
217
+ children of <kai-chat>; inert outside a shadow root. */}
218
+ <slot name="header-start" />
219
+ <Show when={props.chatTitle}>
220
+ <div class="text-sm font-semibold text-foreground">{props.chatTitle}</div>
221
+ </Show>
222
+ </div>
223
+ <div class="flex items-center gap-2">
224
+ <Show when={props.models}>
225
+ <ModelSwitcher
226
+ models={props.models!}
227
+ currentModelId={props.currentModel ?? props.models![0]?.id ?? ''}
228
+ onModelChange={(modelId) => props.onModelChange?.(modelId)}
229
+ />
230
+ </Show>
231
+ <Show when={props.context}>
232
+ <Context
233
+ usedTokens={props.context!.usedTokens} maxTokens={props.context!.maxTokens}
234
+ inputTokens={props.context!.inputTokens} outputTokens={props.context!.outputTokens}
235
+ estimatedCost={props.context!.estimatedCost}
236
+ >
237
+ <ContextTrigger />
238
+ <ContextContent>
239
+ <ContextContentHeader />
240
+ <ContextContentBody><div class="space-y-1.5"><ContextInputUsage /><ContextOutputUsage /></div></ContextContentBody>
241
+ <ContextContentFooter />
242
+ </ContextContent>
243
+ </Context>
244
+ </Show>
245
+ {/* Consumer-injected trailing controls (share, settings, …).
246
+ Projects light-DOM `slot="header-end"` children of <kai-chat>. */}
247
+ <slot name="header-end" />
248
+ </div>
249
+ </header>
250
+ </Show>
251
+ }
252
+ >
253
+ <header part="header" class="shrink-0"><slot name="header" /></header>
254
+ </Show>
255
+ <div class="relative flex-1 overflow-hidden">
256
+ <ChatContainer class="h-full px-4 py-3">
257
+ <ChatContainerContent class="mx-auto w-full max-w-3xl space-y-4">
258
+ {/* REPLACE — custom empty-state slot, shown only while the thread is
259
+ empty. The component still owns WHEN it shows (data state); the
260
+ consumer owns WHAT it looks like. */}
261
+ <Show when={props.empty && props.messages.length === 0}>
262
+ <slot name="empty" />
263
+ </Show>
264
+ <For each={props.messages}>
265
+ {(m) => {
266
+ const body = (
267
+ <MessageBody
268
+ content={m.content}
269
+ reasoning={m.reasoning}
270
+ tools={m.tools}
271
+ attachments={m.attachments}
272
+ isUser={m.role === 'user'}
187
273
  markdown={m.role === 'assistant'}
188
- class={m.role === 'user' ? 'bg-muted text-primary max-w-[85%] rounded-2xl px-4 py-2' : 'bg-transparent p-0'}
274
+ actions={m.actions}
275
+ actionsReveal={reveal()}
276
+ activeFeedback={feedback.resolveFeedback(m)}
277
+ copied={feedback.isCopied(m.id)}
278
+ onAction={(action) => feedback.handleAction(m, action)}
279
+ />
280
+ );
281
+ const rowGroup = reveal() === 'hover' ? 'group ' : '';
282
+ return (
283
+ <Show
284
+ when={m.avatar}
285
+ fallback={
286
+ <Message class={`${rowGroup}${m.role === 'user' ? 'flex-col items-end' : 'flex-col items-start'}`}>
287
+ {body}
288
+ </Message>
289
+ }
189
290
  >
190
- {m.content}
191
- </MessageContent>
192
- <Show when={m.actions?.length}>
193
- <MessageActionBar
194
- actions={m.actions!}
195
- reveal={reveal()}
196
- onAction={(action) => props.onMessageAction?.({ messageId: m.id, action })}
197
- />
291
+ {(av) => (
292
+ <Message class={rowGroup}>
293
+ <MessageAvatar src={av().src ?? ''} alt={av().alt ?? ''} fallback={av().fallback} />
294
+ <div class={`flex min-w-0 flex-1 flex-col ${m.role === 'user' ? 'items-end' : 'items-start'}`}>
295
+ {body}
296
+ </div>
297
+ </Message>
298
+ )}
198
299
  </Show>
199
- </>
200
- );
201
- const rowGroup = reveal() === 'hover' ? 'group ' : '';
202
- return (
203
- <Show
204
- when={m.avatar}
205
- fallback={
206
- <Message class={`${rowGroup}${m.role === 'user' ? 'flex-col items-end' : 'flex-col items-start'}`}>
207
- {body}
208
- </Message>
209
- }
210
- >
211
- {(av) => (
212
- <Message class={rowGroup}>
213
- <MessageAvatar src={av().src ?? ''} alt={av().alt ?? ''} fallback={av().fallback} />
214
- <div class={`flex min-w-0 flex-1 flex-col ${m.role === 'user' ? 'items-end' : 'items-start'}`}>
215
- {body}
216
- </div>
217
- </Message>
218
- )}
219
- </Show>
220
- );
221
- }}
222
- </For>
223
- <ChatContainerScrollAnchor />
224
- </ChatContainerContent>
225
- <Show when={showScrollButton()}>
226
- <div class="absolute bottom-4 left-1/2 flex w-full max-w-3xl -translate-x-1/2 justify-center px-5">
227
- <ScrollButton class="shadow-sm" />
228
- </div>
229
- </Show>
230
- </ChatContainer>
231
- </div>
232
- <div class="shrink-0 px-4 pb-4">
233
- <div class="mx-auto max-w-3xl">
234
- <DefaultPromptInput
235
- value={current()} placeholder={props.placeholder} loading={props.loading === true}
236
- suggestions={visibleSuggestions()} attachments={attachments()}
237
- search={props.search === true} voice={props.voice === true}
238
- slashCommands={props.slashCommands} slashActiveIds={props.slashActiveIds} slashCompact={props.slashCompact === true}
239
- onValueChange={handleChange} onSubmit={handleSubmit} onSuggestionClick={handleSuggestionClick}
240
- onAttachmentsChange={setAttachments}
241
- onSearch={() => props.onSearch?.()} onVoice={() => props.onVoice?.()}
242
- onSlashSelect={(command) => props.onSlashSelect?.(command)}
243
- />
300
+ );
301
+ }}
302
+ </For>
303
+ <ChatContainerScrollAnchor />
304
+ </ChatContainerContent>
305
+ <Show when={showScrollButton()}>
306
+ <div class="absolute bottom-4 left-1/2 flex w-full max-w-3xl -translate-x-1/2 justify-center px-5">
307
+ <ScrollButton class="shadow-sm" />
308
+ </div>
309
+ </Show>
310
+ </ChatContainer>
311
+ </div>
312
+ {/* INJECT — accessory row above the composer (extra actions/toolbar). */}
313
+ <Show when={props.composerActions}>
314
+ <div class="shrink-0 px-4">
315
+ <div class="mx-auto flex max-w-3xl items-center gap-2 pb-2"><slot name="composer-actions" /></div>
316
+ </div>
317
+ </Show>
318
+ <div class="shrink-0 px-4 pb-4">
319
+ <div class="mx-auto max-w-3xl">
320
+ {/* REPLACE — a full `composer` slot stands in for the built-in input.
321
+ The slotted content owns its own submit/loading wiring. */}
322
+ <Show
323
+ when={props.composer}
324
+ fallback={
325
+ <DefaultPromptInput
326
+ value={current()} placeholder={props.placeholder} loading={props.loading === true}
327
+ suggestions={visibleSuggestions()} attachments={attachments()}
328
+ search={props.search === true} voice={props.voice === true}
329
+ triggers={props.triggers} kindIcons={props.kindIcons}
330
+ onValueChange={handleChange} onSubmit={handleSubmit} onSuggestionClick={handleSuggestionClick}
331
+ onAttachmentsChange={(a) => { setAttachments(a); props.onAttachmentsChange?.(a); }}
332
+ onSearch={() => props.onSearch?.()} onVoice={() => props.onVoice?.()}
333
+ />
334
+ }
335
+ >
336
+ <slot name="composer" />
337
+ </Show>
338
+ </div>
244
339
  </div>
340
+ {/* INJECT — footer row below the composer. */}
341
+ <Show when={props.footer}>
342
+ <div part="footer" class="shrink-0 px-4 pb-3">
343
+ <div class="mx-auto max-w-3xl text-center text-xs text-muted-foreground"><slot name="footer" /></div>
344
+ </div>
345
+ </Show>
245
346
  </div>
246
347
  </div>
247
348
  </ChatConfig>