@kitn.ai/ui 0.15.1 → 0.17.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 (333) hide show
  1. package/README.md +37 -13
  2. package/bin/mcp.js +22 -0
  3. package/dist/bash-InADTalH.js +6 -1
  4. package/dist/components/artifact.d.ts +58 -0
  5. package/dist/components/attachments.d.ts +67 -0
  6. package/dist/components/card-fallback.d.ts +10 -0
  7. package/dist/components/card-renderer.d.ts +13 -0
  8. package/dist/components/card.d.ts +28 -0
  9. package/dist/components/chain-of-thought.d.ts +29 -0
  10. package/dist/components/chat-container.d.ts +19 -0
  11. package/dist/components/chat-scope-picker.d.ts +9 -0
  12. package/dist/components/chat-thread.d.ts +91 -0
  13. package/dist/components/checkpoint.d.ts +20 -0
  14. package/dist/components/choice-card.d.ts +78 -0
  15. package/dist/components/code-block.d.ts +16 -0
  16. package/dist/components/confirm-card.d.ts +57 -0
  17. package/dist/components/context.d.ts +65 -0
  18. package/dist/components/conversation-item.d.ts +8 -0
  19. package/dist/components/conversation-list.d.ts +11 -0
  20. package/dist/components/dismissed-stub.d.ts +22 -0
  21. package/dist/components/embed.d.ts +21 -0
  22. package/dist/components/empty.d.ts +43 -0
  23. package/dist/components/feedback-bar.d.ts +45 -0
  24. package/dist/components/file-tree.d.ts +57 -0
  25. package/dist/components/file-upload.d.ts +16 -0
  26. package/dist/components/form-widgets.d.ts +31 -0
  27. package/dist/components/form.d.ts +103 -0
  28. package/dist/components/image.d.ts +12 -0
  29. package/dist/components/link-preview.d.ts +23 -0
  30. package/dist/components/loader.d.ts +60 -0
  31. package/dist/components/markdown.d.ts +8 -0
  32. package/dist/components/message-skills.d.ts +15 -0
  33. package/dist/components/message.d.ts +111 -0
  34. package/dist/components/model-switcher.d.ts +8 -0
  35. package/dist/components/prompt-input.d.ts +38 -0
  36. package/dist/components/prompt-suggestion.d.ts +13 -0
  37. package/dist/components/reasoning.d.ts +20 -0
  38. package/dist/components/response-compare-types.d.ts +66 -0
  39. package/dist/components/response-compare.d.ts +51 -0
  40. package/dist/components/response-stream.d.ts +14 -0
  41. package/dist/components/scroll-button.d.ts +7 -0
  42. package/dist/components/slash-command.d.ts +15 -0
  43. package/dist/components/source.d.ts +23 -0
  44. package/dist/components/tasks-card.d.ts +72 -0
  45. package/dist/components/text-shimmer.d.ts +9 -0
  46. package/dist/components/thinking-bar.d.ts +10 -0
  47. package/dist/components/toast.d.ts +48 -0
  48. package/dist/components/tool.d.ts +16 -0
  49. package/dist/components/use-card-resolution.d.ts +16 -0
  50. package/dist/components/voice-input.d.ts +7 -0
  51. package/dist/core-AYMC6_lb.js +5874 -12
  52. package/dist/css-M7EaDHN_.js +6 -1
  53. package/dist/custom-elements.json +260 -11
  54. package/dist/elements/artifact.d.ts +1 -0
  55. package/dist/elements/artifact.js +1 -0
  56. package/dist/elements/attachments.d.ts +1 -0
  57. package/dist/elements/attachments.js +1 -0
  58. package/dist/elements/autoloader.d.ts +2 -0
  59. package/dist/elements/autoloader.js +1 -0
  60. package/dist/elements/card.d.ts +1 -0
  61. package/dist/elements/card.js +1 -0
  62. package/dist/elements/cards.d.ts +1 -0
  63. package/dist/elements/cards.js +1 -0
  64. package/dist/elements/chain-of-thought.d.ts +1 -0
  65. package/dist/elements/chain-of-thought.js +1 -0
  66. package/dist/elements/chat-scope-picker.d.ts +1 -0
  67. package/dist/elements/chat-scope-picker.js +1 -0
  68. package/dist/elements/chat-workspace.d.ts +1 -0
  69. package/dist/elements/chat-workspace.js +1 -0
  70. package/dist/elements/chat.d.ts +1 -0
  71. package/dist/elements/chat.js +1 -0
  72. package/dist/elements/checkpoint.d.ts +1 -0
  73. package/dist/elements/checkpoint.js +1 -0
  74. package/dist/elements/choice.d.ts +1 -0
  75. package/dist/elements/choice.js +1 -0
  76. package/dist/elements/chunks/Icon-D_Zmwmwh.js +1 -0
  77. package/dist/elements/chunks/action-icons-PVfIvcuG.js +1 -0
  78. package/dist/elements/chunks/attachments-Dp6vqtrc.js +1 -0
  79. package/dist/elements/chunks/bash-InADTalH.js +1 -0
  80. package/dist/elements/chunks/button-CKyYD9G4.js +1 -0
  81. package/dist/elements/chunks/card-Cjho-PYk.js +1 -0
  82. package/dist/elements/chunks/card-routing-C986KuUA.js +1 -0
  83. package/dist/elements/chunks/chat-thread-RT808iPf.js +1 -0
  84. package/dist/elements/chunks/check-CDYaMYrM.js +1 -0
  85. package/dist/elements/chunks/chevron-down-3SBiq8HF.js +1 -0
  86. package/dist/elements/chunks/chevron-right-k2UFlIVK.js +1 -0
  87. package/dist/elements/chunks/cn-Dogu6PbV.js +1 -0
  88. package/dist/elements/chunks/code-block-BYUmfFSd.js +1 -0
  89. package/dist/elements/chunks/collapsible-BiNwdOn6.js +1 -0
  90. package/dist/elements/chunks/context-18g6oi4J.js +1 -0
  91. package/dist/elements/chunks/conversation-list-D9Y0NVdo.js +1 -0
  92. package/dist/elements/chunks/core-AYMC6_lb.js +12 -0
  93. package/dist/elements/chunks/css-M7EaDHN_.js +1 -0
  94. package/dist/elements/chunks/default-input-CSAoYYMd.js +1 -0
  95. package/dist/elements/chunks/download-D8K0Je8r.js +1 -0
  96. package/dist/elements/chunks/dropdown-bUs2iTia.js +1 -0
  97. package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +141 -0
  98. package/dist/elements/chunks/external-link-6mA0wxab.js +1 -0
  99. package/dist/elements/chunks/file-text-DnaYk3Dm.js +1 -0
  100. package/dist/elements/chunks/file-tree-CgtRLlxK.js +1 -0
  101. package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +1 -0
  102. package/dist/elements/chunks/github-light-JYsPkUQd.js +1 -0
  103. package/dist/elements/chunks/hover-card-CIGw62gP.js +1 -0
  104. package/dist/elements/chunks/html-CPZ3oZQ7.js +1 -0
  105. package/dist/elements/chunks/index-CTBEJeo6.js +1 -0
  106. package/dist/elements/chunks/javascript-C25yR2R2.js +1 -0
  107. package/dist/elements/chunks/json-DxJze_jm.js +1 -0
  108. package/dist/elements/chunks/link-BlGSeoPy.js +1 -0
  109. package/dist/elements/chunks/loader-DvhR4qa0.js +1 -0
  110. package/dist/elements/chunks/markdown-CMTGx9r8.js +64 -0
  111. package/dist/elements/chunks/message-CDZwXjhL.js +1 -0
  112. package/dist/elements/chunks/message-feedback-CYx81QiA.js +1 -0
  113. package/dist/elements/chunks/model-switcher-O_tUhoOT.js +1 -0
  114. package/dist/elements/chunks/overlay-DydXYMQW.js +1 -0
  115. package/dist/elements/chunks/prompt-suggestion-ldlWV5kd.js +1 -0
  116. package/dist/elements/chunks/reasoning-2PUnHlmr.js +1 -0
  117. package/dist/elements/chunks/resizable-B5WNbSeb.js +1 -0
  118. package/dist/elements/chunks/star-t9tI-P0q.js +1 -0
  119. package/dist/elements/chunks/store-C6rIooZz.js +1 -0
  120. package/dist/elements/chunks/svelte--5p79yCD.js +1 -0
  121. package/dist/elements/chunks/text-shimmer-uh9V_KUh.js +1 -0
  122. package/dist/elements/chunks/textarea-3nm6Ia9U.js +1 -0
  123. package/dist/elements/chunks/thumbs-up-BBtguGld.js +1 -0
  124. package/dist/elements/chunks/toast-store-D8cL3fWl.js +1 -0
  125. package/dist/elements/chunks/tool-GJ3vwp1U.js +1 -0
  126. package/dist/elements/chunks/tooltip-DwKAz4XR.js +1 -0
  127. package/dist/elements/chunks/triangle-alert-Ct1zt2JL.js +1 -0
  128. package/dist/elements/chunks/tsx-B8rCNbgL.js +1 -0
  129. package/dist/elements/chunks/typescript-RycA9KXf.js +1 -0
  130. package/dist/elements/chunks/use-card-resolution-D-_0Alzy.js +1 -0
  131. package/dist/elements/chunks/video-mVYiM99-.js +1 -0
  132. package/dist/elements/chunks/vue-BmIZj4XD.js +1 -0
  133. package/dist/elements/chunks/x-CzxL27Ch.js +1 -0
  134. package/dist/elements/code-block.d.ts +1 -0
  135. package/dist/elements/code-block.js +1 -0
  136. package/dist/elements/compare.d.ts +1 -0
  137. package/dist/elements/compare.js +1 -0
  138. package/dist/elements/confirm-card.d.ts +1 -0
  139. package/dist/elements/confirm-card.js +1 -0
  140. package/dist/elements/context-meter.d.ts +1 -0
  141. package/dist/elements/context-meter.js +1 -0
  142. package/dist/elements/conversation-list.d.ts +1 -0
  143. package/dist/elements/conversation-list.js +1 -0
  144. package/dist/elements/embed.d.ts +1 -0
  145. package/dist/elements/embed.js +1 -0
  146. package/dist/elements/empty.d.ts +1 -0
  147. package/dist/elements/empty.js +1 -0
  148. package/dist/elements/feedback-bar.d.ts +1 -0
  149. package/dist/elements/feedback-bar.js +1 -0
  150. package/dist/elements/file-tree.d.ts +1 -0
  151. package/dist/elements/file-tree.js +1 -0
  152. package/dist/elements/file-upload.d.ts +1 -0
  153. package/dist/elements/file-upload.js +1 -0
  154. package/dist/elements/form.d.ts +1 -0
  155. package/dist/elements/form.js +1 -0
  156. package/dist/elements/image.d.ts +1 -0
  157. package/dist/elements/image.js +1 -0
  158. package/dist/elements/link-preview.d.ts +1 -0
  159. package/dist/elements/link-preview.js +1 -0
  160. package/dist/elements/loader.d.ts +1 -0
  161. package/dist/elements/loader.js +1 -0
  162. package/dist/elements/markdown.d.ts +1 -0
  163. package/dist/elements/markdown.js +1 -0
  164. package/dist/elements/message-skills.d.ts +1 -0
  165. package/dist/elements/message-skills.js +1 -0
  166. package/dist/elements/message.d.ts +1 -0
  167. package/dist/elements/message.js +1 -0
  168. package/dist/elements/model-switcher.d.ts +1 -0
  169. package/dist/elements/model-switcher.js +1 -0
  170. package/dist/elements/popover.d.ts +1 -0
  171. package/dist/elements/popover.js +1 -0
  172. package/dist/elements/prompt-input.d.ts +1 -0
  173. package/dist/elements/prompt-input.js +1 -0
  174. package/dist/elements/prompt-suggestions.d.ts +1 -0
  175. package/dist/elements/prompt-suggestions.js +1 -0
  176. package/dist/elements/reasoning.d.ts +1 -0
  177. package/dist/elements/reasoning.js +1 -0
  178. package/dist/elements/resizable.d.ts +1 -0
  179. package/dist/elements/resizable.js +1 -0
  180. package/dist/elements/response-stream.d.ts +1 -0
  181. package/dist/elements/response-stream.js +14 -0
  182. package/dist/elements/scroll-button.d.ts +1 -0
  183. package/dist/elements/scroll-button.js +1 -0
  184. package/dist/elements/source.d.ts +1 -0
  185. package/dist/elements/source.js +1 -0
  186. package/dist/elements/switch.d.ts +1 -0
  187. package/dist/elements/switch.js +1 -0
  188. package/dist/elements/tasks.d.ts +1 -0
  189. package/dist/elements/tasks.js +1 -0
  190. package/dist/elements/text-shimmer.d.ts +1 -0
  191. package/dist/elements/text-shimmer.js +1 -0
  192. package/dist/elements/thinking-bar.d.ts +1 -0
  193. package/dist/elements/thinking-bar.js +1 -0
  194. package/dist/elements/toast.d.ts +1 -0
  195. package/dist/elements/toast.js +1 -0
  196. package/dist/elements/tool.d.ts +1 -0
  197. package/dist/elements/tool.js +1 -0
  198. package/dist/elements/voice-input.d.ts +1 -0
  199. package/dist/elements/voice-input.js +1 -0
  200. package/dist/elements.d.ts +768 -0
  201. package/dist/engine-javascript-vq0WuIJl.js +2516 -14
  202. package/dist/github-dark-dimmed-DUshB20C.js +4 -1
  203. package/dist/github-light-JYsPkUQd.js +4 -1
  204. package/dist/html-CPZ3oZQ7.js +10 -1
  205. package/dist/index.d.ts +124 -2
  206. package/dist/index.js +15593 -0
  207. package/dist/javascript-C25yR2R2.js +6 -1
  208. package/dist/json-DxJze_jm.js +6 -1
  209. package/dist/kitn-chat.es.js +1 -77
  210. package/dist/llms/llms-full.txt +57 -12
  211. package/dist/llms/llms.txt +3 -3
  212. package/dist/mcp.es.js +2296 -0
  213. package/dist/primitives/card-contract.d.ts +119 -0
  214. package/dist/primitives/card-host.d.ts +12 -0
  215. package/dist/primitives/card-recovery.d.ts +55 -0
  216. package/dist/primitives/card-registry.d.ts +17 -0
  217. package/dist/primitives/card-resolution.d.ts +8 -0
  218. package/dist/primitives/card-routing.d.ts +12 -0
  219. package/dist/primitives/card-validate.d.ts +25 -0
  220. package/dist/primitives/chat-config.d.ts +31 -0
  221. package/dist/primitives/controllable.d.ts +13 -0
  222. package/dist/primitives/embed-providers.d.ts +65 -0
  223. package/dist/primitives/highlighter.d.ts +23 -0
  224. package/dist/primitives/link-preview.d.ts +47 -0
  225. package/dist/primitives/message-feedback.d.ts +35 -0
  226. package/dist/primitives/pdf-preview.d.ts +50 -0
  227. package/dist/primitives/toast-store.d.ts +88 -0
  228. package/dist/primitives/use-auto-resize.d.ts +8 -0
  229. package/dist/primitives/use-resize-observer.d.ts +1 -0
  230. package/dist/primitives/use-stick-to-bottom.d.ts +5 -0
  231. package/dist/primitives/use-text-stream.d.ts +19 -0
  232. package/dist/primitives/use-voice-recorder.d.ts +9 -0
  233. package/dist/react/index.d.ts +1198 -0
  234. package/dist/react/runtime.d.ts +15 -0
  235. package/dist/react.js +275 -0
  236. package/dist/register-JyTglR6m.js +1 -0
  237. package/dist/register-impl-C6wlSsts.js +77 -0
  238. package/dist/remote/host-embed.d.ts +33 -0
  239. package/dist/remote/index.d.ts +2 -0
  240. package/dist/remote/origin.d.ts +5 -0
  241. package/dist/remote/provider-runtime.d.ts +27 -0
  242. package/dist/remote/provider.d.ts +2 -0
  243. package/dist/remote/validate.d.ts +4 -0
  244. package/dist/remote/version.d.ts +4 -0
  245. package/dist/remote/wire.d.ts +53 -0
  246. package/dist/schemas/choice.schema.json +5 -0
  247. package/dist/schemas/tasks.schema.json +5 -0
  248. package/dist/svelte--5p79yCD.js +15 -1
  249. package/dist/tsx-B8rCNbgL.js +6 -1
  250. package/dist/types.d.ts +42 -0
  251. package/dist/typescript-RycA9KXf.js +6 -1
  252. package/dist/ui/action-icons.d.ts +11 -0
  253. package/dist/ui/avatar.d.ts +8 -0
  254. package/dist/ui/badge.d.ts +9 -0
  255. package/dist/ui/button.d.ts +10 -0
  256. package/dist/ui/collapsible.d.ts +27 -0
  257. package/dist/ui/dropdown.d.ts +20 -0
  258. package/dist/ui/hover-card.d.ts +28 -0
  259. package/dist/ui/overlay.d.ts +67 -0
  260. package/dist/ui/popover.d.ts +32 -0
  261. package/dist/ui/resizable.d.ts +76 -0
  262. package/dist/ui/scroll-area.d.ts +5 -0
  263. package/dist/ui/separator.d.ts +5 -0
  264. package/dist/ui/skeleton.d.ts +5 -0
  265. package/dist/ui/switch.d.ts +19 -0
  266. package/dist/ui/textarea.d.ts +6 -0
  267. package/dist/ui/tooltip.d.ts +9 -0
  268. package/dist/utils/cn.d.ts +2 -0
  269. package/dist/vue-BmIZj4XD.js +33 -1
  270. package/frameworks/react/index.tsx +67 -11
  271. package/frameworks/react/runtime.tsx +16 -2
  272. package/llms-full.txt +57 -12
  273. package/llms.txt +3 -3
  274. package/package.json +36 -14
  275. package/src/agent-tooling/archetypes.ts +46 -0
  276. package/src/agent-tooling/integrations/cloudflare.ts +88 -0
  277. package/src/agent-tooling/integrations/langgraph.ts +60 -0
  278. package/src/agent-tooling/integrations/mastra.ts +27 -0
  279. package/src/agent-tooling/integrations/mock.ts +34 -0
  280. package/src/agent-tooling/integrations/ollama.ts +47 -0
  281. package/src/agent-tooling/integrations/openrouter.ts +26 -0
  282. package/src/agent-tooling/integrations/pi.ts +40 -0
  283. package/src/agent-tooling/integrations/pydantic-ai.ts +52 -0
  284. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +44 -0
  285. package/src/agent-tooling/mcp/manifest.ts +128 -0
  286. package/src/agent-tooling/mcp/server.ts +59 -0
  287. package/src/agent-tooling/mcp/stdio.ts +18 -0
  288. package/src/agent-tooling/mcp/tools/debug.ts +489 -0
  289. package/src/agent-tooling/mcp/tools/reference.ts +132 -0
  290. package/src/agent-tooling/mcp/tools/scaffold.ts +1759 -0
  291. package/src/agent-tooling/mcp/tools/theme.ts +340 -0
  292. package/src/agent-tooling/mcp/tools/types.ts +14 -0
  293. package/src/agent-tooling/registry.ts +41 -0
  294. package/src/agent-tooling/types.ts +30 -0
  295. package/src/components/chat-thread.tsx +27 -35
  296. package/src/components/choice-card.tsx +33 -4
  297. package/src/components/component-meta.json +250 -26
  298. package/src/components/confirm-card.tsx +15 -1
  299. package/src/components/dismissed-stub.tsx +80 -0
  300. package/src/components/form.tsx +21 -3
  301. package/src/components/message.tsx +151 -10
  302. package/src/components/response-compare-types.ts +127 -0
  303. package/src/components/response-compare.tsx +431 -0
  304. package/src/components/tasks-card.tsx +33 -3
  305. package/src/components/toast.tsx +398 -0
  306. package/src/components/use-card-resolution.ts +24 -8
  307. package/src/elements/autoloader.ts +89 -0
  308. package/src/elements/chat-types.ts +7 -0
  309. package/src/elements/chat-workspace.tsx +4 -2
  310. package/src/elements/chat.tsx +4 -2
  311. package/src/elements/compare.tsx +88 -0
  312. package/src/elements/compiled.css +1 -1
  313. package/src/elements/define.tsx +7 -1
  314. package/src/elements/element-manifest.json +182 -0
  315. package/src/elements/element-meta.json +191 -68
  316. package/src/elements/element-types.d.ts +43 -6
  317. package/src/elements/framework-usage.json +25 -0
  318. package/src/elements/message.tsx +27 -45
  319. package/src/elements/register-impl.ts +58 -0
  320. package/src/elements/register.ts +26 -51
  321. package/src/elements/remote.tsx +4 -0
  322. package/src/elements/styles.css +19 -0
  323. package/src/elements/toast.tsx +74 -0
  324. package/src/index.ts +30 -0
  325. package/src/primitives/card-contract.ts +14 -5
  326. package/src/primitives/card-recovery.ts +149 -0
  327. package/src/primitives/card-routing.ts +3 -0
  328. package/src/primitives/card-schemas/choice.schema.json +5 -0
  329. package/src/primitives/card-schemas/tasks.schema.json +5 -0
  330. package/src/primitives/message-feedback.ts +123 -0
  331. package/src/primitives/toast-store.ts +235 -0
  332. package/src/ui/tooltip.tsx +8 -2
  333. package/theme.css +4 -2
@@ -2,6 +2,10 @@
2
2
  // Typed React wrappers for every kitn custom element. Usage:
3
3
  // import { Message } from '@kitn.ai/ui/react';
4
4
  // <Message message={msg} onMessageAction={(e) => …} />
5
+ // The built bundle self-registers all kai-* custom elements — the elements import is
6
+ // injected at build time (see vite.config.react.ts output.banner), so consumers need
7
+ // only this one import. It is kept OUT of this .tsx source so the React typecheck
8
+ // (tsconfig.react.json) does not walk the Solid element source under react-jsx.
5
9
  import { createWebComponent, type WebComponentProps } from './runtime';
6
10
 
7
11
 
@@ -96,11 +100,11 @@ export const Card = createWebComponent<CardProps>(
96
100
 
97
101
  export interface CardsProps extends WebComponentProps {
98
102
  /** The stream of card envelopes to render. Set as a JS PROPERTY: `el.cards = [...]`. */
99
- cards?: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } }[];
103
+ cards?: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } | { kind: "dismissed"; at?: string } | { kind: "expired"; reason?: string; at?: string } }[];
100
104
  /** Optional type→tag overrides/additions (merged over the built-ins). Property: `el.types`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. */
101
105
  types?: Record<string, string>;
102
106
  /** Optional CardPolicy handling child events. Property: `el.policy`. */
103
- policy?: { onSubmit?: (cardId: string, data: unknown) => void; onAction?: (cardId: string, action: string, payload?: unknown) => void; onSendPrompt?: (text: string, opts: { mode: "compose" | "send"; context?: unknown; }) => void; onOpen?: (url: string, target: "tab" | "artifact") => void; onState?: (cardId: string, patch: unknown) => void; onDismiss?: (cardId: string) => void; onError?: (cardId: string, message: string) => void; maxSendPromptMode?: "compose" | "send" };
107
+ policy?: { onSubmit?: (cardId: string, data: unknown) => void; onAction?: (cardId: string, action: string, payload?: unknown) => void; onSendPrompt?: (text: string, opts: { mode: "compose" | "send"; context?: unknown; }) => void; onOpen?: (url: string, target: "tab" | "artifact") => void; onState?: (cardId: string, patch: unknown) => void; onDismiss?: (cardId: string) => void; onReopen?: (cardId: string) => void; onError?: (cardId: string, message: string) => void; maxSendPromptMode?: "compose" | "send" };
104
108
  }
105
109
 
106
110
  export const Cards = createWebComponent<CardsProps>(
@@ -122,7 +126,7 @@ export const ChainOfThought = createWebComponent<ChainOfThoughtProps>(
122
126
 
123
127
  export interface ChatProps extends WebComponentProps {
124
128
  /** The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions. Set as a JS property (`el.messages = [...]`). */
125
- messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string } }[];
129
+ messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | "like" | "dislike" }[];
126
130
  /** Controlled value of the input. When set, the host owns the input text and must update it on `kai-value-change`; leave unset for uncontrolled behavior. */
127
131
  value?: string;
128
132
  /** Placeholder text shown in the empty input. */
@@ -167,8 +171,8 @@ export interface ChatProps extends WebComponentProps {
167
171
  slashCompact?: boolean;
168
172
  /** Whether each message's action bar is always visible (`'always'`, default) or only revealed on hover of that message row (`'hover'`). */
169
173
  actionsReveal?: "always" | "hover";
170
- /** An action button on a message was clicked. `action` is the built-in name or custom id. */
171
- onMessageAction?: (event: CustomEvent<{ messageId: string; action: string }>) => void;
174
+ /** An action button on a message was clicked. `action` is the built-in name or custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
175
+ onMessageAction?: (event: CustomEvent<{ messageId: string; action: string; state?: undefined | "on" | "off" }>) => void;
172
176
  /** The header model switcher changed. */
173
177
  onModelChange?: (event: CustomEvent<{ modelId: string }>) => void;
174
178
  /** The Search button was clicked. */
@@ -246,6 +250,35 @@ export const CodeBlock = createWebComponent<CodeBlockProps>(
246
250
  { },
247
251
  );
248
252
 
253
+ export interface CompareProps extends WebComponentProps {
254
+ /** The compare definition (prompt + the two candidates). Set as a JS PROPERTY: `el.data = { prompt, candidates: [A, B], collapse? }`. Import `ResponseCompareData` from `@kitn.ai/ui` for the full shape. */
255
+ data?: Record<string, unknown>;
256
+ /** Stable id correlating every emitted event. Attribute: `compare-id`. */
257
+ compareId?: string;
258
+ /** Re-hydrate / control the user's pick. Set as a JS PROPERTY: `el.selection = { chosenId, rejectedIds }`. Renders the collapsed winner. */
259
+ selection?: Record<string, unknown>;
260
+ /** Layout: `'auto'` (default — columns when wide, tabs when narrow, by CONTAINER width) | `'columns'` (side-by-side) | `'tabs'` (pills to switch). Attribute: `layout`. */
261
+ layout?: "auto" | "columns" | "tabs";
262
+ /** Prose/text size for the rendered candidates. Attribute: `prose-size`. */
263
+ proseSize?: "xs" | "sm" | "base" | "lg";
264
+ /** Shiki theme for code blocks in the candidates. Attribute: `code-theme`. */
265
+ codeTheme?: string;
266
+ /** Whether code blocks are syntax-highlighted. Attribute: `code-highlight`. */
267
+ codeHighlight?: boolean;
268
+ /** The user committed a pick. `detail` = `{ chosenId, rejectedIds, at }`. */
269
+ onCompareSelect?: (event: CustomEvent<{ chosenId: string; rejectedIds: string[]; at?: undefined | number }>) => void;
270
+ /** The definition was unusable. */
271
+ onError?: (event: CustomEvent<{ compareId: string; message: string }>) => void;
272
+ /** Both candidates have settled and the pick is live. */
273
+ onReady?: (event: CustomEvent<{ compareId: string }>) => void;
274
+ }
275
+
276
+ export const Compare = createWebComponent<CompareProps>(
277
+ 'kai-compare',
278
+ ["theme","data","compareId","selection","layout","proseSize","codeTheme","codeHighlight"],
279
+ { onCompareSelect: 'kai-compare-select', onError: 'kai-error', onReady: 'kai-ready' },
280
+ );
281
+
249
282
  export interface ConfirmProps extends WebComponentProps {
250
283
  /** The confirm definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { body, tone, actions:[…] }`. Import `ConfirmCardData` from `@kitn.ai/ui` for the full shape. */
251
284
  data?: Record<string, unknown>;
@@ -475,7 +508,7 @@ export const Markdown = createWebComponent<MarkdownProps>(
475
508
 
476
509
  export interface MessageProps extends WebComponentProps {
477
510
  /** The full message object. Set as a JS property. */
478
- message?: { id: string; role: "user" | "assistant"; content: string; reasoning?: { text: string; label?: string }; tools?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string }[]; attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string } };
511
+ message?: { id: string; role: "user" | "assistant"; content: string; reasoning?: { text: string; label?: string }; tools?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string }[]; attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" };
479
512
  /** Convenience for simple cases when not passing a `message` object. */
480
513
  role?: "user" | "assistant";
481
514
  /** Convenience content (used when `message` is not set). */
@@ -494,8 +527,8 @@ export interface MessageProps extends WebComponentProps {
494
527
  avatarSrc?: string;
495
528
  /** Convenience avatar fallback text (used when `message.avatar` is not set). */
496
529
  avatarFallback?: string;
497
- /** An action button was clicked. `action` is the built-in name or custom id. */
498
- onMessageAction?: (event: CustomEvent<{ messageId: string; action: string }>) => void;
530
+ /** An action button was clicked. `action` is the built-in name or custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
531
+ onMessageAction?: (event: CustomEvent<{ messageId: string; action: string; state?: undefined | "on" | "off" }>) => void;
499
532
  }
500
533
 
501
534
  export const Message = createWebComponent<MessageProps>(
@@ -850,6 +883,29 @@ export const ThinkingBar = createWebComponent<ThinkingBarProps>(
850
883
  { onStop: 'kai-stop' },
851
884
  );
852
885
 
886
+ export interface ToastRegionProps extends WebComponentProps {
887
+ /** The toasts to render. Newest is shown on top. Set as a JS property (array); pass a new array reference to update. */
888
+ toasts: { id: string; message: string; variant?: undefined | "neutral" | "success"; action?: undefined | { label: string; onAction: () => void | false }; duration?: undefined | number; dismissible?: undefined | boolean; target?: undefined | HTMLElement }[];
889
+ /** Stack anchor: `'top-center'` (default), `'top-right'`, `'bottom-center'`, … */
890
+ position?: "top-center" | "top-right" | "top-left" | "bottom-center" | "bottom-right" | "bottom-left";
891
+ /** Max simultaneously-visible toasts; the rest queue. Defaults to `3`. */
892
+ max?: number;
893
+ /** Stacking: 'expanded' (default, full column) | 'collapsed' (Sonner-style pile that expands on hover/focus). Attribute: stack. */
894
+ stack?: "expanded" | "collapsed";
895
+ /** Container element to anchor this region to (JS property). Set by the store for a scoped region; unset = the global viewport region. */
896
+ target?: HTMLElement;
897
+ /** A toast's action button was pressed. */
898
+ onAction?: (event: CustomEvent<{ id: string; label: string }>) => void;
899
+ /** A toast left the stack. `reason` is `'timeout' | 'close' | 'action'`. */
900
+ onDismiss?: (event: CustomEvent<{ id: string; reason: "action" | "timeout" | "close" }>) => void;
901
+ }
902
+
903
+ export const ToastRegion = createWebComponent<ToastRegionProps>(
904
+ 'kai-toast-region',
905
+ ["theme","toasts","position","max","stack","target"],
906
+ { onAction: 'kai-action', onDismiss: 'kai-dismiss' },
907
+ );
908
+
853
909
  export interface ToolProps extends WebComponentProps {
854
910
  /** The tool-call to display. Set as a JS property. */
855
911
  tool?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string };
@@ -888,7 +944,7 @@ export interface WorkspaceProps extends WebComponentProps {
888
944
  /** Id of the open conversation, highlighted in the sidebar. */
889
945
  activeId?: string;
890
946
  /** The active conversation's message thread, newest last. Set as a JS property. */
891
- messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string } }[];
947
+ messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | "like" | "dislike" }[];
892
948
  value?: string;
893
949
  placeholder?: string;
894
950
  loading?: boolean;
@@ -919,8 +975,8 @@ export interface WorkspaceProps extends WebComponentProps {
919
975
  defaultSidebarCollapsed?: boolean;
920
976
  /** A conversation was selected in the sidebar. */
921
977
  onConversationSelect?: (event: CustomEvent<{ id: string }>) => void;
922
- /** An action button on a message was clicked. */
923
- onMessageAction?: (event: CustomEvent<{ messageId: string; action: string }>) => void;
978
+ /** An action button on a message was clicked. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
979
+ onMessageAction?: (event: CustomEvent<{ messageId: string; action: string; state?: undefined | "on" | "off" }>) => void;
924
980
  /** The header model switcher changed. */
925
981
  onModelChange?: (event: CustomEvent<{ modelId: string }>) => void;
926
982
  /** The "New chat" button was clicked. */
@@ -49,11 +49,25 @@ export function createWebComponent<P extends WebComponentProps>(
49
49
  // objects pass through unstringified; booleans become real boolean
50
50
  // properties so the element's `flag()` reads them. Updated props re-assign
51
51
  // because this effect runs after every render.
52
+ //
53
+ // Upgrade-race guard: if the element isn't upgraded yet (customElements.get
54
+ // returns undefined), writes land on a plain HTMLElement and are lost when
55
+ // Solid's solid-element upgrades the tag later. We call whenDefined() so
56
+ // props set before upgrade are re-applied once the definition arrives.
57
+ // With self-registration (elements/register imported at the top of
58
+ // react/index.tsx) this is belt-and-braces — the element is already defined
59
+ // before React renders — but keeps the runtime safe regardless of import order.
52
60
  useLayoutEffect(() => {
53
61
  const el = elRef.current;
54
62
  if (!el) return;
55
- for (const name of propNames) {
56
- if (name in p && p[name] !== undefined) (el as unknown as Record<string, unknown>)[name] = p[name];
63
+ const applyProps = () => {
64
+ for (const name of propNames) {
65
+ if (name in p && p[name] !== undefined) (el as unknown as Record<string, unknown>)[name] = p[name];
66
+ }
67
+ };
68
+ applyProps();
69
+ if (typeof customElements !== 'undefined' && !customElements.get(tagName)) {
70
+ customElements.whenDefined(tagName).then(applyProps);
57
71
  }
58
72
  });
59
73
 
package/llms-full.txt CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @kitn.ai/ui
5
5
 
6
- > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 44 `kitn-*` custom elements: 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.
6
+ > 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.
7
7
 
8
8
  ## Install
9
9
 
@@ -37,7 +37,7 @@ Drop an element into any framework (React, Vue, plain HTML). Data in via JS prop
37
37
  - `<kai-prompt-input>` — standalone composer with send button.
38
38
 
39
39
  **Layer 2 — composable primitives** (`import { … } from '@kitn.ai/ui'`):
40
- All 44 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.
40
+ 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.
41
41
 
42
42
  ## Key rules for the web components
43
43
 
@@ -99,7 +99,7 @@ For Tailwind builds: `@import "@kitn.ai/ui/theme.css"` in your CSS.
99
99
 
100
100
  ## Docs
101
101
 
102
- - Full element reference (all 44 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
102
+ - Full element reference (all 46 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
103
103
  - Machine-readable Custom Elements Manifest: https://unpkg.com/@kitn.ai/ui/dist/custom-elements.json
104
104
  - Working examples: https://github.com/kitn-ai/ui/tree/main/examples
105
105
  - Storybook: https://storybook.kitn.dev
@@ -173,7 +173,7 @@ The same rule applies to every array/object property (`models`, `context`, `sugg
173
173
 
174
174
  ---
175
175
 
176
- ## Element reference (44 elements, generated from custom-elements.json)
176
+ ## Element reference (46 elements, generated from custom-elements.json)
177
177
 
178
178
  Every element also accepts the `theme` attribute. Array/object properties are marked with a `—` attribute: they must be set as JS properties.
179
179
 
@@ -253,9 +253,9 @@ _No events._
253
253
 
254
254
  | Property | Attribute | Type | Description |
255
255
  |---|---|---|---|
256
- | `cards` | — | `undefined \| { type: string; id: string; data: unknown; title?: undefined \| string; resolution?: undefined \| { kind: "action"; action: string; payload?: unknown; at?: undefined \| string } \| { kind: "submit"; data: unknown; at?: undefined \| string } }[]` | The stream of card envelopes to render. Set as a JS PROPERTY: `el.cards = [...]`. |
256
+ | `cards` | — | `undefined \| { type: string; id: string; data: unknown; title?: undefined \| string; resolution?: undefined \| { kind: "action"; action: string; payload?: unknown; at?: undefined \| string } \| { kind: "submit"; data: unknown; at?: undefined \| string } \| { kind: "dismissed"; at?: undefined \| string } \| { kind: "expired"; reason?: undefined \| string; at?: undefined \| string } }[]` | The stream of card envelopes to render. Set as a JS PROPERTY: `el.cards = [...]`. |
257
257
  | `types` | — | `undefined \| Record<string, string>` | Optional type→tag overrides/additions (merged over the built-ins). Property: `el.types`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. |
258
- | `policy` | — | `undefined \| { onSubmit?: undefined \| (cardId: string, data: unknown) => void; onAction?: undefined \| (cardId: string, action: string, payload?: unknown) => void; onSendPrompt?: undefined \| (text: string, opts: { mode: "compose" \| "send"; context?: unknown; }) => void; onOpen?: undefined \| (url: string, target: "tab" \| "artifact") => void; onState?: undefined \| (cardId: string, patch: unknown) => void; onDismiss?: undefined \| (cardId: string) => void; onError?: undefined \| (cardId: string, message: string) => void; maxSendPromptMode?: undefined \| "compose" \| "send" }` | Optional CardPolicy handling child events. Property: `el.policy`. |
258
+ | `policy` | — | `undefined \| { onSubmit?: undefined \| (cardId: string, data: unknown) => void; onAction?: undefined \| (cardId: string, action: string, payload?: unknown) => void; onSendPrompt?: undefined \| (text: string, opts: { mode: "compose" \| "send"; context?: unknown; }) => void; onOpen?: undefined \| (url: string, target: "tab" \| "artifact") => void; onState?: undefined \| (cardId: string, patch: unknown) => void; onDismiss?: undefined \| (cardId: string) => void; onReopen?: undefined \| (cardId: string) => void; onError?: undefined \| (cardId: string, message: string) => void; maxSendPromptMode?: undefined \| "compose" \| "send" }` | Optional CardPolicy handling child events. Property: `el.policy`. |
259
259
 
260
260
  _No events._
261
261
 
@@ -279,7 +279,7 @@ _No events._
279
279
 
280
280
  | Property | Attribute | Type | Description |
281
281
  |---|---|---|---|
282
- | `messages` | — | `{ id: string; role: "user" \| "assistant"; content: string; reasoning?: undefined \| { text: string; label?: undefined \| string }; tools?: undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }[]; attachments?: undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]; actions?: undefined \| ("copy" \| "like" \| "dislike" \| "regenerate" \| "edit" \| { id: string; label: string; icon?: undefined \| string; tooltip?: undefined \| string })[]; avatar?: undefined \| { src?: undefined \| string; fallback?: undefined \| string; alt?: undefined \| string } }[]` | The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions. Set as a JS property (`el.messages = [...]`). |
282
+ | `messages` | — | `{ id: string; role: "user" \| "assistant"; content: string; reasoning?: undefined \| { text: string; label?: undefined \| string }; tools?: undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }[]; attachments?: undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]; actions?: undefined \| ("copy" \| "like" \| "dislike" \| "regenerate" \| "edit" \| { id: string; label: string; icon?: undefined \| string; tooltip?: undefined \| string })[]; avatar?: undefined \| { src?: undefined \| string; fallback?: undefined \| string; alt?: undefined \| string }; feedback?: undefined \| "like" \| "dislike" }[]` | The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions. Set as a JS property (`el.messages = [...]`). |
283
283
  | `value` | `value` | `undefined \| string` | Controlled value of the input. When set, the host owns the input text and must update it on `kai-value-change`; leave unset for uncontrolled behavior. |
284
284
  | `placeholder` | `placeholder` | `undefined \| string` | Placeholder text shown in the empty input. |
285
285
  | `loading` | `loading` | `undefined \| false \| true` | When true, shows the loading/streaming state and disables submit (use while awaiting the assistant's reply). |
@@ -307,7 +307,7 @@ _No events._
307
307
 
308
308
  | Event | `detail` type | Description |
309
309
  |---|---|---|
310
- | `kai-message-action` | `CustomEvent<{ messageId: string; action: string }>` | An action button on a message was clicked. `action` is the built-in name or custom id. |
310
+ | `kai-message-action` | `CustomEvent<{ messageId: string; action: string; state?: undefined \| "on" \| "off" }>` | An action button on a message was clicked. `action` is the built-in name or custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. |
311
311
  | `kai-model-change` | `CustomEvent<{ modelId: string }>` | The header model switcher changed. |
312
312
  | `kai-search` | `CustomEvent<Record<string, never>>` | The Search button was clicked. |
313
313
  | `kai-slash-select` | `CustomEvent<{ command: { id: string; label: string; description?: undefined \| string; category?: undefined \| string } }>` | A slash command was chosen from the palette. |
@@ -368,6 +368,30 @@ _No events._
368
368
 
369
369
  ---
370
370
 
371
+ ### `kai-compare` / `Compare`
372
+
373
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
374
+
375
+ | Property | Attribute | Type | Description |
376
+ |---|---|---|---|
377
+ | `data` | — | `undefined \| Record<string, unknown>` | The compare definition (prompt + the two candidates). Set as a JS PROPERTY: `el.data = { prompt, candidates: [A, B], collapse? }`. Import `ResponseCompareData` from `@kitn.ai/ui` for the full shape. |
378
+ | `compareId` | `compare-id` | `undefined \| string` | Stable id correlating every emitted event. Attribute: `compare-id`. |
379
+ | `selection` | — | `undefined \| Record<string, unknown>` | Re-hydrate / control the user's pick. Set as a JS PROPERTY: `el.selection = { chosenId, rejectedIds }`. Renders the collapsed winner. |
380
+ | `layout` | `layout` | `undefined \| "auto" \| "columns" \| "tabs"` | Layout: `'auto'` (default — columns when wide, tabs when narrow, by CONTAINER width) \| `'columns'` (side-by-side) \| `'tabs'` (pills to switch). Attribute: `layout`. |
381
+ | `proseSize` | `prose-size` | `undefined \| "xs" \| "sm" \| "base" \| "lg"` | Prose/text size for the rendered candidates. Attribute: `prose-size`. |
382
+ | `codeTheme` | `code-theme` | `undefined \| string` | Shiki theme for code blocks in the candidates. Attribute: `code-theme`. |
383
+ | `codeHighlight` | `code-highlight` | `undefined \| false \| true` | Whether code blocks are syntax-highlighted. Attribute: `code-highlight`. |
384
+
385
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
386
+
387
+ | Event | `detail` type | Description |
388
+ |---|---|---|
389
+ | `kai-compare-select` | `CustomEvent<{ chosenId: string; rejectedIds: string[]; at?: undefined \| number }>` | The user committed a pick. `detail` = `{ chosenId, rejectedIds, at }`. |
390
+ | `kai-error` | `CustomEvent<{ compareId: string; message: string }>` | The definition was unusable. |
391
+ | `kai-ready` | `CustomEvent<{ compareId: string }>` | Both candidates have settled and the pick is live. |
392
+
393
+ ---
394
+
371
395
  ### `kai-confirm` / `Confirm`
372
396
 
373
397
  **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
@@ -587,7 +611,7 @@ _No events._
587
611
 
588
612
  | Property | Attribute | Type | Description |
589
613
  |---|---|---|---|
590
- | `message` | — | `undefined \| { id: string; role: "user" \| "assistant"; content: string; reasoning?: undefined \| { text: string; label?: undefined \| string }; tools?: undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }[]; attachments?: undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]; actions?: undefined \| ("copy" \| "like" \| "dislike" \| "regenerate" \| "edit" \| { id: string; label: string; icon?: undefined \| string; tooltip?: undefined \| string })[]; avatar?: undefined \| { src?: undefined \| string; fallback?: undefined \| string; alt?: undefined \| string } }` | The full message object. Set as a JS property. |
614
+ | `message` | — | `undefined \| { id: string; role: "user" \| "assistant"; content: string; reasoning?: undefined \| { text: string; label?: undefined \| string }; tools?: undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }[]; attachments?: undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]; actions?: undefined \| ("copy" \| "like" \| "dislike" \| "regenerate" \| "edit" \| { id: string; label: string; icon?: undefined \| string; tooltip?: undefined \| string })[]; avatar?: undefined \| { src?: undefined \| string; fallback?: undefined \| string; alt?: undefined \| string }; feedback?: undefined \| "like" \| "dislike" }` | The full message object. Set as a JS property. |
591
615
  | `role` | `role` | `undefined \| "user" \| "assistant"` | Convenience for simple cases when not passing a `message` object. |
592
616
  | `content` | `content` | `undefined \| string` | Convenience content (used when `message` is not set). |
593
617
  | `markdown` | `markdown` | `undefined \| false \| true` | Force markdown on/off. Defaults to on for assistant, off for user. |
@@ -602,7 +626,7 @@ _No events._
602
626
 
603
627
  | Event | `detail` type | Description |
604
628
  |---|---|---|
605
- | `kai-message-action` | `CustomEvent<{ messageId: string; action: string }>` | An action button was clicked. `action` is the built-in name or custom id. |
629
+ | `kai-message-action` | `CustomEvent<{ messageId: string; action: string; state?: undefined \| "on" \| "off" }>` | An action button was clicked. `action` is the built-in name or custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. |
606
630
 
607
631
  ---
608
632
 
@@ -933,6 +957,27 @@ _No events._
933
957
 
934
958
  ---
935
959
 
960
+ ### `kai-toast-region` / `ToastRegion`
961
+
962
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
963
+
964
+ | Property | Attribute | Type | Description |
965
+ |---|---|---|---|
966
+ | `toasts` | — | `{ id: string; message: string; variant?: undefined \| "neutral" \| "success"; action?: undefined \| { label: string; onAction: () => void \| false }; duration?: undefined \| number; dismissible?: undefined \| false \| true; target?: undefined \| HTMLElement }[]` | The toasts to render. Newest is shown on top. Set as a JS property (array); pass a new array reference to update. |
967
+ | `position` | `position` | `undefined \| "top-center" \| "top-right" \| "top-left" \| "bottom-center" \| "bottom-right" \| "bottom-left"` | Stack anchor: `'top-center'` (default), `'top-right'`, `'bottom-center'`, … |
968
+ | `max` | `max` | `undefined \| number` | Max simultaneously-visible toasts; the rest queue. Defaults to `3`. |
969
+ | `stack` | `stack` | `undefined \| "expanded" \| "collapsed"` | Stacking: 'expanded' (default, full column) \| 'collapsed' (Sonner-style pile that expands on hover/focus). Attribute: stack. |
970
+ | `target` | — | `undefined \| HTMLElement` | Container element to anchor this region to (JS property). Set by the store for a scoped region; unset = the global viewport region. |
971
+
972
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
973
+
974
+ | Event | `detail` type | Description |
975
+ |---|---|---|
976
+ | `kai-action` | `CustomEvent<{ id: string; label: string }>` | A toast's action button was pressed. |
977
+ | `kai-dismiss` | `CustomEvent<{ id: string; reason: "action" \| "timeout" \| "close" }>` | A toast left the stack. `reason` is `'timeout' \| 'close' \| 'action'`. |
978
+
979
+ ---
980
+
936
981
  ### `kai-tool` / `Tool`
937
982
 
938
983
  **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
@@ -973,7 +1018,7 @@ _No events._
973
1018
  | `groups` | — | `{ id: string; userId?: undefined \| string; teamId?: undefined \| string; name: string; sortOrder: number; createdAt: string }[]` | Pre-bucketed conversation groups for the sidebar. Set as a JS property. |
974
1019
  | `conversations` | — | `{ id: string; title: string; groupId?: undefined \| string; scope: { type: "document" \| "collection"; documentId?: undefined \| string; filters?: undefined \| { tags?: undefined \| string[]; authors?: undefined \| string[]; contentType?: undefined \| "transcript" \| "markdown"; dateRange?: undefined \| { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string }[]` | Flat conversation list (auto-bucketed if `groups` is empty). Set as a JS property. |
975
1020
  | `activeId` | `active-id` | `undefined \| string` | Id of the open conversation, highlighted in the sidebar. |
976
- | `messages` | — | `{ id: string; role: "user" \| "assistant"; content: string; reasoning?: undefined \| { text: string; label?: undefined \| string }; tools?: undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }[]; attachments?: undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]; actions?: undefined \| ("copy" \| "like" \| "dislike" \| "regenerate" \| "edit" \| { id: string; label: string; icon?: undefined \| string; tooltip?: undefined \| string })[]; avatar?: undefined \| { src?: undefined \| string; fallback?: undefined \| string; alt?: undefined \| string } }[]` | The active conversation's message thread, newest last. Set as a JS property. |
1021
+ | `messages` | — | `{ id: string; role: "user" \| "assistant"; content: string; reasoning?: undefined \| { text: string; label?: undefined \| string }; tools?: undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }[]; attachments?: undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]; actions?: undefined \| ("copy" \| "like" \| "dislike" \| "regenerate" \| "edit" \| { id: string; label: string; icon?: undefined \| string; tooltip?: undefined \| string })[]; avatar?: undefined \| { src?: undefined \| string; fallback?: undefined \| string; alt?: undefined \| string }; feedback?: undefined \| "like" \| "dislike" }[]` | The active conversation's message thread, newest last. Set as a JS property. |
977
1022
  | `value` | `value` | `undefined \| string` | |
978
1023
  | `placeholder` | `placeholder` | `undefined \| string` | |
979
1024
  | `loading` | `loading` | `undefined \| false \| true` | |
@@ -1003,7 +1048,7 @@ _No events._
1003
1048
  | Event | `detail` type | Description |
1004
1049
  |---|---|---|
1005
1050
  | `kai-conversation-select` | `CustomEvent<{ id: string }>` | A conversation was selected in the sidebar. |
1006
- | `kai-message-action` | `CustomEvent<{ messageId: string; action: string }>` | An action button on a message was clicked. |
1051
+ | `kai-message-action` | `CustomEvent<{ messageId: string; action: string; state?: undefined \| "on" \| "off" }>` | An action button on a message was clicked. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. |
1007
1052
  | `kai-model-change` | `CustomEvent<{ modelId: string }>` | The header model switcher changed. |
1008
1053
  | `kai-new-chat` | `CustomEvent<Record<string, never>>` | The "New chat" button was clicked. |
1009
1054
  | `kai-search` | `CustomEvent<Record<string, never>>` | The Search button was clicked. |
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. 44 `kitn-*` custom elements: 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. 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.
5
5
 
6
6
  ## Install
7
7
 
@@ -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 44 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 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.
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 44 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
100
+ - Full element reference (all 46 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,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitn.ai/ui",
3
- "version": "0.15.1",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "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
6
  "keywords": [
@@ -30,20 +30,38 @@
30
30
  "bugs": {
31
31
  "url": "https://github.com/kitn-ai/ui/issues"
32
32
  },
33
- "main": "src/index.ts",
34
- "types": "src/index.ts",
33
+ "main": "./dist/index.js",
34
+ "module": "./dist/index.js",
35
+ "types": "./dist/index.d.ts",
35
36
  "unpkg": "./dist/kitn-chat.es.js",
36
37
  "jsdelivr": "./dist/kitn-chat.es.js",
37
38
  "customElements": "dist/custom-elements.json",
39
+ "bin": {
40
+ "kai-mcp": "./bin/mcp.js"
41
+ },
38
42
  "exports": {
39
- ".": "./src/index.ts",
43
+ ".": {
44
+ "types": "./dist/index.d.ts",
45
+ "default": "./dist/index.js"
46
+ },
40
47
  "./elements": {
41
- "types": "./src/elements/element-types.d.ts",
48
+ "types": "./dist/elements.d.ts",
42
49
  "default": "./dist/kitn-chat.es.js"
43
50
  },
51
+ "./elements/*": {
52
+ "types": "./dist/elements/*.d.ts",
53
+ "default": "./dist/elements/*.js"
54
+ },
55
+ "./autoloader": {
56
+ "types": "./dist/elements/autoloader.d.ts",
57
+ "default": "./dist/elements/autoloader.js"
58
+ },
44
59
  "./theme.css": "./theme.css",
45
60
  "./theme.tokens.css": "./dist/theme.tokens.css",
46
- "./react": "./frameworks/react/index.tsx",
61
+ "./react": {
62
+ "types": "./dist/react/index.d.ts",
63
+ "default": "./dist/react.js"
64
+ },
47
65
  "./provider": {
48
66
  "types": "./dist/kitn-chat-provider.d.ts",
49
67
  "default": "./dist/kitn-chat-provider.es.js"
@@ -52,6 +70,7 @@
52
70
  "files": [
53
71
  "dist",
54
72
  "src",
73
+ "bin",
55
74
  "!src/**/*.stories.tsx",
56
75
  "!src/**/*.test.ts",
57
76
  "!src/**/*.test.tsx",
@@ -65,7 +84,8 @@
65
84
  "scripts": {
66
85
  "prepublishOnly": "npm run build",
67
86
  "prebuild": "npm run build:css",
68
- "build": "vite build --config vite.config.ts && vite build --config vite.config.provider.ts",
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",
88
+ "build:elements": "node scripts/gen-elements-manifest.mjs && vite build --config vite.config.elements.ts && node scripts/gen-element-dts.mjs",
69
89
  "postbuild": "npm run build:theme && npm run build:api && npm run build:schemas",
70
90
  "build:theme": "node scripts/build-theme-tokens.mjs",
71
91
  "build:api": "node scripts/gen-element-api.mjs",
@@ -74,7 +94,7 @@
74
94
  "test:react": "vitest run --config vitest.react.config.ts",
75
95
  "test:storybook": "vitest run --project=storybook",
76
96
  "test:watch": "vitest",
77
- "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.react.json && tsc --noEmit -p tsconfig.react.test.json",
97
+ "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.react.json && tsc --noEmit -p tsconfig.react.test.json && tsc --noEmit -p tsconfig.mcp.json",
78
98
  "examples": "echo 'Serving repo root on http://localhost:8000 — open http://localhost:8000/examples/composable/index.html' && python3 -m http.server 8000",
79
99
  "dev": "npm run build:css && storybook dev -p 6006",
80
100
  "storybook": "npm run build:css && storybook dev -p 6006",
@@ -87,19 +107,20 @@
87
107
  },
88
108
  "dependencies": {
89
109
  "@floating-ui/dom": "^1.7.6",
90
- "@shikijs/langs": "^4.2.0",
91
- "@shikijs/themes": "^4.2.0",
110
+ "@modelcontextprotocol/sdk": "^1.29.0",
92
111
  "class-variance-authority": "^0.7.0",
93
112
  "clsx": "^2.1.0",
94
113
  "lucide-solid": "^0.400.0",
95
114
  "marked": "^18.0.0",
96
- "shiki": "^4.0.2",
97
115
  "solid-element": "^1.9.1",
98
116
  "solid-js": "^1.9.0",
99
- "tailwind-merge": "^2.5.0"
117
+ "tailwind-merge": "^3.0.0",
118
+ "zod": "^4.4.3"
100
119
  },
101
120
  "devDependencies": {
102
121
  "@playwright/test": "^1.60.0",
122
+ "@shikijs/langs": "^4.2.0",
123
+ "@shikijs/themes": "^4.2.0",
103
124
  "@solidjs/testing-library": "^0.8.0",
104
125
  "@storybook/addon-a11y": "^10.4.2",
105
126
  "@storybook/addon-docs": "^10.3.5",
@@ -110,6 +131,7 @@
110
131
  "@tailwindcss/typography": "^0.5.19",
111
132
  "@testing-library/jest-dom": "^6.0.0",
112
133
  "@testing-library/react": "^16.3.2",
134
+ "@types/node": "^26.0.0",
113
135
  "@types/react": "^19.2.17",
114
136
  "@types/react-dom": "^19.2.3",
115
137
  "@vitejs/plugin-react": "^4.7.0",
@@ -123,6 +145,7 @@
123
145
  "react": "^19.2.7",
124
146
  "react-dom": "^19.2.7",
125
147
  "remark-gfm": "^4.0.1",
148
+ "shiki": "^4.0.2",
126
149
  "storybook": "^10.3.5",
127
150
  "storybook-dark-mode": "^5.0.0",
128
151
  "storybook-solidjs-vite": "^10.0.12",
@@ -135,8 +158,7 @@
135
158
  "vitest": "^4.1.0"
136
159
  },
137
160
  "peerDependencies": {
138
- "react": ">=18",
139
- "solid-js": "^1.9.0"
161
+ "react": ">=18"
140
162
  },
141
163
  "peerDependenciesMeta": {
142
164
  "react": {
@@ -0,0 +1,46 @@
1
+ import type { Archetype } from './types';
2
+
3
+ export const archetypes: Archetype[] = [
4
+ {
5
+ id: 'drop-in-chat',
6
+ title: 'Drop-in chat',
7
+ components: ['kai-chat'],
8
+ defaultPlacement: 'full-page',
9
+ docsSlug: 'examples/drop-in-chat',
10
+ },
11
+ {
12
+ id: 'support-widget',
13
+ title: 'Support widget',
14
+ components: ['kai-chat'],
15
+ defaultPlacement: 'docked-widget',
16
+ docsSlug: 'examples/support-widget',
17
+ },
18
+ {
19
+ id: 'knowledge-base',
20
+ title: 'Knowledge base / RAG',
21
+ components: ['kai-chat', 'kai-sources'],
22
+ defaultPlacement: 'full-page',
23
+ docsSlug: 'examples/knowledge-base',
24
+ },
25
+ {
26
+ id: 'agentic',
27
+ title: 'Agentic assistant',
28
+ components: ['kai-chat', 'kai-tool', 'kai-reasoning'],
29
+ defaultPlacement: 'side',
30
+ docsSlug: 'examples/agentic-assistant',
31
+ },
32
+ {
33
+ id: 'workspace',
34
+ title: 'Agentic workspace',
35
+ components: ['kai-chat', 'kai-artifact', 'kai-resizable'],
36
+ defaultPlacement: 'side',
37
+ docsSlug: 'examples/workspace',
38
+ },
39
+ {
40
+ id: 'voice',
41
+ title: 'Voice assistant',
42
+ components: ['kai-chat', 'kai-voice-input'],
43
+ defaultPlacement: 'full-page',
44
+ docsSlug: 'examples/voice-assistant',
45
+ },
46
+ ];