@kitn.ai/ui 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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-DLLBeLG5.js +1 -0
  57. package/dist/elements/chunks/action-icons-UB4V5FNq.js +1 -0
  58. package/dist/elements/chunks/arrow-left-C-gwlUmx.js +1 -0
  59. package/dist/elements/chunks/attachments-CgbErf1r.js +1 -0
  60. package/dist/elements/chunks/badge-DTQpgB6N.js +1 -0
  61. package/dist/elements/chunks/button-XDUM6lXs.js +1 -0
  62. package/dist/elements/chunks/card-CBlFZ-7I.js +1 -0
  63. package/dist/elements/chunks/chat-thread-BIhmqwNL.js +1 -0
  64. package/dist/elements/chunks/check-hGUoVIKb.js +1 -0
  65. package/dist/elements/chunks/chevron-down-DDoaSUtO.js +1 -0
  66. package/dist/elements/chunks/chevron-right-CdGEUakB.js +1 -0
  67. package/dist/elements/chunks/circle-BKAZdmzb.js +1 -0
  68. package/dist/elements/chunks/circle-check-CmYG-y3I.js +1 -0
  69. package/dist/elements/chunks/circle-x-DewgAEym.js +1 -0
  70. package/dist/elements/chunks/cn-CU7UAWzk.js +1 -0
  71. package/dist/elements/chunks/code-block-DedwxwFI.js +1 -0
  72. package/dist/elements/chunks/collapsible-FfgmTHtM.js +1 -0
  73. package/dist/elements/chunks/composer-Cfbw5HKT.js +65 -0
  74. package/dist/elements/chunks/context-DwJmxlRE.js +1 -0
  75. package/dist/elements/chunks/conversation-list-DsCQMfPq.js +1 -0
  76. package/dist/elements/chunks/default-input-BuqsoENC.js +1 -0
  77. package/dist/elements/chunks/define-rGsaWsLL.js +1 -0
  78. package/dist/elements/chunks/disclosure-CwoAkpMH.js +1 -0
  79. package/dist/elements/chunks/download-DJ06G3Bz.js +1 -0
  80. package/dist/elements/chunks/dropdown-BFg8ri_R.js +1 -0
  81. package/dist/elements/chunks/ellipsis-dlN6YvGw.js +1 -0
  82. package/dist/elements/chunks/external-link-DBX2lc_R.js +1 -0
  83. package/dist/elements/chunks/file-text-HfwUx4F9.js +1 -0
  84. package/dist/elements/chunks/file-tree-C6Toj71u.js +1 -0
  85. package/dist/elements/chunks/folder-MYuqa9Xp.js +1 -0
  86. package/dist/elements/chunks/hover-card-gE7iyXdW.js +1 -0
  87. package/dist/elements/chunks/icon-Vqz4ivrY.js +1 -0
  88. package/dist/elements/chunks/{index-CTBEJeo6.js → index-BCRhi84a.js} +1 -1
  89. package/dist/elements/chunks/info-B_toFS0l.js +1 -0
  90. package/dist/elements/chunks/input-gzbHYZvQ.js +1 -0
  91. package/dist/elements/chunks/kbd-n49c4KZm.js +1 -0
  92. package/dist/elements/chunks/link-CKPs9yM0.js +1 -0
  93. package/dist/elements/chunks/loader-q6MamGus.js +1 -0
  94. package/dist/elements/chunks/{markdown-CMTGx9r8.js → markdown-DBrcqq4S.js} +9 -9
  95. package/dist/elements/chunks/message-CTqaYI0s.js +1 -0
  96. package/dist/elements/chunks/message-feedback-Cvzm03w0.js +1 -0
  97. package/dist/elements/chunks/message-square-CUg9eRCi.js +1 -0
  98. package/dist/elements/chunks/minimize-2-l2klxP6K.js +1 -0
  99. package/dist/elements/chunks/model-switcher-CmyjiHO1.js +1 -0
  100. package/dist/elements/chunks/overlay-C8sOYqjT.js +1 -0
  101. package/dist/elements/chunks/paperclip-42Ia7xHD.js +1 -0
  102. package/dist/elements/chunks/progress-bar-tzKMWAwO.js +1 -0
  103. package/dist/elements/chunks/prompt-suggestion-D3F6vP_A.js +1 -0
  104. package/dist/elements/chunks/reasoning-BJNmmyov.js +1 -0
  105. package/dist/elements/chunks/resizable-BRsk19qI.js +1 -0
  106. package/dist/elements/chunks/rotate-cw-BgcggLHC.js +1 -0
  107. package/dist/elements/chunks/scroll-area-CgGbFFbT.js +1 -0
  108. package/dist/elements/chunks/separator-8hM4GdHE.js +1 -0
  109. package/dist/elements/chunks/settings-CaUIYOg-.js +1 -0
  110. package/dist/elements/chunks/settings-group-CYjOVIZQ.js +1 -0
  111. package/dist/elements/chunks/share-BTYM3Ddt.js +1 -0
  112. package/dist/elements/chunks/skeleton-DsTYrPUe.js +1 -0
  113. package/dist/elements/chunks/slots-DkZ-Cmha.js +1 -0
  114. package/dist/elements/chunks/star-9R3LBQ9n.js +1 -0
  115. package/dist/elements/chunks/store-CYl5Y0_u.js +1 -0
  116. package/dist/elements/chunks/text-shimmer-CaYGv8Se.js +1 -0
  117. package/dist/elements/chunks/textarea-NEr2SLcD.js +1 -0
  118. package/dist/elements/chunks/thumbs-up-DZYZkFfc.js +1 -0
  119. package/dist/elements/chunks/toast-store-ClxVZRcc.js +1 -0
  120. package/dist/elements/chunks/tool-CHZOmoe9.js +1 -0
  121. package/dist/elements/chunks/tooltip-WpHElELC.js +1 -0
  122. package/dist/elements/chunks/triangle-alert-BlS80PUg.js +1 -0
  123. package/dist/elements/chunks/use-card-resolution-VSVoxDeJ.js +1 -0
  124. package/dist/elements/chunks/video-DxTPZqT8.js +1 -0
  125. package/dist/elements/chunks/x-C1qtndxn.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 +8256 -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-CYWGkgbI.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 +75 -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 +23 -8
  287. package/src/agent-tooling/mcp/manifest.ts +14 -0
  288. package/src/agent-tooling/mcp/tools/debug.ts +10 -6
  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 +245 -0
  300. package/src/components/component-meta.json +691 -102
  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 +342 -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 +1 -1
  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 +47 -6
  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 +212 -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 +116 -0
  429. package/src/ui/pane-group.tsx +280 -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
package/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- AUTO-GENERATED by scripts/gen-llms.mjs — do not edit by hand. Run `npm run build`. -->
2
2
  # @kitn.ai/ui
3
3
 
4
- > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 46 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
4
+ > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 78 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
5
5
 
6
6
  ## Install
7
7
 
@@ -13,7 +13,7 @@ npm install solid-js
13
13
 
14
14
  ## #1 rule: array/object data goes on JS PROPERTIES, not HTML attributes
15
15
 
16
- This is the single most common mistake. Arrays and objects (`messages`, `models`, `context`, `suggestions`, `slashCommands`, …) MUST be assigned as JavaScript properties on the element. They CANNOT be passed as HTML attributes — an HTML attribute is always a string and will be ignored or mis-parsed.
16
+ This is the single most common mistake. Arrays and objects (`messages`, `models`, `context`, `suggestions`, `triggers`, …) MUST be assigned as JavaScript properties on the element. They CANNOT be passed as HTML attributes — an HTML attribute is always a string and will be ignored or mis-parsed.
17
17
 
18
18
  ```js
19
19
  const chat = document.querySelector('kai-chat');
@@ -35,7 +35,7 @@ Drop an element into any framework (React, Vue, plain HTML). Data in via JS prop
35
35
  - `<kai-prompt-input>` — standalone composer with send button.
36
36
 
37
37
  **Layer 2 — composable primitives** (`import { … } from '@kitn.ai/ui'`):
38
- All 46 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
38
+ All 78 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
39
39
 
40
40
  ## Key rules for the web components
41
41
 
@@ -97,7 +97,7 @@ For Tailwind builds: `@import "@kitn.ai/ui/theme.css"` in your CSS.
97
97
 
98
98
  ## Docs
99
99
 
100
- - Full element reference (all 46 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
100
+ - Full element reference (all 78 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
101
101
  - Machine-readable Custom Elements Manifest: https://unpkg.com/@kitn.ai/ui/dist/custom-elements.json
102
102
  - Working examples: https://github.com/kitn-ai/ui/tree/main/examples
103
103
  - Storybook: https://storybook.kitn.dev
package/package.json CHANGED
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "name": "@kitn.ai/ui",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "type": "module",
5
+ "sideEffects": [
6
+ "**/*.css",
7
+ "./dist/kai.es.js",
8
+ "./dist/elements/*.js"
9
+ ],
5
10
  "description": "Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.",
6
11
  "keywords": [
7
12
  "web-components",
@@ -33,8 +38,8 @@
33
38
  "main": "./dist/index.js",
34
39
  "module": "./dist/index.js",
35
40
  "types": "./dist/index.d.ts",
36
- "unpkg": "./dist/kitn-chat.es.js",
37
- "jsdelivr": "./dist/kitn-chat.es.js",
41
+ "unpkg": "./dist/kai.es.js",
42
+ "jsdelivr": "./dist/kai.es.js",
38
43
  "customElements": "dist/custom-elements.json",
39
44
  "bin": {
40
45
  "kai-mcp": "./bin/mcp.js"
@@ -46,7 +51,7 @@
46
51
  },
47
52
  "./elements": {
48
53
  "types": "./dist/elements.d.ts",
49
- "default": "./dist/kitn-chat.es.js"
54
+ "default": "./dist/kai.es.js"
50
55
  },
51
56
  "./elements/*": {
52
57
  "types": "./dist/elements/*.d.ts",
@@ -62,9 +67,13 @@
62
67
  "types": "./dist/react/index.d.ts",
63
68
  "default": "./dist/react.js"
64
69
  },
70
+ "./state": {
71
+ "types": "./dist/state/index.d.ts",
72
+ "default": "./dist/state.js"
73
+ },
65
74
  "./provider": {
66
- "types": "./dist/kitn-chat-provider.d.ts",
67
- "default": "./dist/kitn-chat-provider.es.js"
75
+ "types": "./dist/kai-provider.d.ts",
76
+ "default": "./dist/kai-provider.es.js"
68
77
  }
69
78
  },
70
79
  "files": [
@@ -76,6 +85,7 @@
76
85
  "!src/**/*.test.tsx",
77
86
  "!src/**/*.mdx",
78
87
  "!src/stories",
88
+ "!src/elements/logos",
79
89
  "frameworks",
80
90
  "theme.css",
81
91
  "llms.txt",
@@ -84,7 +94,7 @@
84
94
  "scripts": {
85
95
  "prepublishOnly": "npm run build",
86
96
  "prebuild": "npm run build:css",
87
- "build": "vite build --config vite.config.ts && vite build --config vite.config.provider.ts && vite build --config vite.config.react.ts && vite build --config vite.config.barrel.ts && vite build --config vite.config.mcp.ts && npm run build:elements",
97
+ "build": "vite build --config vite.config.ts && vite build --config vite.config.provider.ts && vite build --config vite.config.react.ts && vite build --config vite.config.barrel.ts && vite build --config vite.config.state.ts && vite build --config vite.config.mcp.ts && npm run build:elements && node scripts/verify-elements-bundle.mjs && node scripts/verify-react-wrappers.mjs",
88
98
  "build:elements": "node scripts/gen-elements-manifest.mjs && vite build --config vite.config.elements.ts && node scripts/gen-element-dts.mjs",
89
99
  "postbuild": "npm run build:theme && npm run build:api && npm run build:schemas",
90
100
  "build:theme": "node scripts/build-theme-tokens.mjs",
@@ -93,6 +103,7 @@
93
103
  "test": "vitest run",
94
104
  "test:react": "vitest run --config vitest.react.config.ts",
95
105
  "test:storybook": "vitest run --project=storybook",
106
+ "test:storybook:ci": "node scripts/run-storybook-tests.mjs",
96
107
  "test:watch": "vitest",
97
108
  "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.react.json && tsc --noEmit -p tsconfig.react.test.json && tsc --noEmit -p tsconfig.mcp.json",
98
109
  "examples": "echo 'Serving repo root on http://localhost:8000 — open http://localhost:8000/examples/composable/index.html' && python3 -m http.server 8000",
@@ -103,7 +114,11 @@
103
114
  "build:css:watch": "tailwindcss -i src/elements/styles.css -o src/elements/compiled.css --watch",
104
115
  "dev:provider": "vite examples/remote-provider --port 6007 --strictPort",
105
116
  "dev:host": "vite examples/remote-host --port 6006 --strictPort",
106
- "test:e2e": "playwright test"
117
+ "test:e2e": "playwright test",
118
+ "test:composer-ivp": "playwright test --config playwright.composer.config.ts",
119
+ "test:slots-ivp": "playwright test --config playwright.slots.config.ts",
120
+ "test:menu-ivp": "playwright test --config playwright.menu.config.ts",
121
+ "test:command-ivp": "playwright test --config playwright.command.config.ts"
107
122
  },
108
123
  "dependencies": {
109
124
  "@floating-ui/dom": "^1.7.6",
@@ -46,6 +46,18 @@ export interface CemCssProperty {
46
46
  default?: string;
47
47
  }
48
48
 
49
+ export interface CemSlot {
50
+ name: string;
51
+ description?: string;
52
+ }
53
+
54
+ export interface CemCssPart {
55
+ name: string;
56
+ description?: string;
57
+ /** Our extension: a copy-paste styling example. */
58
+ recipe?: string;
59
+ }
60
+
49
61
  export interface Declaration {
50
62
  tagName?: string;
51
63
  name: string;
@@ -55,6 +67,8 @@ export interface Declaration {
55
67
  attributes?: CemAttribute[];
56
68
  events?: CemEvent[];
57
69
  cssProperties?: CemCssProperty[];
70
+ slots?: CemSlot[];
71
+ cssParts?: CemCssPart[];
58
72
  }
59
73
 
60
74
  interface CemModule {
@@ -27,11 +27,11 @@ const RULES: Rule[] = [
27
27
  // Source: for-ai-agents.mdx §1; context7.json rule 2
28
28
  id: 'array-as-attribute',
29
29
  test: (t) =>
30
- /\b(messages|models|context|suggestions|slashCommands)\s*=\s*["']/.test(t),
30
+ /\b(messages|models|context|suggestions|triggers)\s*=\s*["']/.test(t),
31
31
  title: 'Array/object prop set as an HTML attribute (silent failure)',
32
32
  cause:
33
33
  'An HTML attribute is always a string. Passing `messages`, `models`, `context`, ' +
34
- '`suggestions`, or `slashCommands` as an HTML attribute silently fails — ' +
34
+ '`suggestions`, or `triggers` as an HTML attribute silently fails — ' +
35
35
  'the element receives a stringified value it cannot parse.',
36
36
  fix:
37
37
  'Set the property in JavaScript, not as an HTML attribute. ' +
@@ -72,7 +72,11 @@ const RULES: Rule[] = [
72
72
  '// ❌ Does NOT trigger re-render\n' +
73
73
  'chat.messages.push(newMsg);\n' +
74
74
  'chat.messages[i].content = accumulated;\n' +
75
- '```',
75
+ '```\n\n' +
76
+ 'The ergonomic path: helpers in `@kitn.ai/ui/state` (`appendMessage`, `updateMessage`, `appendContent`) ' +
77
+ 'and `createAssistantStream` handle the new-reference contract for you. ' +
78
+ '`useKaiChat` (React) and `createKaiChat` (Solid) own state entirely so mutation is never an option.\n\n' +
79
+ '// setMessages((m) => appendMessage(m, msg)) // new array, no footgun',
76
80
  },
77
81
  {
78
82
  // Rule 3 — listening for events on a parent / wrong element
@@ -108,15 +112,15 @@ const RULES: Rule[] = [
108
112
  title: 'Wrong element prefix `kitn-` (should be `kai-`)',
109
113
  cause:
110
114
  'The custom element prefix is `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`). ' +
111
- '`kitn-chat` is only a bundle filename — it is not a registered element name. ' +
112
- 'Using `<kitn-chat>` results in an unknown element that renders nothing.',
115
+ '`kitn-` is a legacy name (the register-all bundle is `kai.es.js`) — it is not a ' +
116
+ 'registered element name. Using `<kitn-chat>` results in an unknown element that renders nothing.',
113
117
  fix:
114
118
  'Replace the `kitn-` prefix with `kai-` everywhere.\n\n' +
115
119
  '```html\n' +
116
120
  '<!-- ✅ Correct element prefix -->\n' +
117
121
  '<kai-chat></kai-chat>\n' +
118
122
  '<kai-artifact></kai-artifact>\n\n' +
119
- '<!-- ❌ Wrong — kitn-chat is a bundle filename, not an element -->\n' +
123
+ '<!-- ❌ Wrong — kitn-chat is not an element (the bundle is kai.es.js) -->\n' +
120
124
  '<kitn-chat></kitn-chat>\n' +
121
125
  '```',
122
126
  },
@@ -104,6 +104,38 @@ function formatReference(tag: string): string {
104
104
  }
105
105
  }
106
106
 
107
+ // ── Composition slots ──────────────────────────────────────────────────────
108
+ const slots = el.slots ?? [];
109
+ if (slots.length > 0) {
110
+ lines.push(
111
+ '',
112
+ '### Composition slots',
113
+ 'Project your own markup into these named regions — add a light-DOM child ' +
114
+ 'with a `slot="…"` attribute (e.g. `<div slot="sidebar">…</div>`).',
115
+ );
116
+ for (const slot of slots) {
117
+ const desc = slot.description?.trim() ?? '';
118
+ lines.push(`- **${slot.name}**${desc ? ` — ${desc}` : ''}`);
119
+ }
120
+ }
121
+
122
+ // ── Styleable parts (::part) ───────────────────────────────────────────────
123
+ const parts = el.cssParts ?? [];
124
+ if (parts.length > 0) {
125
+ lines.push(
126
+ '',
127
+ '### Styleable parts (`::part`)',
128
+ 'Restyle these from outside the Shadow DOM via `' + tag + '::part(name) { … }`.',
129
+ );
130
+ for (const part of parts) {
131
+ const desc = part.description?.trim() ?? '';
132
+ lines.push(`- **${part.name}**${desc ? ` — ${desc}` : ''}`);
133
+ if (part.recipe) {
134
+ lines.push(' ```css', ` ${part.recipe}`, ' ```');
135
+ }
136
+ }
137
+ }
138
+
107
139
  return lines.join('\n');
108
140
  }
109
141
 
@@ -1651,10 +1651,37 @@ function interactionPatternsBlock(): string {
1651
1651
  `});`,
1652
1652
  ].join('\n');
1653
1653
 
1654
+ const statePattern = [
1655
+ `--- Pattern: State helpers + streaming (new-array contract) ---`,
1656
+ `// Setter contract: always (prev) => next — every helper returns a new array.`,
1657
+ `// Vanilla adapter (works with any element ref):`,
1658
+ `// const set = (fn) => { el.messages = fn(el.messages ?? []); };`,
1659
+ ``,
1660
+ `// Low-level helpers from @kitn.ai/ui/state:`,
1661
+ `// import { appendMessage, updateMessage, appendContent, createAssistantStream } from '@kitn.ai/ui/state';`,
1662
+ ``,
1663
+ `// Streaming loop (framework-agnostic):`,
1664
+ `// const stream = createAssistantStream(set);`,
1665
+ `// stream.appendText(chunk); // text delta`,
1666
+ `// stream.appendReasoning(chunk); // reasoning delta`,
1667
+ `// stream.upsertTool(toolCall); // tool call delta`,
1668
+ `// stream.done(); // seal the message`,
1669
+ ``,
1670
+ `// One-liner for React (batteries-included):`,
1671
+ `// import { useKaiChat } from '@kitn.ai/ui/react';`,
1672
+ `// const chat = useKaiChat();`,
1673
+ `// <Chat {...chat.bind} />`,
1674
+ ``,
1675
+ `// One-liner for Solid (batteries-included):`,
1676
+ `// import { createKaiChat } from '@kitn.ai/ui';`,
1677
+ `// const chat = createKaiChat();`,
1678
+ `// <kai-chat {...chat.bind} on:kai-submit={chat.handleSubmit} />`,
1679
+ ].join('\n');
1680
+
1654
1681
  return [
1655
1682
  `=== INTERACTION PATTERNS ===`,
1656
1683
  ``,
1657
- `Optional snippets for confirmations, card recovery, and preference capture.`,
1684
+ `Optional snippets for confirmations, card recovery, preference capture, and state/streaming helpers.`,
1658
1685
  `Drop in the one(s) you need; all imports resolve from @kitn.ai/ui.`,
1659
1686
  ``,
1660
1687
  toastPattern,
@@ -1662,6 +1689,8 @@ function interactionPatternsBlock(): string {
1662
1689
  recoveryPattern,
1663
1690
  ``,
1664
1691
  preferencePattern,
1692
+ ``,
1693
+ statePattern,
1665
1694
  ].join('\n');
1666
1695
  }
1667
1696
 
@@ -35,13 +35,43 @@ export type ArtifactTab = 'preview' | 'code';
35
35
  /** A file the artifact can preview + show source for. */
36
36
  export type ArtifactFile = FileTreeFile;
37
37
 
38
+ /** Imperative handle exposed via `controllerRef` — surfaces the artifact's latent
39
+ * toolbar capabilities (history back/forward/reload/home, programmatic navigate,
40
+ * file selection, open-in-new-tab, maximize/restore) so the `<kai-artifact>`
41
+ * facade can forward them as instance methods. Each delegates to the SAME internal
42
+ * handler the toolbar buttons use, so every existing event still fires. */
43
+ export interface ArtifactController {
44
+ /** Go back in the artifact's own history stack (no-op when there's no prior entry). */
45
+ back(): void;
46
+ /** Go forward in the history stack (no-op when there's no forward entry). */
47
+ forward(): void;
48
+ /** Force-reload the current preview url (also re-renders an inline PDF). */
49
+ reload(): void;
50
+ /** Navigate to the `src` home url (no-op when there's no `src`). */
51
+ home(): void;
52
+ /** Push + load a url in the preview (the path-field submit path). */
53
+ navigate(url: string): void;
54
+ /** Select a file by path: highlights the tree, shows its source, navigates the preview. */
55
+ selectFile(path: string): void;
56
+ /** Open the current url in a new browser tab (no-op when there's no concrete url). */
57
+ openExternal(): void;
58
+ /** Enter the maximized view-state (fires onMaximizeChange/kai-maximize-change). */
59
+ maximize(): void;
60
+ /** Exit the maximized view-state. */
61
+ restore(): void;
62
+ }
63
+
38
64
  export interface ArtifactProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, 'onSelect'> {
39
65
  /** URL the preview iframe frames. */
40
66
  src?: string;
41
67
  /** Files for the Code tab's tree (+ each file's preview `url`). */
42
68
  files?: ArtifactFile[];
43
- /** Active tab. Default `preview`. */
69
+ /** Controlled active tab when set, the artifact follows it (re-asserted on
70
+ * every change). When undefined the tab is uncontrolled (see `defaultTab`). */
44
71
  tab?: ArtifactTab;
72
+ /** Uncontrolled INITIAL tab (used only when `tab` is undefined). The user can
73
+ * then freely switch tabs; defaults to `preview`. */
74
+ defaultTab?: ArtifactTab;
45
75
  /** Selected file path (syncs tree highlight + Code source + preview). */
46
76
  activeFile?: string;
47
77
  /** iframe `sandbox` override. Default `allow-scripts allow-forms`. */
@@ -80,6 +110,15 @@ export interface ArtifactProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>,
80
110
  standalone?: boolean;
81
111
  /** Make the path field read-only (visible, nav-tracking, non-editable). */
82
112
  readonlyPath?: boolean;
113
+ /** Friendly address shown in the path field INSTEAD of the real current url
114
+ * (read-only, non-navigable). Use when the framed url is not consumer-facing
115
+ * (e.g. a `data:` blob) so a clean address is shown instead of leaking it.
116
+ * Unset = show the real url (editable per `readonlyPath`). */
117
+ displayUrl?: string;
118
+ /** Receive the imperative controller once mounted. The `<kai-artifact>` facade
119
+ * forwards these as element methods (back/forward/reload/home/navigate/
120
+ * selectFile/openExternal/maximize/restore). */
121
+ controllerRef?: (controller: ArtifactController) => void;
83
122
  }
84
123
 
85
124
  const DEFAULT_SANDBOX = 'allow-scripts allow-forms';
@@ -116,7 +155,9 @@ export function Artifact(props: ArtifactProps): JSX.Element {
116
155
  const merged = mergeProps(
117
156
  {
118
157
  files: [] as ArtifactFile[],
119
- tab: 'preview' as ArtifactTab,
158
+ // No `tab` default: a present `tab` means controlled. The uncontrolled
159
+ // initial tab comes from `defaultTab` (seeded into the internal signal below).
160
+ defaultTab: 'preview' as ArtifactTab,
120
161
  sandbox: DEFAULT_SANDBOX,
121
162
  showNav: true,
122
163
  showReload: true,
@@ -135,6 +176,7 @@ export function Artifact(props: ArtifactProps): JSX.Element {
135
176
  'src',
136
177
  'files',
137
178
  'tab',
179
+ 'defaultTab',
138
180
  'activeFile',
139
181
  'sandbox',
140
182
  'iframeTitle',
@@ -152,6 +194,8 @@ export function Artifact(props: ArtifactProps): JSX.Element {
152
194
  'openInTab',
153
195
  'standalone',
154
196
  'readonlyPath',
197
+ 'displayUrl',
198
+ 'controllerRef',
155
199
  'class',
156
200
  ]);
157
201
 
@@ -169,7 +213,11 @@ export function Artifact(props: ArtifactProps): JSX.Element {
169
213
  const canBack = () => cursor() > 0;
170
214
  const canForward = () => cursor() < history().length - 1;
171
215
 
172
- const [tab, setTab] = createSignal<ArtifactTab>(local.tab);
216
+ // Seed the internal tab: a present `tab` (controlled) wins; otherwise the
217
+ // uncontrolled `defaultTab` (which merges to 'preview'). The user can then
218
+ // switch freely unless `tab` is set (the effect below re-asserts the controlled
219
+ // value on each change).
220
+ const [tab, setTab] = createSignal<ArtifactTab>(local.tab ?? local.defaultTab);
173
221
  const [activeFile, setActiveFile] = createSignal<string | undefined>(local.activeFile);
174
222
  const [reloadKey, setReloadKey] = createSignal(0);
175
223
 
@@ -208,8 +256,12 @@ export function Artifact(props: ArtifactProps): JSX.Element {
208
256
 
209
257
  let iframeEl: HTMLIFrameElement | undefined;
210
258
 
211
- // Controlled syncing: when the consumer changes the props, follow them.
212
- createEffect(() => setTab(local.tab));
259
+ // Controlled syncing: when the consumer changes the props, follow them. `tab` is
260
+ // followed ONLY when it's actually set — an undefined `tab` means uncontrolled,
261
+ // so the internal signal (seeded from defaultTab) is left for the user to drive.
262
+ createEffect(() => {
263
+ if (local.tab !== undefined) setTab(local.tab);
264
+ });
213
265
  createEffect(() => setActiveFile(local.activeFile));
214
266
  // `src` change → navigate. Use `on(local.src, …)` so the effect tracks ONLY
215
267
  // the `src` prop — NOT `currentUrl()` — otherwise navigating away (file click,
@@ -290,6 +342,38 @@ export function Artifact(props: ArtifactProps): JSX.Element {
290
342
  if (local.src) navigate(local.src);
291
343
  };
292
344
 
345
+ // Explicitly drive the maximize view-state to a target (the imperative twin of
346
+ // the toggle button). Fires onMaximizeChange only when the value actually flips,
347
+ // matching toggleMaximize's "report on change" contract.
348
+ const setMaximizeState = (next: boolean) => {
349
+ if (maximized() === next) return;
350
+ setMaximized(next);
351
+ local.onMaximizeChange?.(next);
352
+ };
353
+
354
+ // --- Imperative controller (Pattern C): hand the facade a handle over the
355
+ // artifact's latent toolbar capabilities. Every method delegates to the
356
+ // SAME internal handler the toolbar buttons use, so navigate/tab-change/
357
+ // file-select/maximize-change all still fire. ---
358
+ onMount(() => {
359
+ local.controllerRef?.({
360
+ back: () => goBack(),
361
+ forward: () => goForward(),
362
+ reload: () => reload(),
363
+ home: () => goHome(),
364
+ navigate: (url) => navigate(url),
365
+ // Resolve the file for the path so highlight + source + preview all sync;
366
+ // a path with no matching file entry is a no-op (nothing to show).
367
+ selectFile: (path) => {
368
+ const file = fileFor(path);
369
+ if (file) selectFile(path, file);
370
+ },
371
+ openExternal: () => openInNewTab(),
372
+ maximize: () => setMaximizeState(true),
373
+ restore: () => setMaximizeState(false),
374
+ });
375
+ });
376
+
293
377
  // Best-effort: if the consumer opted into `allow-same-origin`, keep the path
294
378
  // field truthful as the framed doc navigates itself. Cross-origin (the secure
295
379
  // default) throws and we keep our own stack.
@@ -311,9 +395,10 @@ export function Artifact(props: ArtifactProps): JSX.Element {
311
395
  const input = (e.currentTarget as HTMLFormElement).elements.namedItem(
312
396
  'kai-artifact-path',
313
397
  ) as HTMLInputElement | null;
314
- if (local.readonlyPath) {
315
- // Submit is a no-op while read-only; keep the field reflecting currentUrl.
316
- if (input) input.value = currentUrl();
398
+ if (local.readonlyPath || local.displayUrl != null) {
399
+ // Submit is a no-op while read-only or showing a friendly displayUrl; keep
400
+ // the field reflecting the shown value (never push the real, possibly data:, url).
401
+ if (input) input.value = local.displayUrl ?? currentUrl();
317
402
  return;
318
403
  }
319
404
  if (input && input.value) navigate(input.value);
@@ -330,7 +415,7 @@ export function Artifact(props: ArtifactProps): JSX.Element {
330
415
  >
331
416
  <Show when={showAnyToolbar()}>
332
417
  <ArtifactToolbar
333
- url={currentUrl}
418
+ url={() => local.displayUrl ?? currentUrl()}
334
419
  tab={tab}
335
420
  canBack={canBack}
336
421
  canForward={canForward}
@@ -352,7 +437,7 @@ export function Artifact(props: ArtifactProps): JSX.Element {
352
437
  onToggleMaximize={toggleMaximize}
353
438
  canOpenInTab={canOpenInTab}
354
439
  onOpenInTab={openInNewTab}
355
- readonlyPath={() => local.readonlyPath}
440
+ readonlyPath={() => local.readonlyPath || local.displayUrl != null}
356
441
  />
357
442
  </Show>
358
443
  <div class="relative min-h-0 flex-1">
@@ -420,7 +505,7 @@ function ArtifactToolbar(props: ToolbarProps): JSX.Element {
420
505
  return (
421
506
  <div
422
507
  data-artifact-toolbar
423
- class="flex shrink-0 items-center gap-1.5 border-b border-border bg-muted/40 px-2 py-1.5"
508
+ class="flex shrink-0 items-center gap-1.5 border-b border-border bg-surface px-2 py-1.5"
424
509
  >
425
510
  <Show when={props.showNav()}>
426
511
  <Button
@@ -595,7 +680,7 @@ interface CodeProps {
595
680
  function ArtifactCode(props: CodeProps): JSX.Element {
596
681
  return (
597
682
  <div class="absolute inset-0 flex">
598
- <div class="w-56 shrink-0 overflow-auto border-r border-border bg-muted/20 py-1.5 scrollbar-thin">
683
+ <div class="w-56 shrink-0 overflow-auto border-r border-border bg-surface-sunken py-1.5 scrollbar-thin">
599
684
  <FileTree
600
685
  files={props.files}
601
686
  activeFile={props.activeFile()}
@@ -728,7 +813,7 @@ function ArtifactPdfPreview(props: { url: string; reloadKey: number }): JSX.Elem
728
813
  aria-label="PDF preview"
729
814
  aria-busy={state() === 'loading'}
730
815
  tabindex="0"
731
- class="absolute inset-0 flex flex-col items-center gap-3 overflow-auto bg-muted/20 p-3 scrollbar-thin focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset"
816
+ class="absolute inset-0 flex flex-col items-center gap-3 overflow-auto bg-surface-sunken p-3 scrollbar-thin focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset"
732
817
  />
733
818
  <Show when={isPdfPreviewEnabled() && state() === 'loading'}>
734
819
  <div class="pointer-events-none absolute inset-0 flex items-center justify-center">
@@ -0,0 +1,13 @@
1
+ /** A message attachment descriptor. Pure type — kept JSX-free for the
2
+ * framework-neutral consumers (state core, React hook typecheck). */
3
+ export interface AttachmentData {
4
+ id: string;
5
+ type: 'file' | 'source-document';
6
+ filename?: string;
7
+ mediaType?: string;
8
+ url?: string;
9
+ title?: string;
10
+ }
11
+
12
+ export type AttachmentMediaCategory = 'image' | 'video' | 'audio' | 'document' | 'source' | 'unknown';
13
+ export type AttachmentVariant = 'grid' | 'inline' | 'list';
@@ -11,23 +11,13 @@ import {
11
11
  Video,
12
12
  X,
13
13
  } from 'lucide-solid';
14
+ import type { AttachmentData, AttachmentMediaCategory, AttachmentVariant } from './attachment-types';
15
+ export type { AttachmentData, AttachmentMediaCategory, AttachmentVariant } from './attachment-types';
14
16
 
15
17
  // ============================================================================
16
18
  // Types
17
19
  // ============================================================================
18
20
 
19
- export interface AttachmentData {
20
- id: string;
21
- type: 'file' | 'source-document';
22
- filename?: string;
23
- mediaType?: string;
24
- url?: string;
25
- title?: string;
26
- }
27
-
28
- export type AttachmentMediaCategory = 'image' | 'video' | 'audio' | 'document' | 'source' | 'unknown';
29
- export type AttachmentVariant = 'grid' | 'inline' | 'list';
30
-
31
21
  const mediaCategoryIcons: Record<AttachmentMediaCategory, typeof ImageIcon> = {
32
22
  audio: Music2,
33
23
  document: FileText,
@@ -159,12 +149,12 @@ function Attachment(props: AttachmentProps) {
159
149
  ctx.variant === 'grid' && 'size-24 overflow-hidden rounded-lg',
160
150
  ctx.variant === 'inline' && [
161
151
  'flex h-8 cursor-pointer select-none items-center gap-1.5',
162
- 'rounded-md bg-muted/50 px-1.5 text-foreground',
152
+ 'rounded-md bg-surface-strong px-1.5 text-foreground',
163
153
  'font-medium text-sm transition-all',
164
154
  'hover:bg-muted',
165
155
  ],
166
156
  ctx.variant === 'list' && [
167
- 'flex w-full items-center gap-3 rounded-lg bg-muted/30 p-3 text-foreground',
157
+ 'flex w-full items-center gap-3 rounded-lg bg-surface p-3 text-foreground',
168
158
  'hover:bg-muted/50',
169
159
  ],
170
160
  local.class,