@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
@@ -0,0 +1,151 @@
1
+ import { createSignal } from 'solid-js';
2
+ import { defineWebComponent } from './define';
3
+ import type { ComposerDoc, EntityRef } from '../primitives/composer-model';
4
+ import type { TriggerDef, TriggerItem, HighlightRule, ComposerChange, ComposerController } from '../components/composer';
5
+ import { Composer } from '../components/composer';
6
+
7
+ /**
8
+ * Parse a single light-DOM `<kai-trigger-item>` element into a TriggerItem.
9
+ * Attribute mapping:
10
+ * - `item-id` → TriggerItem.id (required; empty string fallback)
11
+ * - textContent → TriggerItem.label (primary); `label` attr as fallback
12
+ * - `icon` → TriggerItem.icon
13
+ * - `prompt-text` → TriggerItem.promptText
14
+ * - `data` is left undefined (complex object, not representable as an attribute)
15
+ *
16
+ * @param n The `<kai-trigger-item>` element to parse.
17
+ * @param char The trigger character this item belongs to (e.g. `/` or `@`).
18
+ * @param kind The entity kind for this trigger (e.g. `'skill'` or `'mention'`).
19
+ */
20
+ export function parseKaiTriggerItemElement(n: Element, char: string, kind: string): TriggerItem {
21
+ // char and kind inform the consumer but are not stored on TriggerItem itself.
22
+ void char;
23
+ void kind;
24
+ return {
25
+ id: n.getAttribute('item-id') ?? '',
26
+ label: n.textContent?.trim() || n.getAttribute('label') || n.getAttribute('item-id') || '',
27
+ icon: n.getAttribute('icon') ?? undefined,
28
+ promptText: n.getAttribute('prompt-text') ?? undefined,
29
+ data: undefined,
30
+ };
31
+ }
32
+
33
+ interface Props extends Record<string, unknown> {
34
+ /** Controlled value — string or a full ComposerDoc (set as JS property). */
35
+ value?: string | ComposerDoc;
36
+ /** Placeholder text shown when the composer is empty. */
37
+ placeholder?: string;
38
+ /** Disable the composer entirely (non-interactive). */
39
+ disabled?: boolean;
40
+ /** Show a loading/streaming state and block submit. */
41
+ loading?: boolean;
42
+ /** Maximum height in px before the content scrolls. Default 240. */
43
+ maxHeight?: number | string;
44
+ /** Whether pressing Enter (without Shift) submits. Default true. */
45
+ submitOnEnter?: boolean;
46
+ /** Trigger definitions — set as a JS property. */
47
+ triggers?: TriggerDef[];
48
+ /** Keyword highlight rules — set as a JS property. */
49
+ highlights?: HighlightRule[];
50
+ /** Default icon per entity kind (kind → image URL/data-URI) for items without
51
+ * their own `icon`. Overrides the built-in agent/plugin glyphs. JS property. */
52
+ kindIcons?: Record<string, string>;
53
+ }
54
+
55
+ /** Events fired by `<kai-composer>`. */
56
+ interface Events {
57
+ /** The user submitted the composer (Enter or programmatic submit). */
58
+ 'kai-submit': { doc: ComposerDoc; text: string; entities: EntityRef[] };
59
+ /** The content changed (fires on every input event). */
60
+ 'kai-value-change': { doc: ComposerDoc; text: string; entities: EntityRef[] };
61
+ /** An entity pill was inserted into the composer. */
62
+ 'kai-entity-add': { entity: EntityRef };
63
+ /** An entity pill was deleted from the composer. */
64
+ 'kai-entity-remove': { entity: EntityRef };
65
+ /** A trigger character was detected at the caret (e.g. `/` or `@`). */
66
+ 'kai-trigger': { char: string; query: string; rect: DOMRect };
67
+ /** The active trigger was dismissed (Escape, space, or outside click). */
68
+ 'kai-trigger-close': Record<string, never>;
69
+ /** The composer gained focus. `focus`/`blur` are NOT composed natively, so they
70
+ * don't escape the shadow root — these re-expose them on the host. (For
71
+ * `keydown`/`paste`/`focusin`/`focusout`, listen NATIVELY on `<kai-composer>`:
72
+ * they're composed and already cross the shadow boundary.) */
73
+ 'kai-focus': { originalEvent: FocusEvent };
74
+ /** The composer lost focus. */
75
+ 'kai-blur': { originalEvent: FocusEvent };
76
+ }
77
+
78
+ defineWebComponent<Props, Events>('kai-composer', {
79
+ value: undefined,
80
+ placeholder: undefined,
81
+ disabled: false,
82
+ loading: false,
83
+ maxHeight: 240,
84
+ submitOnEnter: true,
85
+ triggers: undefined,
86
+ highlights: undefined,
87
+ kindIcons: undefined,
88
+ }, (props, { dispatch, flag, expose }) => {
89
+ // Internal signal for uncontrolled value; when the consumer sets `value` as a
90
+ // JS property the controlled path takes precedence (same pattern as prompt-input).
91
+ const [internal, setInternal] = createSignal<string | ComposerDoc | undefined>(props.value);
92
+
93
+ const current = () => props.value ?? internal();
94
+
95
+ // ── Imperative API (instance methods on the host) ──────────────────────────
96
+ // Pattern C: the Composer component owns the editable + doc state and hands up
97
+ // a controller; the facade captures it and exposes delegating methods. The
98
+ // composer's own callbacks still fire (clear → onChange → kai-value-change;
99
+ // send → onSubmit → kai-submit; insertEntity → onEntityAdd → kai-entity-add).
100
+ let controller: ComposerController | undefined;
101
+ expose({
102
+ /** Focus the editable element. `focus`/`blur` are NOT composed natively, so a
103
+ * host-level focus() can't reach the editable inside the shadow root — this is
104
+ * the only way to focus the composer programmatically. */
105
+ focus: (options?: FocusOptions) => controller?.focus(options),
106
+ /** Blur the editable element. */
107
+ blur: () => controller?.blur(),
108
+ /** Empty the composer to a blank doc (resets the internal value + history
109
+ * baseline; fires kai-value-change). */
110
+ clear: () => controller?.clear(),
111
+ /** Submit the current content programmatically — same path as Enter (fires
112
+ * kai-submit). Named `send`, not `submit`, to match the shared vocabulary and
113
+ * avoid any submit collision. */
114
+ send: () => controller?.send(),
115
+ /** Insert an atomic entity pill (skill/agent/plugin) at the caret without
116
+ * typing a trigger (fires kai-entity-add). */
117
+ insertEntity: (entity: EntityRef) => controller?.insertEntity(entity),
118
+ });
119
+
120
+ const handleChange = (change: ComposerChange) => {
121
+ setInternal(change.doc);
122
+ dispatch('kai-value-change', { doc: change.doc, text: change.text, entities: change.entities });
123
+ };
124
+
125
+ const handleSubmit = (change: ComposerChange) => {
126
+ dispatch('kai-submit', { doc: change.doc, text: change.text, entities: change.entities });
127
+ };
128
+
129
+ return (
130
+ <Composer
131
+ value={current()}
132
+ placeholder={props.placeholder}
133
+ disabled={flag('disabled')}
134
+ loading={flag('loading')}
135
+ maxHeight={props.maxHeight as number | string | undefined}
136
+ submitOnEnter={flag('submitOnEnter')}
137
+ triggers={props.triggers}
138
+ highlights={props.highlights}
139
+ kindIcons={props.kindIcons as Record<string, string> | undefined}
140
+ onChange={handleChange}
141
+ onSubmit={handleSubmit}
142
+ onEntityAdd={(entity) => dispatch('kai-entity-add', { entity })}
143
+ onEntityRemove={(entity) => dispatch('kai-entity-remove', { entity })}
144
+ onTrigger={(info) => dispatch('kai-trigger', info)}
145
+ onTriggerClose={() => dispatch('kai-trigger-close', {})}
146
+ onFocus={(e) => dispatch('kai-focus', { originalEvent: e })}
147
+ onBlur={(e) => dispatch('kai-blur', { originalEvent: e })}
148
+ controllerRef={(c) => (controller = c)}
149
+ />
150
+ );
151
+ });
@@ -1,5 +1,5 @@
1
1
  import { defineWebComponent } from './define';
2
- import { ConfirmCard, type ConfirmCardData } from '../components/confirm-card';
2
+ import { ConfirmCard, type ConfirmCardData, type ConfirmController } from '../components/confirm-card';
3
3
  import type { CardResolution } from '../primitives/card-contract';
4
4
 
5
5
  interface Props extends Record<string, unknown> {
@@ -28,6 +28,9 @@ interface Props extends Record<string, unknown> {
28
28
  * optional close affordance, and `error` for a malformed definition (inline error).
29
29
  * Routes through a `CardProvider` when present, else the bubbling `kai-card` event.
30
30
  * Isolated in Shadow DOM; theme-aware via the shared kit tokens.
31
+ *
32
+ * Exposes instance methods `focus()`/`confirm(actionId?)`/`dismiss()`/`reopen()`
33
+ * that drive the same internal paths as the buttons.
31
34
  */
32
35
  defineWebComponent<Props>(
33
36
  'kai-confirm',
@@ -38,14 +41,36 @@ defineWebComponent<Props>(
38
41
  autofocus: false,
39
42
  resolution: undefined,
40
43
  },
41
- (props, { element, flag }) => (
42
- <ConfirmCard
43
- data={props.data as ConfirmCardData | undefined}
44
- cardId={props.cardId ?? (element.id || 'kai-confirm')}
45
- heading={props.heading}
46
- autofocus={flag('autofocus')}
47
- resolution={props.resolution as CardResolution | undefined}
48
- hostElement={element}
49
- />
50
- ),
44
+ (props, { element, flag, expose }) => {
45
+ // Pattern C: the ConfirmCard owns the action/dismiss state and hands up a
46
+ // controller; the facade captures it and exposes delegating methods. The card's
47
+ // own paths still fire (confirm kai-card `action`; dismiss/reopen → kai-card
48
+ // `dismiss`/`reopen`).
49
+ let controller: ConfirmController | undefined;
50
+ expose({
51
+ /** Focus the default action button (or the first action if none is default) —
52
+ * the same target `autofocus` focuses on mount, but on demand. */
53
+ focus: (options?: FocusOptions) => controller?.focus(options),
54
+ /** Activate an action by id — emits the `action` verb on kai-card and resolves
55
+ * the card (single-shot). With no id, invokes the default action. */
56
+ confirm: (actionId?: string) => controller?.confirm(actionId),
57
+ /** Trigger the dismiss path — emits `dismiss` on kai-card and optimistically
58
+ * collapses the card to its re-openable stub. */
59
+ dismiss: () => controller?.dismiss(),
60
+ /** Re-open a dismissed card from its stub — emits `reopen` on kai-card. */
61
+ reopen: () => controller?.reopen(),
62
+ });
63
+
64
+ return (
65
+ <ConfirmCard
66
+ data={props.data as ConfirmCardData | undefined}
67
+ cardId={props.cardId ?? (element.id || 'kai-confirm')}
68
+ heading={props.heading}
69
+ autofocus={flag('autofocus')}
70
+ resolution={props.resolution as CardResolution | undefined}
71
+ controllerRef={(c) => (controller = c)}
72
+ hostElement={element}
73
+ />
74
+ );
75
+ },
51
76
  );
@@ -1,6 +1,8 @@
1
- import { createSignal, onMount, onCleanup } from 'solid-js';
1
+ import { createSignal, onMount, onCleanup, Show } from 'solid-js';
2
2
  import { defineWebComponent } from './define';
3
- import { ConversationList } from '../components/conversation-list';
3
+ import { createControllableSignal } from '../primitives/controllable';
4
+ import { readSlots, CONVERSATIONS_SLOTS } from './slots';
5
+ import { ConversationList, CollapsedRail, type ConversationListController } from '../components/conversation-list';
4
6
  import type { ConversationGroup, ConversationSummary, ConversationScope } from '../types';
5
7
 
6
8
  interface Props extends Record<string, unknown> {
@@ -13,6 +15,14 @@ interface Props extends Record<string, unknown> {
13
15
  conversations: ConversationSummary[];
14
16
  /** The id of the currently-open conversation, highlighted in the list. */
15
17
  activeId?: string;
18
+ /** Controlled collapsed state. Set as a JS property (`el.collapsed = true`) to
19
+ * drive the rail from your app, updating it in response to `kai-collapse-toggle`.
20
+ * Omit for uncontrolled (the element manages it). Collapsed shrinks the rail to
21
+ * a floating reopen button. */
22
+ collapsed?: boolean;
23
+ /** Initial collapsed state when uncontrolled (default false). Use the
24
+ * `default-collapsed` attribute to start collapsed in plain HTML. */
25
+ defaultCollapsed?: boolean;
16
26
  }
17
27
 
18
28
  interface Events {
@@ -22,6 +32,12 @@ interface Events {
22
32
  'kai-new-chat': Record<string, never>;
23
33
  /** The sidebar toggle was clicked. */
24
34
  'kai-toggle-sidebar': Record<string, never>;
35
+ /** The rail was collapsed or expanded (via the toggle, the reopen button, or a
36
+ * `collapse()`/`expand()`/`toggle()` call). */
37
+ 'kai-collapse-toggle': { collapsed: boolean };
38
+ /** The built-in search box query changed (typing, or a programmatic `clear()`
39
+ * which fires it with `''`). Lets a consumer mirror or server-side the filter. */
40
+ 'kai-search': { query: string };
25
41
  }
26
42
 
27
43
  /** Parse a single light-DOM `<kai-conversation>` element into a `ConversationSummary`.
@@ -49,14 +65,19 @@ defineWebComponent<Props, Events>('kai-conversations', {
49
65
  groups: [],
50
66
  conversations: [],
51
67
  activeId: undefined,
52
- }, (props, { dispatch, element }) => {
68
+ collapsed: undefined,
69
+ defaultCollapsed: undefined,
70
+ }, (props, { dispatch, element, expose, flag }) => {
53
71
  // Read declarative <kai-conversation> children from light DOM.
54
72
  // Shadow DOM with no <slot> suppresses them visually — they're invisible data carriers.
55
73
  const [slottedConversations, setSlottedConversations] = createSignal<ConversationSummary[]>([]);
74
+ // Which composition slots (header/empty/footer) the consumer has filled.
75
+ const [slots, setSlots] = createSignal<Record<string, boolean>>({});
56
76
  onMount(() => {
57
77
  const read = () => {
58
78
  const nodes = [...element.querySelectorAll('kai-conversation')];
59
79
  setSlottedConversations(nodes.map(parseKaiConversationElement));
80
+ setSlots(readSlots(element, CONVERSATIONS_SLOTS));
60
81
  };
61
82
  read();
62
83
  const observer = new MutationObserver(read);
@@ -67,14 +88,62 @@ defineWebComponent<Props, Events>('kai-conversations', {
67
88
  // Prop conversations take precedence; slotted children are appended after.
68
89
  const allConversations = () => [...(props.conversations ?? []), ...slottedConversations()];
69
90
 
91
+ // ── Rail collapse (controlled/uncontrolled, same pattern as kai-workspace) ──
92
+ // `collapsed` (when set) wins; otherwise the element manages its own state,
93
+ // seeded from `defaultCollapsed`. `setCollapsedTo` always writes the internal
94
+ // value (a no-op visually while controlled) and emits `kai-collapse-toggle` so
95
+ // a controlling app can update its own state. Collapsed → the shared
96
+ // CollapsedRail (the same floating reopen button kai-workspace renders).
97
+ const [collapsed, setCollapsed] = createControllableSignal(
98
+ () => props.collapsed as boolean | undefined,
99
+ flag('defaultCollapsed'),
100
+ );
101
+ const setCollapsedTo = (next: boolean) => { setCollapsed(next); dispatch('kai-collapse-toggle', { collapsed: next }); };
102
+
103
+ // ── Imperative API (instance methods on the host) ──────────────────────────
104
+ // The search box's query lives inside ConversationList; we capture its
105
+ // controller (Pattern C) to focus / clear it from the facade.
106
+ let controller: ConversationListController | undefined;
107
+ expose({
108
+ /** Focus the built-in search input inside the shadow root. */
109
+ focus: (options?: FocusOptions) => {
110
+ // Prefer the captured controller; fall back to a shadow query (the search
111
+ // box only renders when there are conversations).
112
+ if (controller) controller.focus(options);
113
+ else element.shadowRoot?.querySelector<HTMLInputElement>('input')?.focus(options);
114
+ },
115
+ /** Clear the internal search query (resets the list filter) and fire
116
+ * kai-search with an empty string. */
117
+ clear: () => controller?.clearSearch(),
118
+ /** Programmatically select a conversation by id — mirror of the
119
+ * kai-conversation-select event (a convenience over driving `activeId`). */
120
+ select: (id: string) => dispatch('kai-conversation-select', { id }),
121
+ /** Collapse the rail to its floating reopen button (fires `kai-collapse-toggle`). */
122
+ collapse: () => setCollapsedTo(true),
123
+ /** Expand the rail back to the full list (fires `kai-collapse-toggle`). */
124
+ expand: () => setCollapsedTo(false),
125
+ /** Toggle the rail collapsed/expanded (fires `kai-collapse-toggle`). */
126
+ toggle: () => setCollapsedTo(!collapsed()),
127
+ });
128
+
70
129
  return (
71
- <ConversationList
72
- groups={props.groups}
73
- conversations={allConversations()}
74
- activeId={props.activeId}
75
- onSelect={(id) => dispatch('kai-conversation-select', { id })}
76
- onNewChat={() => dispatch('kai-new-chat')}
77
- onToggleSidebar={() => dispatch('kai-toggle-sidebar')}
78
- />
130
+ <Show
131
+ when={!collapsed()}
132
+ fallback={<CollapsedRail onExpand={() => setCollapsedTo(false)} />}
133
+ >
134
+ <ConversationList
135
+ groups={props.groups}
136
+ conversations={allConversations()}
137
+ activeId={props.activeId}
138
+ onSelect={(id) => dispatch('kai-conversation-select', { id })}
139
+ onNewChat={() => dispatch('kai-new-chat')}
140
+ onToggleSidebar={() => { dispatch('kai-toggle-sidebar'); setCollapsedTo(true); }}
141
+ onSearchChange={(query) => dispatch('kai-search', { query })}
142
+ controllerRef={(c) => (controller = c)}
143
+ header={slots().header ? <slot name="header" /> : undefined}
144
+ footer={slots().footer ? <slot name="footer" /> : undefined}
145
+ empty={slots().empty ? <slot name="empty" /> : undefined}
146
+ />
147
+ </Show>
79
148
  );
80
149
  });
@@ -1,7 +1,8 @@
1
1
  import { For, Show } from 'solid-js';
2
2
  import { PromptInput, PromptInputTextarea, PromptInputActions } from '../components/prompt-input';
3
+ import type { TriggerDef, ComposerChange } from '../components/composer';
4
+ import { type ComposerDoc, normalizeValue, serializeToText } from '../primitives/composer-model';
3
5
  import { PromptSuggestion } from '../components/prompt-suggestion';
4
- import { SlashCommand, type SlashCommandItem } from '../components/slash-command';
5
6
  import { Button } from '../ui/button';
6
7
  import { Tooltip } from '../ui/tooltip';
7
8
  import { Paperclip, Globe, Mic, Square } from 'lucide-solid';
@@ -17,7 +18,8 @@ import { actionIcon } from '../ui/action-icons';
17
18
  import type { CustomAction } from './chat-types';
18
19
 
19
20
  export interface DefaultPromptInputProps {
20
- value: string;
21
+ /** String = controlled text mirror; ComposerDoc = a seed that pre-populates pills. */
22
+ value: string | ComposerDoc;
21
23
  placeholder?: string;
22
24
  disabled?: boolean;
23
25
  loading?: boolean;
@@ -25,23 +27,26 @@ export interface DefaultPromptInputProps {
25
27
  /** Attachments staged in the input. Provide `onAttachmentsChange` to enable
26
28
  * the attach button + removable previews. */
27
29
  attachments?: AttachmentData[];
30
+ /** When `false`, the built-in paperclip attach button is hidden even if
31
+ * `onAttachmentsChange` is provided (e.g. when a `+` menu already covers
32
+ * file-attach). Defaults to `true`. */
33
+ attach?: boolean;
28
34
  /** Show a Search (Globe) button in the left toolbar; calls `onSearch`. */
29
35
  search?: boolean;
30
36
  /** Show a Voice (Mic) button in the left toolbar; calls `onVoice`. */
31
37
  voice?: boolean;
32
- /** Slash commands when set, typing `/` opens the command palette. */
33
- slashCommands?: SlashCommandItem[];
34
- /** Currently-active command ids (highlighted in the palette). */
35
- slashActiveIds?: string[];
36
- /** Single-line palette rows. */
37
- slashCompact?: boolean;
38
+ /** Send-button visibility. `'always'` (default) always shows it; `'auto'` shows
39
+ * it only when there's text/attachments (an empty composer hides it — Enter
40
+ * still submits). To hide it entirely (Enter-only), it's pure CSS:
41
+ * `::part(send){display:none}` — no prop needed. Restyle via `::part(send)`.
42
+ * The Stop button (stoppable + loading) is unaffected. */
43
+ submit?: 'always' | 'auto';
38
44
  onValueChange: (v: string) => void;
39
45
  onSubmit: () => void;
40
46
  onSuggestionClick: (v: string) => void;
41
47
  onAttachmentsChange?: (attachments: AttachmentData[]) => void;
42
48
  onSearch?: () => void;
43
49
  onVoice?: () => void;
44
- onSlashSelect?: (command: SlashCommandItem) => void;
45
50
  /** When `true` and `loading` is also `true`, the send button is replaced by
46
51
  * a Stop button that calls `onStop`. */
47
52
  stoppable?: boolean;
@@ -51,6 +56,12 @@ export interface DefaultPromptInputProps {
51
56
  toolbarActions?: CustomAction[];
52
57
  /** Called when a custom toolbar action button is clicked, with the action id. */
53
58
  onAction?: (id: string) => void;
59
+ /** Rich entity triggers (`/` skills, `@` agents) passed to the composer. */
60
+ triggers?: TriggerDef[];
61
+ /** Default icon per entity kind (kind → image src) passed to the composer. */
62
+ kindIcons?: Record<string, string>;
63
+ /** Structured change (doc + entities) from the composer, on every edit. */
64
+ onComposerChange?: (change: ComposerChange) => void;
54
65
  }
55
66
 
56
67
  function fileToAttachment(file: File): AttachmentData {
@@ -79,10 +90,20 @@ export function DefaultPromptInput(props: DefaultPromptInputProps) {
79
90
  const removeAttachment = (id: string) =>
80
91
  props.onAttachmentsChange?.(attachments().filter((a) => a.id !== id));
81
92
 
93
+ // `value` may be a string or a seeded ComposerDoc — compute emptiness from the
94
+ // flattened text so a pill-only seed still enables Send.
95
+ const valueText = () => serializeToText(normalizeValue(props.value));
82
96
  const sendDisabled = () =>
83
- props.disabled || props.loading || (!props.value.trim() && attachments().length === 0);
97
+ props.disabled || props.loading || (!valueText().trim() && attachments().length === 0);
84
98
 
85
99
  const showStop = () => !!props.loading && !!props.stoppable;
100
+ const hasContent = () => !!valueText().trim() || attachments().length > 0;
101
+ // Send-button visibility: 'always' (default) or 'auto' (only with content).
102
+ // Full-hide (Enter-only) is CSS: `::part(send){display:none}`.
103
+ const showSend = () => {
104
+ const mode = props.submit ?? 'always';
105
+ return mode === 'always' || (mode === 'auto' && hasContent());
106
+ };
86
107
 
87
108
  return (
88
109
  <>
@@ -103,17 +124,6 @@ export function DefaultPromptInput(props: DefaultPromptInputProps) {
103
124
  disabled={props.disabled}
104
125
  class="relative"
105
126
  >
106
- <Show when={props.slashCommands?.length}>
107
- {/* Rendered inside PromptInput so SlashCommand's usePromptInput()
108
- context (input value + textarea ref) resolves; the `relative` root
109
- anchors its `absolute bottom-full` palette above the input. */}
110
- <SlashCommand
111
- commands={props.slashCommands!}
112
- activeIds={props.slashActiveIds}
113
- compact={props.slashCompact}
114
- onSelect={(command) => props.onSlashSelect?.(command)}
115
- />
116
- </Show>
117
127
  <Show when={canAttach() && attachments().length}>
118
128
  <div class="px-3 pt-3">
119
129
  <Attachments variant="inline">
@@ -129,13 +139,18 @@ export function DefaultPromptInput(props: DefaultPromptInputProps) {
129
139
  </Attachments>
130
140
  </div>
131
141
  </Show>
132
- {/* Consumer-injected controls rendered before the input area. Native
133
- slot; inert outside a shadow root, projected by the custom element. */}
134
- <slot name="leading" />
135
- <PromptInputTextarea placeholder={props.placeholder} aria-label={props.placeholder || 'Message'} class="min-h-[44px] pt-3 pl-4" />
136
- <PromptInputActions class="mt-2 flex w-full items-center justify-between gap-2 px-3 pb-3">
142
+ {/* Consumer-injected content inside the card, above the textarea (e.g. an
143
+ inline status strip). A shadow-internal hole unreachable from outside.
144
+ Native slot; inert outside a shadow root, projected by the custom element. */}
145
+ <slot name="input-top" />
146
+ <PromptInputTextarea placeholder={props.placeholder} aria-label={props.placeholder || 'Message'} class="min-h-[44px] pt-3 pl-4" triggers={props.triggers} kindIcons={props.kindIcons} onComposerChange={props.onComposerChange} />
147
+ <PromptInputActions class="mt-2 flex w-full items-center justify-between gap-2 px-3 pb-0">
137
148
  <div class="flex items-center gap-2">
138
- <Show when={canAttach()}>
149
+ {/* Consumer-injected leading toolbar controls (e.g. a + menu). display:contents
150
+ ensures an empty slot adds no stray gap; projected nodes lay out as toolbar
151
+ items. Native slot; projected by the custom element. */}
152
+ <slot name="toolbar-start" style={{ display: 'contents' }} />
153
+ <Show when={canAttach() && props.attach !== false}>
139
154
  <input
140
155
  ref={fileInput}
141
156
  type="file"
@@ -209,37 +224,44 @@ export function DefaultPromptInput(props: DefaultPromptInputProps) {
209
224
  }}
210
225
  </For>
211
226
  </div>
212
- {/* Consumer-injected controls rendered after the input area, beside
213
- the send button. Native slot; projected by the custom element. */}
214
- <slot name="trailing" />
215
- <Show
216
- when={showStop()}
217
- fallback={
227
+ {/* Right cluster consumer trailing controls (model/effort/voice…)
228
+ hug the send button, right-aligned. The `toolbar-end` slot and the send
229
+ button live together so justify-between pins them to the right edge
230
+ (left group stays left). Native slot; projected by the element. */}
231
+ <div class="flex items-center gap-2">
232
+ <slot name="toolbar-end" />
233
+ <Show
234
+ when={showStop()}
235
+ fallback={
236
+ <Show when={showSend()}>
237
+ <Button
238
+ size="icon-sm"
239
+ class="rounded-full"
240
+ part="send"
241
+ data-testid="send"
242
+ aria-label="Send message"
243
+ disabled={sendDisabled()}
244
+ onClick={props.onSubmit}
245
+ >
246
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
247
+ <line x1="12" y1="19" x2="12" y2="5" /><polyline points="5 12 12 5 19 12" />
248
+ </svg>
249
+ </Button>
250
+ </Show>
251
+ }
252
+ >
218
253
  <Button
219
254
  size="icon-sm"
255
+ variant="outline"
220
256
  class="rounded-full"
221
- data-testid="send"
222
- aria-label="Send message"
223
- disabled={sendDisabled()}
224
- onClick={props.onSubmit}
257
+ data-testid="stop"
258
+ aria-label="Stop"
259
+ onClick={props.onStop}
225
260
  >
226
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
227
- <line x1="12" y1="19" x2="12" y2="5" /><polyline points="5 12 12 5 19 12" />
228
- </svg>
261
+ <Square class="size-3" />
229
262
  </Button>
230
- }
231
- >
232
- <Button
233
- size="icon-sm"
234
- variant="outline"
235
- class="rounded-full"
236
- data-testid="stop"
237
- aria-label="Stop"
238
- onClick={props.onStop}
239
- >
240
- <Square class="size-3" />
241
- </Button>
242
- </Show>
263
+ </Show>
264
+ </div>
243
265
  </PromptInputActions>
244
266
  </PromptInput>
245
267
  </>