@kitn.ai/ui 0.17.0 → 0.18.1

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 (494) hide show
  1. package/README.md +28 -5
  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 +37 -12
  9. package/dist/components/choice-card.d.ts +26 -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/file-tree.d.ts +15 -0
  19. package/dist/components/form.d.ts +34 -0
  20. package/dist/components/markdown.d.ts +3 -0
  21. package/dist/components/message.d.ts +12 -0
  22. package/dist/components/model-switcher.d.ts +7 -0
  23. package/dist/components/prompt-input.d.ts +13 -4
  24. package/dist/components/prompt-suggestion.d.ts +9 -1
  25. package/dist/components/reasoning.d.ts +14 -1
  26. package/dist/components/response-compare.d.ts +14 -0
  27. package/dist/components/screen.d.ts +46 -0
  28. package/dist/components/tasks-card.d.ts +49 -1
  29. package/dist/components/toast.d.ts +12 -2
  30. package/dist/components/tool-types.d.ts +10 -0
  31. package/dist/components/tool.d.ts +8 -8
  32. package/dist/components/voice-input.d.ts +27 -0
  33. package/dist/components/voice-output.d.ts +33 -0
  34. package/dist/core-C8fzo39E.js +12 -0
  35. package/dist/custom-elements.json +8392 -1860
  36. package/dist/elements/agent-card.d.ts +1 -0
  37. package/dist/elements/agent-card.js +1 -0
  38. package/dist/elements/artifact.js +1 -1
  39. package/dist/elements/attachments.js +1 -1
  40. package/dist/elements/autoloader.js +1 -1
  41. package/dist/elements/avatar.d.ts +1 -0
  42. package/dist/elements/avatar.js +1 -0
  43. package/dist/elements/badge.d.ts +1 -0
  44. package/dist/elements/badge.js +1 -0
  45. package/dist/elements/button.d.ts +1 -0
  46. package/dist/elements/button.js +1 -0
  47. package/dist/elements/card.js +1 -1
  48. package/dist/elements/cards.js +1 -1
  49. package/dist/elements/chain-of-thought.js +1 -1
  50. package/dist/elements/chat-scope-picker.js +1 -1
  51. package/dist/elements/chat-types.d.ts +47 -0
  52. package/dist/elements/chat-workspace.js +1 -1
  53. package/dist/elements/chat.js +1 -1
  54. package/dist/elements/checkpoint.js +1 -1
  55. package/dist/elements/choice.js +1 -1
  56. package/dist/elements/chunks/Icon-C2LTALdM.js +1 -0
  57. package/dist/elements/chunks/action-icons-Dtl8Ox5D.js +1 -0
  58. package/dist/elements/chunks/arrow-left-GbBceGBE.js +1 -0
  59. package/dist/elements/chunks/attachments-DLJcWCDV.js +1 -0
  60. package/dist/elements/chunks/badge-BTNZTODL.js +1 -0
  61. package/dist/elements/chunks/button-DBDZebGr.js +1 -0
  62. package/dist/elements/chunks/card-YfCyI4fH.js +1 -0
  63. package/dist/elements/chunks/chat-thread-Dz2qbzvI.js +1 -0
  64. package/dist/elements/chunks/check-fhmRksq_.js +1 -0
  65. package/dist/elements/chunks/chevron-down-DcRg1aRU.js +1 -0
  66. package/dist/elements/chunks/chevron-right-ChzBcNJ-.js +1 -0
  67. package/dist/elements/chunks/circle-B4fTe9v6.js +1 -0
  68. package/dist/elements/chunks/circle-check-CJV-3Rem.js +1 -0
  69. package/dist/elements/chunks/circle-x-pDtzlghQ.js +1 -0
  70. package/dist/elements/chunks/cn-CU7UAWzk.js +1 -0
  71. package/dist/elements/chunks/code-block-DZ6mz6vs.js +1 -0
  72. package/dist/elements/chunks/collapsible-CWUAShMC.js +1 -0
  73. package/dist/elements/chunks/composer-BZyPU6gD.js +65 -0
  74. package/dist/elements/chunks/context-Cx6eQA_G.js +1 -0
  75. package/dist/elements/chunks/conversation-list-C4xTQSpT.js +1 -0
  76. package/dist/elements/chunks/default-input-BZcwyKcP.js +1 -0
  77. package/dist/elements/chunks/define-CNSKFZCd.js +1 -0
  78. package/dist/elements/chunks/disclosure-BcBs--Jf.js +1 -0
  79. package/dist/elements/chunks/download-BDQwcFav.js +1 -0
  80. package/dist/elements/chunks/dropdown-wgs8xCJZ.js +1 -0
  81. package/dist/elements/chunks/ellipsis-CUiEJ6R1.js +1 -0
  82. package/dist/elements/chunks/external-link-DJUmC7g2.js +1 -0
  83. package/dist/elements/chunks/file-text-DOYfYvrh.js +1 -0
  84. package/dist/elements/chunks/file-tree-DQzNQrbr.js +1 -0
  85. package/dist/elements/chunks/folder-DBDUBANz.js +1 -0
  86. package/dist/elements/chunks/hover-card-BQGdGAQ3.js +1 -0
  87. package/dist/elements/chunks/icon-CAyRqVrg.js +1 -0
  88. package/dist/elements/chunks/{index-CTBEJeo6.js → index-BCRhi84a.js} +1 -1
  89. package/dist/elements/chunks/info-DBQl-m6e.js +1 -0
  90. package/dist/elements/chunks/input-DZD67EvW.js +1 -0
  91. package/dist/elements/chunks/kbd-DbyVrlnU.js +1 -0
  92. package/dist/elements/chunks/link-vko7AttA.js +1 -0
  93. package/dist/elements/chunks/loader-Cg6rO8tQ.js +1 -0
  94. package/dist/elements/chunks/{markdown-CMTGx9r8.js → markdown-n3Xbj3PR.js} +9 -9
  95. package/dist/elements/chunks/message-CgKytiSB.js +1 -0
  96. package/dist/elements/chunks/message-feedback-Ds3-US0e.js +1 -0
  97. package/dist/elements/chunks/message-square-MmRkvc-M.js +1 -0
  98. package/dist/elements/chunks/minimize-2-3kCdE0q3.js +1 -0
  99. package/dist/elements/chunks/model-switcher-BMtXGwLU.js +1 -0
  100. package/dist/elements/chunks/overlay-B1-MBI6h.js +1 -0
  101. package/dist/elements/chunks/paperclip-DDEfmkHc.js +1 -0
  102. package/dist/elements/chunks/progress-bar-Dwbiyv3s.js +1 -0
  103. package/dist/elements/chunks/prompt-suggestion-9lvgFcEa.js +1 -0
  104. package/dist/elements/chunks/reasoning-DzHWsdAJ.js +1 -0
  105. package/dist/elements/chunks/resizable-Bq_eHxUm.js +1 -0
  106. package/dist/elements/chunks/rotate-cw-jpisOdOV.js +1 -0
  107. package/dist/elements/chunks/scroll-area-g5Ze3K6f.js +1 -0
  108. package/dist/elements/chunks/separator-Bmjc5XyX.js +1 -0
  109. package/dist/elements/chunks/settings-Cz1bMJP9.js +1 -0
  110. package/dist/elements/chunks/settings-group-9imY3kRA.js +1 -0
  111. package/dist/elements/chunks/share-BdenF0wQ.js +1 -0
  112. package/dist/elements/chunks/skeleton-Pjc5jiaY.js +1 -0
  113. package/dist/elements/chunks/slots-DkZ-Cmha.js +1 -0
  114. package/dist/elements/chunks/star-DY6z1UUH.js +1 -0
  115. package/dist/elements/chunks/store-th4VyJXM.js +1 -0
  116. package/dist/elements/chunks/text-shimmer-CEi-tlXr.js +1 -0
  117. package/dist/elements/chunks/textarea-CboigarR.js +1 -0
  118. package/dist/elements/chunks/thumbs-up-BR33KLfA.js +1 -0
  119. package/dist/elements/chunks/toast-store-BEMda0fv.js +1 -0
  120. package/dist/elements/chunks/tool-TMued3WO.js +1 -0
  121. package/dist/elements/chunks/tooltip-Cft_Rxiw.js +1 -0
  122. package/dist/elements/chunks/triangle-alert-B07fX3Q8.js +1 -0
  123. package/dist/elements/chunks/use-card-resolution-M36zVciB.js +1 -0
  124. package/dist/elements/chunks/video-MKp3LmNT.js +1 -0
  125. package/dist/elements/chunks/x-Ckwicf6g.js +1 -0
  126. package/dist/elements/coachmark.d.ts +1 -0
  127. package/dist/elements/coachmark.js +1 -0
  128. package/dist/elements/code-block.js +1 -1
  129. package/dist/elements/command.d.ts +1 -0
  130. package/dist/elements/command.js +1 -0
  131. package/dist/elements/compare.js +1 -1
  132. package/dist/elements/composer.d.ts +1 -0
  133. package/dist/elements/composer.js +1 -0
  134. package/dist/elements/confirm-card.js +1 -1
  135. package/dist/elements/context-meter.js +1 -1
  136. package/dist/elements/conversation-list.js +1 -1
  137. package/dist/elements/css.d.ts +1 -0
  138. package/dist/elements/default-input.d.ts +51 -0
  139. package/dist/elements/define.d.ts +53 -0
  140. package/dist/elements/dialog.d.ts +1 -0
  141. package/dist/elements/dialog.js +1 -0
  142. package/dist/elements/disclosure.d.ts +37 -0
  143. package/dist/elements/editable-label.d.ts +1 -0
  144. package/dist/elements/editable-label.js +1 -0
  145. package/dist/elements/embed.js +1 -1
  146. package/dist/elements/empty.js +1 -1
  147. package/dist/elements/feedback-bar.js +1 -1
  148. package/dist/elements/file-tree.js +1 -1
  149. package/dist/elements/file-upload.js +1 -1
  150. package/dist/elements/form.js +1 -1
  151. package/dist/elements/hover-card.d.ts +1 -0
  152. package/dist/elements/hover-card.js +1 -0
  153. package/dist/elements/icon.d.ts +1 -0
  154. package/dist/elements/icon.js +1 -0
  155. package/dist/elements/image.js +1 -1
  156. package/dist/elements/input.d.ts +1 -0
  157. package/dist/elements/input.js +1 -0
  158. package/dist/elements/kbd.d.ts +1 -0
  159. package/dist/elements/kbd.js +1 -0
  160. package/dist/elements/link-preview.js +1 -1
  161. package/dist/elements/loader.js +1 -1
  162. package/dist/elements/markdown.js +1 -1
  163. package/dist/elements/menu.d.ts +1 -0
  164. package/dist/elements/menu.js +1 -0
  165. package/dist/elements/message-skills.js +1 -1
  166. package/dist/elements/message.js +1 -1
  167. package/dist/elements/model-switcher.js +1 -1
  168. package/dist/elements/nav.d.ts +1 -0
  169. package/dist/elements/nav.js +1 -0
  170. package/dist/elements/notice.d.ts +1 -0
  171. package/dist/elements/notice.js +1 -0
  172. package/dist/elements/pane-group.d.ts +1 -0
  173. package/dist/elements/pane-group.js +1 -0
  174. package/dist/elements/pane.d.ts +1 -0
  175. package/dist/elements/pane.js +1 -0
  176. package/dist/elements/popover.js +1 -1
  177. package/dist/elements/progress-bar.d.ts +1 -0
  178. package/dist/elements/progress-bar.js +1 -0
  179. package/dist/elements/prompt-dock.d.ts +1 -0
  180. package/dist/elements/prompt-dock.js +1 -0
  181. package/dist/elements/prompt-input.js +1 -1
  182. package/dist/elements/prompt-suggestions.js +1 -1
  183. package/dist/elements/reasoning.js +1 -1
  184. package/dist/elements/register-impl.d.ts +0 -0
  185. package/dist/elements/register.d.ts +13 -0
  186. package/dist/elements/remote.d.ts +1 -0
  187. package/dist/elements/remote.js +1 -0
  188. package/dist/elements/resizable.js +1 -1
  189. package/dist/elements/response-stream.js +2 -2
  190. package/dist/elements/screen.d.ts +1 -0
  191. package/dist/elements/screen.js +1 -0
  192. package/dist/elements/scroll-area.d.ts +1 -0
  193. package/dist/elements/scroll-area.js +1 -0
  194. package/dist/elements/scroll-button.js +1 -1
  195. package/dist/elements/search.d.ts +1 -0
  196. package/dist/elements/search.js +1 -0
  197. package/dist/elements/segmented.d.ts +1 -0
  198. package/dist/elements/segmented.js +1 -0
  199. package/dist/elements/separator.d.ts +1 -0
  200. package/dist/elements/separator.js +1 -0
  201. package/dist/elements/setting-item.d.ts +1 -0
  202. package/dist/elements/setting-item.js +1 -0
  203. package/dist/elements/settings-group.d.ts +1 -0
  204. package/dist/elements/settings-group.js +1 -0
  205. package/dist/elements/skeleton.d.ts +1 -0
  206. package/dist/elements/skeleton.js +1 -0
  207. package/dist/elements/slots.d.ts +176 -0
  208. package/dist/elements/source.js +1 -1
  209. package/dist/elements/status.d.ts +1 -0
  210. package/dist/elements/status.js +1 -0
  211. package/dist/elements/switch.js +1 -1
  212. package/dist/elements/tabs.d.ts +1 -0
  213. package/dist/elements/tabs.js +1 -0
  214. package/dist/elements/tasks.js +1 -1
  215. package/dist/elements/text-shimmer.js +1 -1
  216. package/dist/elements/thinking-bar.js +1 -1
  217. package/dist/elements/toast.js +1 -1
  218. package/dist/elements/tool.js +1 -1
  219. package/dist/elements/tooltip.d.ts +1 -0
  220. package/dist/elements/tooltip.js +1 -0
  221. package/dist/elements/voice-input.js +1 -1
  222. package/dist/elements/voice-output.d.ts +1 -0
  223. package/dist/elements/voice-output.js +1 -0
  224. package/dist/elements.d.ts +733 -58
  225. package/dist/engine-javascript-C1x7zo1_.js +141 -0
  226. package/dist/index.d.ts +3 -2
  227. package/dist/index.js +8255 -5703
  228. package/dist/kai.es.js +1 -0
  229. package/dist/llms/llms-full.txt +1146 -64
  230. package/dist/llms/llms.txt +4 -4
  231. package/dist/mcp.es.js +62 -7
  232. package/dist/primitives/composer-model.d.ts +22 -0
  233. package/dist/primitives/composer-triggers.d.ts +19 -0
  234. package/dist/primitives/create-kai-chat.d.ts +38 -0
  235. package/dist/primitives/toast-store.d.ts +32 -2
  236. package/dist/primitives/use-speech-recognition.d.ts +26 -0
  237. package/dist/react/index.d.ts +1085 -97
  238. package/dist/react/runtime.d.ts +9 -2
  239. package/dist/react/use-kai-chat.d.ts +41 -0
  240. package/dist/react.js +572 -193
  241. package/dist/register-impl-cKscku5m.js +141 -0
  242. package/dist/schemas/tasks.schema.json +2 -2
  243. package/dist/state/index.d.ts +4 -0
  244. package/dist/state/messages.d.ts +11 -0
  245. package/dist/state/stream.d.ts +22 -0
  246. package/dist/state/suggestions.d.ts +4 -0
  247. package/dist/state.js +117 -0
  248. package/dist/theme.tokens.css +87 -0
  249. package/dist/types.d.ts +4 -0
  250. package/dist/ui/agent-card.d.ts +61 -0
  251. package/dist/ui/button.d.ts +5 -2
  252. package/dist/ui/card.d.ts +61 -0
  253. package/dist/ui/collapsible.d.ts +15 -1
  254. package/dist/ui/command.d.ts +33 -0
  255. package/dist/ui/dialog.d.ts +42 -0
  256. package/dist/ui/dropdown.d.ts +95 -1
  257. package/dist/ui/editable-label.d.ts +26 -0
  258. package/dist/ui/hover-card.d.ts +13 -1
  259. package/dist/ui/icon.d.ts +18 -0
  260. package/dist/ui/input.d.ts +33 -0
  261. package/dist/ui/kbd.d.ts +21 -0
  262. package/dist/ui/nav.d.ts +62 -0
  263. package/dist/ui/notice.d.ts +31 -0
  264. package/dist/ui/overlay.d.ts +12 -0
  265. package/dist/ui/pane-grid.d.ts +58 -0
  266. package/dist/ui/pane-group.d.ts +77 -0
  267. package/dist/ui/pane.d.ts +78 -0
  268. package/dist/ui/popover.d.ts +11 -1
  269. package/dist/ui/progress-bar.d.ts +23 -0
  270. package/dist/ui/prompt-dock.d.ts +96 -0
  271. package/dist/ui/resizable.d.ts +12 -0
  272. package/dist/ui/scroll-area.d.ts +4 -0
  273. package/dist/ui/segmented.d.ts +28 -0
  274. package/dist/ui/settings-group.d.ts +32 -0
  275. package/dist/ui/skeleton.d.ts +12 -0
  276. package/dist/ui/stat.d.ts +16 -0
  277. package/dist/ui/status.d.ts +13 -0
  278. package/dist/ui/switch.d.ts +8 -1
  279. package/dist/ui/tabs.d.ts +35 -0
  280. package/dist/ui/tooltip.d.ts +19 -1
  281. package/frameworks/react/index.tsx +1042 -157
  282. package/frameworks/react/runtime.tsx +30 -1
  283. package/frameworks/react/use-kai-chat.tsx +87 -0
  284. package/llms-full.txt +1146 -64
  285. package/llms.txt +4 -4
  286. package/package.json +31 -10
  287. package/src/agent-tooling/mcp/manifest.ts +14 -0
  288. package/src/agent-tooling/mcp/tools/debug.ts +11 -7
  289. package/src/agent-tooling/mcp/tools/reference.ts +32 -0
  290. package/src/agent-tooling/mcp/tools/scaffold.ts +30 -1
  291. package/src/components/artifact.tsx +98 -13
  292. package/src/components/attachment-types.ts +13 -0
  293. package/src/components/attachments.tsx +4 -14
  294. package/src/components/card.tsx +109 -15
  295. package/src/components/chain-of-thought.tsx +210 -1
  296. package/src/components/chat-scope-picker.tsx +13 -3
  297. package/src/components/chat-thread.tsx +225 -116
  298. package/src/components/choice-card.tsx +103 -11
  299. package/src/components/coachmark.tsx +249 -0
  300. package/src/components/component-meta.json +699 -110
  301. package/src/components/composer-dom.ts +159 -0
  302. package/src/components/composer-highlight.ts +242 -0
  303. package/src/components/composer-history.ts +82 -0
  304. package/src/components/composer.tsx +979 -0
  305. package/src/components/confirm-card.tsx +54 -1
  306. package/src/components/conversation-item.tsx +69 -7
  307. package/src/components/conversation-list.tsx +134 -37
  308. package/src/components/file-tree.tsx +197 -47
  309. package/src/components/form-widgets.tsx +9 -7
  310. package/src/components/form.tsx +140 -17
  311. package/src/components/image.tsx +3 -5
  312. package/src/components/link-preview.tsx +5 -4
  313. package/src/components/markdown.tsx +5 -2
  314. package/src/components/message.tsx +23 -4
  315. package/src/components/model-switcher.tsx +19 -4
  316. package/src/components/prompt-input.tsx +46 -75
  317. package/src/components/prompt-suggestion.tsx +48 -16
  318. package/src/components/reasoning.tsx +29 -6
  319. package/src/components/response-compare.tsx +31 -2
  320. package/src/components/screen.tsx +176 -0
  321. package/src/components/tasks-card.tsx +341 -21
  322. package/src/components/toast.tsx +119 -31
  323. package/src/components/tool-types.ts +10 -0
  324. package/src/components/tool.tsx +22 -16
  325. package/src/components/voice-input.tsx +102 -19
  326. package/src/components/voice-output.tsx +202 -0
  327. package/src/elements/agent-card.tsx +67 -0
  328. package/src/elements/artifact.tsx +53 -4
  329. package/src/elements/attachments.tsx +1 -0
  330. package/src/elements/avatar.tsx +33 -0
  331. package/src/elements/badge.tsx +32 -0
  332. package/src/elements/button.tsx +126 -0
  333. package/src/elements/card-media.jpg +0 -0
  334. package/src/elements/card.tsx +124 -31
  335. package/src/elements/cards.tsx +81 -7
  336. package/src/elements/chain-of-thought.tsx +77 -32
  337. package/src/elements/chat-scope-picker.tsx +35 -8
  338. package/src/elements/chat-types.ts +2 -2
  339. package/src/elements/chat-workspace.tsx +153 -41
  340. package/src/elements/chat.tsx +45 -23
  341. package/src/elements/choice.tsx +71 -19
  342. package/src/elements/coachmark.tsx +90 -0
  343. package/src/elements/command.tsx +209 -0
  344. package/src/elements/compare.tsx +24 -2
  345. package/src/elements/compiled.css +2 -2
  346. package/src/elements/composer.tsx +151 -0
  347. package/src/elements/confirm-card.tsx +36 -11
  348. package/src/elements/conversation-list.tsx +80 -11
  349. package/src/elements/default-input.tsx +75 -53
  350. package/src/elements/define.tsx +87 -7
  351. package/src/elements/dialog.tsx +98 -0
  352. package/src/elements/disclosure.ts +73 -0
  353. package/src/elements/editable-label.tsx +125 -0
  354. package/src/elements/element-manifest.json +129 -1
  355. package/src/elements/element-meta.json +5562 -1336
  356. package/src/elements/element-types.d.ts +732 -57
  357. package/src/elements/file-tree.tsx +12 -2
  358. package/src/elements/file-upload.tsx +1 -1
  359. package/src/elements/form.tsx +54 -11
  360. package/src/elements/hover-card.tsx +80 -0
  361. package/src/elements/icon-names.json +48 -0
  362. package/src/elements/icon.tsx +41 -0
  363. package/src/elements/input.tsx +203 -0
  364. package/src/elements/kbd.tsx +45 -0
  365. package/src/elements/menu.tsx +217 -0
  366. package/src/elements/message.tsx +58 -11
  367. package/src/elements/model-switcher.tsx +27 -1
  368. package/src/elements/nav.tsx +87 -0
  369. package/src/elements/notice.tsx +53 -0
  370. package/src/elements/pane-group.tsx +119 -0
  371. package/src/elements/pane.tsx +129 -0
  372. package/src/elements/popover.tsx +39 -17
  373. package/src/elements/progress-bar.tsx +39 -0
  374. package/src/elements/prompt-dock.tsx +81 -0
  375. package/src/elements/prompt-input.tsx +112 -63
  376. package/src/elements/prompt-suggestions.tsx +25 -9
  377. package/src/elements/reasoning.tsx +30 -9
  378. package/src/elements/register-impl.ts +38 -3
  379. package/src/elements/register.ts +11 -3
  380. package/src/elements/resizable.tsx +48 -11
  381. package/src/elements/screen.tsx +90 -0
  382. package/src/elements/scroll-area.tsx +33 -0
  383. package/src/elements/search.tsx +180 -0
  384. package/src/elements/segmented.tsx +135 -0
  385. package/src/elements/separator.tsx +36 -0
  386. package/src/elements/setting-item.tsx +50 -0
  387. package/src/elements/settings-group.tsx +37 -0
  388. package/src/elements/skeleton.tsx +45 -0
  389. package/src/elements/slots.ts +607 -0
  390. package/src/elements/source.tsx +13 -6
  391. package/src/elements/status.tsx +42 -0
  392. package/src/elements/switch.tsx +89 -14
  393. package/src/elements/tabs.tsx +95 -0
  394. package/src/elements/tasks.tsx +70 -14
  395. package/src/elements/toast.tsx +17 -2
  396. package/src/elements/tool.tsx +43 -9
  397. package/src/elements/tooltip.tsx +85 -0
  398. package/src/elements/video-poster.jpg +0 -0
  399. package/src/elements/voice-input.tsx +66 -16
  400. package/src/elements/voice-output.tsx +69 -0
  401. package/src/index.ts +5 -2
  402. package/src/primitives/card-schemas/tasks.schema.json +2 -2
  403. package/src/primitives/composer-model.ts +49 -0
  404. package/src/primitives/composer-triggers.ts +35 -0
  405. package/src/primitives/create-kai-chat.ts +66 -0
  406. package/src/primitives/toast-store.ts +43 -2
  407. package/src/primitives/use-speech-recognition.ts +135 -0
  408. package/src/state/index.ts +6 -0
  409. package/src/state/messages.ts +36 -0
  410. package/src/state/stream.ts +92 -0
  411. package/src/state/suggestions.ts +9 -0
  412. package/src/types.ts +4 -0
  413. package/src/ui/agent-card.tsx +218 -0
  414. package/src/ui/button.tsx +16 -5
  415. package/src/ui/card.tsx +245 -0
  416. package/src/ui/collapsible.tsx +30 -4
  417. package/src/ui/command.tsx +99 -0
  418. package/src/ui/dialog.tsx +217 -0
  419. package/src/ui/dropdown.tsx +375 -13
  420. package/src/ui/editable-label.tsx +112 -0
  421. package/src/ui/hover-card.tsx +28 -5
  422. package/src/ui/icon.tsx +110 -0
  423. package/src/ui/input.tsx +132 -0
  424. package/src/ui/kbd.tsx +118 -0
  425. package/src/ui/nav.tsx +282 -0
  426. package/src/ui/notice.tsx +84 -0
  427. package/src/ui/overlay.tsx +108 -2
  428. package/src/ui/pane-grid.tsx +117 -0
  429. package/src/ui/pane-group.tsx +291 -0
  430. package/src/ui/pane.tsx +193 -0
  431. package/src/ui/popover.tsx +16 -2
  432. package/src/ui/progress-bar.tsx +83 -0
  433. package/src/ui/prompt-dock.tsx +145 -0
  434. package/src/ui/resizable.tsx +69 -1
  435. package/src/ui/scroll-area.tsx +14 -3
  436. package/src/ui/segmented.tsx +109 -0
  437. package/src/ui/settings-group.tsx +67 -0
  438. package/src/ui/skeleton.tsx +62 -5
  439. package/src/ui/stat.tsx +41 -0
  440. package/src/ui/status.tsx +48 -0
  441. package/src/ui/switch.tsx +49 -23
  442. package/src/ui/tabs.tsx +168 -0
  443. package/src/ui/tooltip.tsx +52 -8
  444. package/theme.css +113 -0
  445. package/dist/components/slash-command.d.ts +0 -15
  446. package/dist/elements/chunks/Icon-D_Zmwmwh.js +0 -1
  447. package/dist/elements/chunks/action-icons-PVfIvcuG.js +0 -1
  448. package/dist/elements/chunks/attachments-Dp6vqtrc.js +0 -1
  449. package/dist/elements/chunks/button-CKyYD9G4.js +0 -1
  450. package/dist/elements/chunks/card-Cjho-PYk.js +0 -1
  451. package/dist/elements/chunks/chat-thread-RT808iPf.js +0 -1
  452. package/dist/elements/chunks/check-CDYaMYrM.js +0 -1
  453. package/dist/elements/chunks/chevron-down-3SBiq8HF.js +0 -1
  454. package/dist/elements/chunks/chevron-right-k2UFlIVK.js +0 -1
  455. package/dist/elements/chunks/cn-Dogu6PbV.js +0 -1
  456. package/dist/elements/chunks/code-block-BYUmfFSd.js +0 -1
  457. package/dist/elements/chunks/collapsible-BiNwdOn6.js +0 -1
  458. package/dist/elements/chunks/context-18g6oi4J.js +0 -1
  459. package/dist/elements/chunks/conversation-list-D9Y0NVdo.js +0 -1
  460. package/dist/elements/chunks/default-input-CSAoYYMd.js +0 -1
  461. package/dist/elements/chunks/download-D8K0Je8r.js +0 -1
  462. package/dist/elements/chunks/dropdown-bUs2iTia.js +0 -1
  463. package/dist/elements/chunks/external-link-6mA0wxab.js +0 -1
  464. package/dist/elements/chunks/file-text-DnaYk3Dm.js +0 -1
  465. package/dist/elements/chunks/file-tree-CgtRLlxK.js +0 -1
  466. package/dist/elements/chunks/hover-card-CIGw62gP.js +0 -1
  467. package/dist/elements/chunks/link-BlGSeoPy.js +0 -1
  468. package/dist/elements/chunks/loader-DvhR4qa0.js +0 -1
  469. package/dist/elements/chunks/message-CDZwXjhL.js +0 -1
  470. package/dist/elements/chunks/message-feedback-CYx81QiA.js +0 -1
  471. package/dist/elements/chunks/model-switcher-O_tUhoOT.js +0 -1
  472. package/dist/elements/chunks/overlay-DydXYMQW.js +0 -1
  473. package/dist/elements/chunks/prompt-suggestion-ldlWV5kd.js +0 -1
  474. package/dist/elements/chunks/reasoning-2PUnHlmr.js +0 -1
  475. package/dist/elements/chunks/resizable-B5WNbSeb.js +0 -1
  476. package/dist/elements/chunks/star-t9tI-P0q.js +0 -1
  477. package/dist/elements/chunks/store-C6rIooZz.js +0 -1
  478. package/dist/elements/chunks/text-shimmer-uh9V_KUh.js +0 -1
  479. package/dist/elements/chunks/textarea-3nm6Ia9U.js +0 -1
  480. package/dist/elements/chunks/thumbs-up-BBtguGld.js +0 -1
  481. package/dist/elements/chunks/toast-store-D8cL3fWl.js +0 -1
  482. package/dist/elements/chunks/tool-GJ3vwp1U.js +0 -1
  483. package/dist/elements/chunks/tooltip-DwKAz4XR.js +0 -1
  484. package/dist/elements/chunks/triangle-alert-Ct1zt2JL.js +0 -1
  485. package/dist/elements/chunks/use-card-resolution-D-_0Alzy.js +0 -1
  486. package/dist/elements/chunks/video-mVYiM99-.js +0 -1
  487. package/dist/elements/chunks/x-CzxL27Ch.js +0 -1
  488. package/dist/kitn-chat.es.js +0 -1
  489. package/dist/register-JyTglR6m.js +0 -1
  490. package/dist/register-impl-C6wlSsts.js +0 -77
  491. package/src/components/slash-command.tsx +0 -232
  492. package/src/elements/framework-usage.json +0 -588
  493. /package/dist/{kitn-chat-provider.d.ts → kai-provider.d.ts} +0 -0
  494. /package/dist/{kitn-chat-provider.es.js → kai-provider.es.js} +0 -0
@@ -7,6 +7,7 @@ import {
7
7
  createMemo,
8
8
  createEffect,
9
9
  on,
10
+ onMount,
10
11
  ErrorBoundary,
11
12
  } from 'solid-js';
12
13
  import { cn } from '../utils/cn';
@@ -121,6 +122,21 @@ export function defaultActionId(actions: ConfirmAction[]): string | undefined {
121
122
  // The <ConfirmCard> component.
122
123
  // ─────────────────────────────────────────────────────────────────────────────
123
124
 
125
+ /** Imperative handle exposed via `controllerRef` — surfaces the confirm card's
126
+ * latent action/dismiss capabilities so the `<kai-confirm>` facade can forward
127
+ * them as instance methods (focus/confirm/dismiss/reopen). */
128
+ export interface ConfirmController {
129
+ /** Focus the default action button (or the first action if none default). */
130
+ focus(options?: FocusOptions): void;
131
+ /** Activate an action by id (or the default action when omitted) — emits the
132
+ * `action` verb + resolves single-shot. */
133
+ confirm(actionId?: string): void;
134
+ /** Dismiss the card — emits `dismiss` + optimistically collapses to the stub. */
135
+ dismiss(): void;
136
+ /** Re-open a dismissed card from its stub — emits `reopen`. */
137
+ reopen(): void;
138
+ }
139
+
124
140
  export interface ConfirmCardProps {
125
141
  /** The confirm definition (CardEnvelope.data). */
126
142
  data?: ConfirmCardData;
@@ -138,6 +154,9 @@ export interface ConfirmCardProps {
138
154
  class?: string;
139
155
  /** When set, render the chromed read-only view instead of the buttons. */
140
156
  resolution?: CardResolution;
157
+ /** Receive the imperative controller once mounted. The `<kai-confirm>` facade
158
+ * forwards these as element methods (focus/confirm/dismiss/reopen). */
159
+ controllerRef?: (controller: ConfirmController) => void;
141
160
  }
142
161
 
143
162
  /**
@@ -159,6 +178,7 @@ export function ConfirmCard(props: ConfirmCardProps): JSX.Element {
159
178
  'autofocus',
160
179
  'class',
161
180
  'resolution',
181
+ 'controllerRef',
162
182
  ]);
163
183
 
164
184
  const ctxHost = useCardHost();
@@ -220,6 +240,39 @@ export function ConfirmCard(props: ConfirmCardProps): JSX.Element {
220
240
  const onReopen = (): void => emit({ kind: 'reopen', cardId: local.cardId });
221
241
 
222
242
  let bodyRef: HTMLDivElement | undefined;
243
+ let actionsRef: HTMLDivElement | undefined;
244
+
245
+ // The default action button (or the first action button if none is marked
246
+ // default) — the same target the `autofocus` prop focuses on mount.
247
+ const focusTarget = (): HTMLButtonElement | null => {
248
+ if (!actionsRef) return null;
249
+ return (
250
+ actionsRef.querySelector<HTMLButtonElement>('button[data-kai-default="true"]') ??
251
+ actionsRef.querySelector<HTMLButtonElement>('button[data-action-id]')
252
+ );
253
+ };
254
+
255
+ // ── Imperative controller (Pattern C): hand the facade a handle over the
256
+ // card's latent action/dismiss capabilities. Every method drives the SAME
257
+ // internal path the buttons drive, so the same kai-card events fire. ──────────
258
+ onMount(() => {
259
+ local.controllerRef?.({
260
+ // Focus the default (or first) action button on demand.
261
+ focus: (options) => focusTarget()?.focus(options),
262
+ // Activate an action by id (or the default action with no id) — the button path.
263
+ confirm: (actionId) => {
264
+ const list = actions();
265
+ const id = actionId ?? defaultId();
266
+ if (id === undefined) return;
267
+ const action = list.find((a) => a.id === id);
268
+ if (action) onAction(action);
269
+ },
270
+ // Trigger the dismiss path (the X-button path).
271
+ dismiss: () => onDismiss(),
272
+ // Re-open a dismissed card (the stub's affordance path).
273
+ reopen: () => onReopen(),
274
+ });
275
+ });
223
276
 
224
277
  // Surface the resolved action id for host styling.
225
278
  createEffect(() => {
@@ -269,7 +322,7 @@ export function ConfirmCard(props: ConfirmCardProps): JSX.Element {
269
322
  <X size={16} aria-hidden="true" />
270
323
  </Button>
271
324
  </Show>
272
- <div class="ml-auto flex flex-wrap items-center gap-2">
325
+ <div ref={actionsRef} class="ml-auto flex flex-wrap items-center gap-2">
273
326
  <For each={actions()}>
274
327
  {(action) => (
275
328
  <Button
@@ -1,16 +1,78 @@
1
- import { splitProps } from 'solid-js';
1
+ import { Show, splitProps, createMemo } from 'solid-js';
2
+ import { MessageSquare } from 'lucide-solid';
2
3
  import { cn } from '../utils/cn';
3
4
  import type { ConversationSummary } from '../types';
4
5
 
5
- export interface ConversationItemProps { conversation: ConversationSummary; isActive: boolean; onSelect: (id: string) => void; class?: string; }
6
+ export interface ConversationItemProps {
7
+ conversation: ConversationSummary;
8
+ isActive: boolean;
9
+ onSelect: (id: string) => void;
10
+ /** Dense single-line row: a leading dot + title, no message count. */
11
+ compact?: boolean;
12
+ class?: string;
13
+ }
14
+
15
+ /**
16
+ * Short relative time from an ISO date string: "just now", "5m ago", "3h ago",
17
+ * "2d ago", "24d ago". Pure — it snapshots `now` (defaults to `Date.now()`) at
18
+ * call time, so it re-derives whenever the list re-renders; there is no internal
19
+ * ticking clock. Returns '' for a missing or unparseable date.
20
+ */
21
+ export function relativeTimeShort(iso?: string, now: number = Date.now()): string {
22
+ if (!iso) return '';
23
+ const then = Date.parse(iso);
24
+ if (Number.isNaN(then)) return '';
25
+ const secs = Math.max(0, Math.round((now - then) / 1000));
26
+ if (secs < 60) return 'just now';
27
+ const mins = Math.floor(secs / 60);
28
+ if (mins < 60) return `${mins}m ago`;
29
+ const hours = Math.floor(mins / 60);
30
+ if (hours < 24) return `${hours}h ago`;
31
+ return `${Math.floor(hours / 24)}d ago`;
32
+ }
6
33
 
7
34
  export function ConversationItem(props: ConversationItemProps) {
8
- const [local] = splitProps(props, ['conversation', 'isActive', 'onSelect', 'class']);
35
+ const [local] = splitProps(props, ['conversation', 'isActive', 'onSelect', 'compact', 'class']);
36
+ // The trailing text: the consumer's own `trailing` field, else an auto relative
37
+ // time from updatedAt (fallback lastMessageAt). REACTIVITY: this (and the auto
38
+ // time) update when the consumer re-assigns the `conversations` array with a new
39
+ // reference — the kit's standard reactivity model — not via an internal clock.
40
+ const trailing = createMemo(
41
+ () => local.conversation.trailing ?? relativeTimeShort(local.conversation.updatedAt ?? local.conversation.lastMessageAt),
42
+ );
9
43
  return (
10
- <button data-conversation-id={local.conversation.id} onClick={() => local.onSelect(local.conversation.id)}
11
- class={cn('w-full text-left rounded-lg px-2.5 py-2 transition-colors', local.isActive ? 'bg-muted' : 'hover:bg-muted/50', local.class)}>
12
- <div class={cn('truncate text-sm', local.isActive ? 'text-foreground font-medium' : 'text-foreground/80')}>{local.conversation.title}</div>
13
- <div class={cn('truncate mt-0.5 text-xs', local.isActive ? 'text-foreground/70' : 'text-muted-foreground')}>{local.conversation.messageCount} messages</div>
44
+ <button
45
+ data-conversation-id={local.conversation.id}
46
+ onClick={() => local.onSelect(local.conversation.id)}
47
+ class={cn(
48
+ 'w-full rounded-lg text-left transition-colors',
49
+ local.compact ? 'px-2.5 py-1.5' : 'px-2.5 py-2',
50
+ local.isActive ? 'bg-muted' : 'hover:bg-muted/50',
51
+ local.class,
52
+ )}
53
+ >
54
+ <Show
55
+ when={local.compact}
56
+ fallback={
57
+ <>
58
+ <div class="flex items-center gap-2">
59
+ <div class={cn('min-w-0 flex-1 truncate text-sm', local.isActive ? 'font-medium text-foreground' : 'text-foreground/80')}>{local.conversation.title}</div>
60
+ <Show when={trailing()}>
61
+ <span part="trailing" class="ml-auto shrink-0 text-xs text-muted-foreground">{trailing()}</span>
62
+ </Show>
63
+ </div>
64
+ <div class={cn('mt-0.5 truncate text-xs', local.isActive ? 'text-foreground/70' : 'text-muted-foreground')}>{local.conversation.messageCount} messages</div>
65
+ </>
66
+ }
67
+ >
68
+ <div class="flex items-center gap-2.5">
69
+ <MessageSquare class={cn('size-3.5 shrink-0', local.isActive ? 'text-foreground' : 'text-muted-foreground')} />
70
+ <span class={cn('min-w-0 flex-1 truncate text-sm', local.isActive ? 'font-medium text-foreground' : 'text-foreground/80')}>{local.conversation.title}</span>
71
+ <Show when={trailing()}>
72
+ <span part="trailing" class="ml-auto shrink-0 text-xs text-muted-foreground">{trailing()}</span>
73
+ </Show>
74
+ </div>
75
+ </Show>
14
76
  </button>
15
77
  );
16
78
  }
@@ -1,4 +1,5 @@
1
- import { splitProps, For, Show, createSignal, createMemo } from 'solid-js';
1
+ import { splitProps, For, Show, createSignal, createMemo, onMount, type JSX } from 'solid-js';
2
+ import { PanelLeftOpen } from 'lucide-solid';
2
3
  import { cn } from '../utils/cn';
3
4
  import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '../ui/collapsible';
4
5
  import { Button } from '../ui/button';
@@ -7,6 +8,26 @@ import { ScrollArea } from '../ui/scroll-area';
7
8
  import { ConversationItem } from './conversation-item';
8
9
  import type { ConversationSummary, ConversationGroup } from '../types';
9
10
 
11
+ /**
12
+ * The collapsed-rail fallback: a floating reopen button shown when the
13
+ * conversation sidebar is collapsed. Shared by `kai-workspace` (its collapsed
14
+ * branch) and the standalone `kai-conversations` (collapsed mode), so the rail
15
+ * collapses identically in both. Renders only the button; the host owns the
16
+ * surrounding region (the workspace puts the thread beside it, the standalone
17
+ * element stands alone). `onExpand` reopens the rail.
18
+ */
19
+ export function CollapsedRail(props: { onExpand: () => void; class?: string }) {
20
+ return (
21
+ <Button
22
+ variant="ghost" size="icon-sm" aria-label="Open sidebar"
23
+ class={cn('rounded-full bg-card/80 shadow-sm backdrop-blur', props.class)}
24
+ onClick={props.onExpand}
25
+ >
26
+ <PanelLeftOpen class="size-4" />
27
+ </Button>
28
+ );
29
+ }
30
+
10
31
  export interface ConversationListProps {
11
32
  groups: ConversationGroup[];
12
33
  conversations: ConversationSummary[];
@@ -14,12 +35,48 @@ export interface ConversationListProps {
14
35
  onSelect: (id: string) => void;
15
36
  onNewChat: () => void;
16
37
  onToggleSidebar?: () => void;
38
+ /** Replaces the built-in title bar (toggle / "Chats" / New chat). */
39
+ header?: JSX.Element;
40
+ /** A row below the list (e.g. account / settings / usage). */
41
+ footer?: JSX.Element;
42
+ /** Replaces the built-in "no conversations yet" state. */
43
+ empty?: JSX.Element;
44
+ /** Dense single-line rows (a leading dot + title, no message count). */
45
+ compact?: boolean;
46
+ /** Fired whenever the built-in search box query changes (typing or a
47
+ * programmatic `clear()`). Lets the facade surface a `kai-search` event. */
48
+ onSearchChange?: (query: string) => void;
49
+ /** Receive the imperative controller once mounted. The `kai-conversations`
50
+ * facade uses it to focus / clear the internal search input. */
51
+ controllerRef?: (controller: ConversationListController) => void;
17
52
  class?: string;
18
53
  }
19
54
 
55
+ /** Imperative handle exposed via `controllerRef` — surfaces the internal search
56
+ * box to the `kai-conversations` facade (the searchQuery signal lives here). */
57
+ export interface ConversationListController {
58
+ /** Focus the built-in search `<input>`. */
59
+ focus(options?: FocusOptions): void;
60
+ /** Clear the internal search query (resets the list filter). */
61
+ clearSearch(): void;
62
+ }
63
+
20
64
  export function ConversationList(props: ConversationListProps) {
21
- const [local] = splitProps(props, ['groups', 'conversations', 'activeId', 'onSelect', 'onNewChat', 'onToggleSidebar', 'class']);
65
+ const [local] = splitProps(props, ['groups', 'conversations', 'activeId', 'onSelect', 'onNewChat', 'onToggleSidebar', 'header', 'footer', 'empty', 'compact', 'onSearchChange', 'controllerRef', 'class']);
22
66
  const [searchQuery, setSearchQuery] = createSignal('');
67
+ const isEmpty = createMemo(() => local.conversations.length === 0);
68
+ // The search query is owned here; setQuery is the single mutation point so both
69
+ // typing and the imperative clearSearch() notify the facade (→ kai-search).
70
+ let searchInput: HTMLInputElement | undefined;
71
+ const setQuery = (q: string) => { setSearchQuery(q); local.onSearchChange?.(q); };
72
+
73
+ // Hand the imperative controller (focus / clear the search box) to the facade.
74
+ onMount(() => {
75
+ local.controllerRef?.({
76
+ focus: (options) => searchInput?.focus(options),
77
+ clearSearch: () => setQuery(''),
78
+ });
79
+ });
23
80
 
24
81
  const filteredConversations = createMemo(() => {
25
82
  const q = searchQuery().toLowerCase();
@@ -41,45 +98,85 @@ export function ConversationList(props: ConversationListProps) {
41
98
 
42
99
  return (
43
100
  <div class={cn('flex flex-col h-full bg-sidebar', local.class)}>
44
- <div class="flex items-center justify-between p-3 pb-2">
45
- <div class="flex items-center gap-2">
46
- <Button variant="ghost" size="icon-sm" aria-label="Toggle sidebar" onClick={local.onToggleSidebar}>
47
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
48
- </Button>
49
- <span class="text-sm font-semibold text-foreground">Chats</span>
101
+ {/* header (replace): the consumer's own title bar, else the built-in one. */}
102
+ <Show
103
+ when={local.header}
104
+ fallback={
105
+ <div class="flex items-center justify-between p-3 pb-2">
106
+ <div class="flex items-center gap-2">
107
+ <Button variant="ghost" size="icon-sm" aria-label="Toggle sidebar" onClick={local.onToggleSidebar}>
108
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="18" x2="21" y2="18"/></svg>
109
+ </Button>
110
+ <span class="text-sm font-semibold text-foreground">Chats</span>
111
+ </div>
112
+ <Button variant="ghost" size="icon-sm" aria-label="New chat" onClick={local.onNewChat}>
113
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
114
+ </Button>
115
+ </div>
116
+ }
117
+ >
118
+ {local.header}
119
+ </Show>
120
+ <Show when={!isEmpty()}>
121
+ <div class="px-3 pb-2">
122
+ <div class="flex items-center gap-2 rounded-md bg-surface-strong px-2.5 py-1.5">
123
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-muted-foreground"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
124
+ <input ref={searchInput} type="text" value={searchQuery()} onInput={(e) => setQuery(e.currentTarget.value)} placeholder="Search chats..."
125
+ aria-label="Search chats"
126
+ class="bg-transparent text-[13px] text-foreground placeholder:text-muted-foreground rounded-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring w-full" />
127
+ </div>
50
128
  </div>
51
- <Button variant="ghost" size="icon-sm" aria-label="New chat" onClick={local.onNewChat}>
52
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
53
- </Button>
54
- </div>
55
- <div class="px-3 pb-2">
56
- <div class="flex items-center gap-2 rounded-md bg-muted/40 px-2.5 py-1.5">
57
- <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-muted-foreground"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
58
- <input type="text" value={searchQuery()} onInput={(e) => setSearchQuery(e.currentTarget.value)} placeholder="Search chats..."
59
- aria-label="Search chats"
60
- class="bg-transparent text-[13px] text-foreground placeholder:text-muted-foreground rounded-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring w-full" />
61
- </div>
62
- </div>
63
- <ScrollArea class="flex-1 px-2">
64
- <For each={local.groups}>
65
- {(group) => {
66
- const convs = createMemo(() => groupedConversations().get(group.id) ?? []);
67
- return (
68
- <Show when={convs().length > 0}>
69
- <GroupSection name={group.name} count={convs().length} conversations={convs()} activeId={local.activeId} onSelect={local.onSelect} />
70
- </Show>
71
- );
72
- }}
73
- </For>
74
- <Show when={ungrouped().length > 0}>
75
- <GroupSection name="Ungrouped" count={ungrouped().length} conversations={ungrouped()} activeId={local.activeId} onSelect={local.onSelect} />
76
- </Show>
77
- </ScrollArea>
129
+ </Show>
130
+ {/* list, or the empty state (replace) when there are no conversations. */}
131
+ <Show
132
+ when={!isEmpty()}
133
+ fallback={
134
+ <Show
135
+ when={local.empty}
136
+ fallback={
137
+ <div class="flex flex-1 flex-col items-center justify-center gap-1 p-6 text-center text-sm text-muted-foreground">
138
+ No conversations yet
139
+ </div>
140
+ }
141
+ >
142
+ {local.empty}
143
+ </Show>
144
+ }
145
+ >
146
+ <ScrollArea class="flex-1 px-2">
147
+ <For each={local.groups}>
148
+ {(group) => {
149
+ const convs = createMemo(() => groupedConversations().get(group.id) ?? []);
150
+ return (
151
+ <Show when={convs().length > 0}>
152
+ <GroupSection name={group.name} count={convs().length} conversations={convs()} activeId={local.activeId} onSelect={local.onSelect} compact={local.compact} />
153
+ </Show>
154
+ );
155
+ }}
156
+ </For>
157
+ <Show when={ungrouped().length > 0}>
158
+ <Show
159
+ when={local.compact}
160
+ fallback={<GroupSection name="Ungrouped" count={ungrouped().length} conversations={ungrouped()} activeId={local.activeId} onSelect={local.onSelect} />}
161
+ >
162
+ <div class="space-y-0.5 py-1">
163
+ <For each={ungrouped()}>
164
+ {(conv) => <ConversationItem conversation={conv} isActive={conv.id === local.activeId} onSelect={local.onSelect} compact />}
165
+ </For>
166
+ </div>
167
+ </Show>
168
+ </Show>
169
+ </ScrollArea>
170
+ </Show>
171
+ {/* footer (inject): a row below the list (account / settings / …). */}
172
+ <Show when={local.footer}>
173
+ <div class="shrink-0 border-t border-border">{local.footer}</div>
174
+ </Show>
78
175
  </div>
79
176
  );
80
177
  }
81
178
 
82
- function GroupSection(props: { name: string; count: number; conversations: ConversationSummary[]; activeId?: string; onSelect: (id: string) => void }) {
179
+ function GroupSection(props: { name: string; count: number; conversations: ConversationSummary[]; activeId?: string; onSelect: (id: string) => void; compact?: boolean }) {
83
180
  const [open, setOpen] = createSignal(true);
84
181
  return (
85
182
  <Collapsible open={open()} onOpenChange={setOpen}>
@@ -92,7 +189,7 @@ function GroupSection(props: { name: string; count: number; conversations: Conve
92
189
  <CollapsibleContent>
93
190
  <div class="pl-2 mt-0.5 space-y-0.5">
94
191
  <For each={props.conversations}>
95
- {(conv) => <ConversationItem conversation={conv} isActive={conv.id === props.activeId} onSelect={props.onSelect} />}
192
+ {(conv) => <ConversationItem conversation={conv} isActive={conv.id === props.activeId} onSelect={props.onSelect} compact={props.compact} />}
96
193
  </For>
97
194
  </div>
98
195
  </CollapsibleContent>