@kitn.ai/ui 0.25.1 → 0.26.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 (409) hide show
  1. package/README.md +5 -7
  2. package/dist/components/attachment-types.d.ts +46 -1
  3. package/dist/components/attachments.d.ts +31 -0
  4. package/dist/components/audio-visualizer/fit-scale.d.ts +50 -0
  5. package/dist/components/audio-visualizer/index.d.ts +15 -1
  6. package/dist/components/audio-visualizer/variant-bar.d.ts +24 -1
  7. package/dist/components/chat-thread.d.ts +3 -41
  8. package/dist/components/code-block.d.ts +22 -0
  9. package/dist/components/conversation-item.d.ts +54 -1
  10. package/dist/components/conversation-list.d.ts +65 -0
  11. package/dist/components/form.d.ts +42 -0
  12. package/dist/components/message.d.ts +7 -0
  13. package/dist/components/toast.d.ts +2 -1
  14. package/dist/components/voice-input.d.ts +8 -0
  15. package/dist/components/voice-output.d.ts +12 -1
  16. package/dist/components/workspace-shell.d.ts +87 -0
  17. package/dist/{create-tween-B5Y4Im8G.js → create-tween-BFT6c-Y8.js} +1 -1
  18. package/dist/{create-tween-4z1XYLkR.js → create-tween-CJNlzoaO.js} +1 -1
  19. package/dist/{create-tween-CUzOlaMS.js → create-tween-CQED4T0g.js} +1 -1
  20. package/dist/custom-elements.json +2931 -2572
  21. package/dist/diagnostics/hook.d.ts +81 -0
  22. package/dist/diagnostics/index.d.ts +7 -0
  23. package/dist/diagnostics/report-request.d.ts +61 -0
  24. package/dist/diagnostics.d.ts +5 -0
  25. package/dist/diagnostics.js +209 -0
  26. package/dist/elements/agent-card.js +1 -1
  27. package/dist/elements/artifact.js +1 -1
  28. package/dist/elements/attachments.js +1 -1
  29. package/dist/elements/audio-visualizer.js +1 -1
  30. package/dist/elements/autoloader.js +1 -1
  31. package/dist/elements/avatar.js +1 -1
  32. package/dist/elements/badge.js +1 -1
  33. package/dist/elements/button.js +1 -1
  34. package/dist/elements/card.js +1 -1
  35. package/dist/elements/cards.js +1 -1
  36. package/dist/elements/chain-of-thought.js +1 -1
  37. package/dist/elements/chat-scope-picker.js +1 -1
  38. package/dist/elements/chat-workspace.js +1 -1
  39. package/dist/elements/chat.js +1 -1
  40. package/dist/elements/checkpoint.js +1 -1
  41. package/dist/elements/choice.js +1 -1
  42. package/dist/elements/chunks/{Icon-b5A8hlHs.js → Icon--Y8vsFal.js} +1 -1
  43. package/dist/elements/chunks/action-icons-D9u3OzYW.js +1 -0
  44. package/dist/elements/chunks/arrow-left-CVh1TeN7.js +1 -0
  45. package/dist/elements/chunks/{artifact-BSuPYFHY.js → artifact-BkYcfIlZ.js} +1 -1
  46. package/dist/elements/chunks/attachments-DwfNlubq.js +1 -0
  47. package/dist/elements/chunks/audio-visualizer-D7lB6mvR.js +1 -0
  48. package/dist/elements/chunks/{badge-TIMiJFKc.js → badge-Q0-Cmwzz.js} +1 -1
  49. package/dist/elements/chunks/{button-B9okqG73.js → button-flUbeufF.js} +1 -1
  50. package/dist/elements/chunks/{card-renderer-CSoTL_e1.js → card-renderer-3Dyl-FpN.js} +1 -1
  51. package/dist/elements/chunks/check-B5kBPKeo.js +1 -0
  52. package/dist/elements/chunks/chevron-down-DZ1GS39h.js +1 -0
  53. package/dist/elements/chunks/chevron-right-CvP7OUd2.js +1 -0
  54. package/dist/elements/chunks/{choice-card-CGMc3kek.js → choice-card-D4QUIOWZ.js} +1 -1
  55. package/dist/elements/chunks/circle-CDf9g6MQ.js +1 -0
  56. package/dist/elements/chunks/circle-check-CA47Nqbz.js +1 -0
  57. package/dist/elements/chunks/{circle-x-mhH7pOK2.js → circle-x-CJ_HVbC8.js} +1 -1
  58. package/dist/elements/chunks/code-block-BdLiTitd.js +1 -0
  59. package/dist/elements/chunks/collapsible-BzbXpPzr.js +1 -0
  60. package/dist/elements/chunks/{composer-CZZmtYOT.js → composer-Byve-n8K.js} +2 -2
  61. package/dist/elements/chunks/{confirm-card-BWjf2-xo.js → confirm-card-B0flE3MN.js} +1 -1
  62. package/dist/elements/chunks/context-VLIL3sJ-.js +1 -0
  63. package/dist/elements/chunks/controllable-DTwTIlwp.js +1 -0
  64. package/dist/elements/chunks/conversation-item-BDztezOG.js +1 -0
  65. package/dist/elements/chunks/copy-Nf-kqxXH.js +1 -0
  66. package/dist/elements/chunks/{create-tween-CUrM6D_o.js → create-tween-c4Z8TDYz.js} +2 -2
  67. package/dist/elements/chunks/default-input-C2iLFq0b.js +1 -0
  68. package/dist/elements/chunks/define-wjHR1MkU.js +1 -0
  69. package/dist/elements/chunks/disclosure-CcNbyLy0.js +1 -0
  70. package/dist/elements/chunks/{download-DnCyWFJE.js → download-C4V7tBdb.js} +1 -1
  71. package/dist/elements/chunks/dropdown-BgWTthUx.js +1 -0
  72. package/dist/elements/chunks/{ellipsis-CVxqfsDZ.js → ellipsis-7gU33mL2.js} +1 -1
  73. package/dist/elements/chunks/embed-D3KewsIJ.js +1 -0
  74. package/dist/elements/chunks/{external-link-DG2sRdQL.js → external-link-CSOEsNlx.js} +1 -1
  75. package/dist/elements/chunks/{file-text-D0J9F6M7.js → file-text-D1G8khle.js} +1 -1
  76. package/dist/elements/chunks/{file-tree-yGWNK0Js.js → file-tree-zvB2i7P9.js} +1 -1
  77. package/dist/elements/chunks/{folder-NV1pi_ud.js → folder-WW2LGLid.js} +1 -1
  78. package/dist/elements/chunks/form-CQirdC4W.js +1 -0
  79. package/dist/elements/chunks/hover-card-CJJkfHTK.js +1 -0
  80. package/dist/elements/chunks/icon-Cfgmf4fa.js +1 -0
  81. package/dist/elements/chunks/{info-C8r5Q6cc.js → info-DX3YMOt6.js} +1 -1
  82. package/dist/elements/chunks/input-BtW9U6Sq.js +1 -0
  83. package/dist/elements/chunks/{kbd-OGJDUT-O.js → kbd-LGXwuT_V.js} +1 -1
  84. package/dist/elements/chunks/{link-BdsfLB7b.js → link-2My69BqT.js} +1 -1
  85. package/dist/elements/chunks/{link-preview-Cf5KOP-i.js → link-preview-OQ9IEq0f.js} +1 -1
  86. package/dist/elements/chunks/{loader-B5QzK_8_.js → loader-iOxc_Tu-.js} +1 -1
  87. package/dist/elements/chunks/{markdown-DbozyYqa.js → markdown-DgBFaGAz.js} +1 -1
  88. package/dist/elements/chunks/{message-DtXKPqiR.js → message-VMZohrXx.js} +1 -1
  89. package/dist/elements/chunks/message-circle-CpXMM-_n.js +1 -0
  90. package/dist/elements/chunks/message-square-DxcWtETQ.js +1 -0
  91. package/dist/elements/chunks/message-tZmV2A3p.js +1 -0
  92. package/dist/elements/chunks/{minimize-2-SegJ_oku.js → minimize-2-DPIUKTrT.js} +1 -1
  93. package/dist/elements/chunks/{model-switcher-D7JrFFHp.js → model-switcher-DsT8tFB0.js} +1 -1
  94. package/dist/elements/chunks/{overlay-CV7z2YuX.js → overlay-DuiwdXjm.js} +1 -1
  95. package/dist/elements/chunks/{paperclip-Bg0ITU3b.js → paperclip-CRZVp4z_.js} +1 -1
  96. package/dist/elements/chunks/{progress-bar-D1_rzt6N.js → progress-bar-DNy66e_E.js} +1 -1
  97. package/dist/elements/chunks/{prompt-suggestion-D5Sm8xF1.js → prompt-suggestion-Bn64Nl7L.js} +1 -1
  98. package/dist/elements/chunks/reasoning-Emn9N4-T.js +1 -0
  99. package/dist/elements/chunks/{resizable-Dpzjlvp4.js → resizable-D181b4fM.js} +1 -1
  100. package/dist/elements/chunks/{rotate-cw-DzVDJOA1.js → rotate-cw-CPWe37D9.js} +1 -1
  101. package/dist/elements/chunks/{scroll-area-93A1bbeG.js → scroll-area-ClZkZxIk.js} +1 -1
  102. package/dist/elements/chunks/scroll-button-DPE-t3x_.js +1 -0
  103. package/dist/elements/chunks/{separator-DH2r_ZSZ.js → separator-CeJHQqLW.js} +1 -1
  104. package/dist/elements/chunks/{settings-BFMOd6yB.js → settings-CqaHgJF9.js} +1 -1
  105. package/dist/elements/chunks/{settings-group-B3VZKIcz.js → settings-group-CjqjLCOn.js} +1 -1
  106. package/dist/elements/chunks/share-CyfnNEqp.js +1 -0
  107. package/dist/elements/chunks/{skeleton-N8BuWYmf.js → skeleton-D8akBnKS.js} +1 -1
  108. package/dist/elements/chunks/slots-DaNjX0rc.js +1 -0
  109. package/dist/elements/chunks/{source-w9V0NnBn.js → source-UWCvmVak.js} +1 -1
  110. package/dist/elements/chunks/{star-DHvACxtm.js → star-DoHFAikQ.js} +1 -1
  111. package/dist/elements/chunks/store-Cjq0qwYN.js +1 -0
  112. package/dist/elements/chunks/{tasks-card-lPxoodlA.js → tasks-card-CmZ5xh6v.js} +1 -1
  113. package/dist/elements/chunks/{text-shimmer-BY_rI3s5.js → text-shimmer-DYn09zrz.js} +1 -1
  114. package/dist/elements/chunks/textarea-skiGHURM.js +1 -0
  115. package/dist/elements/chunks/{thumbs-up-DQe0hvkZ.js → thumbs-up-DX2Ijk3H.js} +1 -1
  116. package/dist/elements/chunks/{toast-store-VUZZBhzH.js → toast-store-CFnQpThX.js} +1 -1
  117. package/dist/elements/chunks/{tool-C1YtxwPu.js → tool-DKQ2D1DP.js} +1 -1
  118. package/dist/elements/chunks/{tooltip-BqwnFWhn.js → tooltip-B0G99y8w.js} +1 -1
  119. package/dist/elements/chunks/{triangle-alert-B6or7F5u.js → triangle-alert-F9cyUEyy.js} +1 -1
  120. package/dist/elements/chunks/{use-card-resolution-DJg32jGH.js → use-card-resolution-DoA2f_EU.js} +1 -1
  121. package/dist/elements/chunks/{variant-aurora-QXTZPyST.js → variant-aurora-qt6Zct8M.js} +2 -2
  122. package/dist/elements/chunks/variant-custom-tJp22_BQ.js +1 -0
  123. package/dist/{variant-wave-BwzrHD1s.js → elements/chunks/variant-wave-CaQ5ti39.js} +2 -2
  124. package/dist/elements/chunks/x-B6UnOiLw.js +1 -0
  125. package/dist/elements/coachmark.js +1 -1
  126. package/dist/elements/code-block.js +1 -1
  127. package/dist/elements/command.js +1 -1
  128. package/dist/elements/compare.js +1 -1
  129. package/dist/elements/composer.js +1 -1
  130. package/dist/elements/confirm-card.js +1 -1
  131. package/dist/elements/context-meter.js +1 -1
  132. package/dist/elements/conversation-item.d.ts +1 -0
  133. package/dist/elements/conversation-item.js +1 -0
  134. package/dist/elements/conversation-list.js +1 -1
  135. package/dist/elements/default-input.d.ts +3 -3
  136. package/dist/elements/define.d.ts +27 -0
  137. package/dist/elements/diagnostic-events.d.ts +74 -0
  138. package/dist/elements/dialog.js +1 -1
  139. package/dist/elements/dock.d.ts +1 -0
  140. package/dist/elements/dock.js +149 -0
  141. package/dist/elements/dropdown.d.ts +1 -0
  142. package/dist/elements/dropdown.js +1 -0
  143. package/dist/elements/editable-label.js +1 -1
  144. package/dist/elements/element-diagnostics.d.ts +81 -0
  145. package/dist/elements/embed.js +1 -1
  146. package/dist/elements/empty.js +1 -1
  147. package/dist/elements/feedback-bar.js +1 -1
  148. package/dist/elements/file-tree.js +1 -1
  149. package/dist/elements/file-upload.js +1 -1
  150. package/dist/elements/form.js +1 -1
  151. package/dist/elements/hover-card.js +1 -1
  152. package/dist/elements/icon.js +1 -1
  153. package/dist/elements/image.js +1 -1
  154. package/dist/elements/input.js +1 -1
  155. package/dist/elements/kbd.js +1 -1
  156. package/dist/elements/link-preview.js +1 -1
  157. package/dist/elements/loader.js +1 -1
  158. package/dist/elements/markdown.js +1 -1
  159. package/dist/elements/menu.js +1 -1
  160. package/dist/elements/message-skills.js +1 -1
  161. package/dist/elements/message.js +1 -1
  162. package/dist/elements/model-switcher.js +1 -1
  163. package/dist/elements/nav.js +1 -1
  164. package/dist/elements/notice.js +1 -1
  165. package/dist/elements/pane-group.js +1 -1
  166. package/dist/elements/pane.js +1 -1
  167. package/dist/elements/popover.js +1 -1
  168. package/dist/elements/progress-bar.js +1 -1
  169. package/dist/elements/prompt-dock.js +1 -1
  170. package/dist/elements/prompt-input.js +1 -1
  171. package/dist/elements/prompt-suggestions.js +1 -1
  172. package/dist/elements/reasoning.js +1 -1
  173. package/dist/elements/register.d.ts +2 -0
  174. package/dist/elements/remote.js +1 -1
  175. package/dist/elements/resizable.js +1 -1
  176. package/dist/elements/response-stream.js +3 -3
  177. package/dist/elements/screen.js +1 -1
  178. package/dist/elements/scroll-area.js +1 -1
  179. package/dist/elements/scroll-button.js +1 -1
  180. package/dist/elements/search.js +1 -1
  181. package/dist/elements/segmented.js +1 -1
  182. package/dist/elements/separator.js +1 -1
  183. package/dist/elements/setting-item.js +1 -1
  184. package/dist/elements/settings-group.js +1 -1
  185. package/dist/elements/skeleton.js +1 -1
  186. package/dist/elements/slots.d.ts +35 -3
  187. package/dist/elements/source.js +1 -1
  188. package/dist/elements/status.js +1 -1
  189. package/dist/elements/switch.js +1 -1
  190. package/dist/elements/tabs.js +1 -1
  191. package/dist/elements/tasks.js +1 -1
  192. package/dist/elements/text-shimmer.js +1 -1
  193. package/dist/elements/thinking-bar.js +1 -1
  194. package/dist/elements/thread.js +1 -1
  195. package/dist/elements/toast.js +1 -1
  196. package/dist/elements/tool.js +1 -1
  197. package/dist/elements/tooltip.js +1 -1
  198. package/dist/elements/voice-input.js +1 -1
  199. package/dist/elements/voice-output.js +1 -1
  200. package/dist/elements.d.ts +232 -148
  201. package/dist/index.d.ts +2 -0
  202. package/dist/index.js +5456 -4931
  203. package/dist/index.server.js +4142 -3669
  204. package/dist/kai-provider.es.js +40 -40
  205. package/dist/kai.es.js +1 -1
  206. package/dist/llms/llms-full.txt +184 -69
  207. package/dist/llms/llms.txt +3 -3
  208. package/dist/mcp.es.js +2669 -546
  209. package/dist/primitives/use-resize-observer.d.ts +23 -0
  210. package/dist/primitives/use-speech-recognition.d.ts +8 -0
  211. package/dist/primitives/use-text-stream.d.ts +5 -0
  212. package/dist/react/index.d.ts +115 -266
  213. package/dist/react.js +247 -221
  214. package/dist/register-impl-DpE7icIb.js +293 -0
  215. package/dist/schemas/index.d.ts +1 -1
  216. package/dist/schemas/tool-defs.d.ts +35 -0
  217. package/dist/schemas.js +403 -310
  218. package/dist/{solid-BMuDmFo_.js → solid-BtdqNZI7.js} +8435 -7394
  219. package/dist/{solid-CGYNdLRR.js → solid-CnavwBye.js} +5987 -5035
  220. package/dist/solid.d.ts +5 -0
  221. package/dist/solid.js +210 -203
  222. package/dist/solid.server.js +210 -203
  223. package/dist/state/index.d.ts +4 -0
  224. package/dist/state/persistence.d.ts +51 -0
  225. package/dist/state/stream.d.ts +50 -0
  226. package/dist/state/threads.d.ts +71 -0
  227. package/dist/state.js +269 -169
  228. package/dist/types.d.ts +4 -2
  229. package/dist/ui/dock.d.ts +109 -0
  230. package/dist/ui/hover-card.d.ts +44 -0
  231. package/dist/{variant-aurora-DwSOfraQ.js → variant-aurora-B8II3-I1.js} +27 -27
  232. package/dist/{variant-aurora-wKvAQ5wp.js → variant-aurora-CMNWOSJR.js} +28 -28
  233. package/dist/{variant-aurora-XEkPT0_z.js → variant-aurora-CcuDMWwQ.js} +2 -2
  234. package/dist/{variant-custom-eFIg2XWQ.js → variant-custom-BdvYC7af.js} +40 -40
  235. package/dist/{variant-custom-BhS9wIpU.js → variant-custom-C714mqKl.js} +65 -65
  236. package/dist/variant-custom-L16JLLZy.js +1 -0
  237. package/dist/{elements/chunks/variant-wave-DDCwhLas.js → variant-wave-2S4La2Ka.js} +2 -2
  238. package/dist/{variant-wave-CbVsmgwT.js → variant-wave-D7ruiA1W.js} +25 -25
  239. package/dist/{variant-wave-CUWGx9Bn.js → variant-wave-ecwykeyL.js} +21 -21
  240. package/dist/wire/chunk.d.ts +47 -0
  241. package/dist/wire/diagnostics.d.ts +575 -0
  242. package/dist/wire/encode-probe.d.ts +70 -0
  243. package/dist/wire/encode.d.ts +24 -0
  244. package/dist/wire/index.d.ts +2 -0
  245. package/dist/wire/sse.d.ts +10 -2
  246. package/dist/wire.js +917 -480
  247. package/frameworks/react/index.tsx +132 -93
  248. package/llms-full.txt +184 -69
  249. package/llms.txt +3 -3
  250. package/package.json +27 -7
  251. package/src/agent-tooling/archetypes.ts +41 -9
  252. package/src/agent-tooling/catalog/README.md +676 -0
  253. package/src/agent-tooling/catalog/catalog-types.ts +231 -0
  254. package/src/agent-tooling/catalog/fabrications.ts +96 -0
  255. package/src/agent-tooling/catalog/invariants.ts +284 -0
  256. package/src/agent-tooling/catalog/labs-titles.ts +114 -0
  257. package/src/agent-tooling/catalog/scenarios.ts +87 -0
  258. package/src/agent-tooling/catalog/surfaces.ts +275 -0
  259. package/src/agent-tooling/integrations/anthropic.ts +7 -1
  260. package/src/agent-tooling/integrations/cloudflare.ts +43 -2
  261. package/src/agent-tooling/integrations/langgraph.ts +7 -1
  262. package/src/agent-tooling/integrations/mastra.ts +7 -1
  263. package/src/agent-tooling/integrations/mock.ts +92 -17
  264. package/src/agent-tooling/integrations/ollama.ts +7 -1
  265. package/src/agent-tooling/integrations/openai.ts +7 -1
  266. package/src/agent-tooling/integrations/openrouter.ts +7 -1
  267. package/src/agent-tooling/integrations/pi.ts +56 -1
  268. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +7 -1
  269. package/src/agent-tooling/mcp/css-raw.d.ts +12 -0
  270. package/src/agent-tooling/mcp/manifest.ts +100 -1
  271. package/src/agent-tooling/mcp/server.ts +61 -5
  272. package/src/agent-tooling/mcp/tools/reference.ts +440 -4
  273. package/src/agent-tooling/mcp/tools/scaffold.ts +1834 -307
  274. package/src/agent-tooling/mcp/tools/theme.ts +146 -30
  275. package/src/agent-tooling/mcp/validate-args.ts +141 -0
  276. package/src/agent-tooling/registry.ts +19 -7
  277. package/src/agent-tooling/route-emit.ts +26 -2
  278. package/src/components/attachment-types.ts +47 -1
  279. package/src/components/attachments.tsx +169 -22
  280. package/src/components/audio-visualizer/fit-scale.ts +112 -0
  281. package/src/components/audio-visualizer/index.tsx +80 -3
  282. package/src/components/audio-visualizer/variant-aurora.tsx +10 -4
  283. package/src/components/audio-visualizer/variant-bar.tsx +38 -6
  284. package/src/components/audio-visualizer/variant-custom.tsx +8 -2
  285. package/src/components/audio-visualizer/variant-grid.tsx +16 -11
  286. package/src/components/audio-visualizer/variant-radial.tsx +15 -10
  287. package/src/components/audio-visualizer/variant-wave.tsx +7 -2
  288. package/src/components/chat-container.tsx +4 -1
  289. package/src/components/chat-thread.tsx +36 -7
  290. package/src/components/code-block.tsx +79 -3
  291. package/src/components/composer.tsx +8 -1
  292. package/src/components/conversation-item.tsx +114 -4
  293. package/src/components/conversation-list.tsx +212 -12
  294. package/src/components/embed.tsx +4 -0
  295. package/src/components/form.tsx +41 -14
  296. package/src/components/message.tsx +75 -5
  297. package/src/components/response-stream.tsx +13 -7
  298. package/src/components/screen.tsx +5 -0
  299. package/src/components/scroll-button.tsx +7 -0
  300. package/src/components/toast.tsx +11 -5
  301. package/src/components/voice-input.tsx +35 -3
  302. package/src/components/voice-output.tsx +46 -6
  303. package/src/components/workspace-shell.tsx +285 -0
  304. package/src/diagnostics/hook.ts +352 -0
  305. package/src/diagnostics/index.ts +82 -0
  306. package/src/diagnostics/report-request.ts +296 -0
  307. package/src/elements/attachments.tsx +6 -7
  308. package/src/elements/audio-visualizer.tsx +48 -4
  309. package/src/elements/chat-workspace.tsx +159 -287
  310. package/src/elements/chat.tsx +12 -9
  311. package/src/elements/code-block.tsx +19 -1
  312. package/src/elements/command.tsx +4 -1
  313. package/src/elements/compiled.css +1 -1
  314. package/src/elements/conversation-item.tsx +80 -0
  315. package/src/elements/conversation-list.tsx +60 -11
  316. package/src/elements/default-input.tsx +5 -5
  317. package/src/elements/define.tsx +168 -8
  318. package/src/elements/diagnostic-events.ts +114 -0
  319. package/src/elements/dialog.tsx +47 -0
  320. package/src/elements/disclosure.ts +34 -12
  321. package/src/elements/dock.tsx +204 -0
  322. package/src/elements/dropdown.tsx +123 -0
  323. package/src/elements/element-diagnostics.ts +392 -0
  324. package/src/elements/element-manifest.json +12 -0
  325. package/src/elements/element-meta.json +672 -439
  326. package/src/elements/element-nonscalar.json +170 -0
  327. package/src/elements/element-types.d.ts +232 -148
  328. package/src/elements/menu.tsx +13 -0
  329. package/src/elements/prompt-dock.tsx +2 -1
  330. package/src/elements/prompt-input.tsx +8 -8
  331. package/src/elements/register-impl.ts +46 -0
  332. package/src/elements/register.ts +28 -0
  333. package/src/elements/resizable.tsx +52 -25
  334. package/src/elements/scroll-button.tsx +5 -0
  335. package/src/elements/slots.ts +107 -12
  336. package/src/elements/styles.css +30 -6
  337. package/src/elements/thinking-bar.tsx +16 -7
  338. package/src/elements/toast.tsx +3 -0
  339. package/src/elements/tool.tsx +26 -5
  340. package/src/elements/voice-input.tsx +11 -2
  341. package/src/elements/voice-output.tsx +16 -3
  342. package/src/index.ts +2 -0
  343. package/src/primitives/use-resize-observer.ts +33 -0
  344. package/src/primitives/use-speech-recognition.ts +12 -1
  345. package/src/primitives/use-stick-to-bottom.ts +34 -2
  346. package/src/primitives/use-text-stream.ts +33 -2
  347. package/src/remote/provider-runtime.ts +6 -3
  348. package/src/schemas/index.ts +1 -0
  349. package/src/schemas/tool-defs.ts +297 -6
  350. package/src/solid.ts +5 -0
  351. package/src/state/index.ts +12 -0
  352. package/src/state/persistence.ts +180 -0
  353. package/src/state/stream.ts +71 -4
  354. package/src/state/threads.ts +142 -0
  355. package/src/types.ts +4 -2
  356. package/src/ui/dialog.tsx +6 -0
  357. package/src/ui/dock.tsx +445 -0
  358. package/src/ui/dropdown.tsx +67 -23
  359. package/src/ui/hover-card.tsx +156 -6
  360. package/src/ui/input.tsx +29 -10
  361. package/src/ui/resizable.tsx +11 -0
  362. package/src/wire/chunk.ts +47 -0
  363. package/src/wire/consume.ts +185 -26
  364. package/src/wire/diagnostics.ts +727 -0
  365. package/src/wire/encode-probe.ts +214 -0
  366. package/src/wire/encode.ts +267 -14
  367. package/src/wire/formats/anthropic.ts +8 -1
  368. package/src/wire/formats/openai.ts +5 -0
  369. package/src/wire/index.ts +22 -0
  370. package/src/wire/read.ts +250 -6
  371. package/src/wire/sse.ts +16 -3
  372. package/dist/elements/chunks/action-icons-DW9muWrY.js +0 -1
  373. package/dist/elements/chunks/arrow-left-iJVnQmxA.js +0 -1
  374. package/dist/elements/chunks/attachments-CL6TaqIb.js +0 -1
  375. package/dist/elements/chunks/audio-visualizer-BuUqQmaO.js +0 -1
  376. package/dist/elements/chunks/chat-thread-DxoKaStk.js +0 -1
  377. package/dist/elements/chunks/check-MdLzbxrm.js +0 -1
  378. package/dist/elements/chunks/chevron-down-MK7IzDqe.js +0 -1
  379. package/dist/elements/chunks/chevron-right-C5jXhmtV.js +0 -1
  380. package/dist/elements/chunks/circle-BG7VkPep.js +0 -1
  381. package/dist/elements/chunks/circle-check-GqvO2UBs.js +0 -1
  382. package/dist/elements/chunks/code-block-ClhQO9RW.js +0 -1
  383. package/dist/elements/chunks/collapsible-DBcBkFPh.js +0 -1
  384. package/dist/elements/chunks/context-hKjNqiyQ.js +0 -1
  385. package/dist/elements/chunks/conversation-list-CsGJjSKG.js +0 -1
  386. package/dist/elements/chunks/default-input-B1Mem5wu.js +0 -1
  387. package/dist/elements/chunks/define-B_tXMYRm.js +0 -1
  388. package/dist/elements/chunks/disclosure-DAoYOKew.js +0 -1
  389. package/dist/elements/chunks/dropdown-CmNna5lT.js +0 -1
  390. package/dist/elements/chunks/embed-CjAD2jSi.js +0 -1
  391. package/dist/elements/chunks/form-Cp8Y00Wn.js +0 -1
  392. package/dist/elements/chunks/hover-card-6KtXpLwT.js +0 -1
  393. package/dist/elements/chunks/icon-97R8SR2p.js +0 -1
  394. package/dist/elements/chunks/input-DrseEjhp.js +0 -1
  395. package/dist/elements/chunks/message-CE4k-qaj.js +0 -1
  396. package/dist/elements/chunks/message-square-C9ovmtOo.js +0 -1
  397. package/dist/elements/chunks/reasoning-BrxQfpfI.js +0 -1
  398. package/dist/elements/chunks/scroll-button-CrTo7wm4.js +0 -1
  399. package/dist/elements/chunks/share-DgNbkJKY.js +0 -1
  400. package/dist/elements/chunks/slots-CIw9RlAe.js +0 -1
  401. package/dist/elements/chunks/store-HIPGhNz9.js +0 -1
  402. package/dist/elements/chunks/textarea-DPfuhswM.js +0 -1
  403. package/dist/elements/chunks/variant-custom-D5ZlmziF.js +0 -1
  404. package/dist/elements/chunks/video-Bb86fVYI.js +0 -1
  405. package/dist/elements/chunks/x-BOhjBeOd.js +0 -1
  406. package/dist/primitives/card-validate-generator.testlib.d.ts +0 -20
  407. package/dist/register-impl-DGmGzrEM.js +0 -145
  408. package/dist/variant-custom-MkTNTycd.js +0 -1
  409. package/src/primitives/card-validate-generator.testlib.ts +0 -38
@@ -492,6 +492,16 @@
492
492
  "name": "preview",
493
493
  "doc": "The image shown in an attachment’s hover-card preview. Bounded by default (max ~320×256, aspect preserved) so a large image never blows up the card. Raise or lower the cap from outside.",
494
494
  "recipe": "kai-attachments::part(preview) { max-width: 32rem; max-height: 24rem }"
495
+ },
496
+ {
497
+ "name": "attachment",
498
+ "doc": "One attachment item: the chip, row or tile, whichever variant is rendering. Restyle its background, radius or border from outside without caring which layout it is.",
499
+ "recipe": "kai-chat::part(attachment) { border-radius: 0.25rem }"
500
+ },
501
+ {
502
+ "name": "attachment-name",
503
+ "doc": "The attachment’s filename label. Present in every variant that shows one (a grid tile omits it for an image, which is its own label). Retune its type or hide it entirely.",
504
+ "recipe": "kai-chat::part(attachment-name) { font-size: 0.75rem }"
495
505
  }
496
506
  ]
497
507
  },
@@ -606,7 +616,7 @@
606
616
  "type": "undefined | MediaStream",
607
617
  "optional": true,
608
618
  "scalar": false,
609
- "description": "Live microphone or WebRTC audio to analyze. JS property only.",
619
+ "description": "Live microphone or WebRTC audio to analyze. JS property only. NOTE: amplitude renders only while state is \"speaking\" unless listening-amplitude is set; every other state plays its scripted animation and ignores the audio.",
610
620
  "displayType": "undefined | MediaStream"
611
621
  },
612
622
  {
@@ -614,7 +624,7 @@
614
624
  "type": "undefined | HTMLMediaElement",
615
625
  "optional": true,
616
626
  "scalar": false,
617
- "description": "An `<audio>` or `<video>` element to tap for its audio. JS property only.",
627
+ "description": "An `<audio>` or `<video>` element to tap for its audio. JS property only. NOTE: amplitude renders only while state is \"speaking\" unless listening-amplitude is set; every other state plays its scripted animation and ignores the audio.",
618
628
  "displayType": "undefined | HTMLMediaElement"
619
629
  },
620
630
  {
@@ -622,9 +632,17 @@
622
632
  "type": "undefined | number[]",
623
633
  "optional": true,
624
634
  "scalar": false,
625
- "description": "Pre-computed levels, 0..1. Set this and no AudioContext is ever built, which is what keeps headless/SSR rendering and browser-speech-synthesis playback (which exposes no audio node) free of Web Audio entirely. JS property only. A new array reference is required for each update; mutating the existing array in place will not re-render.",
635
+ "description": "Pre-computed levels, 0..1. Set this and no AudioContext is ever built, which is what keeps headless/SSR rendering and browser-speech-synthesis playback (which exposes no audio node) free of Web Audio entirely. JS property only. A new array reference is required for each update; mutating the existing array in place will not re-render. NOTE: amplitude renders only while state is \"speaking\" unless listening-amplitude is set; every other state plays its scripted animation and ignores the audio.",
626
636
  "displayType": "undefined | number[]"
627
637
  },
638
+ {
639
+ "name": "listeningAmplitude",
640
+ "type": "undefined | false | true",
641
+ "optional": true,
642
+ "scalar": true,
643
+ "description": "Render live amplitude during the listening state as well, using the same presentation as speaking. Off by default, which keeps LiveKit parity: amplitude from stream, audio-element or bands renders only while state is \"speaking\". Set it to show a real mic-level picture while the user is the one talking. Boolean. Attribute: `listening-amplitude` (a bare attribute means true; reflected, so the property reads back what the attribute set).",
644
+ "displayType": "undefined | false | true"
645
+ },
628
646
  {
629
647
  "name": "shader",
630
648
  "type": "undefined | { fragment: string; uniforms?: undefined | Record<string, { type: \"1f\" | \"1i\" | \"1fv\" | \"2f\" | \"3f\" | \"3fv\" | \"4f\" | \"4fv\" | \"Matrix2fv\" | \"Matrix3fv\" | \"Matrix4fv\"; value: number | number[] }> }",
@@ -1336,15 +1354,6 @@
1336
1354
  "universal": true,
1337
1355
  "displayType": "\"light\" | \"dark\" | \"auto\""
1338
1356
  },
1339
- {
1340
- "name": "search",
1341
- "type": "undefined | false | true",
1342
- "optional": true,
1343
- "scalar": true,
1344
- "description": "Show a Search (Globe) button in the input toolbar; fires a `search` event.",
1345
- "default": "false",
1346
- "displayType": "undefined | false | true"
1347
- },
1348
1357
  {
1349
1358
  "name": "value",
1350
1359
  "type": "undefined | string | ({ type: \"text\"; text: string } | { type: \"entity\"; entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record<string, unknown> } })[]",
@@ -1535,6 +1544,15 @@
1535
1544
  "description": "INJECT: footer row below the composer (disclaimers, token meter, …).",
1536
1545
  "displayType": "undefined | false | true"
1537
1546
  },
1547
+ {
1548
+ "name": "webSearch",
1549
+ "type": "undefined | false | true",
1550
+ "optional": true,
1551
+ "scalar": true,
1552
+ "description": "Show a web-search (Globe) button in the input toolbar; calls `onWebSearch`.",
1553
+ "default": "false",
1554
+ "displayType": "undefined | false | true"
1555
+ },
1538
1556
  {
1539
1557
  "name": "voice",
1540
1558
  "type": "undefined | false | true",
@@ -1634,12 +1652,6 @@
1634
1652
  "description": "The header model switcher changed.",
1635
1653
  "displayDetail": "{ modelId: string }"
1636
1654
  },
1637
- {
1638
- "name": "kai-search",
1639
- "detail": "Record<string, never>",
1640
- "description": "The Search button was clicked.",
1641
- "displayDetail": "Record<string, never>"
1642
- },
1643
1655
  {
1644
1656
  "name": "kai-submit",
1645
1657
  "detail": "{ value: string; attachments: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }",
@@ -1663,6 +1675,12 @@
1663
1675
  "detail": "Record<string, never>",
1664
1676
  "description": "The Mic / voice button was clicked.",
1665
1677
  "displayDetail": "Record<string, never>"
1678
+ },
1679
+ {
1680
+ "name": "kai-web-search",
1681
+ "detail": "Record<string, never>",
1682
+ "description": "The web-search (Globe) toolbar button was clicked.",
1683
+ "displayDetail": "Record<string, never>"
1666
1684
  }
1667
1685
  ],
1668
1686
  "methods": [
@@ -2177,6 +2195,15 @@
2177
2195
  "default": "true",
2178
2196
  "displayType": "undefined | false | true"
2179
2197
  },
2198
+ {
2199
+ "name": "copy",
2200
+ "type": "undefined | false | true",
2201
+ "optional": true,
2202
+ "scalar": true,
2203
+ "description": "Show the copy button. **Defaults to ON**, because this element is documented as shipping one. Opt out with `copy=\"false\"` or `el.copy = false`.",
2204
+ "default": "true",
2205
+ "displayType": "undefined | false | true"
2206
+ },
2180
2207
  {
2181
2208
  "name": "proseSize",
2182
2209
  "type": "undefined | \"xs\" | \"sm\" | \"base\" | \"lg\"",
@@ -2203,6 +2230,13 @@
2203
2230
  ],
2204
2231
  "tokens": [
2205
2232
  "--color-code-foreground"
2233
+ ],
2234
+ "parts": [
2235
+ {
2236
+ "name": "copy",
2237
+ "doc": "The copy-to-clipboard button in the header row. Hide it with `copy=\"false\"` rather than CSS.",
2238
+ "recipe": "kai-code-block::part(copy) { color: var(--color-primary) }"
2239
+ }
2206
2240
  ]
2207
2241
  },
2208
2242
  {
@@ -2820,6 +2854,111 @@
2820
2854
  }
2821
2855
  ]
2822
2856
  },
2857
+ {
2858
+ "tag": "kai-conversation-item",
2859
+ "className": "KaiConversationItemElement",
2860
+ "displayName": "ConversationItem",
2861
+ "props": [
2862
+ {
2863
+ "name": "theme",
2864
+ "type": "\"light\" | \"dark\" | \"auto\"",
2865
+ "optional": true,
2866
+ "scalar": true,
2867
+ "description": "Color mode (`auto` follows prefers-color-scheme).",
2868
+ "default": "'auto'",
2869
+ "universal": true,
2870
+ "displayType": "\"light\" | \"dark\" | \"auto\""
2871
+ },
2872
+ {
2873
+ "name": "conversationId",
2874
+ "type": "undefined | string",
2875
+ "optional": true,
2876
+ "scalar": true,
2877
+ "description": "The row's identity, handed to the container's selection contract. In the element this is the `conversation-id` attribute (host `id` is the fallback).",
2878
+ "displayType": "undefined | string"
2879
+ },
2880
+ {
2881
+ "name": "active",
2882
+ "type": "undefined | false | true",
2883
+ "optional": true,
2884
+ "scalar": true,
2885
+ "description": "Selected state. Reflected as `aria-current` on the row body and a `data-active` styling hook on the row; the container drives it from its `activeId`.",
2886
+ "displayType": "undefined | false | true"
2887
+ },
2888
+ {
2889
+ "name": "compact",
2890
+ "type": "undefined | false | true",
2891
+ "optional": true,
2892
+ "scalar": true,
2893
+ "description": "Dense single-line row padding.",
2894
+ "displayType": "undefined | false | true"
2895
+ }
2896
+ ],
2897
+ "events": [],
2898
+ "methods": [],
2899
+ "composedFrom": [
2900
+ {
2901
+ "name": "SlottedConversationItem",
2902
+ "group": "Components",
2903
+ "storyId": "solid-advanced-elements-slottedconversationitem--docs"
2904
+ }
2905
+ ],
2906
+ "tokens": [],
2907
+ "slots": [
2908
+ {
2909
+ "name": "",
2910
+ "mode": "inject",
2911
+ "doc": "The row title. `leading`, `meta` and `menu` are the named regions around it."
2912
+ },
2913
+ {
2914
+ "name": "leading",
2915
+ "mode": "inject",
2916
+ "part": true,
2917
+ "doc": "Leading region before the title (an icon or avatar)."
2918
+ },
2919
+ {
2920
+ "name": "meta",
2921
+ "mode": "inject",
2922
+ "part": true,
2923
+ "doc": "Meta region under the title (a timestamp or status line)."
2924
+ },
2925
+ {
2926
+ "name": "menu",
2927
+ "mode": "inject",
2928
+ "part": true,
2929
+ "doc": "Your own row menu (a popover trigger). Never selects the row."
2930
+ }
2931
+ ],
2932
+ "parts": [
2933
+ {
2934
+ "name": "body",
2935
+ "doc": "The activation surface inside the row (button role; carries aria-current and the roving tabindex). The focus ring paints here.",
2936
+ "recipe": "kai-conversation-item::part(body) { outline-offset: 2px }"
2937
+ },
2938
+ {
2939
+ "name": "row",
2940
+ "doc": "The whole row surface. Carries `data-active` while selected.",
2941
+ "recipe": "kai-conversation-item::part(row) { border-radius: 0.5rem }"
2942
+ },
2943
+ {
2944
+ "name": "title",
2945
+ "doc": "The title line (the default slot renders inside it).",
2946
+ "recipe": "kai-conversation-item::part(title) { font-weight: 600 }"
2947
+ },
2948
+ {
2949
+ "name": "leading",
2950
+ "doc": "Leading region before the title (an icon or avatar)."
2951
+ },
2952
+ {
2953
+ "name": "meta",
2954
+ "doc": "Meta region under the title (a timestamp or status line)."
2955
+ },
2956
+ {
2957
+ "name": "menu",
2958
+ "doc": "Your own row menu (a popover trigger). Never selects the row."
2959
+ }
2960
+ ]
2961
+ },
2823
2962
  {
2824
2963
  "tag": "kai-conversations",
2825
2964
  "className": "KaiConversationsElement",
@@ -2849,15 +2988,15 @@
2849
2988
  },
2850
2989
  {
2851
2990
  "name": "conversations",
2852
- "type": "undefined | { id: string; title: string; groupId?: undefined | string; scope: { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: undefined | string }[]",
2991
+ "type": "undefined | { id: string; title: string; groupId?: undefined | string; scope?: undefined | { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt?: undefined | string; updatedAt: string; trailing?: undefined | string }[]",
2853
2992
  "optional": true,
2854
2993
  "scalar": false,
2855
- "description": "Every conversation the list renders, flat. Each one is filed under the group whose `id` equals its `groupId`; one with no `groupId`, or with a `groupId` matching no entry in `groups`, falls into a trailing \"Ungrouped\" section, so nothing you pass in is ever dropped. There is no recency bucketing. Set as a JS property. Omit to supply them as `<kai-conversation>` light-DOM children instead, or for the empty state.",
2994
+ "description": "Every conversation the list renders, flat. Each one is filed under the group whose `id` equals its `groupId`; one with no `groupId`, or with a `groupId` matching no entry in `groups`, falls into a trailing \"Ungrouped\" section, so nothing you pass in is ever dropped. There is no recency bucketing. Set as a JS property. Omit to supply them as `<kai-conversation>` light-DOM children instead, or for the empty state. A search query that matches nothing shows a visible \"No conversations match your search\" state, distinct from the zero-conversations empty state. Slotted `<kai-conversation-item>` children switch the list into item mode instead: your own rows win and this array is not rendered.",
2856
2995
  "typeName": "ConversationSummary[]",
2857
- "typeShape": "{ id: string; title: string; groupId?: undefined | string; scope: { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: undefined | string }[]",
2996
+ "typeShape": "{ id: string; title: string; groupId?: undefined | string; scope?: undefined | { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt?: undefined | string; updatedAt: string; trailing?: undefined | string }[]",
2858
2997
  "default": "[]",
2859
2998
  "typeImport": "ConversationSummary",
2860
- "displayType": "undefined | { id: string; title: string; groupId?: undefined | string; scope: { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: undefined | string }[]"
2999
+ "displayType": "undefined | { id: string; title: string; groupId?: undefined | string; scope?: undefined | { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt?: undefined | string; updatedAt: string; trailing?: undefined | string }[]"
2861
3000
  },
2862
3001
  {
2863
3002
  "name": "activeId",
@@ -2882,6 +3021,14 @@
2882
3021
  "scalar": true,
2883
3022
  "description": "Initial collapsed state when uncontrolled (default false). Use the `default-collapsed` attribute to start collapsed in plain HTML.",
2884
3023
  "displayType": "undefined | false | true"
3024
+ },
3025
+ {
3026
+ "name": "compact",
3027
+ "type": "undefined | false | true",
3028
+ "optional": true,
3029
+ "scalar": true,
3030
+ "description": "Dense single-line rows (a leading dot + title, no message count).",
3031
+ "displayType": "undefined | false | true"
2885
3032
  }
2886
3033
  ],
2887
3034
  "events": [
@@ -2894,7 +3041,7 @@
2894
3041
  {
2895
3042
  "name": "kai-conversation-select",
2896
3043
  "detail": "{ id: string }",
2897
- "description": "A conversation was selected.",
3044
+ "description": "A conversation was selected. The selection event in BOTH modes: a batteries data row, or an activated `<kai-conversation-item>` child (click, Enter or Space).",
2898
3045
  "displayDetail": "{ id: string }"
2899
3046
  },
2900
3047
  {
@@ -2978,10 +3125,15 @@
2978
3125
  "id"
2979
3126
  ],
2980
3127
  "text": true,
2981
- "description": "Parse a single light-DOM `<kai-conversation>` element into a `ConversationSummary`. Attribute mapping: - `id` → ConversationSummary.id - `group-id` → ConversationSummary.groupId (optional) - textContent → ConversationSummary.title Required fields not expressible as HTML attributes (`scope`, `messageCount`, `lastMessageAt`, `updatedAt`) receive safe defaults so the rendered list item is fully functional with just `id` + title text."
3128
+ "description": "Parse a single light-DOM `<kai-conversation>` element into a `ConversationSummary`. Attribute mapping: - `id` → ConversationSummary.id - `group-id` → ConversationSummary.groupId (optional) - textContent → ConversationSummary.title Fields not expressible as HTML attributes are NOT fabricated (F-10): the optional `scope` and `lastMessageAt` stay absent, and the required `messageCount`/`updatedAt` get honest defaults zero messages, and an empty `updatedAt` from which no trailing relative time is derived (the epoch it used to fabricate rendered a bogus \"many days ago\" on every declarative row)."
2982
3129
  }
2983
3130
  ],
2984
3131
  "slots": [
3132
+ {
3133
+ "name": "",
3134
+ "mode": "inject",
3135
+ "doc": "Your own `<kai-conversation-item>` rows (item mode: the consumer-owned loop). Data rows do not render while any are present."
3136
+ },
2985
3137
  {
2986
3138
  "name": "header",
2987
3139
  "mode": "replace",
@@ -3003,6 +3155,11 @@
3003
3155
  "name": "trailing",
3004
3156
  "doc": "The right-aligned trailing text on each conversation row (a count, status, or relative time). Set it per item via the `trailing` field; otherwise a short auto relative time is derived from `updatedAt`. Recolor or resize it from outside.",
3005
3157
  "recipe": "kai-conversations::part(trailing) { color: var(--color-primary); font-variant-numeric: tabular-nums }"
3158
+ },
3159
+ {
3160
+ "name": "items",
3161
+ "doc": "The item-mode listbox region wrapping your slotted `<kai-conversation-item>` children.",
3162
+ "recipe": "kai-conversations::part(items) { gap: 2px }"
3006
3163
  }
3007
3164
  ]
3008
3165
  },
@@ -3036,6 +3193,15 @@
3036
3193
  "scalar": true,
3037
3194
  "description": "Initial open state on mount (uncontrolled seed).",
3038
3195
  "displayType": "undefined | false | true"
3196
+ },
3197
+ {
3198
+ "name": "label",
3199
+ "type": "undefined | string",
3200
+ "optional": true,
3201
+ "scalar": true,
3202
+ "description": "Accessible name for the modal, used when no `header` slot is projected: `<kai-dialog label=\"Delete workspace\">`. A projected `header` WINS over this (it becomes `aria-labelledby`), because ARIA resolves `aria-labelledby` ahead of `aria-label` and the visible heading is the name both a sighted and a screen-reader user can be talked through. Defaults to `Dialog` so a modal is never nameless.",
3203
+ "default": "DEFAULT_LABEL",
3204
+ "displayType": "undefined | string"
3039
3205
  }
3040
3206
  ],
3041
3207
  "events": [
@@ -3126,9 +3292,9 @@
3126
3292
  ]
3127
3293
  },
3128
3294
  {
3129
- "tag": "kai-editable-label",
3130
- "className": "KaiEditableLabelElement",
3131
- "displayName": "EditableLabel",
3295
+ "tag": "kai-dock",
3296
+ "className": "KaiDockElement",
3297
+ "displayName": "Dock",
3132
3298
  "props": [
3133
3299
  {
3134
3300
  "name": "theme",
@@ -3141,95 +3307,418 @@
3141
3307
  "displayType": "\"light\" | \"dark\" | \"auto\""
3142
3308
  },
3143
3309
  {
3144
- "name": "value",
3145
- "type": "undefined | string",
3310
+ "name": "open",
3311
+ "type": "undefined | false | true",
3146
3312
  "optional": true,
3147
3313
  "scalar": true,
3148
- "description": "The label text. Settable and reflected to the `value` attribute. Read `el.value` for live state.",
3149
- "displayType": "undefined | string"
3314
+ "description": "Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute; the element still self-manages on the launcher and Escape). Set `el.open = true`, or `<kai-dock open>`; listen for `kai-open-change`.",
3315
+ "displayType": "undefined | false | true"
3150
3316
  },
3151
3317
  {
3152
- "name": "editing",
3318
+ "name": "defaultOpen",
3153
3319
  "type": "undefined | false | true",
3154
3320
  "optional": true,
3155
3321
  "scalar": true,
3156
- "description": "Controlled edit state. `el.editing = true` opens the field; reflected to the `editing` attribute.",
3157
- "default": "false",
3322
+ "description": "Initial open state on mount (uncontrolled seed).",
3158
3323
  "displayType": "undefined | false | true"
3159
3324
  },
3160
3325
  {
3161
- "name": "placeholder",
3326
+ "name": "position",
3327
+ "type": "undefined | \"bottom-end\" | \"bottom-start\" | \"top-end\" | \"top-start\"",
3328
+ "optional": true,
3329
+ "scalar": true,
3330
+ "description": "Which corner the dock sits in. Logical, so `-end` follows the writing direction and an RTL page docks on the left. Attribute: `position`.",
3331
+ "default": "'bottom-end'",
3332
+ "displayType": "undefined | \"bottom-end\" | \"bottom-start\" | \"top-end\" | \"top-start\""
3333
+ },
3334
+ {
3335
+ "name": "label",
3162
3336
  "type": "undefined | string",
3163
3337
  "optional": true,
3164
3338
  "scalar": true,
3165
- "description": "Placeholder shown while editing / when the value is empty.",
3339
+ "description": "The widget's NAME. Derives the panel's accessible name and both launcher names (`Open ${label}` / `Close ${label}`). Defaults to `Chat`.",
3340
+ "default": "'Chat'",
3341
+ "displayType": "undefined | string"
3342
+ },
3343
+ {
3344
+ "name": "openLabel",
3345
+ "type": "undefined | string",
3346
+ "optional": true,
3347
+ "scalar": true,
3348
+ "description": "i18n override for the launcher's name while closed (default `Open ${label}`).",
3349
+ "displayType": "undefined | string"
3350
+ },
3351
+ {
3352
+ "name": "closeLabel",
3353
+ "type": "undefined | string",
3354
+ "optional": true,
3355
+ "scalar": true,
3356
+ "description": "i18n override for the launcher's name while open (default `Close ${label}`).",
3166
3357
  "displayType": "undefined | string"
3167
3358
  },
3359
+ {
3360
+ "name": "unread",
3361
+ "type": "undefined | false | true",
3362
+ "optional": true,
3363
+ "scalar": true,
3364
+ "description": "Show the unread dot. YOURS: it renders only while closed, and the dock never writes it back. Clear it in your `kai-open-change` handler.",
3365
+ "displayType": "undefined | false | true"
3366
+ },
3168
3367
  {
3169
3368
  "name": "disabled",
3170
3369
  "type": "undefined | false | true",
3171
3370
  "optional": true,
3172
3371
  "scalar": true,
3173
- "description": "Disable entering edit mode.",
3174
- "default": "false",
3372
+ "description": "Disable the launcher; `show()` and `toggle()` are gated on it.",
3175
3373
  "displayType": "undefined | false | true"
3374
+ },
3375
+ {
3376
+ "name": "focusOnOpen",
3377
+ "type": "undefined | \"content\" | \"panel\" | \"none\"",
3378
+ "optional": true,
3379
+ "scalar": true,
3380
+ "description": "Where focus lands on open: `content` (default, the first element you slotted), `panel`, or `none`. Attribute: `focus-on-open`.",
3381
+ "default": "'content'",
3382
+ "displayType": "undefined | \"content\" | \"panel\" | \"none\""
3176
3383
  }
3177
3384
  ],
3178
3385
  "events": [
3179
3386
  {
3180
- "name": "kai-cancel",
3181
- "detail": "Record<string, never>",
3182
- "description": "Edit was cancelled (Esc); the text is restored.",
3183
- "displayDetail": "Record<string, never>"
3184
- },
3185
- {
3186
- "name": "kai-rename",
3187
- "detail": "{ value: string }",
3188
- "description": "Committed a changed value (Enter / blur).",
3189
- "displayDetail": "{ value: string }"
3387
+ "name": "kai-open-change",
3388
+ "detail": "{ open: false | true }",
3389
+ "description": "The dock opened or closed (the launcher, Escape, a driven `open`, or a method).",
3390
+ "displayDetail": "{ open: false | true }"
3190
3391
  }
3191
3392
  ],
3192
3393
  "methods": [
3193
3394
  {
3194
- "name": "edit",
3395
+ "name": "show",
3195
3396
  "params": "",
3196
3397
  "returns": "void",
3197
- "description": "Switch the label into its editing field, which autofocuses and selects the current text. Same entry point as a user double-click, and a no-op while `disabled`. Commit with `commit()` or by blurring, abandon with `cancel()` or Escape."
3398
+ "description": "Open it programmatically (no-op while disabled)."
3198
3399
  },
3199
3400
  {
3200
- "name": "commit",
3401
+ "name": "hide",
3201
3402
  "params": "",
3202
3403
  "returns": "void",
3203
- "description": "Close the field and keep what was typed, exactly as blurring it does. `kai-rename` fires only when the text actually changed, so committing an untouched field is silent. A no-op while the field is closed."
3404
+ "description": "Close it programmatically."
3204
3405
  },
3205
3406
  {
3206
- "name": "cancel",
3407
+ "name": "toggle",
3207
3408
  "params": "",
3208
3409
  "returns": "void",
3209
- "description": "Abandon the edit, exactly as Escape does: the original text is restored, the field closes and `kai-cancel` fires. `kai-rename` never fires, even if the field was edited. Also works when `editing` was set programmatically and the field has not rendered yet."
3410
+ "description": "Flip the open state (closes while disabled)."
3411
+ },
3412
+ {
3413
+ "name": "focus",
3414
+ "params": "options?: FocusOptions",
3415
+ "returns": "void",
3416
+ "description": "Move focus to the panel while open, or to the launcher while closed."
3210
3417
  }
3211
3418
  ],
3212
3419
  "composedFrom": [
3213
3420
  {
3214
- "name": "EditableLabel",
3421
+ "name": "Dock",
3215
3422
  "group": "UI",
3216
- "storyId": "solid-advanced-primitives-editablelabel--docs"
3423
+ "storyId": "solid-advanced-primitives-dock--docs"
3424
+ },
3425
+ {
3426
+ "name": "DockCloseGlyph",
3427
+ "group": "UI",
3428
+ "storyId": "solid-advanced-primitives-dockcloseglyph--docs"
3429
+ },
3430
+ {
3431
+ "name": "DockLauncherGlyph",
3432
+ "group": "UI",
3433
+ "storyId": "solid-advanced-primitives-docklauncherglyph--docs"
3217
3434
  }
3218
3435
  ],
3219
3436
  "tokens": [],
3220
- "parts": [
3437
+ "slots": [
3221
3438
  {
3222
- "name": "text",
3223
- "doc": "The read-mode label text. Restyle its typography; it swaps to the input on edit.",
3224
- "recipe": "kai-editable-label::part(text) { font-weight: 600 }"
3439
+ "name": "",
3440
+ "mode": "inject",
3441
+ "doc": "The panel body, the same region as `slot=\"panel\"`."
3225
3442
  },
3226
3443
  {
3227
- "name": "input",
3228
- "doc": "The edit-mode input (the composed kai-input field).",
3229
- "recipe": "kai-editable-label::part(input) { font: inherit }"
3444
+ "name": "panel",
3445
+ "mode": "replace",
3446
+ "part": true,
3447
+ "doc": "The panel body. ANY element: a `<kai-chat>`, a form, your own component. The dock never reads or types it, and the default slot is the same region."
3448
+ },
3449
+ {
3450
+ "name": "launcher",
3451
+ "mode": "inject",
3452
+ "doc": "Content inside the built-in button while CLOSED; defaults to a chat glyph. Text works as well as an icon: the button keeps its height and grows sideways into a pill, so a label like \"Support\" is not clipped. The BUTTON is never slotted away, because it owns aria-expanded, aria-controls, the toggle wiring and the focus return."
3453
+ },
3454
+ {
3455
+ "name": "launcher-open",
3456
+ "mode": "inject",
3457
+ "doc": "Content inside the button while OPEN; defaults to a ✕. Fill only `launcher` and that glyph stays while open rather than morphing into a built-in that clashes with it."
3230
3458
  }
3231
- ]
3232
- },
3459
+ ],
3460
+ "parts": [
3461
+ {
3462
+ "name": "launcher",
3463
+ "doc": "The launcher button pinned to the corner: a disc by default, a pill once you slot a text label. Restyle its surface or shadow; --kai-dock-launcher-size sets its height and its minimum width.",
3464
+ "recipe": "kai-dock::part(launcher) { background: var(--color-info) }"
3465
+ },
3466
+ {
3467
+ "name": "badge",
3468
+ "doc": "The unread dot on the launcher, rendered only while closed and only when `unread` is set. Restyle its color or size.",
3469
+ "recipe": "kai-dock::part(badge) { background: var(--color-success) }"
3470
+ },
3471
+ {
3472
+ "name": "panel",
3473
+ "doc": "The panel body. ANY element: a `<kai-chat>`, a form, your own component. The dock never reads or types it, and the default slot is the same region."
3474
+ }
3475
+ ]
3476
+ },
3477
+ {
3478
+ "tag": "kai-dropdown",
3479
+ "className": "KaiDropdownElement",
3480
+ "displayName": "Dropdown",
3481
+ "props": [
3482
+ {
3483
+ "name": "theme",
3484
+ "type": "\"light\" | \"dark\" | \"auto\"",
3485
+ "optional": true,
3486
+ "scalar": true,
3487
+ "description": "Color mode (`auto` follows prefers-color-scheme).",
3488
+ "default": "'auto'",
3489
+ "universal": true,
3490
+ "displayType": "\"light\" | \"dark\" | \"auto\""
3491
+ },
3492
+ {
3493
+ "name": "triggerIcon",
3494
+ "type": "undefined | string",
3495
+ "optional": true,
3496
+ "scalar": true,
3497
+ "description": "Built-in trigger: leading icon (a named icon like `\"plus\"`, an image URL/data-URI, or text). A slotted `slot=\"trigger\"` overrides it.",
3498
+ "displayType": "undefined | string"
3499
+ },
3500
+ {
3501
+ "name": "triggerLabel",
3502
+ "type": "undefined | string",
3503
+ "optional": true,
3504
+ "scalar": true,
3505
+ "description": "Built-in trigger: a text label. This is the trigger's VISIBLE text, so it is also its accessible name, and `label` does not override it: an accessible name that does not contain the visible text is unreachable by speech input (WCAG 2.5.3, Label in Name). Same rule `kai-menu` follows.",
3506
+ "displayType": "undefined | string"
3507
+ },
3508
+ {
3509
+ "name": "triggerIconTrailing",
3510
+ "type": "undefined | string",
3511
+ "optional": true,
3512
+ "scalar": true,
3513
+ "description": "Built-in trigger: a trailing icon (e.g. `\"chevron-down\"` for a select look).",
3514
+ "displayType": "undefined | string"
3515
+ },
3516
+ {
3517
+ "name": "label",
3518
+ "type": "undefined | string",
3519
+ "optional": true,
3520
+ "scalar": true,
3521
+ "description": "Accessible name for a trigger with no visible label. Ignored when `triggerLabel` is set, which is already the visible name. It DOES name a slotted `slot=\"trigger\"`, which is VISUAL content with the name supplied separately: the same two-slot distinction `kai-menu` documents.",
3522
+ "displayType": "undefined | string"
3523
+ },
3524
+ {
3525
+ "name": "full",
3526
+ "type": "undefined | false | true",
3527
+ "optional": true,
3528
+ "scalar": true,
3529
+ "description": "Stretch the trigger to the full width of its container (a block row). Attribute: `full`.",
3530
+ "default": "false",
3531
+ "displayType": "undefined | false | true"
3532
+ },
3533
+ {
3534
+ "name": "open",
3535
+ "type": "undefined | false | true",
3536
+ "optional": true,
3537
+ "scalar": true,
3538
+ "description": "Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute, the menu still self-manages on click/keyboard). Set `el.open = true`, or `<kai-dropdown open>`; listen for `kai-open-change`.",
3539
+ "displayType": "undefined | false | true"
3540
+ },
3541
+ {
3542
+ "name": "defaultOpen",
3543
+ "type": "undefined | false | true",
3544
+ "optional": true,
3545
+ "scalar": true,
3546
+ "description": "Initial open state on mount (uncontrolled seed).",
3547
+ "displayType": "undefined | false | true"
3548
+ },
3549
+ {
3550
+ "name": "disabled",
3551
+ "type": "undefined | false | true",
3552
+ "optional": true,
3553
+ "scalar": true,
3554
+ "description": "Disable the trigger: click/keyboard and `show()` no longer open the menu.",
3555
+ "displayType": "undefined | false | true"
3556
+ }
3557
+ ],
3558
+ "events": [
3559
+ {
3560
+ "name": "kai-open-change",
3561
+ "detail": "{ open: false | true }",
3562
+ "description": "The menu opened or closed (click, keyboard, Escape, outside-click, or a method).",
3563
+ "displayDetail": "{ open: false | true }"
3564
+ }
3565
+ ],
3566
+ "methods": [
3567
+ {
3568
+ "name": "show",
3569
+ "params": "",
3570
+ "returns": "void",
3571
+ "description": "Open it programmatically (no-op while disabled)."
3572
+ },
3573
+ {
3574
+ "name": "hide",
3575
+ "params": "",
3576
+ "returns": "void",
3577
+ "description": "Close it programmatically."
3578
+ },
3579
+ {
3580
+ "name": "toggle",
3581
+ "params": "",
3582
+ "returns": "void",
3583
+ "description": "Flip the open state (closes while disabled)."
3584
+ }
3585
+ ],
3586
+ "composedFrom": [
3587
+ {
3588
+ "name": "Dropdown",
3589
+ "group": "UI",
3590
+ "storyId": "solid-advanced-primitives-dropdown--docs"
3591
+ },
3592
+ {
3593
+ "name": "DropdownTrigger",
3594
+ "group": "UI",
3595
+ "storyId": "solid-advanced-primitives-dropdowntrigger--docs"
3596
+ },
3597
+ {
3598
+ "name": "DropdownContent",
3599
+ "group": "UI",
3600
+ "storyId": "solid-advanced-primitives-dropdowncontent--docs"
3601
+ }
3602
+ ],
3603
+ "tokens": [],
3604
+ "slots": [
3605
+ {
3606
+ "name": "",
3607
+ "mode": "inject",
3608
+ "doc": "The menu body: your own rows. Give each `role=\"menuitem\"`. The control that opens it is the `trigger` slot."
3609
+ },
3610
+ {
3611
+ "name": "trigger",
3612
+ "mode": "replace",
3613
+ "doc": "Visual content of the trigger button (an icon, text, an `<svg>`). Replaces the built-in trigger* content; name it with `label`."
3614
+ }
3615
+ ]
3616
+ },
3617
+ {
3618
+ "tag": "kai-editable-label",
3619
+ "className": "KaiEditableLabelElement",
3620
+ "displayName": "EditableLabel",
3621
+ "props": [
3622
+ {
3623
+ "name": "theme",
3624
+ "type": "\"light\" | \"dark\" | \"auto\"",
3625
+ "optional": true,
3626
+ "scalar": true,
3627
+ "description": "Color mode (`auto` follows prefers-color-scheme).",
3628
+ "default": "'auto'",
3629
+ "universal": true,
3630
+ "displayType": "\"light\" | \"dark\" | \"auto\""
3631
+ },
3632
+ {
3633
+ "name": "value",
3634
+ "type": "undefined | string",
3635
+ "optional": true,
3636
+ "scalar": true,
3637
+ "description": "The label text. Settable and reflected to the `value` attribute. Read `el.value` for live state.",
3638
+ "displayType": "undefined | string"
3639
+ },
3640
+ {
3641
+ "name": "editing",
3642
+ "type": "undefined | false | true",
3643
+ "optional": true,
3644
+ "scalar": true,
3645
+ "description": "Controlled edit state. `el.editing = true` opens the field; reflected to the `editing` attribute.",
3646
+ "default": "false",
3647
+ "displayType": "undefined | false | true"
3648
+ },
3649
+ {
3650
+ "name": "placeholder",
3651
+ "type": "undefined | string",
3652
+ "optional": true,
3653
+ "scalar": true,
3654
+ "description": "Placeholder shown while editing / when the value is empty.",
3655
+ "displayType": "undefined | string"
3656
+ },
3657
+ {
3658
+ "name": "disabled",
3659
+ "type": "undefined | false | true",
3660
+ "optional": true,
3661
+ "scalar": true,
3662
+ "description": "Disable entering edit mode.",
3663
+ "default": "false",
3664
+ "displayType": "undefined | false | true"
3665
+ }
3666
+ ],
3667
+ "events": [
3668
+ {
3669
+ "name": "kai-cancel",
3670
+ "detail": "Record<string, never>",
3671
+ "description": "Edit was cancelled (Esc); the text is restored.",
3672
+ "displayDetail": "Record<string, never>"
3673
+ },
3674
+ {
3675
+ "name": "kai-rename",
3676
+ "detail": "{ value: string }",
3677
+ "description": "Committed a changed value (Enter / blur).",
3678
+ "displayDetail": "{ value: string }"
3679
+ }
3680
+ ],
3681
+ "methods": [
3682
+ {
3683
+ "name": "edit",
3684
+ "params": "",
3685
+ "returns": "void",
3686
+ "description": "Switch the label into its editing field, which autofocuses and selects the current text. Same entry point as a user double-click, and a no-op while `disabled`. Commit with `commit()` or by blurring, abandon with `cancel()` or Escape."
3687
+ },
3688
+ {
3689
+ "name": "commit",
3690
+ "params": "",
3691
+ "returns": "void",
3692
+ "description": "Close the field and keep what was typed, exactly as blurring it does. `kai-rename` fires only when the text actually changed, so committing an untouched field is silent. A no-op while the field is closed."
3693
+ },
3694
+ {
3695
+ "name": "cancel",
3696
+ "params": "",
3697
+ "returns": "void",
3698
+ "description": "Abandon the edit, exactly as Escape does: the original text is restored, the field closes and `kai-cancel` fires. `kai-rename` never fires, even if the field was edited. Also works when `editing` was set programmatically and the field has not rendered yet."
3699
+ }
3700
+ ],
3701
+ "composedFrom": [
3702
+ {
3703
+ "name": "EditableLabel",
3704
+ "group": "UI",
3705
+ "storyId": "solid-advanced-primitives-editablelabel--docs"
3706
+ }
3707
+ ],
3708
+ "tokens": [],
3709
+ "parts": [
3710
+ {
3711
+ "name": "text",
3712
+ "doc": "The read-mode label text. Restyle its typography; it swaps to the input on edit.",
3713
+ "recipe": "kai-editable-label::part(text) { font-weight: 600 }"
3714
+ },
3715
+ {
3716
+ "name": "input",
3717
+ "doc": "The edit-mode input (the composed kai-input field).",
3718
+ "recipe": "kai-editable-label::part(input) { font: inherit }"
3719
+ }
3720
+ ]
3721
+ },
3233
3722
  {
3234
3723
  "tag": "kai-embed",
3235
3724
  "className": "KaiEmbedElement",
@@ -4502,6 +4991,15 @@
4502
4991
  "description": "Accessible name for a trigger with no visible label. Ignored when `triggerLabel` is set, which is already the visible name. It DOES name a slotted `slot=\"trigger\"`, and that is a difference in what the two slots MEAN, not a limitation. `<kai-button>`'s slot IS the button's label, so text slotted there is the name and `label` steps aside. This slot is VISUAL content, a `+` or an `<svg>`, with the name supplied separately: decoration beside a name, never a second name competing with one. So `label` names the trigger here by design. Slotting a real WORD rather than a glyph makes that word a visible label, and an accessible name has to contain the visible text. Then either drop `label` or make it contain the word you slotted.",
4503
4992
  "displayType": "undefined | string"
4504
4993
  },
4994
+ {
4995
+ "name": "full",
4996
+ "type": "undefined | false | true",
4997
+ "optional": true,
4998
+ "scalar": true,
4999
+ "description": "Stretch the trigger to the full width of the menu's container (a block row), e.g. a sidebar-footer account row. Same affordance as `<kai-button full>`. Attribute: `full`.",
5000
+ "default": "false",
5001
+ "displayType": "undefined | false | true"
5002
+ },
4505
5003
  {
4506
5004
  "name": "open",
4507
5005
  "type": "undefined | false | true",
@@ -4851,8 +5349,18 @@
4851
5349
  "recipe": "kai-message::part(citations) { gap: 0.5rem }"
4852
5350
  },
4853
5351
  {
4854
- "name": "avatar",
4855
- "doc": "Replaces the built-in avatar rail with your own node. Use `avatar=\"none\"` to omit the rail and let the body span the full row."
5352
+ "name": "attachment",
5353
+ "doc": "One attachment item: the chip, row or tile, whichever variant is rendering. Restyle its background, radius or border from outside without caring which layout it is.",
5354
+ "recipe": "kai-chat::part(attachment) { border-radius: 0.25rem }"
5355
+ },
5356
+ {
5357
+ "name": "attachment-name",
5358
+ "doc": "The attachment’s filename label. Present in every variant that shows one (a grid tile omits it for an image, which is its own label). Retune its type or hide it entirely.",
5359
+ "recipe": "kai-chat::part(attachment-name) { font-size: 0.75rem }"
5360
+ },
5361
+ {
5362
+ "name": "avatar",
5363
+ "doc": "Replaces the built-in avatar rail with your own node. Use `avatar=\"none\"` to omit the rail and let the body span the full row."
4856
5364
  }
4857
5365
  ]
4858
5366
  },
@@ -5781,11 +6289,11 @@
5781
6289
  "displayType": "undefined | \"submit\" | \"fill\""
5782
6290
  },
5783
6291
  {
5784
- "name": "search",
6292
+ "name": "webSearch",
5785
6293
  "type": "undefined | false | true",
5786
6294
  "optional": true,
5787
6295
  "scalar": true,
5788
- "description": "Show a Search (Globe) button in the left toolbar; clicking it fires a `search` event.",
6296
+ "description": "Show a web-search (Globe) button in the left toolbar; clicking it fires a `kai-web-search` event. Attribute: `web-search`.",
5789
6297
  "default": "false",
5790
6298
  "displayType": "undefined | false | true"
5791
6299
  },
@@ -5863,12 +6371,6 @@
5863
6371
  "description": "The staged attachments changed: a file was added (via the paperclip) or removed (per-chip ×). Carries the full current list so a consumer can react in real time (validate, show upload progress, toggle the send button).",
5864
6372
  "displayDetail": "{ attachments: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }"
5865
6373
  },
5866
- {
5867
- "name": "kai-search",
5868
- "detail": "Record<string, never>",
5869
- "description": "The Search (Globe) toolbar button was clicked.",
5870
- "displayDetail": "Record<string, never>"
5871
- },
5872
6374
  {
5873
6375
  "name": "kai-stop",
5874
6376
  "detail": "Record<string, never>",
@@ -5904,6 +6406,12 @@
5904
6406
  "detail": "Record<string, never>",
5905
6407
  "description": "The Voice (Mic) toolbar button was clicked.",
5906
6408
  "displayDetail": "Record<string, never>"
6409
+ },
6410
+ {
6411
+ "name": "kai-web-search",
6412
+ "detail": "Record<string, never>",
6413
+ "description": "The web-search (Globe) toolbar button was clicked.",
6414
+ "displayDetail": "Record<string, never>"
5907
6415
  }
5908
6416
  ],
5909
6417
  "methods": [
@@ -8667,6 +9175,12 @@
8667
9175
  "detail": "{ text: string }",
8668
9176
  "description": "Final transcript: the `transcribe` property resolved, OR native `SpeechRecognition` produced final text (no `transcribe` set).",
8669
9177
  "displayDetail": "{ text: string }"
9178
+ },
9179
+ {
9180
+ "name": "kai-voice-error",
9181
+ "detail": "{ source: \"recognition\"; error: string; message: string }",
9182
+ "description": "A voice session failed, so no failure is ever silent. `detail.source` names the failing side (`recognition` on `<kai-voice-input>`, `synthesis` on `<kai-voice-output>`), `detail.error` carries the platform error code, the thrown exception's name, or `no-result` when recognition ended with no error and no text (the user said nothing), and `detail.message` is human-readable. Deliberate cancellation does not fire.",
9183
+ "displayDetail": "{ source: \"recognition\"; error: string; message: string }"
8670
9184
  }
8671
9185
  ],
8672
9186
  "methods": [
@@ -8747,7 +9261,7 @@
8747
9261
  {
8748
9262
  "name": "kai-speaking-change",
8749
9263
  "detail": "{ speaking: false | true }",
8750
- "description": "Playback started or stopped. Drive your own UI in sync. Fires on real transitions only (manual click and programmatic speak()/stop()), never on mount.",
9264
+ "description": "Playback started or stopped. Drive your own UI in sync. `speaking: true` fires when audio actually starts (utterance.onstart natively; audio playback beginning on the `synthesize` path), not when speak() is called; earlier releases fired it optimistically inside speak() itself. Fires on real transitions only (manual click and programmatic speak()/stop()), never on mount.",
8751
9265
  "displayDetail": "{ speaking: false | true }"
8752
9266
  },
8753
9267
  {
@@ -8755,6 +9269,12 @@
8755
9269
  "detail": "{ blob: Blob }",
8756
9270
  "description": "The model path (`synthesize`) resolved audio: the raw `Blob` before playback.",
8757
9271
  "displayDetail": "{ blob: Blob }"
9272
+ },
9273
+ {
9274
+ "name": "kai-voice-error",
9275
+ "detail": "{ source: \"synthesis\"; error: string; message: string }",
9276
+ "description": "A voice session failed, so no failure is ever silent. `detail.source` names the failing side (`recognition` on `<kai-voice-input>`, `synthesis` on `<kai-voice-output>`), `detail.error` carries the platform error code, the thrown exception's name, or `no-result` when recognition ended with no error and no text (the user said nothing), and `detail.message` is human-readable. Deliberate cancellation does not fire.",
9277
+ "displayDetail": "{ source: \"synthesis\"; error: string; message: string }"
8758
9278
  }
8759
9279
  ],
8760
9280
  "methods": [
@@ -8815,252 +9335,51 @@
8815
9335
  "displayType": "\"light\" | \"dark\" | \"auto\""
8816
9336
  },
8817
9337
  {
8818
- "name": "groups",
8819
- "type": "undefined | { id: string; userId?: undefined | string; teamId?: undefined | string; name: string; sortOrder: number; createdAt: string }[]",
8820
- "optional": true,
8821
- "scalar": false,
8822
- "description": "The sidebar's section headers, rendered in array order. A group carries no conversations of its own; it is matched against `conversations` by id, so the two props are complementary rather than alternatives. Omit for an ungrouped sidebar. Set as a JS property.",
8823
- "typeName": "ConversationGroup[]",
8824
- "typeShape": "{ id: string; userId?: undefined | string; teamId?: undefined | string; name: string; sortOrder: number; createdAt: string }[]",
8825
- "default": "[]",
8826
- "typeImport": "ConversationGroup",
8827
- "displayType": "undefined | { id: string; userId?: undefined | string; teamId?: undefined | string; name: string; sortOrder: number; createdAt: string }[]"
8828
- },
8829
- {
8830
- "name": "conversations",
8831
- "type": "undefined | { id: string; title: string; groupId?: undefined | string; scope: { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: undefined | string }[]",
8832
- "optional": true,
8833
- "scalar": false,
8834
- "description": "Every conversation in the sidebar, flat. Each one is filed under the group whose `id` equals its `groupId`; one with no `groupId`, or with a `groupId` matching no entry in `groups`, falls into a trailing ungrouped section (headerless when `compact`), so nothing you pass in is ever dropped. There is no recency bucketing. Set as a JS property. Omit for an empty sidebar, or when `no-conversations` replaces the built-in list with your own `sidebar-header` content.",
8835
- "typeName": "ConversationSummary[]",
8836
- "typeShape": "{ id: string; title: string; groupId?: undefined | string; scope: { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: undefined | string }[]",
8837
- "default": "[]",
8838
- "typeImport": "ConversationSummary",
8839
- "displayType": "undefined | { id: string; title: string; groupId?: undefined | string; scope: { type: \"document\" | \"collection\"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | \"transcript\" | \"markdown\"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string; trailing?: undefined | string }[]"
8840
- },
8841
- {
8842
- "name": "activeId",
8843
- "type": "undefined | string",
8844
- "optional": true,
8845
- "scalar": true,
8846
- "description": "Id of the open conversation, highlighted in the sidebar.",
8847
- "displayType": "undefined | string"
8848
- },
8849
- {
8850
- "name": "messages",
8851
- "type": "undefined | { id: string; role: \"user\" | \"assistant\"; parts: ({ type: \"text\"; text: string; raw?: undefined | { source: string; payload: unknown } } | { type: \"reasoning\"; text: string; label?: undefined | string; index?: undefined | number; streamId?: undefined | string; signature?: undefined | string; raw?: undefined | { source: string; payload: unknown } } | { type: \"tool\"; tool: { type: string; kind?: undefined | \"command\" | \"file-change\" | \"search\" | \"fetch\" | \"mcp\" | \"image\" | \"generic\"; state: \"input-streaming\" | \"input-available\" | \"output-available\" | \"output-error\"; input?: undefined | Record<string, unknown>; rawInput?: undefined | string; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string; raw?: undefined | { source: string; payload: unknown } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"card\"; envelope: { type: string; id: string; data: unknown; title?: undefined | string; resolution?: undefined | { kind: \"action\"; action: string; payload?: unknown; at?: undefined | string } | { kind: \"submit\"; data: unknown; at?: undefined | string } | { kind: \"dismissed\"; at?: undefined | string } | { kind: \"expired\"; reason?: undefined | string; at?: undefined | string } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"source\"; source: { id?: undefined | string; url?: undefined | string; title?: undefined | string; snippet?: undefined | string; index?: undefined | number }; raw?: undefined | { source: string; payload: unknown } } | { type: \"file\"; attachment: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }; raw?: undefined | { source: string; payload: unknown } })[]; actions?: undefined | (\"copy\" | \"like\" | \"dislike\" | \"regenerate\" | \"edit\" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | \"like\" | \"dislike\" }[]",
8852
- "optional": true,
8853
- "scalar": false,
8854
- "description": "The active conversation's message thread, newest last. Set as a JS property (`el.messages = [...]`); a NEW array reference per streaming chunk re-renders (mutating in place does not). Omit for an empty thread.",
8855
- "typeName": "ChatMessage[]",
8856
- "typeShape": "{ id: string; role: \"user\" | \"assistant\"; parts: ({ type: \"text\"; text: string; raw?: undefined | { source: string; payload: unknown } } | { type: \"reasoning\"; text: string; label?: undefined | string; index?: undefined | number; streamId?: undefined | string; signature?: undefined | string; raw?: undefined | { source: string; payload: unknown } } | { type: \"tool\"; tool: { type: string; kind?: undefined | \"command\" | \"file-change\" | \"search\" | \"fetch\" | \"mcp\" | \"image\" | \"generic\"; state: \"input-streaming\" | \"input-available\" | \"output-available\" | \"output-error\"; input?: undefined | Record<string, unknown>; rawInput?: undefined | string; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string; raw?: undefined | { source: string; payload: unknown } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"card\"; envelope: { type: string; id: string; data: unknown; title?: undefined | string; resolution?: undefined | { kind: \"action\"; action: string; payload?: unknown; at?: undefined | string } | { kind: \"submit\"; data: unknown; at?: undefined | string } | { kind: \"dismissed\"; at?: undefined | string } | { kind: \"expired\"; reason?: undefined | string; at?: undefined | string } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"source\"; source: { id?: undefined | string; url?: undefined | string; title?: undefined | string; snippet?: undefined | string; index?: undefined | number }; raw?: undefined | { source: string; payload: unknown } } | { type: \"file\"; attachment: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }; raw?: undefined | { source: string; payload: unknown } })[]; actions?: undefined | (\"copy\" | \"like\" | \"dislike\" | \"regenerate\" | \"edit\" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | \"like\" | \"dislike\" }[]",
8857
- "default": "[]",
8858
- "typeImport": "ChatMessage",
8859
- "displayType": "undefined | { id: string; role: \"user\" | \"assistant\"; parts: ({ type: \"text\"; text: string; raw?: undefined | { source: string; payload: unknown } } | { type: \"reasoning\"; text: string; label?: undefined | string; index?: undefined | number; streamId?: undefined | string; signature?: undefined | string; raw?: undefined | { source: string; payload: unknown } } | { type: \"tool\"; tool: { type: string; kind?: undefined | \"command\" | \"file-change\" | \"search\" | \"fetch\" | \"mcp\" | \"image\" | \"generic\"; state: \"input-streaming\" | \"input-available\" | \"output-available\" | \"output-error\"; input?: undefined | Record<string, unknown>; rawInput?: undefined | string; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string; raw?: undefined | { source: string; payload: unknown } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"card\"; envelope: { type: string; id: string; data: unknown; title?: undefined | string; resolution?: undefined | { kind: \"action\"; action: string; payload?: unknown; at?: undefined | string } | { kind: \"submit\"; data: unknown; at?: undefined | string } | { kind: \"dismissed\"; at?: undefined | string } | { kind: \"expired\"; reason?: undefined | string; at?: undefined | string } }; raw?: undefined | { source: string; payload: unknown } } | { type: \"source\"; source: { id?: undefined | string; url?: undefined | string; title?: undefined | string; snippet?: undefined | string; index?: undefined | number }; raw?: undefined | { source: string; payload: unknown } } | { type: \"file\"; attachment: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }; raw?: undefined | { source: string; payload: unknown } })[]; actions?: undefined | (\"copy\" | \"like\" | \"dislike\" | \"regenerate\" | \"edit\" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string }; feedback?: undefined | \"like\" | \"dislike\" }[]"
8860
- },
8861
- {
8862
- "name": "value",
8863
- "type": "undefined | string",
8864
- "optional": true,
8865
- "scalar": true,
8866
- "description": "",
8867
- "displayType": "undefined | string"
8868
- },
8869
- {
8870
- "name": "placeholder",
8871
- "type": "undefined | string",
8872
- "optional": true,
8873
- "scalar": true,
8874
- "description": "",
8875
- "default": "'Send a message...'",
8876
- "displayType": "undefined | string"
8877
- },
8878
- {
8879
- "name": "loading",
9338
+ "name": "startCollapsed",
8880
9339
  "type": "undefined | false | true",
8881
9340
  "optional": true,
8882
9341
  "scalar": true,
8883
- "description": "",
8884
- "default": "false",
9342
+ "description": "Controlled collapsed state of the start aside. Set this as a JS property (`el.startCollapsed = true`) to drive the aside from your app, updating it in response to the `kai-aside-toggle` event. Omit for uncontrolled (the element manages it).",
8885
9343
  "displayType": "undefined | false | true"
8886
9344
  },
8887
9345
  {
8888
- "name": "suggestions",
8889
- "type": "undefined | string[]",
8890
- "optional": true,
8891
- "scalar": false,
8892
- "description": "",
8893
- "displayType": "undefined | string[]"
8894
- },
8895
- {
8896
- "name": "suggestionMode",
8897
- "type": "undefined | \"submit\" | \"fill\"",
8898
- "optional": true,
8899
- "scalar": true,
8900
- "description": "",
8901
- "default": "'submit'",
8902
- "displayType": "undefined | \"submit\" | \"fill\""
8903
- },
8904
- {
8905
- "name": "proseSize",
8906
- "type": "undefined | \"xs\" | \"sm\" | \"base\" | \"lg\"",
8907
- "optional": true,
8908
- "scalar": true,
8909
- "description": "",
8910
- "default": "'sm'",
8911
- "displayType": "undefined | \"xs\" | \"sm\" | \"base\" | \"lg\""
8912
- },
8913
- {
8914
- "name": "codeTheme",
8915
- "type": "undefined | string",
8916
- "optional": true,
8917
- "scalar": true,
8918
- "description": "",
8919
- "default": "'github-dark-dimmed'",
8920
- "displayType": "undefined | string"
8921
- },
8922
- {
8923
- "name": "codeHighlight",
9346
+ "name": "defaultStartCollapsed",
8924
9347
  "type": "undefined | false | true",
8925
9348
  "optional": true,
8926
9349
  "scalar": true,
8927
- "description": "",
8928
- "default": "true",
9350
+ "description": "Initial collapsed state of the start aside when uncontrolled (default false). Use the `default-start-collapsed` attribute to start collapsed in plain HTML.",
8929
9351
  "displayType": "undefined | false | true"
8930
9352
  },
8931
9353
  {
8932
- "name": "chatTitle",
8933
- "type": "undefined | string",
8934
- "optional": true,
8935
- "scalar": true,
8936
- "description": "",
8937
- "displayType": "undefined | string"
8938
- },
8939
- {
8940
- "name": "models",
8941
- "type": "undefined | { id: string; name: string; provider?: undefined | string; description?: undefined | string; group?: undefined | string }[]",
8942
- "optional": true,
8943
- "scalar": false,
8944
- "description": "",
8945
- "typeName": "ModelOption[]",
8946
- "typeShape": "{ id: string; name: string; provider?: undefined | string; description?: undefined | string; group?: undefined | string }[]",
8947
- "typeImport": "ModelOption",
8948
- "displayType": "undefined | { id: string; name: string; provider?: undefined | string; description?: undefined | string; group?: undefined | string }[]"
8949
- },
8950
- {
8951
- "name": "currentModel",
8952
- "type": "undefined | string",
8953
- "optional": true,
8954
- "scalar": true,
8955
- "description": "",
8956
- "displayType": "undefined | string"
8957
- },
8958
- {
8959
- "name": "context",
8960
- "type": "undefined | { usedTokens: number; maxTokens: number; inputTokens?: undefined | number; outputTokens?: undefined | number; estimatedCost?: undefined | number }",
8961
- "optional": true,
8962
- "scalar": false,
8963
- "description": "",
8964
- "typeName": "ChatThreadContextUsage",
8965
- "typeShape": "{ usedTokens: number; maxTokens: number; inputTokens?: undefined | number; outputTokens?: undefined | number; estimatedCost?: undefined | number }",
8966
- "typeImport": "ChatThreadContextUsage",
8967
- "displayType": "ContextData | undefined"
8968
- },
8969
- {
8970
- "name": "scrollButton",
8971
- "type": "undefined | false | true",
8972
- "optional": true,
8973
- "scalar": true,
8974
- "description": "",
8975
- "default": "true",
8976
- "displayType": "undefined | false | true"
8977
- },
8978
- {
8979
- "name": "search",
9354
+ "name": "endCollapsed",
8980
9355
  "type": "undefined | false | true",
8981
9356
  "optional": true,
8982
9357
  "scalar": true,
8983
- "description": "",
8984
- "default": "false",
9358
+ "description": "Controlled collapsed state of the end aside. Set this as a JS property (`el.endCollapsed = true`) to drive the aside from your app, updating it in response to the `kai-aside-toggle` event. Omit for uncontrolled (the element manages it).",
8985
9359
  "displayType": "undefined | false | true"
8986
9360
  },
8987
9361
  {
8988
- "name": "voice",
9362
+ "name": "defaultEndCollapsed",
8989
9363
  "type": "undefined | false | true",
8990
9364
  "optional": true,
8991
9365
  "scalar": true,
8992
- "description": "",
8993
- "default": "false",
9366
+ "description": "Initial collapsed state of the end aside when uncontrolled (default false). Use the `default-end-collapsed` attribute to start collapsed in plain HTML.",
8994
9367
  "displayType": "undefined | false | true"
8995
9368
  },
8996
9369
  {
8997
- "name": "triggers",
8998
- "type": "undefined | { char: string; kind: string; items?: undefined | { id: string; label: string; icon?: undefined | string; description?: undefined | string; group?: undefined | string; kind?: undefined | string; promptText?: undefined | string; data?: undefined | Record<string, unknown> }[] }[]",
8999
- "optional": true,
9000
- "scalar": false,
9001
- "description": "Rich entity triggers (`/` skills, `@` agents/plugins) forwarded to the input.",
9002
- "typeName": "TriggerDef[]",
9003
- "typeShape": "{ char: string; kind: string; items?: undefined | { id: string; label: string; icon?: undefined | string; description?: undefined | string; group?: undefined | string; kind?: undefined | string; promptText?: undefined | string; data?: undefined | Record<string, unknown> }[] }[]",
9004
- "typeImport": "TriggerDef",
9005
- "displayType": "undefined | { char: string; kind: string; items?: undefined | { id: string; label: string; icon?: undefined | string; description?: undefined | string; group?: undefined | string; kind?: undefined | string; promptText?: undefined | string; data?: undefined | Record<string, unknown> }[] }[]"
9006
- },
9007
- {
9008
- "name": "kindIcons",
9009
- "type": "undefined | Record<string, string>",
9010
- "optional": true,
9011
- "scalar": false,
9012
- "description": "Default icon per entity kind (kind → image src) forwarded to the input.",
9013
- "displayType": "undefined | Record<string, string>"
9014
- },
9015
- {
9016
- "name": "sidebarWidth",
9017
- "type": "undefined | number",
9018
- "optional": true,
9019
- "scalar": true,
9020
- "description": "Sidebar default width as a percent of the workspace (default 26).",
9021
- "default": "26",
9022
- "displayType": "undefined | number"
9023
- },
9024
- {
9025
- "name": "sidebarMinWidth",
9370
+ "name": "collapseBelow",
9026
9371
  "type": "undefined | number",
9027
9372
  "optional": true,
9028
9373
  "scalar": true,
9029
- "description": "Sidebar min width in px (default 240).",
9030
- "default": "240",
9374
+ "description": "Auto-collapse both asides when the shell's own width drops below this many px, and re-expand when it grows back above. Applies to uncontrolled asides only (it never fights an app-driven collapsed prop); omit to disable. Fires `kai-aside-toggle`. Attribute: `collapse-below`.",
9031
9375
  "displayType": "undefined | number"
9032
9376
  },
9033
9377
  {
9034
- "name": "sidebarMaxWidth",
9378
+ "name": "drawerBelow",
9035
9379
  "type": "undefined | number",
9036
9380
  "optional": true,
9037
9381
  "scalar": true,
9038
- "description": "Sidebar max width in px (default 420).",
9039
- "default": "420",
9040
- "displayType": "undefined | number"
9041
- },
9042
- {
9043
- "name": "sidebarCollapsed",
9044
- "type": "undefined | false | true",
9045
- "optional": true,
9046
- "scalar": true,
9047
- "description": "Controlled collapsed state. Set this as a JS property (`el.sidebarCollapsed = true`) to drive the sidebar from your app, updating it in response to the `kai-sidebar-toggle` event. Omit for uncontrolled (the element manages it).",
9048
- "displayType": "undefined | false | true"
9049
- },
9050
- {
9051
- "name": "defaultSidebarCollapsed",
9052
- "type": "undefined | false | true",
9053
- "optional": true,
9054
- "scalar": true,
9055
- "description": "Initial collapsed state when uncontrolled (default false). Use the `default-sidebar-collapsed` attribute to start collapsed in plain HTML.",
9056
- "displayType": "undefined | false | true"
9057
- },
9058
- {
9059
- "name": "collapseBelow",
9060
- "type": "undefined | number",
9061
- "optional": true,
9062
- "scalar": true,
9063
- "description": "Auto-collapse the rail when the workspace's own width drops below this many px, and re-expand when it grows back above. Uncontrolled only (it never fights an app-driven `sidebarCollapsed`); omit to disable. Fires `kai-sidebar-toggle`. Attribute: `collapse-below`.",
9382
+ "description": "Below this shell width in px, an expanded aside renders as an overlay drawer over the main region instead of a column beside it. Escape inside the drawer closes it and returns focus to the element focused before it opened. Omit to disable. Attribute: `drawer-below`.",
9064
9383
  "displayType": "undefined | number"
9065
9384
  },
9066
9385
  {
@@ -9068,200 +9387,114 @@
9068
9387
  "type": "undefined | false | true",
9069
9388
  "optional": true,
9070
9389
  "scalar": true,
9071
- "description": "Render Recents as dense single-line rows (a leading dot + title, no count).",
9072
- "displayType": "undefined | false | true"
9073
- },
9074
- {
9075
- "name": "noConversations",
9076
- "type": "undefined | false | true",
9077
- "optional": true,
9078
- "scalar": true,
9079
- "description": "Suppress the built-in ConversationList so the `sidebar-header` slot owns the whole rail flex region (for apps that supply their own rail nav). Default false. Attribute: `no-conversations`.",
9390
+ "description": "Density hint. Reflected as a `data-compact` hook on the root (and as the `compact` attribute on the element) for your CSS and slotted content; the shell itself keeps no other opinion about density.",
9080
9391
  "displayType": "undefined | false | true"
9081
- },
9082
- {
9083
- "name": "cardTypes",
9084
- "type": "undefined | Record<string, string>",
9085
- "optional": true,
9086
- "scalar": false,
9087
- "description": "Optional card type -> custom-element tag overrides/additions for `card` parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type.",
9088
- "displayType": "undefined | Record<string, string>"
9089
- },
9090
- {
9091
- "name": "cardSchemas",
9092
- "type": "undefined | Record<string, object>",
9093
- "optional": true,
9094
- "scalar": false,
9095
- "description": "JSON Schemas for the card types this app renders, keyed by envelope type. The companion of `cardTypes`, which says what DRAWS a card while this says what a VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas = { 'pricing-table': pricingSchema }`, never an attribute. `createCardRegistry(...).validationSchemas` is exactly this shape. Without it the kit validates its own seven built-ins and leaves your own card type, the one your app actually cares about, as the only unchecked thing on screen. A schema here WINS over a built-in of the same name. Typed `Record<string, object>` rather than `Record<string, JsonSchema>` deliberately: an imported `.json` schema widens `\"type\"` to `string`, and an authored one carries `$schema`/`title`/`description`/`additionalProperties`, so the tighter type would reject both of the normal ways to supply one.",
9096
- "displayType": "undefined | Record<string, object>"
9097
9392
  }
9098
9393
  ],
9099
9394
  "events": [
9100
9395
  {
9101
- "name": "kai-conversation-select",
9102
- "detail": "{ id: string }",
9103
- "description": "A conversation was selected in the sidebar.",
9104
- "displayDetail": "{ id: string }"
9105
- },
9106
- {
9107
- "name": "kai-message-action",
9108
- "detail": "{ messageId: string; action: string; state?: undefined | \"on\" | \"off\" }",
9109
- "description": "An action button on a message was clicked. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear.",
9110
- "displayDetail": "{ messageId: string; action: string; state?: undefined | \"on\" | \"off\" }"
9111
- },
9112
- {
9113
- "name": "kai-model-change",
9114
- "detail": "{ modelId: string }",
9115
- "description": "The header model switcher changed.",
9116
- "displayDetail": "{ modelId: string }"
9117
- },
9118
- {
9119
- "name": "kai-new-chat",
9120
- "detail": "Record<string, never>",
9121
- "description": "The \"New chat\" button was clicked.",
9122
- "displayDetail": "Record<string, never>"
9123
- },
9124
- {
9125
- "name": "kai-search",
9126
- "detail": "Record<string, never>",
9127
- "description": "The Search button was clicked.",
9128
- "displayDetail": "Record<string, never>"
9129
- },
9130
- {
9131
- "name": "kai-sidebar-toggle",
9132
- "detail": "{ collapsed: false | true }",
9133
- "description": "The sidebar was collapsed or expanded.",
9134
- "displayDetail": "{ collapsed: false | true }"
9135
- },
9136
- {
9137
- "name": "kai-submit",
9138
- "detail": "{ value: string; attachments: { id: string; type: \"file\" | \"source-document\"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }",
9139
- "description": "User submitted a message.",
9140
- "displayDetail": "{ value: string; attachments: AttachmentData[] }"
9141
- },
9142
- {
9143
- "name": "kai-suggestion-click",
9144
- "detail": "{ value: string }",
9145
- "description": "A suggestion chip was clicked (only in `suggestion-mode=\"fill\"`).",
9146
- "displayDetail": "{ value: string }"
9147
- },
9148
- {
9149
- "name": "kai-value-change",
9150
- "detail": "{ value: string }",
9151
- "description": "Fired on every input change.",
9152
- "displayDetail": "{ value: string }"
9396
+ "name": "kai-aside-resize",
9397
+ "detail": "{ side: \"start\" | \"end\"; width: number }",
9398
+ "description": "The aside was resized (fires per drag step, keyboard nudge, or a handle double-click reset), width in px.",
9399
+ "displayDetail": "{ side: \"start\" | \"end\"; width: number }"
9153
9400
  },
9154
9401
  {
9155
- "name": "kai-voice",
9156
- "detail": "Record<string, never>",
9157
- "description": "The Mic / voice button was clicked.",
9158
- "displayDetail": "Record<string, never>"
9402
+ "name": "kai-aside-toggle",
9403
+ "detail": "{ side: \"start\" | \"end\"; collapsed: false | true }",
9404
+ "description": "An aside collapsed or expanded (a method, the breakpoint, the drawer's Escape).",
9405
+ "displayDetail": "{ side: \"start\" | \"end\"; collapsed: false | true }"
9159
9406
  }
9160
9407
  ],
9161
9408
  "methods": [
9162
9409
  {
9163
- "name": "toggleSidebar",
9164
- "params": "",
9410
+ "name": "toggleAside",
9411
+ "params": "side: WorkspaceAsideSide",
9165
9412
  "returns": "void",
9166
- "description": "Collapse/expand the conversation sidebar and fire `kai-sidebar-toggle`."
9413
+ "description": "Collapse/expand one aside (fires `kai-aside-toggle`)."
9167
9414
  },
9168
9415
  {
9169
- "name": "collapseSidebar",
9170
- "params": "",
9416
+ "name": "collapseAside",
9417
+ "params": "side: WorkspaceAsideSide",
9171
9418
  "returns": "void",
9172
- "description": "Force the conversation sidebar collapsed (fires `kai-sidebar-toggle`)."
9419
+ "description": "Force one aside collapsed (fires `kai-aside-toggle`)."
9173
9420
  },
9174
9421
  {
9175
- "name": "expandSidebar",
9176
- "params": "",
9177
- "returns": "void",
9178
- "description": "Force the conversation sidebar expanded (fires `kai-sidebar-toggle`)."
9179
- },
9180
- {
9181
- "name": "focus",
9182
- "params": "options?: FocusOptions",
9422
+ "name": "expandAside",
9423
+ "params": "side: WorkspaceAsideSide",
9183
9424
  "returns": "void",
9184
- "description": "Focus the thread's composer."
9185
- },
9186
- {
9187
- "name": "clear",
9188
- "params": "",
9189
- "returns": "void",
9190
- "description": "Clear the thread draft + staged attachments."
9191
- },
9192
- {
9193
- "name": "send",
9194
- "params": "",
9195
- "returns": "void",
9196
- "description": "Submit the current thread draft programmatically (fires `kai-submit`)."
9197
- },
9198
- {
9199
- "name": "scrollToBottom",
9200
- "params": "behavior?: ScrollBehavior",
9201
- "returns": "void",
9202
- "description": "Scroll the thread to the newest message."
9425
+ "description": "Force one aside expanded (fires `kai-aside-toggle`)."
9203
9426
  }
9204
9427
  ],
9205
9428
  "composedFrom": [
9206
9429
  {
9207
- "name": "ChatThread",
9430
+ "name": "WorkspaceShell",
9208
9431
  "group": "Components",
9209
- "storyId": "solid-advanced-elements-chatthread--docs"
9432
+ "storyId": "solid-advanced-elements-workspaceshell--docs"
9433
+ }
9434
+ ],
9435
+ "tokens": [],
9436
+ "slots": [
9437
+ {
9438
+ "name": "",
9439
+ "mode": "inject",
9440
+ "doc": "The main region content (same region as the `main` slot): your `<kai-chat>`, or any app view."
9210
9441
  },
9211
9442
  {
9212
- "name": "ConversationList",
9213
- "group": "Components",
9214
- "storyId": "solid-advanced-elements-conversationlist--docs"
9443
+ "name": "header",
9444
+ "mode": "inject",
9445
+ "part": true,
9446
+ "doc": "The top band across the full shell width (app bar, tabs, breadcrumbs)."
9215
9447
  },
9216
9448
  {
9217
- "name": "CollapsedRail",
9218
- "group": "Components",
9219
- "storyId": "solid-advanced-elements-collapsedrail--docs"
9449
+ "name": "start",
9450
+ "mode": "inject",
9451
+ "part": true,
9452
+ "doc": "The inline-start aside column (a conversation rail, a nav, a file tree). Resizable and collapsible."
9220
9453
  },
9221
9454
  {
9222
- "name": "ResizablePanelGroup",
9223
- "group": "UI",
9224
- "storyId": "solid-advanced-primitives-resizablepanelgroup--docs"
9455
+ "name": "main",
9456
+ "mode": "inject",
9457
+ "part": true,
9458
+ "doc": "The main region. Unnamed children project here too, via the default slot."
9225
9459
  },
9226
9460
  {
9227
- "name": "ResizablePanel",
9228
- "group": "UI",
9229
- "storyId": "solid-advanced-primitives-resizablepanel--docs"
9461
+ "name": "end",
9462
+ "mode": "inject",
9463
+ "part": true,
9464
+ "doc": "The inline-end aside column (inspector, notes, preview). Resizable and collapsible."
9230
9465
  },
9231
9466
  {
9232
- "name": "ResizableHandle",
9233
- "group": "UI",
9234
- "storyId": "solid-advanced-primitives-resizablehandle--docs"
9467
+ "name": "footer",
9468
+ "mode": "inject",
9469
+ "part": true,
9470
+ "doc": "The bottom band across the full shell width (status bar, disclaimers)."
9235
9471
  }
9236
9472
  ],
9237
- "tokens": [],
9238
- "slots": [
9473
+ "parts": [
9239
9474
  {
9240
- "name": "sidebar-header",
9241
- "mode": "inject",
9242
- "doc": "Top of the conversation rail (brand, a kai-tabs strip)."
9475
+ "name": "aside",
9476
+ "doc": "Both aside columns match this part (each also matches its own start/end part). Restyle the shared aside surface or border from outside; the --kai-workspace-start-* and --kai-workspace-end-* custom properties set the widths.",
9477
+ "recipe": "kai-workspace::part(aside) { background: var(--color-card) }"
9243
9478
  },
9244
9479
  {
9245
- "name": "sidebar-footer",
9246
- "mode": "inject",
9247
- "doc": "Bottom of the rail: an upgrade card, a Design trigger, a user-menu cluster."
9480
+ "name": "header",
9481
+ "doc": "The top band across the full shell width (app bar, tabs, breadcrumbs)."
9248
9482
  },
9249
9483
  {
9250
- "name": "main-header",
9251
- "mode": "inject",
9252
- "doc": "Top of the main region (a top-placed banner or a corner action)."
9484
+ "name": "start",
9485
+ "doc": "The inline-start aside column (a conversation rail, a nav, a file tree). Resizable and collapsible."
9253
9486
  },
9254
9487
  {
9255
9488
  "name": "main",
9256
- "mode": "replace",
9257
- "doc": "Replace the built-in chat thread with your own main view (a home or dashboard screen). Omit to keep the thread."
9258
- }
9259
- ],
9260
- "parts": [
9489
+ "doc": "The main region. Unnamed children project here too, via the default slot."
9490
+ },
9261
9491
  {
9262
- "name": "sidebar",
9263
- "doc": "The conversation rail. Carries a subtle, theme-aware default background (bg-surface); override its background, border, or width from outside. `sidebar-min-width` sets its min px width and `collapse-below` auto-collapses it under a width.",
9264
- "recipe": "kai-workspace::part(sidebar) { background: var(--color-card); border-right: 1px solid var(--color-border) }"
9492
+ "name": "end",
9493
+ "doc": "The inline-end aside column (inspector, notes, preview). Resizable and collapsible."
9494
+ },
9495
+ {
9496
+ "name": "footer",
9497
+ "doc": "The bottom band across the full shell width (status bar, disclaimers)."
9265
9498
  }
9266
9499
  ]
9267
9500
  }