@kitn.ai/ui 0.26.0 → 0.27.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 (474) hide show
  1. package/README.md +16 -5
  2. package/bin/mcp.js +16 -3
  3. package/bin/route.js +23 -0
  4. package/bin/route.test.js +58 -0
  5. package/dist/{elements/chunks/Icon--Y8vsFal.js → Icon-BnFKqqtY.js} +1 -1
  6. package/dist/action-icons-CBskfBMz.js +1 -0
  7. package/dist/arrow-down-Br0qtpsz.js +1 -0
  8. package/dist/arrow-left-Dj7xgE12.js +1 -0
  9. package/dist/artifact-CvXEm1lS.js +1 -0
  10. package/dist/assets/dev-5XzXYR21.js +91 -0
  11. package/dist/attachments-C43ZegEq.js +1 -0
  12. package/dist/{elements/chunks/audio-visualizer-D7lB6mvR.js → audio-visualizer-B-79y1Tj.js} +1 -1
  13. package/dist/badge-BpUbq8c0.js +1 -0
  14. package/dist/bash-InADTalH.js +1 -6
  15. package/dist/bell-sn17Ip9v.js +1 -0
  16. package/dist/{elements/chunks/button-flUbeufF.js → button-BH6rN0U-.js} +1 -1
  17. package/dist/card-renderer-Cb1gQmth.js +1 -0
  18. package/dist/card-routing-DifQgS7n.js +1 -0
  19. package/dist/check-DPeeMUYx.js +1 -0
  20. package/dist/checkbox-Dc9Yov_B.js +1 -0
  21. package/dist/checkbox-group-B1kDLLYk.js +1 -0
  22. package/dist/chevron-down-CHSWk7ZT.js +1 -0
  23. package/dist/chevron-right-B7l_fMgx.js +1 -0
  24. package/dist/choice-card-BT3c1S8g.js +1 -0
  25. package/dist/circle-Bb0yOpqM.js +1 -0
  26. package/dist/circle-check-BGZpCiz7.js +1 -0
  27. package/dist/circle-x-wobWkoSx.js +1 -0
  28. package/dist/{elements/chunks/cn-CU7UAWzk.js → cn-DN5AWfiS.js} +1 -1
  29. package/dist/{elements/chunks/code-block-BdLiTitd.js → code-block-CUQ5mtv0.js} +1 -1
  30. package/dist/{elements/chunks/collapsible-BzbXpPzr.js → collapsible-CPJbf6FM.js} +1 -1
  31. package/dist/components/attachment-types.d.ts +7 -0
  32. package/dist/components/audio-visualizer/fit-scale.d.ts +1 -1
  33. package/dist/components/card-renderer.d.ts +13 -0
  34. package/dist/components/card.d.ts +4 -0
  35. package/dist/components/chat-thread.d.ts +46 -1
  36. package/dist/components/conversation-item.d.ts +19 -7
  37. package/dist/components/conversation-list.d.ts +17 -5
  38. package/dist/components/form-widgets.d.ts +67 -2
  39. package/dist/components/form.d.ts +48 -1
  40. package/dist/components/message.d.ts +25 -3
  41. package/dist/components/reasoning.d.ts +6 -0
  42. package/dist/components/scroll-button.d.ts +11 -0
  43. package/dist/components/thread.d.ts +5 -0
  44. package/dist/components/tool-types.d.ts +9 -0
  45. package/dist/composer-CjngLzal.js +106 -0
  46. package/dist/confirm-card-DCx_A4bU.js +1 -0
  47. package/dist/construct-cli.es.js +1169 -0
  48. package/dist/{elements/chunks/context-VLIL3sJ-.js → context-BY8V-Nlp.js} +1 -1
  49. package/dist/controllable-D43BKmtX.js +1 -0
  50. package/dist/conversation-list-D4lLU_yS.js +1 -0
  51. package/dist/copy-B6DO4PqB.js +1 -0
  52. package/dist/core-AYMC6_lb.js +12 -5874
  53. package/dist/{create-tween-CQED4T0g.js → create-tween-BPzaefTp.js} +1 -1
  54. package/dist/{create-tween-BFT6c-Y8.js → create-tween-CnMHviKB.js} +1 -1
  55. package/dist/{create-tween-CJNlzoaO.js → create-tween-D1aiGZZh.js} +1 -1
  56. package/dist/{elements/chunks/create-tween-c4Z8TDYz.js → create-tween-DUSQUKpr.js} +2 -2
  57. package/dist/css-M7EaDHN_.js +1 -6
  58. package/dist/custom-elements.json +1400 -218
  59. package/dist/default-input-CucQEOqH.js +1 -0
  60. package/dist/define-CGGX-7Vg.js +1 -0
  61. package/dist/define.d.ts +4 -0
  62. package/dist/define.js +510 -0
  63. package/dist/define.server.d.ts +5 -0
  64. package/dist/define.server.js +506 -0
  65. package/dist/{elements/chunks/disclosure-CcNbyLy0.js → disclosure-CbLtajUQ.js} +1 -1
  66. package/dist/{elements/chunks/dropdown-BgWTthUx.js → dropdown-BwhViJFd.js} +1 -1
  67. package/dist/elements/agent-card.js +1 -1
  68. package/dist/elements/artifact.js +1 -1
  69. package/dist/elements/attachments.js +1 -1
  70. package/dist/elements/audio-visualizer.js +1 -1
  71. package/dist/elements/autoloader.js +1 -1
  72. package/dist/elements/avatar.js +1 -1
  73. package/dist/elements/badge.js +1 -1
  74. package/dist/elements/button.js +1 -1
  75. package/dist/elements/card.js +1 -1
  76. package/dist/elements/cards.js +1 -1
  77. package/dist/elements/chain-of-thought.js +1 -1
  78. package/dist/elements/chat-scope-picker.js +1 -1
  79. package/dist/elements/chat-workspace.js +1 -1
  80. package/dist/elements/chat.js +1 -1
  81. package/dist/elements/checkbox-group.d.ts +1 -0
  82. package/dist/elements/checkbox-group.js +1 -0
  83. package/dist/elements/checkbox.d.ts +1 -0
  84. package/dist/elements/checkbox.js +1 -0
  85. package/dist/elements/checkpoint.js +1 -1
  86. package/dist/elements/choice.js +1 -1
  87. package/dist/elements/coachmark.js +1 -1
  88. package/dist/elements/code-block.js +1 -1
  89. package/dist/elements/command.js +1 -1
  90. package/dist/elements/compare.js +1 -1
  91. package/dist/elements/composer.js +1 -1
  92. package/dist/elements/confirm-card.js +1 -1
  93. package/dist/elements/context-meter.js +1 -1
  94. package/dist/elements/conversation-item.js +1 -1
  95. package/dist/elements/conversation-list.js +1 -1
  96. package/dist/elements/define-entry.d.ts +12 -0
  97. package/dist/elements/dialog.js +1 -1
  98. package/dist/elements/dock.js +101 -7
  99. package/dist/elements/dropdown.js +1 -1
  100. package/dist/elements/editable-label.js +1 -1
  101. package/dist/elements/element-data-types.d.ts +37 -0
  102. package/dist/elements/embed.js +1 -1
  103. package/dist/elements/empty.js +1 -1
  104. package/dist/elements/feedback-bar.js +1 -1
  105. package/dist/elements/file-tree.js +1 -1
  106. package/dist/elements/file-upload.js +1 -1
  107. package/dist/elements/form.js +1 -1
  108. package/dist/elements/hover-card.js +1 -1
  109. package/dist/elements/icon.js +1 -1
  110. package/dist/elements/image.js +1 -1
  111. package/dist/elements/input.js +1 -1
  112. package/dist/elements/kbd.js +1 -1
  113. package/dist/elements/link-preview.js +1 -1
  114. package/dist/elements/loader.js +1 -1
  115. package/dist/elements/markdown.js +1 -1
  116. package/dist/elements/menu.js +1 -1
  117. package/dist/elements/message-skills.js +1 -1
  118. package/dist/elements/message.js +1 -1
  119. package/dist/elements/model-switcher.js +1 -1
  120. package/dist/elements/nav.js +1 -1
  121. package/dist/elements/notice.js +1 -1
  122. package/dist/elements/pane-grid.d.ts +1 -0
  123. package/dist/elements/pane-grid.js +1 -0
  124. package/dist/elements/pane-group.js +1 -1
  125. package/dist/elements/pane.js +1 -1
  126. package/dist/elements/popover.js +1 -1
  127. package/dist/elements/progress-bar.js +1 -1
  128. package/dist/elements/prompt-dock.js +1 -1
  129. package/dist/elements/prompt-input.js +1 -1
  130. package/dist/elements/prompt-suggestions.js +1 -1
  131. package/dist/elements/radio-group.d.ts +1 -0
  132. package/dist/elements/radio-group.js +1 -0
  133. package/dist/elements/reasoning.js +1 -1
  134. package/dist/elements/remote.js +1 -1
  135. package/dist/elements/resizable.js +1 -1
  136. package/dist/elements/response-stream.js +2 -2
  137. package/dist/elements/screen.js +1 -1
  138. package/dist/elements/scroll-area.js +1 -1
  139. package/dist/elements/scroll-button.js +1 -1
  140. package/dist/elements/search.js +1 -1
  141. package/dist/elements/segmented.js +1 -1
  142. package/dist/elements/select.d.ts +1 -0
  143. package/dist/elements/select.js +1 -0
  144. package/dist/elements/separator.js +1 -1
  145. package/dist/elements/setting-item.js +1 -1
  146. package/dist/elements/settings-group.js +1 -1
  147. package/dist/elements/skeleton.js +1 -1
  148. package/dist/elements/slider.d.ts +1 -0
  149. package/dist/elements/slider.js +1 -0
  150. package/dist/elements/slots.d.ts +1 -1
  151. package/dist/elements/source.js +1 -1
  152. package/dist/elements/status.js +1 -1
  153. package/dist/elements/switch.js +1 -1
  154. package/dist/elements/tabs.js +1 -1
  155. package/dist/elements/tasks.js +1 -1
  156. package/dist/elements/text-shimmer.js +1 -1
  157. package/dist/elements/thinking-bar.js +1 -1
  158. package/dist/elements/thread.js +1 -1
  159. package/dist/elements/toast.js +1 -1
  160. package/dist/elements/tool.js +1 -1
  161. package/dist/elements/tooltip.js +1 -1
  162. package/dist/elements/voice-input.js +1 -1
  163. package/dist/elements/voice-output.js +1 -1
  164. package/dist/elements.d.ts +362 -24
  165. package/dist/{elements/chunks/ellipsis-7gU33mL2.js → ellipsis-DFr4Vqr3.js} +1 -1
  166. package/dist/embed-5s_vU4J0.js +1 -0
  167. package/dist/engine-javascript-vq0WuIJl.js +14 -2516
  168. package/dist/{elements/chunks/external-link-CSOEsNlx.js → external-link-u9d85ORQ.js} +1 -1
  169. package/dist/file-text-CX7_x42o.js +1 -0
  170. package/dist/{elements/chunks/file-tree-zvB2i7P9.js → file-tree-D3kBjXI5.js} +1 -1
  171. package/dist/folder-V-YdIL8f.js +1 -0
  172. package/dist/form-BRNUMCN2.js +1 -0
  173. package/dist/github-dark-dimmed-DUshB20C.js +1 -4
  174. package/dist/github-light-JYsPkUQd.js +1 -4
  175. package/dist/hover-card-DaeiYrTA.js +1 -0
  176. package/dist/html-CPZ3oZQ7.js +1 -10
  177. package/dist/icon-BpixdZNq.js +1 -0
  178. package/dist/{elements/chunks/index-BCRhi84a.js → index-xu_pdcPi.js} +1 -1
  179. package/dist/index.d.ts +1 -1
  180. package/dist/index.js +7330 -5852
  181. package/dist/index.server.js +5823 -4759
  182. package/dist/info-8mFsIjS3.js +1 -0
  183. package/dist/input-d1Yuu-hz.js +1 -0
  184. package/dist/javascript-C25yR2R2.js +1 -6
  185. package/dist/json-DxJze_jm.js +1 -6
  186. package/dist/kai.es.js +1 -1
  187. package/dist/kbd-961zMPFB.js +1 -0
  188. package/dist/link-DlZZBGaR.js +1 -0
  189. package/dist/{elements/chunks/link-preview-OQ9IEq0f.js → link-preview-DIIbV2Sd.js} +1 -1
  190. package/dist/loader-YQszHFaW.js +1 -0
  191. package/dist/{elements/chunks/markdown-DgBFaGAz.js → markdown-CVk1MPsj.js} +1 -1
  192. package/dist/mcp.es.js +1285 -79
  193. package/dist/message-CwKVEdZg.js +1 -0
  194. package/dist/message-DS8lzHc1.js +1 -0
  195. package/dist/message-circle-Xf8Q-vZp.js +1 -0
  196. package/dist/message-square-Cxnwgkns.js +1 -0
  197. package/dist/{elements/chunks/minimize-2-DPIUKTrT.js → minimize-2-UEZmP2QT.js} +1 -1
  198. package/dist/{elements/chunks/model-switcher-DsT8tFB0.js → model-switcher-Kk1jEQ5t.js} +1 -1
  199. package/dist/{elements/chunks/overlay-DuiwdXjm.js → overlay-C1od6LOz.js} +1 -1
  200. package/dist/panel-right-ryET0yyn.js +1 -0
  201. package/dist/paperclip-BDNoZFJP.js +1 -0
  202. package/dist/play-OFIvYXUQ.js +1 -0
  203. package/dist/primitives/card-data-types.d.ts +49 -0
  204. package/dist/primitives/card-routing.d.ts +1 -33
  205. package/dist/primitives/card-validate.d.ts +2 -2
  206. package/dist/primitives/chat-config.d.ts +29 -2
  207. package/dist/primitives/field-mask.d.ts +96 -0
  208. package/dist/primitives/field-semantics.d.ts +36 -0
  209. package/dist/primitives/input-mask.d.ts +46 -0
  210. package/dist/primitives/url-scheme-policy.d.ts +34 -0
  211. package/dist/primitives/use-resize-observer.d.ts +2 -2
  212. package/dist/progress-bar-BvYX0aoy.js +1 -0
  213. package/dist/prompt-suggestion-BRFu2lcu.js +1 -0
  214. package/dist/radio-DcL23cNJ.js +1 -0
  215. package/dist/react/index.d.ts +193 -19
  216. package/dist/react.js +216 -180
  217. package/dist/reasoning-Cackq4Rh.js +1 -0
  218. package/dist/register-impl-C7rENvPK.js +424 -0
  219. package/dist/{elements/chunks/resizable-D181b4fM.js → resizable-Cp9HUYih.js} +1 -1
  220. package/dist/rotate-ccw-0DLRDHH5.js +1 -0
  221. package/dist/rotate-cw-DOB9IGcU.js +1 -0
  222. package/dist/schemas/form.schema.json +21 -1
  223. package/dist/schemas/tool-defs.d.ts +11 -1
  224. package/dist/schemas.js +81 -81
  225. package/dist/scroll-area-emVmWP4K.js +1 -0
  226. package/dist/scroll-button-CeP_gv1x.js +1 -0
  227. package/dist/select-CWmu00tS.js +1 -0
  228. package/dist/{elements/chunks/separator-CeJHQqLW.js → separator-CE6vly6z.js} +1 -1
  229. package/dist/{elements/chunks/settings-CqaHgJF9.js → settings-CE-78SvZ.js} +1 -1
  230. package/dist/{elements/chunks/settings-group-CjqjLCOn.js → settings-group-ZFWNxFQR.js} +1 -1
  231. package/dist/{elements/chunks/skeleton-D8akBnKS.js → skeleton-BebdP4mf.js} +1 -1
  232. package/dist/slider-BAKRYUlz.js +1 -0
  233. package/dist/{solid-BtdqNZI7.js → solid-BE5ui6sy.js} +8727 -7212
  234. package/dist/{solid-CnavwBye.js → solid-DFhsce3O.js} +7015 -5886
  235. package/dist/solid.d.ts +10 -0
  236. package/dist/solid.js +240 -234
  237. package/dist/solid.server.js +240 -234
  238. package/dist/source-B0FlguSx.js +1 -0
  239. package/dist/star-CBMZvLuN.js +1 -0
  240. package/dist/state/index.d.ts +1 -1
  241. package/dist/state/mock.d.ts +32 -2
  242. package/dist/state.js +133 -108
  243. package/dist/{elements/chunks/store-Cjq0qwYN.js → store-7eoadydQ.js} +1 -1
  244. package/dist/svelte--5p79yCD.js +1 -15
  245. package/dist/switch-CViARZCy.js +1 -0
  246. package/dist/tasks-card-MjCcOhR_.js +1 -0
  247. package/dist/text-shimmer-DKlwRF2G.js +1 -0
  248. package/dist/textarea-3ay2Me2-.js +1 -0
  249. package/dist/theme.tokens.css +82 -13
  250. package/dist/{elements/chunks/thumbs-up-DX2Ijk3H.js → thumbs-up-DQcu2HMO.js} +1 -1
  251. package/dist/toast-store-C6yKOhbk.js +1 -0
  252. package/dist/{elements/chunks/tool-DKQ2D1DP.js → tool-BCYNlfKy.js} +1 -1
  253. package/dist/{elements/chunks/tooltip-B0G99y8w.js → tooltip-05zI4hjs.js} +1 -1
  254. package/dist/trash-2-BR1RxGky.js +1 -0
  255. package/dist/{elements/chunks/triangle-alert-F9cyUEyy.js → triangle-alert-DHohDOCy.js} +1 -1
  256. package/dist/tsx-B8rCNbgL.js +1 -6
  257. package/dist/typescript-RycA9KXf.js +1 -6
  258. package/dist/ui/checkbox-group.d.ts +83 -0
  259. package/dist/ui/checkbox.d.ts +40 -0
  260. package/dist/ui/dock.d.ts +22 -0
  261. package/dist/ui/icon.d.ts +3 -0
  262. package/dist/ui/input.d.ts +48 -2
  263. package/dist/ui/radio.d.ts +85 -0
  264. package/dist/ui/select.d.ts +71 -0
  265. package/dist/ui/slider.d.ts +65 -0
  266. package/dist/ui/switch.d.ts +9 -2
  267. package/dist/upload-BbGW6A_u.js +1 -0
  268. package/dist/url-scheme-policy-DHpoTJwB.js +1 -0
  269. package/dist/use-card-resolution-CJW4grFa.js +1 -0
  270. package/dist/{variant-aurora-B8II3-I1.js → variant-aurora-BUOVgPOB.js} +2 -2
  271. package/dist/{variant-aurora-CMNWOSJR.js → variant-aurora-CUsUJvFI.js} +2 -2
  272. package/dist/{variant-aurora-CcuDMWwQ.js → variant-aurora-CW2i4bfr.js} +1 -1
  273. package/dist/{elements/chunks/variant-aurora-qt6Zct8M.js → variant-aurora-xiMPty8f.js} +1 -1
  274. package/dist/{variant-custom-L16JLLZy.js → variant-custom-BQtOnmeO.js} +1 -1
  275. package/dist/{variant-custom-C714mqKl.js → variant-custom-CAm9L-E5.js} +2 -2
  276. package/dist/{variant-custom-BdvYC7af.js → variant-custom-CAnzzppW.js} +2 -2
  277. package/dist/{elements/chunks/variant-custom-tJp22_BQ.js → variant-custom-D91HjAKz.js} +1 -1
  278. package/dist/{variant-wave-ecwykeyL.js → variant-wave-Ca1Ls4_y.js} +2 -2
  279. package/dist/{variant-wave-D7ruiA1W.js → variant-wave-CxX39DKd.js} +2 -2
  280. package/dist/{elements/chunks/variant-wave-CaQ5ti39.js → variant-wave-DYyzIIZv.js} +1 -1
  281. package/dist/{variant-wave-2S4La2Ka.js → variant-wave-uY5crU_K.js} +1 -1
  282. package/dist/vue-BmIZj4XD.js +1 -33
  283. package/dist/x-C5m1JFgi.js +1 -0
  284. package/frameworks/react/index.tsx +198 -20
  285. package/llms-full.txt +1178 -21
  286. package/llms.txt +6 -3
  287. package/package.json +17 -4
  288. package/src/agent-tooling/catalog/invariants.ts +1 -1
  289. package/src/agent-tooling/catalog/surfaces.ts +72 -0
  290. package/src/agent-tooling/construct/cli-entry.ts +8 -0
  291. package/src/agent-tooling/construct/cli.ts +131 -0
  292. package/src/agent-tooling/construct/codegen.ts +1353 -0
  293. package/src/agent-tooling/construct/construct.v1.schema.json +250 -0
  294. package/src/agent-tooling/construct/dev.ts +148 -0
  295. package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +7 -0
  296. package/src/agent-tooling/construct/fixtures/ops-console.construct.json +44 -0
  297. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +23 -0
  298. package/src/agent-tooling/construct/schema.ts +371 -0
  299. package/src/agent-tooling/mcp/server.ts +2 -1
  300. package/src/agent-tooling/mcp/tools/construct.ts +130 -0
  301. package/src/agent-tooling/mcp/tools/debug.ts +126 -4
  302. package/src/agent-tooling/mcp/tools/reference.ts +104 -3
  303. package/src/agent-tooling/recipes/composed-thread.ts +714 -0
  304. package/src/agent-tooling/recipes/index.ts +22 -0
  305. package/src/agent-tooling/recipes/types.ts +32 -0
  306. package/src/agent-tooling/registry.ts +5 -0
  307. package/src/components/attachment-types.ts +7 -0
  308. package/src/components/audio-visualizer/fit-scale.ts +1 -1
  309. package/src/components/card-renderer.tsx +39 -8
  310. package/src/components/card.tsx +10 -2
  311. package/src/components/chat-scope-picker.tsx +2 -2
  312. package/src/components/chat-thread.tsx +72 -9
  313. package/src/components/choice-card.tsx +102 -37
  314. package/src/components/coachmark.tsx +1 -1
  315. package/src/components/code-block.tsx +2 -2
  316. package/src/components/composer.tsx +89 -15
  317. package/src/components/confirm-card.tsx +20 -4
  318. package/src/components/conversation-item.tsx +33 -9
  319. package/src/components/conversation-list.tsx +25 -10
  320. package/src/components/empty.tsx +14 -3
  321. package/src/components/file-tree.tsx +5 -1
  322. package/src/components/form-widgets.tsx +257 -195
  323. package/src/components/form.tsx +297 -9
  324. package/src/components/loader.tsx +12 -5
  325. package/src/components/message-skills.tsx +1 -1
  326. package/src/components/message.tsx +71 -11
  327. package/src/components/prompt-input.tsx +7 -1
  328. package/src/components/prompt-suggestion.tsx +4 -1
  329. package/src/components/reasoning.tsx +30 -3
  330. package/src/components/response-compare.tsx +2 -2
  331. package/src/components/scroll-button.tsx +56 -4
  332. package/src/components/source.tsx +6 -1
  333. package/src/components/tasks-card.tsx +58 -16
  334. package/src/components/thread.tsx +10 -1
  335. package/src/components/toast.tsx +1 -1
  336. package/src/components/tool-types.ts +9 -0
  337. package/src/elements/attachments.tsx +3 -1
  338. package/src/elements/chat-workspace.tsx +1 -1
  339. package/src/elements/chat.tsx +22 -4
  340. package/src/elements/checkbox-group.tsx +164 -0
  341. package/src/elements/checkbox.tsx +134 -0
  342. package/src/elements/compiled.css +1 -1
  343. package/src/elements/composer.tsx +12 -1
  344. package/src/elements/conversation-item.tsx +62 -22
  345. package/src/elements/conversation-list.tsx +2 -2
  346. package/src/elements/define-entry.ts +12 -0
  347. package/src/elements/dock.tsx +11 -0
  348. package/src/elements/element-data-types.ts +40 -0
  349. package/src/elements/element-manifest.json +24 -0
  350. package/src/elements/element-meta.json +736 -46
  351. package/src/elements/element-nonscalar.json +15 -0
  352. package/src/elements/element-types.d.ts +362 -24
  353. package/src/elements/feedback-bar.tsx +5 -0
  354. package/src/elements/icon-names.json +29 -0
  355. package/src/elements/input.tsx +312 -23
  356. package/src/elements/message.tsx +2 -0
  357. package/src/elements/pane-grid.tsx +111 -0
  358. package/src/elements/prompt-input.tsx +8 -2
  359. package/src/elements/radio-group.tsx +129 -0
  360. package/src/elements/register-impl.ts +6 -0
  361. package/src/elements/scroll-button.tsx +54 -6
  362. package/src/elements/select.tsx +165 -0
  363. package/src/elements/slider.tsx +171 -0
  364. package/src/elements/slots.ts +1 -1
  365. package/src/elements/styles.css +89 -3
  366. package/src/elements/thread.tsx +2 -0
  367. package/src/elements/toast.tsx +14 -1
  368. package/src/index.ts +2 -1
  369. package/src/primitives/card-data-types.ts +49 -0
  370. package/src/primitives/card-host.tsx +4 -2
  371. package/src/primitives/card-routing.ts +7 -56
  372. package/src/primitives/card-schemas/form.schema.json +21 -1
  373. package/src/primitives/card-validate.ts +10 -2
  374. package/src/primitives/chat-config.tsx +33 -6
  375. package/src/primitives/field-mask.ts +256 -0
  376. package/src/primitives/field-semantics.ts +115 -0
  377. package/src/primitives/input-mask.ts +853 -0
  378. package/src/primitives/toast-store.ts +66 -4
  379. package/src/primitives/url-scheme-policy.ts +70 -0
  380. package/src/primitives/use-resize-observer.ts +2 -2
  381. package/src/schemas/tool-defs.ts +12 -2
  382. package/src/solid.ts +10 -0
  383. package/src/state/index.ts +1 -1
  384. package/src/state/mock.ts +92 -6
  385. package/src/ui/agent-card.tsx +2 -2
  386. package/src/ui/avatar.tsx +1 -1
  387. package/src/ui/checkbox-group.tsx +153 -0
  388. package/src/ui/checkbox.tsx +63 -0
  389. package/src/ui/dock.tsx +145 -6
  390. package/src/ui/icon.tsx +53 -0
  391. package/src/ui/input.tsx +249 -9
  392. package/src/ui/kbd.tsx +1 -1
  393. package/src/ui/nav.tsx +1 -1
  394. package/src/ui/pane-group.tsx +2 -2
  395. package/src/ui/radio.tsx +150 -0
  396. package/src/ui/select.tsx +168 -0
  397. package/src/ui/slider.tsx +178 -0
  398. package/src/ui/switch.tsx +49 -18
  399. package/src/utils/cn.ts +11 -5
  400. package/theme.css +84 -13
  401. package/dist/elements/chunks/action-icons-D9u3OzYW.js +0 -1
  402. package/dist/elements/chunks/arrow-left-CVh1TeN7.js +0 -1
  403. package/dist/elements/chunks/artifact-BkYcfIlZ.js +0 -1
  404. package/dist/elements/chunks/attachments-DwfNlubq.js +0 -1
  405. package/dist/elements/chunks/badge-Q0-Cmwzz.js +0 -1
  406. package/dist/elements/chunks/bash-InADTalH.js +0 -1
  407. package/dist/elements/chunks/card-renderer-3Dyl-FpN.js +0 -1
  408. package/dist/elements/chunks/card-routing-BK09BdmL.js +0 -1
  409. package/dist/elements/chunks/check-B5kBPKeo.js +0 -1
  410. package/dist/elements/chunks/chevron-down-DZ1GS39h.js +0 -1
  411. package/dist/elements/chunks/chevron-right-CvP7OUd2.js +0 -1
  412. package/dist/elements/chunks/choice-card-D4QUIOWZ.js +0 -1
  413. package/dist/elements/chunks/circle-CDf9g6MQ.js +0 -1
  414. package/dist/elements/chunks/circle-check-CA47Nqbz.js +0 -1
  415. package/dist/elements/chunks/circle-x-CJ_HVbC8.js +0 -1
  416. package/dist/elements/chunks/composer-Byve-n8K.js +0 -69
  417. package/dist/elements/chunks/confirm-card-B0flE3MN.js +0 -1
  418. package/dist/elements/chunks/controllable-DTwTIlwp.js +0 -1
  419. package/dist/elements/chunks/conversation-item-BDztezOG.js +0 -1
  420. package/dist/elements/chunks/copy-Nf-kqxXH.js +0 -1
  421. package/dist/elements/chunks/core-AYMC6_lb.js +0 -12
  422. package/dist/elements/chunks/css-M7EaDHN_.js +0 -1
  423. package/dist/elements/chunks/default-input-C2iLFq0b.js +0 -1
  424. package/dist/elements/chunks/define-wjHR1MkU.js +0 -1
  425. package/dist/elements/chunks/download-C4V7tBdb.js +0 -1
  426. package/dist/elements/chunks/embed-D3KewsIJ.js +0 -1
  427. package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +0 -141
  428. package/dist/elements/chunks/file-text-D1G8khle.js +0 -1
  429. package/dist/elements/chunks/folder-WW2LGLid.js +0 -1
  430. package/dist/elements/chunks/form-CQirdC4W.js +0 -1
  431. package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +0 -1
  432. package/dist/elements/chunks/github-light-JYsPkUQd.js +0 -1
  433. package/dist/elements/chunks/hover-card-CJJkfHTK.js +0 -1
  434. package/dist/elements/chunks/html-CPZ3oZQ7.js +0 -1
  435. package/dist/elements/chunks/icon-Cfgmf4fa.js +0 -1
  436. package/dist/elements/chunks/info-DX3YMOt6.js +0 -1
  437. package/dist/elements/chunks/input-BtW9U6Sq.js +0 -1
  438. package/dist/elements/chunks/javascript-C25yR2R2.js +0 -1
  439. package/dist/elements/chunks/json-DxJze_jm.js +0 -1
  440. package/dist/elements/chunks/kbd-LGXwuT_V.js +0 -1
  441. package/dist/elements/chunks/link-2My69BqT.js +0 -1
  442. package/dist/elements/chunks/loader-iOxc_Tu-.js +0 -1
  443. package/dist/elements/chunks/message-VMZohrXx.js +0 -1
  444. package/dist/elements/chunks/message-circle-CpXMM-_n.js +0 -1
  445. package/dist/elements/chunks/message-square-DxcWtETQ.js +0 -1
  446. package/dist/elements/chunks/message-tZmV2A3p.js +0 -1
  447. package/dist/elements/chunks/paperclip-CRZVp4z_.js +0 -1
  448. package/dist/elements/chunks/progress-bar-DNy66e_E.js +0 -1
  449. package/dist/elements/chunks/prompt-suggestion-Bn64Nl7L.js +0 -1
  450. package/dist/elements/chunks/reasoning-Emn9N4-T.js +0 -1
  451. package/dist/elements/chunks/rotate-cw-CPWe37D9.js +0 -1
  452. package/dist/elements/chunks/scroll-area-ClZkZxIk.js +0 -1
  453. package/dist/elements/chunks/scroll-button-DPE-t3x_.js +0 -1
  454. package/dist/elements/chunks/share-CyfnNEqp.js +0 -1
  455. package/dist/elements/chunks/source-UWCvmVak.js +0 -1
  456. package/dist/elements/chunks/star-DoHFAikQ.js +0 -1
  457. package/dist/elements/chunks/svelte--5p79yCD.js +0 -1
  458. package/dist/elements/chunks/tasks-card-CmZ5xh6v.js +0 -1
  459. package/dist/elements/chunks/text-shimmer-DYn09zrz.js +0 -1
  460. package/dist/elements/chunks/textarea-skiGHURM.js +0 -1
  461. package/dist/elements/chunks/toast-store-CFnQpThX.js +0 -1
  462. package/dist/elements/chunks/tsx-B8rCNbgL.js +0 -1
  463. package/dist/elements/chunks/typescript-RycA9KXf.js +0 -1
  464. package/dist/elements/chunks/use-card-resolution-DoA2f_EU.js +0 -1
  465. package/dist/elements/chunks/vue-BmIZj4XD.js +0 -1
  466. package/dist/elements/chunks/x-B6UnOiLw.js +0 -1
  467. package/dist/llms/llms-full.txt +0 -2949
  468. package/dist/llms/llms.txt +0 -156
  469. package/dist/register-impl-DpE7icIb.js +0 -293
  470. package/dist/ui/stat.d.ts +0 -16
  471. package/src/ui/stat.tsx +0 -41
  472. /package/dist/{elements/chunks/card-tags-D8lZ-C_U.js → card-tags-D8lZ-C_U.js} +0 -0
  473. /package/dist/{elements/chunks/link-preview-DNILK391.js → link-preview-DNILK391.js} +0 -0
  474. /package/dist/{elements/chunks/slots-DaNjX0rc.js → slots-DaNjX0rc.js} +0 -0
@@ -0,0 +1,22 @@
1
+ import type { CodeRecipe } from './types';
2
+ import { composedThread } from './composed-thread';
3
+
4
+ export type { CodeRecipe, CodeRecipeFile } from './types';
5
+
6
+ /**
7
+ * The code-recipe registry.
8
+ *
9
+ * Registered here → served by `component_reference({ name: "<id>" })` AND
10
+ * compiled by `verify:scaffold` (which loads this list through the registry
11
+ * bundle, so adding an entry moves that gate's printed cell count by itself —
12
+ * the same derive-don't-list contract as the integration and surface axes).
13
+ */
14
+ export const codeRecipes: CodeRecipe[] = [composedThread];
15
+
16
+ export function listCodeRecipes(): CodeRecipe[] {
17
+ return codeRecipes;
18
+ }
19
+
20
+ export function getCodeRecipe(id: string): CodeRecipe | undefined {
21
+ return codeRecipes.find((r) => r.id === id);
22
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * A CODE recipe: a complete, compiling composition the MCP serves as files.
3
+ *
4
+ * Distinct from a `TSurfaceRecipe` (../catalog/catalog-types.ts) on purpose:
5
+ * the catalog record is DATA — ingredients, wiring edges, invariants, each
6
+ * resolved and executed by its own guards — while a code recipe is the full
7
+ * host module a builder pastes. The two meet on `id`: a code recipe whose id
8
+ * also names a surface recipe is that record's body.
9
+ *
10
+ * `verify:scaffold` compiles every `lang: 'ts'` file of every registered code
11
+ * recipe with a stock consumer tsconfig, resolving `@kitn.ai/ui` through the
12
+ * shipped exports map — the same gate the scaffolder's emitted string literals
13
+ * go through, because this code is string literals with the same failure mode.
14
+ */
15
+ export interface CodeRecipeFile {
16
+ /** Path inside the consumer's app, e.g. `src/main.ts`. */
17
+ path: string;
18
+ lang: 'ts' | 'html' | 'css';
19
+ code: string;
20
+ }
21
+
22
+ export interface CodeRecipe {
23
+ /** Kebab-case id, e.g. `composed-thread`. Also the component_reference topic name. */
24
+ id: string;
25
+ title: string;
26
+ intent: string;
27
+ /** The kai-* tags the composition places. */
28
+ ingredients: string[];
29
+ /** The teaching notes served above the files — the WHY a prop table cannot carry. */
30
+ notes: string[];
31
+ files: CodeRecipeFile[];
32
+ }
@@ -23,6 +23,11 @@ export {
23
23
  type SurfaceProbe,
24
24
  } from './archetypes';
25
25
 
26
+ // The code-recipe axis, same contract as the two above: the gate loads it from
27
+ // this registry bundle, so registering a recipe adds its compile cells without
28
+ // touching the verify script.
29
+ export { listCodeRecipes, getCodeRecipe, type CodeRecipe, type CodeRecipeFile } from './recipes';
30
+
26
31
  // Order is the order a scaffolding agent reads them in. `openai` and `anthropic`
27
32
  // lead because they are the two keys a developer is most likely to already hold.
28
33
  export const integrations: Integration[] = [
@@ -5,6 +5,13 @@ export interface AttachmentData {
5
5
  type: 'file' | 'source-document';
6
6
  filename?: string;
7
7
  mediaType?: string;
8
+ /** A `data:` URI or an https URL — this is the field the wire encodes, so it
9
+ * is what reaches the model. NEVER `URL.createObjectURL`: an object URL
10
+ * resolves only inside the tab that minted it, so a `blob:` URL renders a
11
+ * flawless preview and is meaningless to any provider —
12
+ * `toOpenAIMessages`/`toAnthropicMessages` refuse it rather than send an
13
+ * address the model cannot fetch. Read picked files with
14
+ * `FileReader.readAsDataURL` instead (see `elements/default-input.tsx`). */
8
15
  url?: string;
9
16
  title?: string;
10
17
  }
@@ -1,7 +1,7 @@
1
1
  import { createSignal, onCleanup, type Accessor } from 'solid-js';
2
2
 
3
3
  /**
4
- * Fit-to-container scaling (owner finding, rung 2): the size tiers are fixed
4
+ * Fit-to-container scaling: the size tiers are fixed
5
5
  * px by design (`sizes.ts`), so a container narrower than a tier's natural
6
6
  * footprint used to CLIP the picture at its edges. The dispatcher now scales
7
7
  * the WHOLE visualization down proportionally to fit, and renders byte-equal
@@ -5,8 +5,9 @@
5
5
  // Invalid data → two-tier validation, mirroring the remote transport; see below.
6
6
  import { createEffect, createMemo, untrack, Show, type JSX } from 'solid-js';
7
7
  import { Dynamic } from 'solid-js/web';
8
- import type { CardEnvelope } from '../primitives/card-contract';
8
+ import type { CardContext, CardEnvelope, CardHost } from '../primitives/card-contract';
9
9
  import { useCardHost } from '../primitives/card-host';
10
+ import { emitCardEvent } from '../primitives/card-routing';
10
11
  import { BUILTIN_CARD_COMPONENTS, mergeCardComponents, type CardComponentMap } from '../primitives/card-registry';
11
12
  import type { JsonSchema } from '../primitives/card-validate';
12
13
  import { cardValidationMessage, validateCardData, type CardValidationReport } from '../primitives/card-validate-cards';
@@ -63,6 +64,35 @@ export interface CardRendererProps {
63
64
  * supplied through `schemas` — is never validated either way.
64
65
  */
65
66
  validateCards?: boolean;
67
+ /**
68
+ * The custom-element host node to emit off when no `CardProvider` is above this
69
+ * renderer: events leave as the bubbling, composed `kai-card` CustomEvent
70
+ * (`emitCardEvent`), so `listenForCardEvents(element)` — or a plain
71
+ * `addEventListener('kai-card', …)` on the element — receives them.
72
+ *
73
+ * This is what makes cards INSIDE `<kai-chat>`/`<kai-message>`/`<kai-thread>`
74
+ * interactive: those facades pass their own host element down here, and
75
+ * with neither this nor a `CardProvider` every emit — ready/action/submit/
76
+ * dismiss/reopen and the contract `error` — used to be silently discarded.
77
+ * An ambient `CardProvider` still wins when present.
78
+ */
79
+ hostElement?: HTMLElement;
80
+ }
81
+
82
+ /**
83
+ * The effective CardHost: an ambient `CardProvider` when present, otherwise a
84
+ * bubbling-`kai-card` host over `hostElement`, otherwise none (a truly bare card).
85
+ *
86
+ * The fallback's `context()` mirrors the remote transport's `defaultContext()`
87
+ * (`remote/provider-runtime.ts`): the contract return is non-optional, but no
88
+ * native card reads it today — the element facades own theme/locale through
89
+ * `ChatConfig`, not through card context.
90
+ */
91
+ function resolveHost(ctxHost: CardHost | undefined, hostElement: HTMLElement | undefined): CardHost | undefined {
92
+ if (ctxHost) return ctxHost;
93
+ if (!hostElement) return undefined;
94
+ const context = (): CardContext => ({ theme: { mode: 'light' }, locale: 'en' });
95
+ return { context, emit: (event) => emitCardEvent(hostElement, event) };
66
96
  }
67
97
 
68
98
  /**
@@ -84,7 +114,8 @@ export function hasConsumerSchema(schemas: CardSchemaMap | undefined, type: stri
84
114
  }
85
115
 
86
116
  export function CardRenderer(props: CardRendererProps): JSX.Element {
87
- const host = useCardHost();
117
+ const ctxHost = useCardHost();
118
+ const host = createMemo(() => resolveHost(ctxHost, props.hostElement));
88
119
  const map = createMemo(() => mergeCardComponents(props.types));
89
120
  const entry = createMemo(() => map()[props.envelope.type]);
90
121
 
@@ -139,18 +170,18 @@ export function CardRenderer(props: CardRendererProps): JSX.Element {
139
170
  const message = cardValidationMessage(r);
140
171
  if (message === lastEmitted) return;
141
172
  lastEmitted = message;
142
- host?.emit({ kind: 'error', cardId: props.envelope.id, message });
173
+ host()?.emit({ kind: 'error', cardId: props.envelope.id, message });
143
174
  });
144
175
 
145
176
  return (
146
- <Show when={entry()} fallback={<UnknownCard envelope={props.envelope} />}>
177
+ <Show when={entry()} fallback={<UnknownCard envelope={props.envelope} hostElement={props.hostElement} />}>
147
178
  {(comp) => (
148
179
  <Show
149
180
  when={report()?.tier === 'hard'}
150
181
  // SOFT and valid both take this branch: the card renders exactly as it
151
182
  // does today. The soft failure is reported through the effect above and
152
183
  // changes nothing on screen, which is the whole point of the tiering.
153
- fallback={<Dynamic component={comp()} envelope={props.envelope} host={host} />}
184
+ fallback={<Dynamic component={comp()} envelope={props.envelope} host={host()} />}
154
185
  >
155
186
  {/* HARD: there is nothing to draw, so name the field instead. */}
156
187
  <CardFallback type={props.envelope.type} cardId={props.envelope.id} reason={report()!.summary} />
@@ -161,10 +192,10 @@ export function CardRenderer(props: CardRendererProps): JSX.Element {
161
192
  }
162
193
 
163
194
  /** Renders the fallback and emits exactly one `error` (untracked, on first render). */
164
- function UnknownCard(props: { envelope: CardEnvelope }): JSX.Element {
165
- const host = useCardHost();
195
+ function UnknownCard(props: { envelope: CardEnvelope; hostElement?: HTMLElement }): JSX.Element {
196
+ const ctxHost = useCardHost();
166
197
  untrack(() =>
167
- host?.emit({
198
+ resolveHost(ctxHost, props.hostElement)?.emit({
168
199
  kind: 'error',
169
200
  cardId: props.envelope.id,
170
201
  message: `Unsupported card type: ${props.envelope.type}`,
@@ -20,6 +20,10 @@ export interface CardProps extends JSX.HTMLAttributes<HTMLDivElement> {
20
20
  /** Stable id for the heading (so composing cards can `aria-labelledby` it).
21
21
  * Auto-generated when omitted. */
22
22
  headingId?: string;
23
+ /** Stable id for the description (so composing cards can `aria-describedby` it
24
+ * — e.g. `kai-choice`'s radiogroup points at its prompt). Auto-generated when
25
+ * omitted, mirroring `headingId`. */
26
+ descriptionId?: string;
23
27
  /** Render a dismiss (×) button that hides the card and calls `onDismiss`.
24
28
  * Opt-in, OFF by default — the contract cards never set it, so they are
25
29
  * unaffected. */
@@ -67,6 +71,7 @@ export function Card(props: CardProps): JSX.Element {
67
71
  'errorMessage',
68
72
  'dense',
69
73
  'headingId',
74
+ 'descriptionId',
70
75
  'dismissible',
71
76
  'onDismiss',
72
77
  'href',
@@ -80,6 +85,7 @@ export function Card(props: CardProps): JSX.Element {
80
85
 
81
86
  const autoId = createUniqueId();
82
87
  const headingId = () => local.headingId ?? `kai-card-heading-${autoId}`;
88
+ const descriptionId = () => local.descriptionId ?? `kai-card-description-${autoId}`;
83
89
  const hasError = () => local.errorMessage !== undefined && local.errorMessage !== '';
84
90
  const hasHeader = () => Boolean(local.heading) || Boolean(local.description);
85
91
 
@@ -123,13 +129,15 @@ export function Card(props: CardProps): JSX.Element {
123
129
  <Show when={local.heading}>
124
130
  <h3
125
131
  id={headingId()}
126
- class="text-[1.0625rem] font-semibold leading-snug tracking-tight text-foreground"
132
+ class="text-title font-semibold tracking-tight text-foreground"
127
133
  >
128
134
  {local.heading}
129
135
  </h3>
130
136
  </Show>
131
137
  <Show when={local.description}>
132
- <p class="text-[0.8125rem] leading-relaxed text-muted-foreground">{local.description}</p>
138
+ <p id={descriptionId()} class="text-body text-muted-foreground">
139
+ {local.description}
140
+ </p>
133
141
  </Show>
134
142
  </div>
135
143
  </Show>
@@ -36,7 +36,7 @@ export function ChatScopePicker(props: ChatScopePickerProps) {
36
36
  <DropdownContent class="min-w-[180px]">
37
37
  <DropdownItem onSelect={() => local.onScopeChange(undefined)}>All Content</DropdownItem>
38
38
  <Show when={local.availableAuthors?.length}>
39
- <div class="px-2 py-1 text-[10px] uppercase tracking-wider text-muted-foreground">Authors</div>
39
+ <div class="px-2 py-1 text-micro uppercase tracking-wider text-muted-foreground">Authors</div>
40
40
  <For each={local.availableAuthors}>
41
41
  {(author) => (
42
42
  <DropdownItem onSelect={() => local.onScopeChange({ authors: [author] })}>{author}</DropdownItem>
@@ -44,7 +44,7 @@ export function ChatScopePicker(props: ChatScopePickerProps) {
44
44
  </For>
45
45
  </Show>
46
46
  <Show when={local.availableTags?.length}>
47
- <div class="px-2 py-1 text-[10px] uppercase tracking-wider text-muted-foreground">Tags</div>
47
+ <div class="px-2 py-1 text-micro uppercase tracking-wider text-muted-foreground">Tags</div>
48
48
  <For each={local.availableTags}>
49
49
  {(tag) => (
50
50
  <DropdownItem onSelect={() => local.onScopeChange({ tags: [tag] })}>{tag}</DropdownItem>
@@ -19,6 +19,7 @@ import type { ProseSize } from '../primitives/chat-config';
19
19
  import type { ModelOption } from '../types';
20
20
  import type { CardComponentMap } from '../primitives/card-registry';
21
21
  import type { CardSchemaMap } from './card-renderer';
22
+ import type { JSX } from 'solid-js';
22
23
 
23
24
  export interface ChatThreadContextUsage {
24
25
  usedTokens: number;
@@ -45,6 +46,11 @@ export interface ChatThreadProps {
45
46
  * the kit checks its own seven built-ins and leaves your own card type
46
47
  * unvalidated. A schema here WINS over a built-in of the same name. */
47
48
  cardSchemas?: CardSchemaMap;
49
+ /** The custom-element host node to emit card events off when no `CardProvider`
50
+ * is present, forwarded through `MessageBody` to `CardRenderer`. The
51
+ * element facades pass their own host element so card events leave as the
52
+ * bubbling `kai-card` CustomEvent. */
53
+ cardHostElement?: HTMLElement;
48
54
  /** Value of the input. A **string** is controlled (the host owns the text and
49
55
  * updates it on `kai-value-change`). A **ComposerDoc** is a one-time seed that
50
56
  * pre-populates pills; the user then edits freely. Leave unset for uncontrolled. */
@@ -73,6 +79,19 @@ export interface ChatThreadProps {
73
79
  /** Enable Shiki syntax highlighting in code blocks. Turn off to render plain
74
80
  * `<pre>` blocks (lighter, no highlighter load). Default true. */
75
81
  codeHighlight?: boolean;
82
+ /** How `reasoning` parts render across the thread. `'full'` (default) is the
83
+ * current collapsible-disclosure behavior; `'compact'` shows only a shimmer
84
+ * loader while a reasoning part streams and nothing once it settles (no
85
+ * expandable detail); `'off'` renders reasoning parts not at all. Forwarded
86
+ * to every `MessageBody` as `reasoningMode`. */
87
+ reasoning?: 'full' | 'compact' | 'off';
88
+ /** Seeds the reasoning disclosure open AND keeps it tracking the stream
89
+ * (open while streaming, closes when it settles): the pre-Task-19f `full`
90
+ * behavior. Default false/absent: the panel starts closed (just the
91
+ * "Thinking" shimmer chip) and only opens on click, the current default
92
+ * (owner ruling, 2026-08-26). Meaningless when `reasoning` is `'compact'`
93
+ * or `'off'`. Forwarded to every `MessageBody` as `reasoningDefaultOpen`. */
94
+ reasoningOpen?: boolean;
76
95
  /** Optional header title shown on the left of the header. */
77
96
  chatTitle?: string;
78
97
  /** Optional model list. When set (>1 model) a ModelSwitcher is shown in the
@@ -90,6 +109,17 @@ export interface ChatThreadProps {
90
109
  headerStart?: boolean;
91
110
  /** Whether the host has `slot="header-end"` content (right of the controls). */
92
111
  headerEnd?: boolean;
112
+ /** Extra content rendered in the header-end region, AFTER `slot="header-end"`.
113
+ * This is a JSX escape hatch for a caller composing `ChatThread` directly as a
114
+ * Solid component (no shadow-DOM host, so there is no light-DOM node to slot) —
115
+ * the `kai-dock`-docked construct widget is the motivating case: it needs its
116
+ * own close affordance to sit IN the header row, sharing it with the title
117
+ * instead of floating as a second control with no visible relationship to the
118
+ * chat surface. Renders alongside the named slot rather than replacing it, so a
119
+ * real `slot="header-end"` consumer and this prop can both be present. Counts
120
+ * toward `showHeader()` the same as `headerEnd`, so a construct with no title
121
+ * and only this content still gets a header row to sit in. */
122
+ headerEndContent?: JSX.Element;
93
123
  // ── Composition slots ─────────────────────────────────────────────────────
94
124
  // Each flag below is set by the `<kai-chat>` facade when matching light-DOM
95
125
  // `slot="…"` content is projected, and gates one composition slot. Two kinds:
@@ -106,6 +136,17 @@ export interface ChatThreadProps {
106
136
  sidebar?: boolean;
107
137
  /** REPLACE: custom zero-state rendered in the message area while the thread is empty (replaces the empty message list only; the composer and its suggestions still render). */
108
138
  empty?: boolean;
139
+ /** REPLACE, JSX form: the empty-state content itself, for a caller composing
140
+ * `ChatThread` directly as a Solid component rather than through the `<kai-chat>`
141
+ * shadow-DOM boundary that `empty`/`slot="empty"` targets. Renders INSIDE this
142
+ * component's own tree — so a caller passing the kit's own `<Empty>` composition
143
+ * (`components/empty.tsx`) gets it fully styled by the adopted stylesheet, unlike
144
+ * `slot="empty"`: that slot only ever receives LIGHT-DOM children of the shadow
145
+ * HOST, and light-DOM nodes are outside the shadow root's adopted stylesheets, so
146
+ * Tailwind-utility-class content projected there renders bare. Takes priority
147
+ * over `empty`/`slot="empty"` when both are set — the two are alternate delivery
148
+ * mechanisms for the same region, not additive like `headerEndContent`. */
149
+ emptyContent?: JSX.Element;
109
150
  /** REPLACE: full custom composer in place of the built-in prompt input. The
110
151
  * projected content wires its own submit (the data-flow boundary). */
111
152
  composer?: boolean;
@@ -120,6 +161,10 @@ export interface ChatThreadProps {
120
161
  accept?: MediaTypeFilter;
121
162
  /** Files the composer refused because `accept` excluded them. */
122
163
  onAttachmentsRejected?: (rejected: RejectedAttachment[]) => void;
164
+ /** When `false`, hides the built-in paperclip attach button. Defaults to
165
+ * `true` (undeclared keeps today's behavior: attach visible), matching
166
+ * `DefaultPromptInput`'s own default: only an explicit `false` hides it. */
167
+ attach?: boolean;
123
168
  /** Show a web-search (Globe) button in the input toolbar; calls `onWebSearch`. */
124
169
  webSearch?: boolean;
125
170
  /** Show a Voice (Mic) button in the input toolbar; fires a `voice` event. */
@@ -252,7 +297,7 @@ export function ChatThread(props: ChatThreadProps) {
252
297
  if ((props.suggestionMode ?? 'submit') === 'fill') { handleChange(v); props.onSuggestionClick?.(v); }
253
298
  else { props.onSubmit?.({ value: v, attachments: attachments() }); afterSubmit(); }
254
299
  };
255
- const showHeader = () => !!(props.chatTitle || props.models || props.context || props.headerStart || props.headerEnd);
300
+ const showHeader = () => !!(props.chatTitle || props.models || props.context || props.headerStart || props.headerEnd || props.headerEndContent);
256
301
  // Suggestions are conversation starters: show only on an empty thread unless
257
302
  // the host opts into persisting them.
258
303
  const visibleSuggestions = () =>
@@ -328,6 +373,11 @@ export function ChatThread(props: ChatThreadProps) {
328
373
  {/* Consumer-injected trailing controls (share, settings, …).
329
374
  Projects light-DOM `slot="header-end"` children of <kai-chat>. */}
330
375
  <slot name="header-end" />
376
+ {/* JSX escape hatch for a Solid-composed caller with no shadow-DOM
377
+ host to slot into (see the prop doc) — a docked widget's own
378
+ close affordance is the motivating case, sharing this row with
379
+ the title instead of floating as an unrelated second control. */}
380
+ {props.headerEndContent}
331
381
  </div>
332
382
  </header>
333
383
  </Show>
@@ -338,11 +388,15 @@ export function ChatThread(props: ChatThreadProps) {
338
388
  <div class="relative flex-1 overflow-hidden">
339
389
  <ChatContainer class="h-full px-4 py-3">
340
390
  <ChatContainerContent class="mx-auto w-full max-w-3xl space-y-4">
341
- {/* REPLACE — custom empty-state slot, shown only while the thread is
391
+ {/* REPLACE — custom empty-state content, shown only while the thread is
342
392
  empty. The component still owns WHEN it shows (data state); the
343
- consumer owns WHAT it looks like. */}
344
- <Show when={props.empty && props.messages.length === 0}>
345
- <slot name="empty" />
393
+ consumer owns WHAT it looks like. `emptyContent` (JSX, rendered
394
+ in-tree and fully styled) wins over `empty`/`slot="empty"`
395
+ (light-DOM projection) when both are set — see the prop doc. */}
396
+ <Show when={(props.empty || props.emptyContent) && props.messages.length === 0}>
397
+ <Show when={props.emptyContent} fallback={<slot name="empty" />}>
398
+ {props.emptyContent}
399
+ </Show>
346
400
  </Show>
347
401
  {/* Keyed by message id (see the note above this component), so a
348
402
  streaming delta updates the row instead of replacing it. */}
@@ -361,11 +415,17 @@ export function ChatThread(props: ChatThreadProps) {
361
415
  parts={m().parts}
362
416
  /* F-21: streaming-ness = the thread's ONE existing
363
417
  loading signal + being the last message and an
364
- assistant turn. No second streaming source; the
365
- reasoning disclosure auto-opens on it. */
418
+ assistant turn. No second streaming source. The
419
+ reasoning disclosure no longer auto-opens on it
420
+ by default (Task 19f, owner ruling 2026-08-26) —
421
+ only the trigger's shimmer reflects streaming
422
+ unless `reasoningOpen` opts back in. */
366
423
  isStreaming={props.loading === true && m().role === 'assistant' && i() === props.messages.length - 1}
424
+ reasoningMode={props.reasoning}
425
+ reasoningDefaultOpen={props.reasoningOpen}
367
426
  cardTypes={props.cardTypes}
368
427
  cardSchemas={props.cardSchemas}
428
+ cardHostElement={props.cardHostElement}
369
429
  isUser={m().role === 'user'}
370
430
  markdown={m().role === 'assistant'}
371
431
  actions={m().actions}
@@ -408,7 +468,10 @@ export function ChatThread(props: ChatThreadProps) {
408
468
  </ChatContainerContent>
409
469
  <Show when={showScrollButton()}>
410
470
  <div class="absolute bottom-4 left-1/2 flex w-full max-w-3xl -translate-x-1/2 justify-center px-5">
411
- <ScrollButton class="shadow-sm" />
471
+ {/* The button now owns its elevation (kai-elevation); a `shadow-sm`
472
+ here would set box-shadow a second time and the winner would
473
+ be stylesheet order, not this call site. */}
474
+ <ScrollButton />
412
475
  </div>
413
476
  </Show>
414
477
  </ChatContainer>
@@ -430,7 +493,7 @@ export function ChatThread(props: ChatThreadProps) {
430
493
  value={current()} placeholder={props.placeholder} loading={props.loading === true}
431
494
  suggestions={visibleSuggestions()} attachments={attachments()}
432
495
  accept={props.accept} onAttachmentsRejected={props.onAttachmentsRejected}
433
- webSearch={props.webSearch === true} voice={props.voice === true}
496
+ attach={props.attach} webSearch={props.webSearch === true} voice={props.voice === true}
434
497
  triggers={props.triggers} kindIcons={props.kindIcons}
435
498
  onValueChange={handleChange} onSubmit={handleSubmit} onSuggestionClick={handleSuggestionClick}
436
499
  onAttachmentsChange={(a) => { setAttachments(a); props.onAttachmentsChange?.(a); }}