@kitn.ai/ui 0.27.0 → 0.29.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 (612) hide show
  1. package/README.md +10 -2
  2. package/dist/{Icon-BnFKqqtY.js → Icon-DObhsRtm.js} +1 -1
  3. package/dist/{action-icons-CBskfBMz.js → action-icons-CcgNN2oT.js} +1 -1
  4. package/dist/agent-tooling/construct/public.d.ts +15 -0
  5. package/dist/agent-tooling/construct/schema.d.ts +111 -0
  6. package/dist/arrow-down-CjRU3JgV.js +1 -0
  7. package/dist/arrow-left-Bnpb1UEW.js +1 -0
  8. package/dist/{artifact-CvXEm1lS.js → artifact-Bwt7OgcR.js} +1 -1
  9. package/dist/{attachments-C43ZegEq.js → attachments-Qr4kg-2b.js} +1 -1
  10. package/dist/{audio-visualizer-B-79y1Tj.js → audio-visualizer-DToYdfSc.js} +1 -1
  11. package/dist/{badge-BpUbq8c0.js → badge-CdEu_jn2.js} +1 -1
  12. package/dist/{bell-sn17Ip9v.js → bell-DQAAOpDz.js} +1 -1
  13. package/dist/{button-BH6rN0U-.js → button-DkuOnGLy.js} +1 -1
  14. package/dist/{card-renderer-Cb1gQmth.js → card-renderer-Jx70m6_l.js} +1 -1
  15. package/dist/{card-routing-DifQgS7n.js → card-routing-0YidER_3.js} +1 -1
  16. package/dist/check-njkVdZu2.js +1 -0
  17. package/dist/{checkbox-Dc9Yov_B.js → checkbox-D7iRB3nL.js} +1 -1
  18. package/dist/{checkbox-group-B1kDLLYk.js → checkbox-group-B2_rpoPM.js} +1 -1
  19. package/dist/chevron-down-B72s6PXR.js +1 -0
  20. package/dist/chevron-right-BatuHzUm.js +1 -0
  21. package/dist/{choice-card-BT3c1S8g.js → choice-card-m0BYqqOK.js} +1 -1
  22. package/dist/circle-check-B62pODB3.js +1 -0
  23. package/dist/{circle-x-wobWkoSx.js → circle-x-BPG0iPst.js} +1 -1
  24. package/dist/circle-zx0ByzY9.js +1 -0
  25. package/dist/code-block-ClMLKb7C.js +1 -0
  26. package/dist/{collapsible-CPJbf6FM.js → collapsible-B4DlWicL.js} +1 -1
  27. package/dist/components/chat-thread.d.ts +89 -1
  28. package/dist/components/conversation-item.d.ts +16 -0
  29. package/dist/components/conversation-panel.d.ts +29 -0
  30. package/dist/components/home-panel.d.ts +34 -0
  31. package/dist/components/widget-tab-bar.d.ts +16 -0
  32. package/dist/{composer-CjngLzal.js → composer-sQ0HcvyG.js} +3 -3
  33. package/dist/{confirm-card-DCx_A4bU.js → confirm-card-rQWDQsnC.js} +1 -1
  34. package/dist/construct-cli.es.js +185 -17
  35. package/dist/construct.d.ts +5 -0
  36. package/dist/construct.js +327 -0
  37. package/dist/{context-BY8V-Nlp.js → context-0kg4ZX1J.js} +1 -1
  38. package/dist/controllable-CnGpMF6r.js +1 -0
  39. package/dist/conversation-item-BxwQLaFJ.js +1 -0
  40. package/dist/conversation-list-BCfGN1JU.js +1 -0
  41. package/dist/{copy-B6DO4PqB.js → copy-n9u9rqpi.js} +1 -1
  42. package/dist/core-C8fzo39E.js +1 -12
  43. package/dist/{create-tween-CnMHviKB.js → create-tween-C-q-JCM-.js} +1 -1
  44. package/dist/{create-tween-D1aiGZZh.js → create-tween-CRrJXxBd.js} +1 -1
  45. package/dist/{create-tween-BPzaefTp.js → create-tween-DZ3RRDHD.js} +1 -1
  46. package/dist/{create-tween-DUSQUKpr.js → create-tween-uPkArjIG.js} +1 -1
  47. package/dist/custom-elements.json +51 -2
  48. package/dist/{default-input-CucQEOqH.js → default-input-CaMrJkgH.js} +1 -1
  49. package/dist/define-By-uL588.js +1 -0
  50. package/dist/define.js +2 -2
  51. package/dist/define.server.js +2 -2
  52. package/dist/{disclosure-CbLtajUQ.js → disclosure-WUImBbDv.js} +1 -1
  53. package/dist/{dropdown-BwhViJFd.js → dropdown-wZVeJOMd.js} +1 -1
  54. package/dist/elements/agent-card.js +1 -1
  55. package/dist/elements/artifact.js +1 -1
  56. package/dist/elements/attachments.js +1 -1
  57. package/dist/elements/audio-visualizer.js +1 -1
  58. package/dist/elements/avatar.js +1 -1
  59. package/dist/elements/badge.js +1 -1
  60. package/dist/elements/button.js +1 -1
  61. package/dist/elements/card.js +1 -1
  62. package/dist/elements/cards.js +1 -1
  63. package/dist/elements/chain-of-thought.js +1 -1
  64. package/dist/elements/chat-scope-picker.js +1 -1
  65. package/dist/elements/chat-workspace.js +1 -1
  66. package/dist/elements/chat.js +1 -1
  67. package/dist/elements/checkbox-group.js +1 -1
  68. package/dist/elements/checkbox.js +1 -1
  69. package/dist/elements/checkpoint.js +1 -1
  70. package/dist/elements/choice.js +1 -1
  71. package/dist/elements/coachmark.js +1 -1
  72. package/dist/elements/code-block.js +1 -1
  73. package/dist/elements/command.js +1 -1
  74. package/dist/elements/compare.js +1 -1
  75. package/dist/elements/composer.js +1 -1
  76. package/dist/elements/confirm-card.js +1 -1
  77. package/dist/elements/context-meter.js +1 -1
  78. package/dist/elements/conversation-item.js +1 -1
  79. package/dist/elements/conversation-list.js +1 -1
  80. package/dist/elements/dialog.js +1 -1
  81. package/dist/elements/dock.js +3 -3
  82. package/dist/elements/dropdown.js +1 -1
  83. package/dist/elements/editable-label.js +1 -1
  84. package/dist/elements/embed.js +1 -1
  85. package/dist/elements/empty.js +1 -1
  86. package/dist/elements/feedback-bar.js +1 -1
  87. package/dist/elements/file-tree.js +1 -1
  88. package/dist/elements/file-upload.js +1 -1
  89. package/dist/elements/form.js +1 -1
  90. package/dist/elements/hover-card.js +1 -1
  91. package/dist/elements/icon.js +1 -1
  92. package/dist/elements/image.js +1 -1
  93. package/dist/elements/input.js +1 -1
  94. package/dist/elements/kbd.js +1 -1
  95. package/dist/elements/link-preview.js +1 -1
  96. package/dist/elements/loader.js +1 -1
  97. package/dist/elements/markdown.js +1 -1
  98. package/dist/elements/menu.js +1 -1
  99. package/dist/elements/message-skills.js +1 -1
  100. package/dist/elements/message.js +1 -1
  101. package/dist/elements/model-switcher.js +1 -1
  102. package/dist/elements/nav.js +1 -1
  103. package/dist/elements/notice.js +1 -1
  104. package/dist/elements/pane-grid.js +1 -1
  105. package/dist/elements/pane-group.js +1 -1
  106. package/dist/elements/pane.js +1 -1
  107. package/dist/elements/popover.js +1 -1
  108. package/dist/elements/progress-bar.js +1 -1
  109. package/dist/elements/prompt-dock.js +1 -1
  110. package/dist/elements/prompt-input.js +1 -1
  111. package/dist/elements/prompt-suggestions.js +1 -1
  112. package/dist/elements/radio-group.js +1 -1
  113. package/dist/elements/reasoning.js +1 -1
  114. package/dist/elements/remote.js +1 -1
  115. package/dist/elements/resizable.js +1 -1
  116. package/dist/elements/response-stream.js +1 -1
  117. package/dist/elements/screen.js +1 -1
  118. package/dist/elements/scroll-area.js +1 -1
  119. package/dist/elements/scroll-button.js +1 -1
  120. package/dist/elements/search.js +1 -1
  121. package/dist/elements/segmented.js +1 -1
  122. package/dist/elements/select.js +1 -1
  123. package/dist/elements/separator.js +1 -1
  124. package/dist/elements/setting-item.js +1 -1
  125. package/dist/elements/settings-group.js +1 -1
  126. package/dist/elements/skeleton.js +1 -1
  127. package/dist/elements/slider.js +1 -1
  128. package/dist/elements/source.js +1 -1
  129. package/dist/elements/status.js +1 -1
  130. package/dist/elements/switch.js +1 -1
  131. package/dist/elements/tabs.js +1 -1
  132. package/dist/elements/tasks.js +1 -1
  133. package/dist/elements/text-shimmer.js +1 -1
  134. package/dist/elements/thinking-bar.js +1 -1
  135. package/dist/elements/thread.js +1 -1
  136. package/dist/elements/toast.js +1 -1
  137. package/dist/elements/tool.js +1 -1
  138. package/dist/elements/tooltip.js +1 -1
  139. package/dist/elements/voice-input.js +1 -1
  140. package/dist/elements/voice-output.js +1 -1
  141. package/dist/elements.d.ts +20 -4
  142. package/dist/{ellipsis-DFr4Vqr3.js → ellipsis-CbOpJnU3.js} +1 -1
  143. package/dist/{embed-5s_vU4J0.js → embed-CrfjkbUG.js} +1 -1
  144. package/dist/engine-javascript-C1x7zo1_.js +1 -141
  145. package/dist/{external-link-u9d85ORQ.js → external-link-ByXAwBBQ.js} +1 -1
  146. package/dist/{file-text-CX7_x42o.js → file-text-DMib2qwt.js} +1 -1
  147. package/dist/{file-tree-D3kBjXI5.js → file-tree-CJqM2aP7.js} +1 -1
  148. package/dist/{folder-V-YdIL8f.js → folder-_BAb929C.js} +1 -1
  149. package/dist/{form-BRNUMCN2.js → form-DSZgZQZk.js} +1 -1
  150. package/dist/{hover-card-DaeiYrTA.js → hover-card-BQbul9eq.js} +1 -1
  151. package/dist/{icon-BpixdZNq.js → icon-CdcfRhYI.js} +1 -1
  152. package/dist/index.d.ts +3 -1
  153. package/dist/index.js +2842 -2703
  154. package/dist/index.server.js +2820 -2681
  155. package/dist/{info-8mFsIjS3.js → info-DsFjGuI_.js} +1 -1
  156. package/dist/{input-d1Yuu-hz.js → input-DKbmkMos.js} +1 -1
  157. package/dist/kai.es.js +1 -1
  158. package/dist/{kbd-961zMPFB.js → kbd-PvdGhX4s.js} +1 -1
  159. package/dist/{link-preview-DIIbV2Sd.js → link-preview-DbM1866N.js} +1 -1
  160. package/dist/{link-DlZZBGaR.js → link-zF8PzWfF.js} +1 -1
  161. package/dist/{loader-YQszHFaW.js → loader-BM4CEz4G.js} +1 -1
  162. package/dist/{markdown-CVk1MPsj.js → markdown-LMvmAyBk.js} +7 -7
  163. package/dist/mcp.es.js +79 -5
  164. package/dist/{message-CwKVEdZg.js → message-BSsgvHvf.js} +1 -1
  165. package/dist/{message-DS8lzHc1.js → message-BYZECyek.js} +1 -1
  166. package/dist/message-circle-DruwObfX.js +1 -0
  167. package/dist/message-square-BG6q6mlm.js +1 -0
  168. package/dist/{minimize-2-UEZmP2QT.js → minimize-2-BQRoBV1V.js} +1 -1
  169. package/dist/{model-switcher-Kk1jEQ5t.js → model-switcher-CMpCOYcB.js} +1 -1
  170. package/dist/{overlay-C1od6LOz.js → overlay-Cb-MkyDa.js} +1 -1
  171. package/dist/{panel-right-ryET0yyn.js → panel-right-i8warFxT.js} +1 -1
  172. package/dist/{paperclip-BDNoZFJP.js → paperclip-ByY3UVO6.js} +1 -1
  173. package/dist/play-BvKKq3fX.js +1 -0
  174. package/dist/primitives/conversation-store.d.ts +54 -0
  175. package/dist/{progress-bar-BvYX0aoy.js → progress-bar-jVAHvMUf.js} +1 -1
  176. package/dist/{prompt-suggestion-BRFu2lcu.js → prompt-suggestion-CD-qtNgC.js} +1 -1
  177. package/dist/{radio-DcL23cNJ.js → radio-BsoBMhkF.js} +1 -1
  178. package/dist/react/index.d.ts +393 -0
  179. package/dist/react.js +20 -20
  180. package/dist/{reasoning-Cackq4Rh.js → reasoning-4kBPtlTx.js} +1 -1
  181. package/dist/register-impl-B1hLkrI8.js +424 -0
  182. package/dist/{resizable-Cp9HUYih.js → resizable-uPmY9VY-.js} +1 -1
  183. package/dist/{rotate-ccw-0DLRDHH5.js → rotate-ccw-B2xn93py.js} +1 -1
  184. package/dist/{rotate-cw-DOB9IGcU.js → rotate-cw-CMVLoCyH.js} +1 -1
  185. package/dist/{scroll-area-emVmWP4K.js → scroll-area-BqLUo8ZZ.js} +1 -1
  186. package/dist/{scroll-button-CeP_gv1x.js → scroll-button-DslXiJyL.js} +1 -1
  187. package/dist/{select-CWmu00tS.js → select-2cLRtPGT.js} +1 -1
  188. package/dist/{separator-CE6vly6z.js → separator-BWQtNJcM.js} +1 -1
  189. package/dist/{settings-CE-78SvZ.js → settings-BBR63jLg.js} +1 -1
  190. package/dist/{settings-group-ZFWNxFQR.js → settings-group-B2ciy-Iw.js} +1 -1
  191. package/dist/{skeleton-BebdP4mf.js → skeleton-CkHI-HgC.js} +1 -1
  192. package/dist/{slider-BAKRYUlz.js → slider-DDR9U-i0.js} +1 -1
  193. package/dist/{solid-BE5ui6sy.js → solid-BzCFdL25.js} +7720 -7058
  194. package/dist/{solid-DFhsce3O.js → solid-DruVOXnf.js} +5864 -5283
  195. package/dist/solid.d.ts +6 -2
  196. package/dist/solid.js +217 -210
  197. package/dist/solid.server.js +217 -210
  198. package/dist/{source-B0FlguSx.js → source-GEnFF528.js} +1 -1
  199. package/dist/{star-CBMZvLuN.js → star-CilHq8GP.js} +1 -1
  200. package/dist/store-Ciyk6eZG.js +1 -0
  201. package/dist/{switch-CViARZCy.js → switch-KkeQIbuH.js} +1 -1
  202. package/dist/{tasks-card-MjCcOhR_.js → tasks-card-BrN4bggJ.js} +1 -1
  203. package/dist/{text-shimmer-DKlwRF2G.js → text-shimmer-Dcj1MHuq.js} +1 -1
  204. package/dist/{textarea-3ay2Me2-.js → textarea-Dpvbngbg.js} +1 -1
  205. package/dist/theme.tokens.css +28 -0
  206. package/dist/{thumbs-up-DQcu2HMO.js → thumbs-up-CsT9Wzb9.js} +1 -1
  207. package/dist/{toast-store-C6yKOhbk.js → toast-store-tgK6MuMv.js} +1 -1
  208. package/dist/{tool-BCYNlfKy.js → tool-DzUjIBT8.js} +1 -1
  209. package/dist/{tooltip-05zI4hjs.js → tooltip-Bkkg_4t0.js} +1 -1
  210. package/dist/{trash-2-BR1RxGky.js → trash-2-jBKxjGGQ.js} +1 -1
  211. package/dist/{triangle-alert-DHohDOCy.js → triangle-alert-DlQ68ppf.js} +1 -1
  212. package/dist/types.d.ts +48 -3
  213. package/dist/ui/dock.d.ts +29 -0
  214. package/dist/{upload-BbGW6A_u.js → upload-TcAHXv9W.js} +1 -1
  215. package/dist/{url-scheme-policy-DHpoTJwB.js → url-scheme-policy-DR5DgvkM.js} +1 -1
  216. package/dist/{use-card-resolution-CJW4grFa.js → use-card-resolution-DaZqAdWf.js} +1 -1
  217. package/dist/{variant-aurora-xiMPty8f.js → variant-aurora-BhLuYxJR.js} +1 -1
  218. package/dist/{variant-aurora-BUOVgPOB.js → variant-aurora-CNmfHhcx.js} +2 -2
  219. package/dist/{variant-aurora-CUsUJvFI.js → variant-aurora-D6GsdTPA.js} +2 -2
  220. package/dist/{variant-aurora-CW2i4bfr.js → variant-aurora-DbW_OWL2.js} +1 -1
  221. package/dist/{variant-custom-D91HjAKz.js → variant-custom-BRvaNHSi.js} +1 -1
  222. package/dist/{variant-custom-BQtOnmeO.js → variant-custom-BvYHR62b.js} +1 -1
  223. package/dist/{variant-custom-CAnzzppW.js → variant-custom-DMTrEO5w.js} +2 -2
  224. package/dist/{variant-custom-CAm9L-E5.js → variant-custom-DV2x254s.js} +2 -2
  225. package/dist/{variant-wave-Ca1Ls4_y.js → variant-wave-BNMGrDfj.js} +2 -2
  226. package/dist/{variant-wave-uY5crU_K.js → variant-wave-BpDd8t3Z.js} +1 -1
  227. package/dist/{variant-wave-CxX39DKd.js → variant-wave-CyBueXj9.js} +2 -2
  228. package/dist/{variant-wave-DYyzIIZv.js → variant-wave-sp-qwsdI.js} +1 -1
  229. package/dist/x-Z5UntkIJ.js +1 -0
  230. package/frameworks/react/index.tsx +14 -4
  231. package/llms-full.txt +7 -2
  232. package/package.json +16 -16
  233. package/src/elements/element-meta.json +49 -6
  234. package/theme.css +28 -0
  235. package/bin/route.test.js +0 -58
  236. package/dist/arrow-down-Br0qtpsz.js +0 -1
  237. package/dist/arrow-left-Dj7xgE12.js +0 -1
  238. package/dist/check-DPeeMUYx.js +0 -1
  239. package/dist/chevron-down-CHSWk7ZT.js +0 -1
  240. package/dist/chevron-right-B7l_fMgx.js +0 -1
  241. package/dist/circle-Bb0yOpqM.js +0 -1
  242. package/dist/circle-check-BGZpCiz7.js +0 -1
  243. package/dist/code-block-CUQ5mtv0.js +0 -1
  244. package/dist/controllable-D43BKmtX.js +0 -1
  245. package/dist/conversation-list-D4lLU_yS.js +0 -1
  246. package/dist/define-CGGX-7Vg.js +0 -1
  247. package/dist/message-circle-Xf8Q-vZp.js +0 -1
  248. package/dist/message-square-Cxnwgkns.js +0 -1
  249. package/dist/play-OFIvYXUQ.js +0 -1
  250. package/dist/register-impl-C7rENvPK.js +0 -424
  251. package/dist/store-7eoadydQ.js +0 -1
  252. package/dist/x-C5m1JFgi.js +0 -1
  253. package/src/agent-tooling/archetypes.ts +0 -205
  254. package/src/agent-tooling/catalog/README.md +0 -676
  255. package/src/agent-tooling/catalog/catalog-types.ts +0 -231
  256. package/src/agent-tooling/catalog/fabrications.ts +0 -96
  257. package/src/agent-tooling/catalog/invariants.ts +0 -284
  258. package/src/agent-tooling/catalog/labs-titles.ts +0 -114
  259. package/src/agent-tooling/catalog/scenarios.ts +0 -87
  260. package/src/agent-tooling/catalog/surfaces.ts +0 -347
  261. package/src/agent-tooling/construct/cli-entry.ts +0 -8
  262. package/src/agent-tooling/construct/cli.ts +0 -131
  263. package/src/agent-tooling/construct/codegen.ts +0 -1353
  264. package/src/agent-tooling/construct/construct.v1.schema.json +0 -250
  265. package/src/agent-tooling/construct/dev.ts +0 -148
  266. package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +0 -7
  267. package/src/agent-tooling/construct/fixtures/ops-console.construct.json +0 -44
  268. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +0 -23
  269. package/src/agent-tooling/construct/schema.ts +0 -371
  270. package/src/agent-tooling/integrations/anthropic.ts +0 -442
  271. package/src/agent-tooling/integrations/cloudflare.ts +0 -218
  272. package/src/agent-tooling/integrations/langgraph.ts +0 -133
  273. package/src/agent-tooling/integrations/mastra.ts +0 -182
  274. package/src/agent-tooling/integrations/mock.ts +0 -148
  275. package/src/agent-tooling/integrations/ollama.ts +0 -97
  276. package/src/agent-tooling/integrations/openai.ts +0 -95
  277. package/src/agent-tooling/integrations/openrouter.ts +0 -82
  278. package/src/agent-tooling/integrations/pi.ts +0 -176
  279. package/src/agent-tooling/integrations/pydantic-ai.ts +0 -108
  280. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +0 -398
  281. package/src/agent-tooling/mcp/css-raw.d.ts +0 -12
  282. package/src/agent-tooling/mcp/manifest.ts +0 -422
  283. package/src/agent-tooling/mcp/server.ts +0 -116
  284. package/src/agent-tooling/mcp/stdio.ts +0 -18
  285. package/src/agent-tooling/mcp/tools/construct.ts +0 -130
  286. package/src/agent-tooling/mcp/tools/debug.ts +0 -621
  287. package/src/agent-tooling/mcp/tools/reference.ts +0 -980
  288. package/src/agent-tooling/mcp/tools/scaffold.ts +0 -6708
  289. package/src/agent-tooling/mcp/tools/theme.ts +0 -456
  290. package/src/agent-tooling/mcp/tools/types.ts +0 -14
  291. package/src/agent-tooling/mcp/validate-args.ts +0 -141
  292. package/src/agent-tooling/recipes/composed-thread.ts +0 -714
  293. package/src/agent-tooling/recipes/index.ts +0 -22
  294. package/src/agent-tooling/recipes/types.ts +0 -32
  295. package/src/agent-tooling/registry.ts +0 -132
  296. package/src/agent-tooling/route-emit.ts +0 -305
  297. package/src/agent-tooling/types.ts +0 -390
  298. package/src/components/artifact-card.tsx +0 -120
  299. package/src/components/artifact.tsx +0 -914
  300. package/src/components/attachment-types.ts +0 -66
  301. package/src/components/attachments.tsx +0 -536
  302. package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +0 -257
  303. package/src/components/audio-visualizer/aurora.glsl.ts +0 -330
  304. package/src/components/audio-visualizer/fit-scale.ts +0 -112
  305. package/src/components/audio-visualizer/index.tsx +0 -528
  306. package/src/components/audio-visualizer/labs/lab-choreography.ts +0 -187
  307. package/src/components/audio-visualizer/labs/lab-shaders.ts +0 -363
  308. package/src/components/audio-visualizer/labs/lab-visualizer.tsx +0 -102
  309. package/src/components/audio-visualizer/shader-canvas.tsx +0 -876
  310. package/src/components/audio-visualizer/sizes.ts +0 -54
  311. package/src/components/audio-visualizer/variant-aurora.tsx +0 -305
  312. package/src/components/audio-visualizer/variant-bar.tsx +0 -175
  313. package/src/components/audio-visualizer/variant-custom.tsx +0 -344
  314. package/src/components/audio-visualizer/variant-grid.tsx +0 -175
  315. package/src/components/audio-visualizer/variant-radial.tsx +0 -163
  316. package/src/components/audio-visualizer/variant-wave.tsx +0 -130
  317. package/src/components/audio-visualizer/wave.glsl.ts +0 -130
  318. package/src/components/card-fallback.tsx +0 -60
  319. package/src/components/card-renderer.tsx +0 -220
  320. package/src/components/card.tsx +0 -212
  321. package/src/components/chain-of-thought.tsx +0 -348
  322. package/src/components/chat-container.tsx +0 -89
  323. package/src/components/chat-scope-picker.tsx +0 -57
  324. package/src/components/chat-thread.tsx +0 -518
  325. package/src/components/checkpoint.tsx +0 -88
  326. package/src/components/choice-card.tsx +0 -743
  327. package/src/components/coachmark.tsx +0 -249
  328. package/src/components/code-block.tsx +0 -181
  329. package/src/components/composer-dom.ts +0 -159
  330. package/src/components/composer-highlight.ts +0 -242
  331. package/src/components/composer-history.ts +0 -82
  332. package/src/components/composer.tsx +0 -1075
  333. package/src/components/confirm-card.tsx +0 -402
  334. package/src/components/context.tsx +0 -377
  335. package/src/components/conversation-item.tsx +0 -218
  336. package/src/components/conversation-list.tsx +0 -429
  337. package/src/components/dismissed-stub.tsx +0 -80
  338. package/src/components/embed.tsx +0 -200
  339. package/src/components/empty.tsx +0 -177
  340. package/src/components/feedback-bar.tsx +0 -166
  341. package/src/components/file-tree.tsx +0 -530
  342. package/src/components/file-upload.tsx +0 -167
  343. package/src/components/form-widgets.tsx +0 -525
  344. package/src/components/form.tsx +0 -1296
  345. package/src/components/image.tsx +0 -65
  346. package/src/components/link-preview.tsx +0 -195
  347. package/src/components/loader.tsx +0 -367
  348. package/src/components/markdown.tsx +0 -162
  349. package/src/components/message-skills.tsx +0 -40
  350. package/src/components/message.tsx +0 -765
  351. package/src/components/model-switcher.tsx +0 -132
  352. package/src/components/prompt-input.tsx +0 -188
  353. package/src/components/prompt-suggestion.tsx +0 -150
  354. package/src/components/reasoning.tsx +0 -293
  355. package/src/components/response-compare-types.ts +0 -152
  356. package/src/components/response-compare.tsx +0 -455
  357. package/src/components/response-stream.tsx +0 -109
  358. package/src/components/screen.tsx +0 -181
  359. package/src/components/scroll-button.tsx +0 -93
  360. package/src/components/source.tsx +0 -192
  361. package/src/components/tasks-card.tsx +0 -801
  362. package/src/components/text-shimmer.tsx +0 -37
  363. package/src/components/thinking-bar.tsx +0 -50
  364. package/src/components/thread.tsx +0 -228
  365. package/src/components/toast.tsx +0 -503
  366. package/src/components/tool-classify.ts +0 -26
  367. package/src/components/tool-types.ts +0 -49
  368. package/src/components/tool.tsx +0 -190
  369. package/src/components/use-card-resolution.ts +0 -44
  370. package/src/components/voice-input.tsx +0 -222
  371. package/src/components/voice-output.tsx +0 -242
  372. package/src/components/workspace-shell.tsx +0 -285
  373. package/src/diagnostics/hook.ts +0 -352
  374. package/src/diagnostics/index.ts +0 -82
  375. package/src/diagnostics/report-request.ts +0 -296
  376. package/src/elements/agent-card.tsx +0 -67
  377. package/src/elements/artifact.tsx +0 -194
  378. package/src/elements/attachments.tsx +0 -140
  379. package/src/elements/audio-visualizer.tsx +0 -227
  380. package/src/elements/autoloader.ts +0 -89
  381. package/src/elements/avatar.tsx +0 -33
  382. package/src/elements/badge.tsx +0 -32
  383. package/src/elements/button.tsx +0 -149
  384. package/src/elements/card.tsx +0 -133
  385. package/src/elements/cards.tsx +0 -266
  386. package/src/elements/chain-of-thought.tsx +0 -141
  387. package/src/elements/chat-scope-picker.tsx +0 -65
  388. package/src/elements/chat-types.ts +0 -102
  389. package/src/elements/chat-workspace.tsx +0 -188
  390. package/src/elements/chat.tsx +0 -212
  391. package/src/elements/checkbox-group.tsx +0 -164
  392. package/src/elements/checkbox.tsx +0 -134
  393. package/src/elements/checkpoint.tsx +0 -47
  394. package/src/elements/choice.tsx +0 -100
  395. package/src/elements/coachmark.tsx +0 -90
  396. package/src/elements/code-block.tsx +0 -60
  397. package/src/elements/command.tsx +0 -197
  398. package/src/elements/compare.tsx +0 -111
  399. package/src/elements/compiled.css +0 -2
  400. package/src/elements/composer.tsx +0 -162
  401. package/src/elements/confirm-card.tsx +0 -76
  402. package/src/elements/context-meter.tsx +0 -107
  403. package/src/elements/conversation-item.tsx +0 -120
  404. package/src/elements/conversation-list.tsx +0 -203
  405. package/src/elements/css.ts +0 -5
  406. package/src/elements/default-input.tsx +0 -392
  407. package/src/elements/define-entry.ts +0 -12
  408. package/src/elements/define.tsx +0 -563
  409. package/src/elements/diagnostic-events.ts +0 -114
  410. package/src/elements/dialog.tsx +0 -145
  411. package/src/elements/disclosure.ts +0 -95
  412. package/src/elements/dock.tsx +0 -215
  413. package/src/elements/dropdown.tsx +0 -123
  414. package/src/elements/editable-label.tsx +0 -140
  415. package/src/elements/element-data-types.ts +0 -152
  416. package/src/elements/element-diagnostics.ts +0 -392
  417. package/src/elements/element-manifest.json +0 -354
  418. package/src/elements/element-nonscalar.json +0 -185
  419. package/src/elements/element-types.d.ts +0 -4337
  420. package/src/elements/embed.tsx +0 -35
  421. package/src/elements/empty.tsx +0 -29
  422. package/src/elements/feedback-bar.tsx +0 -66
  423. package/src/elements/file-tree.tsx +0 -62
  424. package/src/elements/file-upload.tsx +0 -44
  425. package/src/elements/form.tsx +0 -94
  426. package/src/elements/hover-card.tsx +0 -80
  427. package/src/elements/icon.tsx +0 -41
  428. package/src/elements/image.tsx +0 -32
  429. package/src/elements/input.tsx +0 -492
  430. package/src/elements/kbd.tsx +0 -45
  431. package/src/elements/link-preview.tsx +0 -34
  432. package/src/elements/loader.tsx +0 -25
  433. package/src/elements/markdown.tsx +0 -38
  434. package/src/elements/menu.tsx +0 -241
  435. package/src/elements/message-skills.tsx +0 -83
  436. package/src/elements/message.tsx +0 -361
  437. package/src/elements/model-switcher.tsx +0 -121
  438. package/src/elements/nav.tsx +0 -87
  439. package/src/elements/notice.tsx +0 -53
  440. package/src/elements/pane-grid.tsx +0 -111
  441. package/src/elements/pane-group.tsx +0 -119
  442. package/src/elements/pane.tsx +0 -129
  443. package/src/elements/popover.tsx +0 -81
  444. package/src/elements/progress-bar.tsx +0 -39
  445. package/src/elements/prompt-dock.tsx +0 -82
  446. package/src/elements/prompt-input.tsx +0 -240
  447. package/src/elements/prompt-suggestions.tsx +0 -113
  448. package/src/elements/radio-group.tsx +0 -129
  449. package/src/elements/reasoning.tsx +0 -71
  450. package/src/elements/register-impl.ts +0 -148
  451. package/src/elements/register.ts +0 -76
  452. package/src/elements/remote.tsx +0 -225
  453. package/src/elements/resizable.globals.d.ts +0 -36
  454. package/src/elements/resizable.tsx +0 -704
  455. package/src/elements/response-stream.tsx +0 -40
  456. package/src/elements/screen.tsx +0 -90
  457. package/src/elements/scroll-area.tsx +0 -33
  458. package/src/elements/scroll-button.tsx +0 -179
  459. package/src/elements/search.tsx +0 -185
  460. package/src/elements/segmented.tsx +0 -129
  461. package/src/elements/select.tsx +0 -165
  462. package/src/elements/separator.tsx +0 -36
  463. package/src/elements/setting-item.tsx +0 -50
  464. package/src/elements/settings-group.tsx +0 -37
  465. package/src/elements/skeleton.tsx +0 -45
  466. package/src/elements/slider.tsx +0 -171
  467. package/src/elements/slot-text.ts +0 -73
  468. package/src/elements/slots.ts +0 -787
  469. package/src/elements/source.tsx +0 -126
  470. package/src/elements/status.tsx +0 -42
  471. package/src/elements/styles.css +0 -328
  472. package/src/elements/switch.tsx +0 -118
  473. package/src/elements/tabs.tsx +0 -95
  474. package/src/elements/tasks.tsx +0 -103
  475. package/src/elements/text-shimmer.tsx +0 -28
  476. package/src/elements/thinking-bar.tsx +0 -43
  477. package/src/elements/thread.tsx +0 -139
  478. package/src/elements/toast.tsx +0 -106
  479. package/src/elements/tool.tsx +0 -78
  480. package/src/elements/tooltip.tsx +0 -85
  481. package/src/elements/validate-messages.ts +0 -76
  482. package/src/elements/voice-input.tsx +0 -100
  483. package/src/elements/voice-output.tsx +0 -82
  484. package/src/index.ts +0 -428
  485. package/src/primitives/audio-bands.ts +0 -174
  486. package/src/primitives/card-component-types.ts +0 -63
  487. package/src/primitives/card-contract.ts +0 -80
  488. package/src/primitives/card-data-types.ts +0 -361
  489. package/src/primitives/card-host.tsx +0 -37
  490. package/src/primitives/card-recovery.ts +0 -160
  491. package/src/primitives/card-registry.tsx +0 -78
  492. package/src/primitives/card-resolution.ts +0 -36
  493. package/src/primitives/card-routing.ts +0 -85
  494. package/src/primitives/card-schemas/artifact.schema.json +0 -92
  495. package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
  496. package/src/primitives/card-schemas/card-event.schema.json +0 -12
  497. package/src/primitives/card-schemas/choice.schema.json +0 -75
  498. package/src/primitives/card-schemas/confirm.schema.json +0 -65
  499. package/src/primitives/card-schemas/embed.schema.json +0 -63
  500. package/src/primitives/card-schemas/form.result.schema.json +0 -7
  501. package/src/primitives/card-schemas/form.schema.json +0 -53
  502. package/src/primitives/card-schemas/link.schema.json +0 -54
  503. package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
  504. package/src/primitives/card-schemas/tasks.schema.json +0 -83
  505. package/src/primitives/card-tags.ts +0 -61
  506. package/src/primitives/card-validate-cards.ts +0 -255
  507. package/src/primitives/card-validate-schemas.ts +0 -58
  508. package/src/primitives/card-validate.ts +0 -131
  509. package/src/primitives/chat-config.tsx +0 -103
  510. package/src/primitives/composer-model.ts +0 -49
  511. package/src/primitives/composer-triggers.ts +0 -35
  512. package/src/primitives/controllable.ts +0 -21
  513. package/src/primitives/create-kai-chat.ts +0 -66
  514. package/src/primitives/create-tween.ts +0 -266
  515. package/src/primitives/embed-providers.ts +0 -254
  516. package/src/primitives/field-mask.ts +0 -256
  517. package/src/primitives/field-semantics.ts +0 -115
  518. package/src/primitives/highlighter.ts +0 -157
  519. package/src/primitives/input-mask.ts +0 -853
  520. package/src/primitives/link-preview.ts +0 -87
  521. package/src/primitives/message-feedback.ts +0 -124
  522. package/src/primitives/pdf-preview.ts +0 -121
  523. package/src/primitives/toast-store.ts +0 -338
  524. package/src/primitives/url-scheme-policy.ts +0 -70
  525. package/src/primitives/use-audio-analysis.ts +0 -340
  526. package/src/primitives/use-auto-resize.ts +0 -31
  527. package/src/primitives/use-resize-observer.ts +0 -45
  528. package/src/primitives/use-sequencer.ts +0 -72
  529. package/src/primitives/use-speech-recognition.ts +0 -146
  530. package/src/primitives/use-stick-to-bottom.ts +0 -75
  531. package/src/primitives/use-text-stream.ts +0 -143
  532. package/src/primitives/use-voice-recorder.ts +0 -62
  533. package/src/primitives/visualizer-sequences.ts +0 -350
  534. package/src/remote/host-embed.ts +0 -345
  535. package/src/remote/index.ts +0 -2
  536. package/src/remote/origin.ts +0 -30
  537. package/src/remote/provider-runtime.ts +0 -262
  538. package/src/remote/provider.ts +0 -2
  539. package/src/remote/validate.ts +0 -22
  540. package/src/remote/version.ts +0 -12
  541. package/src/remote/wire.ts +0 -48
  542. package/src/schemas/from-tool-call.ts +0 -151
  543. package/src/schemas/index.ts +0 -341
  544. package/src/schemas/provider-subsets.ts +0 -538
  545. package/src/schemas/registry.ts +0 -355
  546. package/src/schemas/tool-defs.ts +0 -793
  547. package/src/solid.ts +0 -165
  548. package/src/state/index.ts +0 -44
  549. package/src/state/messages.ts +0 -53
  550. package/src/state/mock.ts +0 -297
  551. package/src/state/parts.ts +0 -295
  552. package/src/state/persistence.ts +0 -180
  553. package/src/state/stream.ts +0 -246
  554. package/src/state/suggestions.ts +0 -9
  555. package/src/state/threads.ts +0 -142
  556. package/src/test-utils/fake-clock.ts +0 -88
  557. package/src/types.ts +0 -53
  558. package/src/ui/action-icons.ts +0 -53
  559. package/src/ui/agent-card.tsx +0 -218
  560. package/src/ui/avatar.tsx +0 -23
  561. package/src/ui/badge.tsx +0 -21
  562. package/src/ui/button.tsx +0 -49
  563. package/src/ui/card.tsx +0 -245
  564. package/src/ui/checkbox-group.tsx +0 -153
  565. package/src/ui/checkbox.tsx +0 -63
  566. package/src/ui/collapsible.tsx +0 -163
  567. package/src/ui/command.tsx +0 -103
  568. package/src/ui/dialog.tsx +0 -223
  569. package/src/ui/dock.tsx +0 -584
  570. package/src/ui/dropdown.tsx +0 -636
  571. package/src/ui/editable-label.tsx +0 -112
  572. package/src/ui/hover-card.tsx +0 -345
  573. package/src/ui/icon.tsx +0 -167
  574. package/src/ui/input.tsx +0 -391
  575. package/src/ui/kbd.tsx +0 -118
  576. package/src/ui/nav.tsx +0 -282
  577. package/src/ui/notice.tsx +0 -84
  578. package/src/ui/overlay.tsx +0 -277
  579. package/src/ui/pane-grid.tsx +0 -117
  580. package/src/ui/pane-group.tsx +0 -291
  581. package/src/ui/pane.tsx +0 -193
  582. package/src/ui/popover.tsx +0 -106
  583. package/src/ui/progress-bar.tsx +0 -83
  584. package/src/ui/prompt-dock.tsx +0 -145
  585. package/src/ui/radio.tsx +0 -150
  586. package/src/ui/resizable.tsx +0 -693
  587. package/src/ui/scroll-area.tsx +0 -26
  588. package/src/ui/segmented.tsx +0 -109
  589. package/src/ui/select.tsx +0 -168
  590. package/src/ui/separator.tsx +0 -10
  591. package/src/ui/settings-group.tsx +0 -67
  592. package/src/ui/skeleton.tsx +0 -73
  593. package/src/ui/slider.tsx +0 -178
  594. package/src/ui/status.tsx +0 -48
  595. package/src/ui/switch.tsx +0 -119
  596. package/src/ui/tabs.tsx +0 -168
  597. package/src/ui/textarea.tsx +0 -21
  598. package/src/ui/tooltip.tsx +0 -118
  599. package/src/utils/cn.ts +0 -30
  600. package/src/wire/chunk.ts +0 -248
  601. package/src/wire/consume.ts +0 -599
  602. package/src/wire/diagnostics.ts +0 -727
  603. package/src/wire/encode-probe.ts +0 -214
  604. package/src/wire/encode.ts +0 -947
  605. package/src/wire/files.ts +0 -342
  606. package/src/wire/formats/anthropic.ts +0 -274
  607. package/src/wire/formats/openai.ts +0 -228
  608. package/src/wire/index.ts +0 -95
  609. package/src/wire/media-types.ts +0 -344
  610. package/src/wire/read.ts +0 -396
  611. package/src/wire/sink-helpers.ts +0 -50
  612. package/src/wire/sse.ts +0 -153
@@ -1,765 +0,0 @@
1
- import { type JSX, For, Index, Switch, Match, createMemo, createSignal, splitProps, Show } from "solid-js";
2
- import { Tooltip } from "../ui/tooltip";
3
- import { Copy, Check } from "lucide-solid";
4
- import { cn } from "../utils/cn";
5
- import { Markdown } from "./markdown";
6
- import { Button } from "../ui/button";
7
- import { actionIcon, BUILTIN_ACTION_LABEL } from "../ui/action-icons";
8
- import type { ChatMessageAction, CustomAction, FeedbackVote, MessagePart, MessageSource } from "../elements/chat-types";
9
- import { useChatConfig, textClass } from "../primitives/chat-config";
10
- import { Reasoning, ReasoningTrigger, ReasoningContent } from "./reasoning";
11
- import { Loader } from "./loader";
12
- import { Tool } from "./tool";
13
- import {
14
- Attachments,
15
- Attachment,
16
- AttachmentPreview,
17
- AttachmentInfo,
18
- AttachmentHoverCard,
19
- AttachmentHoverCardTrigger,
20
- AttachmentHoverCardContent,
21
- getAttachmentLabel,
22
- getMediaCategory,
23
- } from "./attachments";
24
- import { Source, SourceTrigger, SourceContent, SourceList } from "./source";
25
- import { CardRenderer, type CardSchemaMap } from "./card-renderer";
26
- import type { CardComponentMap } from "../primitives/card-registry";
27
-
28
- // --- Message ---
29
-
30
- /** Who is speaking in a message row. This is the SEMANTIC role of the message,
31
- * not an ARIA role — see `MessageProps['role']`. */
32
- export type MessageRole = 'user' | 'assistant' | 'system';
33
-
34
- /** The accessible name given to a row that declares a speaker. `role="article"`
35
- * supports naming; the bare `<div>` a role-less `<Message>` renders does not,
36
- * so the label is only attached alongside that role. */
37
- const MESSAGE_ROLE_LABEL: Record<MessageRole, string> = {
38
- user: 'User message',
39
- assistant: 'Assistant message',
40
- system: 'System message',
41
- };
42
-
43
- export interface MessageProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, 'role'> {
44
- children: JSX.Element;
45
- /** Who is speaking: `'user'`, `'assistant'` or `'system'`.
46
- *
47
- * This SHADOWS the inherited ARIA `role` attribute on purpose, and is the
48
- * reason `JSX.HTMLAttributes` is `Omit`ted above. Before this existed, `role`
49
- * resolved to ARIA and was spread straight onto the row, so `<Message
50
- * role="user">` shipped `role="user"` on a div — not a valid ARIA role, and a
51
- * critical axe `aria-roles` violation ("Role must be one of the valid ARIA
52
- * roles: user") on every message that used the prop. Chromium discards the
53
- * unknown token and computes `generic`, so the damage was a failed a11y audit
54
- * and a row with no accessible role or name at all, not a mis-announced one.
55
- *
56
- * It is now consumed here and never reaches the DOM. What the row gets
57
- * instead is a VALID ARIA role that can carry a name — `role="article"` plus
58
- * an `aria-label` naming the speaker — and `data-role` for styling and
59
- * querying. Omit the prop and the row stays an unlabelled `<div>`, exactly as
60
- * before, so the many role-less call sites are untouched.
61
- *
62
- * The trade-off: the row's ARIA role can no longer be set through this prop.
63
- * Pass `aria-label` (or any other ARIA attribute) to override the default
64
- * naming — the spread below still wins over what this computes. */
65
- role?: MessageRole;
66
- }
67
-
68
- function Message(props: MessageProps) {
69
- const [local, rest] = splitProps(props, ["children", "class", "role"]);
70
- return (
71
- <div
72
- part="row"
73
- class={cn("flex items-start gap-3", local.class)}
74
- data-role={local.role}
75
- role={local.role ? 'article' : undefined}
76
- aria-label={local.role ? MESSAGE_ROLE_LABEL[local.role] : undefined}
77
- {...rest}
78
- >
79
- {local.children}
80
- </div>
81
- );
82
- }
83
-
84
- // --- MessageAvatar ---
85
-
86
- export interface MessageAvatarProps {
87
- /** Avatar image URL. Optional: with no `src` the component renders `fallback`
88
- * (initials), which is the whole point of having a fallback — requiring `src`
89
- * forced `<MessageAvatar src="" …/>` at every initials-only call site. */
90
- src?: string;
91
- /** Alt text for the image. Only meaningful alongside `src`; defaults to `''`
92
- * so an avatar stays decorative rather than announcing a filename. */
93
- alt?: string;
94
- fallback?: string;
95
- class?: string;
96
- }
97
-
98
- function MessageAvatar(props: MessageAvatarProps) {
99
- return (
100
- <div
101
- part="avatar"
102
- class={cn("h-8 w-8 shrink-0 overflow-hidden rounded-full", props.class)}
103
- >
104
- <Show
105
- when={props.src}
106
- fallback={
107
- <Show when={props.fallback}>
108
- <div class="flex h-full w-full items-center justify-center bg-muted text-xs font-medium text-muted-foreground">
109
- {props.fallback}
110
- </div>
111
- </Show>
112
- }
113
- >
114
- <img
115
- src={props.src}
116
- alt={props.alt ?? ''}
117
- class="h-full w-full object-cover"
118
- />
119
- </Show>
120
- </div>
121
- );
122
- }
123
-
124
- // --- MessageContent ---
125
-
126
- export interface MessageContentProps extends JSX.HTMLAttributes<HTMLDivElement> {
127
- children: JSX.Element | string;
128
- markdown?: boolean;
129
- /** `::part` name(s) exposed on the content node. The body passes
130
- * `"bubble content"` so consumers can target either the rounded bubble or the
131
- * text region from outside the shadow boundary. */
132
- part?: string;
133
- }
134
-
135
- function MessageContent(props: MessageContentProps) {
136
- const [local, rest] = splitProps(props, ["children", "markdown", "class", "part"]);
137
- const config = useChatConfig();
138
- const classNames = () =>
139
- cn(
140
- "min-w-0 rounded-lg p-2 text-foreground bg-secondary max-w-none break-words whitespace-normal",
141
- textClass(config.proseSize()),
142
- local.class,
143
- );
144
-
145
- return (
146
- <Show
147
- when={local.markdown}
148
- fallback={
149
- <div part={local.part} class={classNames()} {...rest}>
150
- {local.children}
151
- </div>
152
- }
153
- >
154
- <Markdown part={local.part} content={local.children as string} class={classNames()} />
155
- </Show>
156
- );
157
- }
158
-
159
- // --- MessageActions ---
160
-
161
- export interface MessageActionsProps extends JSX.HTMLAttributes<HTMLDivElement> {
162
- children: JSX.Element;
163
- }
164
-
165
- function MessageActions(props: MessageActionsProps) {
166
- const [local, rest] = splitProps(props, ["children", "class"]);
167
- return (
168
- <div
169
- class={cn(
170
- "flex items-center gap-0.5 mt-0.5",
171
- local.class,
172
- )}
173
- {...rest}
174
- >
175
- {local.children}
176
- </div>
177
- );
178
- }
179
-
180
- // --- MessageActionBar ---
181
-
182
- export interface MessageActionBarProps {
183
- /** Built-in action names and/or custom action descriptors, in order. */
184
- actions: (ChatMessageAction | CustomAction)[];
185
- /** `'always'` (default) keeps the bar visible; `'hover'` reveals it on
186
- * parent `.group` hover. */
187
- reveal?: 'always' | 'hover';
188
- /** Fired with the built-in name or the custom action id when a button is clicked. */
189
- onAction: (id: string) => void;
190
- /** The active feedback vote. When `'like'`/`'dislike'` is set, that button is
191
- * marked pressed (filled) and the OTHER vote button animates out. `undefined`
192
- * shows both. Pure/prop-driven so the bar survives re-renders. */
193
- activeFeedback?: FeedbackVote;
194
- /** When true, the `copy` button shows its emerald check icon instead of the
195
- * copy glyph (cleared by the owner after ~2s). */
196
- copied?: boolean;
197
- class?: string;
198
- }
199
-
200
- /** Normalize a bar entry (string built-in or custom object) to a uniform shape. */
201
- function normalizeAction(a: ChatMessageAction | CustomAction) {
202
- if (typeof a === 'string') {
203
- return { id: a, label: BUILTIN_ACTION_LABEL[a], Icon: actionIcon(a) };
204
- }
205
- return { id: a.id, label: a.label, Icon: actionIcon(a.icon) };
206
- }
207
-
208
- /** Is this entry one of the two feedback votes? */
209
- function feedbackVoteOf(a: ChatMessageAction | CustomAction): FeedbackVote | undefined {
210
- return a === 'like' || a === 'dislike' ? a : undefined;
211
- }
212
-
213
- /**
214
- * The shared message action toolbar. Renders one ghost icon button per entry —
215
- * built-in names pull their label+icon from the curated registry; custom
216
- * descriptors use their `label` plus `actionIcon(icon)` (label-only when the
217
- * icon is unknown or absent). `reveal="hover"` makes the bar fade in on the
218
- * parent `.group`'s hover.
219
- *
220
- * Pure/prop-driven: feedback (`activeFeedback`) and copy (`copied`) state are
221
- * owned by the parent facade and passed in — the bar holds no internal signals,
222
- * so it survives the new-array-per-chunk re-renders of a streaming thread. With
223
- * a vote active, the chosen `like`/`dislike` button is marked `aria-pressed` +
224
- * filled and the other vote button collapses its width (sliding the active thumb
225
- * into its place) via a 0fr↔1fr grid transition. The
226
- * `copy` button swaps to an emerald check while `copied`.
227
- */
228
- function MessageActionBar(props: MessageActionBarProps) {
229
- return (
230
- <MessageActions
231
- part="actions"
232
- class={cn(
233
- 'mt-1 flex gap-0',
234
- props.reveal === 'hover' && 'opacity-0 transition-opacity group-hover:opacity-100',
235
- props.class,
236
- )}
237
- >
238
- <For each={props.actions}>
239
- {(a) => {
240
- const item = normalizeAction(a);
241
- const tooltipText = () => (typeof a !== 'string' && a.tooltip) ? a.tooltip : item.label;
242
- const vote = feedbackVoteOf(a);
243
- // A vote button is the active one when it matches the resolved vote.
244
- const isActiveVote = () => vote !== undefined && props.activeFeedback === vote;
245
- // The COPY button reflects the copied check.
246
- const isCopy = item.id === 'copy';
247
- const showCheck = () => isCopy && props.copied === true;
248
-
249
- // Factory (not a shared node): each Show branch gets its own Button so
250
- // the eager DOM node is never referenced from two places.
251
- const button = () => (
252
- <Button
253
- variant="ghost"
254
- size="icon-sm"
255
- class={cn('rounded-full', isActiveVote() && 'text-primary')}
256
- data-action={item.id}
257
- aria-label={showCheck() ? 'Copied' : item.label}
258
- aria-pressed={vote !== undefined ? isActiveVote() : undefined}
259
- onClick={() => props.onAction(item.id)}
260
- >
261
- <Show
262
- when={showCheck()}
263
- fallback={
264
- <Show when={item.Icon} fallback={<span class="px-1 text-xs">{item.label}</span>}>
265
- {(Icon) => {
266
- const I = Icon();
267
- return <I class={cn('size-3.5', isActiveVote() && 'fill-current')} />;
268
- }}
269
- </Show>
270
- }
271
- >
272
- <Check class="size-3.5 text-emerald-400" />
273
- </Show>
274
- </Button>
275
- );
276
- // Icon-only buttons get a tooltip; label-only buttons (text already
277
- // visible) don't.
278
- const rendered = () => (
279
- <Show when={item.Icon} fallback={button()}>
280
- <Tooltip content={tooltipText()}>{button()}</Tooltip>
281
- </Show>
282
- );
283
-
284
- // When the OTHER vote is active, this vote button collapses — its WIDTH
285
- // animates to zero via a 0fr↔1fr grid so the remaining thumb slides into
286
- // its place, while it fades out; it slides + fades back on un-vote. (Kept
287
- // mounted-but-collapsed, not unmounted, so the sibling can slide.) No
288
- // vote active → both shown; non-vote entries always render.
289
- return (
290
- <Show when={vote !== undefined} fallback={rendered()}>
291
- {(() => {
292
- const show = () => props.activeFeedback === undefined || props.activeFeedback === vote;
293
- return (
294
- <span
295
- data-feedback-collapsed={show() ? undefined : ''}
296
- class={cn(
297
- 'grid transition-[grid-template-columns,opacity] duration-300 ease-out',
298
- show() ? 'grid-cols-[1fr] opacity-100' : 'grid-cols-[0fr] opacity-0',
299
- )}
300
- >
301
- <span class="min-w-0 overflow-hidden">{rendered()}</span>
302
- </span>
303
- );
304
- })()}
305
- </Show>
306
- );
307
- }}
308
- </For>
309
- </MessageActions>
310
- );
311
- }
312
-
313
- // --- MessageBody ---
314
-
315
- export interface MessageBodyProps {
316
- /** The message's ordered parts (text, reasoning, tool, card, source, file),
317
- * rendered in a single pass in the order they appear. A run of consecutive
318
- * `source` parts renders as ONE citation row (`part="citations"`), placed
319
- * OUTSIDE the message bubble so a citation is never confused with a link the
320
- * model typed into its prose. */
321
- parts: MessagePart[];
322
- /** Add/override card type -> component entries, forwarded to `CardRenderer`
323
- * for `card` parts. */
324
- cardTypes?: CardComponentMap;
325
- /** JSON Schemas for the card types this app renders, keyed by envelope type,
326
- * forwarded to `CardRenderer` for `card` parts. The companion of `cardTypes`:
327
- * that says what DRAWS a card, this says what a VALID one looks like.
328
- * `createCardRegistry(...).validationSchemas` is exactly this shape. Without it
329
- * the kit checks its own seven built-ins and leaves your own card type
330
- * unvalidated. A schema here WINS over a built-in of the same name. */
331
- cardSchemas?: CardSchemaMap;
332
- /** The custom-element host node to emit card events off when no `CardProvider`
333
- * is above this body, forwarded to `CardRenderer` as `hostElement`. The
334
- * `<kai-chat>`/`<kai-message>`/`<kai-thread>` facades pass their own element,
335
- * so a `card` part's events leave as the bubbling `kai-card` CustomEvent
336
- * instead of being silently discarded. */
337
- cardHostElement?: HTMLElement;
338
- /** Whether this is a user message (right-aligned bubble) vs an assistant
339
- * message (full-width transparent). */
340
- isUser: boolean;
341
- /** Whether text parts render as markdown. */
342
- markdown: boolean;
343
- /** Action-bar entries — built-in names and/or custom descriptors. When empty
344
- * the bar is not rendered. */
345
- actions?: (ChatMessageAction | CustomAction)[];
346
- /** `'always'` (default) keeps the bar visible; `'hover'` reveals it on parent
347
- * `.group` hover. */
348
- actionsReveal?: 'always' | 'hover';
349
- /** Fired with the built-in name or custom id when an action is clicked. */
350
- onAction?: (id: string) => void;
351
- /** The currently-active feedback vote, so the bar can mark like/dislike and
352
- * hide the other. */
353
- activeFeedback?: FeedbackVote;
354
- /** When true, the copy button shows its "copied" check icon. */
355
- copied?: boolean;
356
- /** Whether this message is the one currently streaming. Forwarded to each
357
- * reasoning part's `<Reasoning>` so the disclosure auto-opens while the
358
- * model is thinking and settles back once the stream ends. Without it the
359
- * user watches a static collapsed "Reasoning" label for the whole thinking
360
- * window. The caller owns the definition of "streaming" — for
361
- * `ChatThread` that is `loading` + being the last assistant message. */
362
- isStreaming?: boolean;
363
- /** How a `reasoning` part renders. `'full'` (default) is the current
364
- * behavior: the collapsible `<Reasoning>` disclosure, with the "Thinking…"
365
- * shimmer on its trigger while `isStreaming`. `'compact'` drops the
366
- * disclosure entirely and shows only a shimmer loader while the part is
367
- * streaming — nothing once it settles, so there is no expandable detail to
368
- * open. `'off'` renders the part not at all, in either state. Kit-decides-
369
- * HOW: this is a display-mode fact about the medium, not a per-message
370
- * toggle, so it applies uniformly to every reasoning part in the body. */
371
- reasoningMode?: 'full' | 'compact' | 'off';
372
- /** Seeds the reasoning disclosure open AND keeps it tracking the stream
373
- * (open while streaming, closes when it settles): the pre-Task-19f `full`
374
- * behavior. Default false/absent: the panel starts closed (just the
375
- * "Thinking" shimmer chip) and only opens on click, the current default
376
- * (owner ruling, 2026-08-26). Meaningless when `reasoningMode` is
377
- * `'compact'`/`'off'` (no disclosure exists to open). */
378
- reasoningDefaultOpen?: boolean;
379
- /** INJECT slot projected at the TOP of the body — above the reasoning / tools /
380
- * content. A per-message header: a model-name label, a role + timestamp line.
381
- * In the `<kai-message>` shadow this is `<slot name="before-body" />`. */
382
- beforeBody?: JSX.Element;
383
- /** INJECT slot projected at the BOTTOM of the body — below the action bar. A
384
- * citation / sources row, a token-cost / latency line. In the `<kai-message>`
385
- * shadow this is `<slot name="after-body" />`. */
386
- afterBody?: JSX.Element;
387
- }
388
-
389
- /** One render group over an ordered `parts` array. Two part types collapse runs:
390
- * consecutive `file` parts become a single `'files'` group so they share one
391
- * `<Attachments>` row (matching the pre-parts layout) instead of each opening
392
- * its own, and consecutive `source` parts become a single `'sources'` group so
393
- * the N citations one search produced are ONE wrapped row rather than N stacked
394
- * rows. Every other part is its own `'single'` group. Pure and order-preserving:
395
- * it only decides where the wrapper boundaries fall, never reorders or drops
396
- * anything, so a group sits exactly where its parts sat in `parts`. */
397
- export type MessagePartGroup =
398
- | { kind: 'single'; part: Exclude<MessagePart, { type: 'file' } | { type: 'source' }> }
399
- | { kind: 'files'; parts: Extract<MessagePart, { type: 'file' }>[] }
400
- | { kind: 'sources'; parts: Extract<MessagePart, { type: 'source' }>[] };
401
-
402
- export function groupMessageParts(parts: MessagePart[]): MessagePartGroup[] {
403
- const groups: MessagePartGroup[] = [];
404
- for (const part of parts) {
405
- if (part.type === 'file') {
406
- const last = groups[groups.length - 1];
407
- if (last?.kind === 'files') {
408
- groups[groups.length - 1] = { kind: 'files', parts: [...last.parts, part] };
409
- continue;
410
- }
411
- groups.push({ kind: 'files', parts: [part] });
412
- continue;
413
- }
414
- if (part.type === 'source') {
415
- const last = groups[groups.length - 1];
416
- if (last?.kind === 'sources') {
417
- groups[groups.length - 1] = { kind: 'sources', parts: [...last.parts, part] };
418
- continue;
419
- }
420
- groups.push({ kind: 'sources', parts: [part] });
421
- continue;
422
- }
423
- groups.push({ kind: 'single', part });
424
- }
425
- return groups;
426
- }
427
-
428
- /** The citation chip's label. `index` when the model numbered its citations;
429
- * otherwise `undefined` so `SourceTrigger` falls back to the domain. A source
430
- * with NO url has no domain to fall back to, so its title (then a generic word)
431
- * stands in rather than rendering an empty chip. */
432
- function citationLabel(s: MessageSource): string | number | undefined {
433
- if (s.index !== undefined) return s.index;
434
- if (s.url) return undefined;
435
- return s.title || 'Source';
436
- }
437
-
438
- /** The hover card's headline. Every field is optional, so fall back through
439
- * title -> url -> a generic word. */
440
- function citationTitle(s: MessageSource): string {
441
- return s.title || s.url || 'Source';
442
- }
443
-
444
- /** Narrow a group to one variant IN A SINGLE READ.
445
- *
446
- * The render body below reads its group/part through accessors (see the
447
- * `<Index>` note in `MessageBody`), and TypeScript cannot narrow a
448
- * discriminated union across two separate accessor CALLS —
449
- * `g().kind === 'files' && g()` leaves the second call widened, because as far
450
- * as the compiler knows the two calls could return different values. So the
451
- * test and the cast happen together, on one already-read value. Returns
452
- * `false` rather than `undefined` so it reads as a plain falsy `<Match when>`. */
453
- function groupAs<T extends MessagePartGroup['kind']>(
454
- group: MessagePartGroup,
455
- kind: T,
456
- ): Extract<MessagePartGroup, { kind: T }> | false {
457
- return group.kind === kind ? (group as Extract<MessagePartGroup, { kind: T }>) : false;
458
- }
459
-
460
- /** The same single-read narrowing for `MessagePart`. */
461
- function partAs<T extends MessagePart['type']>(
462
- part: MessagePart,
463
- type: T,
464
- ): Extract<MessagePart, { type: T }> | false {
465
- return part.type === type ? (part as Extract<MessagePart, { type: T }>) : false;
466
- }
467
-
468
- /**
469
- * The shared message body: the message's `parts` rendered in a single ordered
470
- * pass (text, reasoning, tool calls, generative-UI cards, citations and file
471
- * attachments interleaved exactly as they appear), followed by the action bar.
472
- * Runs of `source` and `file` parts each collapse into one row. This is the
473
- * single source of truth for how a message renders, consumed by `ChatThread`
474
- * (the `<For>` over `messages`), the standalone `<kai-message>` facade, and (in
475
- * future) `kai-compare` for each candidate. Pure/prop-driven: all interaction
476
- * state (copied, feedback vote) is owned above and passed in.
477
- */
478
- function MessageBody(props: MessageBodyProps) {
479
- const groups = createMemo(() => groupMessageParts(props.parts));
480
- return (
481
- <>
482
- {/* before-body (inject): a per-message header above everything else. */}
483
- <Show when={props.beforeBody}>{props.beforeBody}</Show>
484
- {/* <Index>, NOT <For>, on purpose — this is load-bearing.
485
- *
486
- * A streaming message re-renders once per delta with a brand-new `parts`
487
- * array (a new reference IS the re-render signal), and
488
- * `groupMessageParts` allocates fresh wrapper objects on top of that. A
489
- * <For> is REFERENCE-keyed, so every chunk looks like an entirely new
490
- * list and every row is torn down and rebuilt. Everything the user has
491
- * done inside a row dies with it: expanding a tool panel or a reasoning
492
- * block mid-stream silently did nothing, because the disclosure opened
493
- * and was discarded microseconds later by the next token (a live probe
494
- * caught the collapsibles' `createUniqueId()` walking cl-9 -> cl-11 ->
495
- * cl-15 across three deltas).
496
- *
497
- * <Index> keys by POSITION and hands each row its value as a SIGNAL, so
498
- * a row stays mounted while its content keeps updating. That is exactly
499
- * the shape of a stream: the folds behind `parts`
500
- * (appendTextPart/appendReasoningPart/upsertToolPart) only ever append
501
- * to the end or replace one part IN PLACE with the same variant — never
502
- * reorder, never change a part's type — so a part's position is a stable
503
- * identity, and a growing text/reasoning block or a tool patched from
504
- * `input-streaming` to `output-available` reaches the DOM through the
505
- * accessor instead of through a remount.
506
- *
507
- * The trade-off of position-keying: splicing a part out of the MIDDLE of
508
- * a message shifts the rows after it, so their local state (an open
509
- * disclosure) stays with the position rather than following the part.
510
- * <For> got that right for a STATIC array and got streaming wrong every
511
- * single time — no consumer splices mid-message, every consumer streams.
512
- *
513
- * This only works while the children read through the accessors below:
514
- * capturing `g().part` once re-freezes the row at its first delta. */}
515
- <Index each={groups()}>
516
- {(group) => (
517
- <Switch fallback={null}>
518
- <Match when={groupAs(group(), 'files')}>
519
- {(g) => (
520
- /* `grid`, NOT `inline`. The inline chip gives an image a 20x20
521
- preview — a thumbnail nobody can read — while the 96px tile
522
- and the hover-card full preview both already existed here and
523
- the thread used neither.
524
-
525
- WHY GRID AND NOT LIST, since `list` shows the filename
526
- outright: `list` stacks (`flex-col`), so a message carrying
527
- four attachments becomes four full-width rows and pushes the
528
- conversation off screen. `grid` is `flex-wrap w-fit`, so the
529
- same four are one 96px-tall row of tiles. Density is what
530
- keeps a thread readable, and it is the whole reason the
531
- thread is not the composer's chip strip.
532
-
533
- A grid tile draws no filename of its own, and hiding one
534
- behind the hover card is not good enough: that serves a
535
- pointer and nothing else. So `<AttachmentInfo>` renders a
536
- VISIBLE truncated caption on every non-image tile — no hover,
537
- no focus, no tap required — and the hover card is an upgrade
538
- to the full name and media type rather than the only way to
539
- get either. */
540
- <Attachments variant="grid" class={props.isUser ? 'mb-2 ml-auto' : 'mb-2'}>
541
- {/* Reference-keyed <For> is right HERE: the run's part objects
542
- are carried over untouched by the folds, and an attachment
543
- holds no state worth preserving. */}
544
- <For each={g().parts}>
545
- {(fp) => (
546
- <Attachment data={fp.attachment}>
547
- <AttachmentHoverCard>
548
- <AttachmentHoverCardTrigger class="block size-full">
549
- <AttachmentPreview />
550
- <AttachmentInfo />
551
- </AttachmentHoverCardTrigger>
552
- <AttachmentHoverCardContent>
553
- {/* An image gets the full preview; everything else
554
- gets the name and type the tile could not fit. */}
555
- <Show
556
- when={
557
- getMediaCategory(fp.attachment) === 'image' &&
558
- fp.attachment.type === 'file' &&
559
- fp.attachment.url
560
- }
561
- fallback={
562
- <>
563
- <div class="text-body font-medium">
564
- {getAttachmentLabel(fp.attachment)}
565
- </div>
566
- <Show when={fp.attachment.mediaType}>
567
- <div class="text-muted-foreground text-caption">
568
- {fp.attachment.mediaType}
569
- </div>
570
- </Show>
571
- </>
572
- }
573
- >
574
- <img
575
- alt={getAttachmentLabel(fp.attachment)}
576
- class="block max-h-64 max-w-xs rounded object-contain"
577
- src={fp.attachment.url}
578
- />
579
- </Show>
580
- </AttachmentHoverCardContent>
581
- </AttachmentHoverCard>
582
- </Attachment>
583
- )}
584
- </For>
585
- </Attachments>
586
- )}
587
- </Match>
588
- <Match when={groupAs(group(), 'sources')}>
589
- {(g) => (
590
- // OUTSIDE the bubble, deliberately. A citation nested inside
591
- // `MessageContent` is indistinguishable from a link the MODEL
592
- // typed into its prose — which is exactly how the first version
593
- // of the S12 conformance check passed while proving nothing.
594
- // `SourceList` is its own container, so the row is a sibling of
595
- // the content part, and `part="citations"` lets a consumer target
596
- // it through the shadow boundary.
597
- <SourceList part="citations" class={props.isUser ? 'justify-end' : undefined}>
598
- {/* Reference-keyed <For> is right HERE, as with files: the
599
- run's part objects are carried over untouched by the folds. */}
600
- <For each={g().parts}>
601
- {(sp) => (
602
- <Source href={sp.source.url}>
603
- <SourceTrigger label={citationLabel(sp.source)} />
604
- <SourceContent
605
- title={citationTitle(sp.source)}
606
- description={sp.source.snippet ?? ''}
607
- />
608
- </Source>
609
- )}
610
- </For>
611
- </SourceList>
612
- )}
613
- </Match>
614
- <Match when={groupAs(group(), 'single')}>
615
- {(g) => {
616
- // An ACCESSOR, never a captured value: the row outlives the
617
- // delta that rebuilt this part, so every read below has to go
618
- // through here for the new content to land. `partAs` does the
619
- // type test and the narrowing cast in one read (see its note).
620
- const part = () => g().part;
621
- const reasoning = () => partAs(part(), 'reasoning');
622
- // A reasoning part with NO text is a round-trip carrier, not
623
- // something to show. Anthropic's redacted_thinking blocks carry
624
- // an opaque blob with no readable text, and the block assembled
625
- // at content_block_stop carries the verbatim payload the encoder
626
- // must echo back. Both are empty-text parts that MUST stay in
627
- // `parts` (the encoder needs them, in order) and must not render
628
- // a blank disclosure.
629
- const carrierOnly = () => { const r = reasoning(); return r !== false && r.text === ''; };
630
- const shownReasoning = () => { const r = reasoning(); return r !== false && r.text !== '' && r; };
631
- return (
632
- <Switch fallback={null}>
633
- <Match when={partAs(part(), 'text')}>
634
- {(p) => (
635
- <MessageContent
636
- part="bubble content"
637
- markdown={props.markdown}
638
- class={props.isUser
639
- // Content token, not the brand token: `--color-primary`
640
- // is the documented consumer brand override
641
- // (theme.css `--kai-color-primary`), so toking message
642
- // TEXT to it means every consumer that brands primary
643
- // gets brand-colored message text. `text-foreground` is
644
- // already `MessageContent`'s base color (matches the
645
- // assistant path's `bg-transparent p-0`, which carries
646
- // no color override and falls through to the same
647
- // base) — dropping `text-primary` here just lets that
648
- // base apply on the user bubble too.
649
- ? 'bg-muted max-w-[85%] rounded-2xl px-4 py-2'
650
- : 'bg-transparent p-0'}
651
- >
652
- {p().text}
653
- </MessageContent>
654
- )}
655
- </Match>
656
- <Match when={carrierOnly()}>{null}</Match>
657
- <Match when={shownReasoning()}>
658
- {(p) => {
659
- // Default 'full' is the pre-existing DISPLAY MODE byte
660
- // for byte; the OPEN behavior changed under Task 19f —
661
- // it no longer auto-opens while streaming by default
662
- // (owner ruling 2026-08-26). `reasoningDefaultOpen`
663
- // reproduces the old always-auto-opens behavior when set.
664
- const mode = () => props.reasoningMode ?? 'full';
665
- return (
666
- <Switch fallback={null}>
667
- <Match when={mode() === 'full'}>
668
- <Reasoning
669
- class="mb-2 w-full"
670
- isStreaming={props.isStreaming}
671
- defaultOpen={props.reasoningDefaultOpen}
672
- openOnStream={props.reasoningDefaultOpen}
673
- >
674
- <ReasoningTrigger>{p().label ?? 'Reasoning'}</ReasoningTrigger>
675
- <ReasoningContent markdown>{p().text}</ReasoningContent>
676
- </Reasoning>
677
- </Match>
678
- {/* 'compact': the same "Thinking…" shimmer the full
679
- disclosure's trigger shows while streaming — no
680
- <Reasoning>/<ReasoningContent>, so there is no
681
- expandable detail and nothing left once the part
682
- settles (isStreaming false → this Match doesn't
683
- fire, matching 'off'). 'off' never reaches here:
684
- its Match doesn't fire either. */}
685
- <Match when={mode() === 'compact' && props.isStreaming}>
686
- <Loader variant="text-shimmer" text={p().label ?? 'Reasoning'} class="mb-2" />
687
- </Match>
688
- </Switch>
689
- );
690
- }}
691
- </Match>
692
- <Match when={partAs(part(), 'tool')}>
693
- {(p) => <Tool toolPart={p().tool} class="mb-2 w-full" />}
694
- </Match>
695
- <Match when={partAs(part(), 'card')}>
696
- {(p) => <CardRenderer envelope={p().envelope} types={props.cardTypes} schemas={props.cardSchemas} hostElement={props.cardHostElement} />}
697
- </Match>
698
- {/* No `source` match here on purpose: source parts never
699
- reach a 'single' group — they are collapsed into a
700
- 'sources' run above and rendered as one citation row. */}
701
- </Switch>
702
- );
703
- }}
704
- </Match>
705
- </Switch>
706
- )}
707
- </Index>
708
- <Show when={(props.actions?.length ?? 0) > 0}>
709
- <MessageActionBar
710
- actions={props.actions!}
711
- reveal={props.actionsReveal === 'hover' ? 'hover' : 'always'}
712
- activeFeedback={props.activeFeedback}
713
- copied={props.copied}
714
- onAction={(id) => props.onAction?.(id)}
715
- />
716
- </Show>
717
- {/* after-body (inject): a citation row / cost line below the action bar. */}
718
- <Show when={props.afterBody}>{props.afterBody}</Show>
719
- </>
720
- );
721
- }
722
-
723
- // --- MessageAction ---
724
-
725
- export interface MessageActionProps {
726
- tooltip: string;
727
- children: JSX.Element;
728
- side?: "top" | "bottom" | "left" | "right";
729
- class?: string;
730
- }
731
-
732
- function MessageAction(props: MessageActionProps) {
733
- return <>{props.children}</>;
734
- }
735
-
736
- // --- MessageCopyButton ---
737
-
738
- export interface MessageCopyButtonProps {
739
- content: string;
740
- size?: number;
741
- class?: string;
742
- }
743
-
744
- function MessageCopyButton(props: MessageCopyButtonProps) {
745
- const [copied, setCopied] = createSignal(false);
746
- const iconSize = () => props.size ?? 14;
747
-
748
- return (
749
- <button
750
- class={props.class}
751
- aria-label={copied() ? 'Copied' : 'Copy message'}
752
- onClick={() => {
753
- navigator.clipboard.writeText(props.content);
754
- setCopied(true);
755
- setTimeout(() => setCopied(false), 2000);
756
- }}
757
- >
758
- <Show when={copied()} fallback={<Copy size={iconSize()} />}>
759
- <Check size={iconSize()} class="text-emerald-400" />
760
- </Show>
761
- </button>
762
- );
763
- }
764
-
765
- export { Message, MessageAvatar, MessageContent, MessageActions, MessageActionBar, MessageBody, MessageAction, MessageCopyButton };