@kitn.ai/ui 0.27.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (612) hide show
  1. package/README.md +10 -2
  2. package/dist/{Icon-BnFKqqtY.js → Icon-DObhsRtm.js} +1 -1
  3. package/dist/{action-icons-CBskfBMz.js → action-icons-CcgNN2oT.js} +1 -1
  4. package/dist/agent-tooling/construct/public.d.ts +15 -0
  5. package/dist/agent-tooling/construct/schema.d.ts +111 -0
  6. package/dist/arrow-down-CjRU3JgV.js +1 -0
  7. package/dist/arrow-left-Bnpb1UEW.js +1 -0
  8. package/dist/{artifact-CvXEm1lS.js → artifact-Bwt7OgcR.js} +1 -1
  9. package/dist/{attachments-C43ZegEq.js → attachments-Qr4kg-2b.js} +1 -1
  10. package/dist/{audio-visualizer-B-79y1Tj.js → audio-visualizer-DToYdfSc.js} +1 -1
  11. package/dist/{badge-BpUbq8c0.js → badge-CdEu_jn2.js} +1 -1
  12. package/dist/{bell-sn17Ip9v.js → bell-DQAAOpDz.js} +1 -1
  13. package/dist/{button-BH6rN0U-.js → button-DkuOnGLy.js} +1 -1
  14. package/dist/{card-renderer-Cb1gQmth.js → card-renderer-Jx70m6_l.js} +1 -1
  15. package/dist/{card-routing-DifQgS7n.js → card-routing-0YidER_3.js} +1 -1
  16. package/dist/check-njkVdZu2.js +1 -0
  17. package/dist/{checkbox-Dc9Yov_B.js → checkbox-D7iRB3nL.js} +1 -1
  18. package/dist/{checkbox-group-B1kDLLYk.js → checkbox-group-B2_rpoPM.js} +1 -1
  19. package/dist/chevron-down-B72s6PXR.js +1 -0
  20. package/dist/chevron-right-BatuHzUm.js +1 -0
  21. package/dist/{choice-card-BT3c1S8g.js → choice-card-m0BYqqOK.js} +1 -1
  22. package/dist/circle-check-B62pODB3.js +1 -0
  23. package/dist/{circle-x-wobWkoSx.js → circle-x-BPG0iPst.js} +1 -1
  24. package/dist/circle-zx0ByzY9.js +1 -0
  25. package/dist/code-block-ClMLKb7C.js +1 -0
  26. package/dist/{collapsible-CPJbf6FM.js → collapsible-B4DlWicL.js} +1 -1
  27. package/dist/components/chat-thread.d.ts +89 -1
  28. package/dist/components/conversation-item.d.ts +16 -0
  29. package/dist/components/conversation-panel.d.ts +29 -0
  30. package/dist/components/home-panel.d.ts +34 -0
  31. package/dist/components/widget-tab-bar.d.ts +16 -0
  32. package/dist/{composer-CjngLzal.js → composer-sQ0HcvyG.js} +3 -3
  33. package/dist/{confirm-card-DCx_A4bU.js → confirm-card-rQWDQsnC.js} +1 -1
  34. package/dist/construct-cli.es.js +185 -17
  35. package/dist/construct.d.ts +5 -0
  36. package/dist/construct.js +327 -0
  37. package/dist/{context-BY8V-Nlp.js → context-0kg4ZX1J.js} +1 -1
  38. package/dist/controllable-CnGpMF6r.js +1 -0
  39. package/dist/conversation-item-BxwQLaFJ.js +1 -0
  40. package/dist/conversation-list-BCfGN1JU.js +1 -0
  41. package/dist/{copy-B6DO4PqB.js → copy-n9u9rqpi.js} +1 -1
  42. package/dist/core-C8fzo39E.js +1 -12
  43. package/dist/{create-tween-CnMHviKB.js → create-tween-C-q-JCM-.js} +1 -1
  44. package/dist/{create-tween-D1aiGZZh.js → create-tween-CRrJXxBd.js} +1 -1
  45. package/dist/{create-tween-BPzaefTp.js → create-tween-DZ3RRDHD.js} +1 -1
  46. package/dist/{create-tween-DUSQUKpr.js → create-tween-uPkArjIG.js} +1 -1
  47. package/dist/custom-elements.json +51 -2
  48. package/dist/{default-input-CucQEOqH.js → default-input-CaMrJkgH.js} +1 -1
  49. package/dist/define-By-uL588.js +1 -0
  50. package/dist/define.js +2 -2
  51. package/dist/define.server.js +2 -2
  52. package/dist/{disclosure-CbLtajUQ.js → disclosure-WUImBbDv.js} +1 -1
  53. package/dist/{dropdown-BwhViJFd.js → dropdown-wZVeJOMd.js} +1 -1
  54. package/dist/elements/agent-card.js +1 -1
  55. package/dist/elements/artifact.js +1 -1
  56. package/dist/elements/attachments.js +1 -1
  57. package/dist/elements/audio-visualizer.js +1 -1
  58. package/dist/elements/avatar.js +1 -1
  59. package/dist/elements/badge.js +1 -1
  60. package/dist/elements/button.js +1 -1
  61. package/dist/elements/card.js +1 -1
  62. package/dist/elements/cards.js +1 -1
  63. package/dist/elements/chain-of-thought.js +1 -1
  64. package/dist/elements/chat-scope-picker.js +1 -1
  65. package/dist/elements/chat-workspace.js +1 -1
  66. package/dist/elements/chat.js +1 -1
  67. package/dist/elements/checkbox-group.js +1 -1
  68. package/dist/elements/checkbox.js +1 -1
  69. package/dist/elements/checkpoint.js +1 -1
  70. package/dist/elements/choice.js +1 -1
  71. package/dist/elements/coachmark.js +1 -1
  72. package/dist/elements/code-block.js +1 -1
  73. package/dist/elements/command.js +1 -1
  74. package/dist/elements/compare.js +1 -1
  75. package/dist/elements/composer.js +1 -1
  76. package/dist/elements/confirm-card.js +1 -1
  77. package/dist/elements/context-meter.js +1 -1
  78. package/dist/elements/conversation-item.js +1 -1
  79. package/dist/elements/conversation-list.js +1 -1
  80. package/dist/elements/dialog.js +1 -1
  81. package/dist/elements/dock.js +3 -3
  82. package/dist/elements/dropdown.js +1 -1
  83. package/dist/elements/editable-label.js +1 -1
  84. package/dist/elements/embed.js +1 -1
  85. package/dist/elements/empty.js +1 -1
  86. package/dist/elements/feedback-bar.js +1 -1
  87. package/dist/elements/file-tree.js +1 -1
  88. package/dist/elements/file-upload.js +1 -1
  89. package/dist/elements/form.js +1 -1
  90. package/dist/elements/hover-card.js +1 -1
  91. package/dist/elements/icon.js +1 -1
  92. package/dist/elements/image.js +1 -1
  93. package/dist/elements/input.js +1 -1
  94. package/dist/elements/kbd.js +1 -1
  95. package/dist/elements/link-preview.js +1 -1
  96. package/dist/elements/loader.js +1 -1
  97. package/dist/elements/markdown.js +1 -1
  98. package/dist/elements/menu.js +1 -1
  99. package/dist/elements/message-skills.js +1 -1
  100. package/dist/elements/message.js +1 -1
  101. package/dist/elements/model-switcher.js +1 -1
  102. package/dist/elements/nav.js +1 -1
  103. package/dist/elements/notice.js +1 -1
  104. package/dist/elements/pane-grid.js +1 -1
  105. package/dist/elements/pane-group.js +1 -1
  106. package/dist/elements/pane.js +1 -1
  107. package/dist/elements/popover.js +1 -1
  108. package/dist/elements/progress-bar.js +1 -1
  109. package/dist/elements/prompt-dock.js +1 -1
  110. package/dist/elements/prompt-input.js +1 -1
  111. package/dist/elements/prompt-suggestions.js +1 -1
  112. package/dist/elements/radio-group.js +1 -1
  113. package/dist/elements/reasoning.js +1 -1
  114. package/dist/elements/remote.js +1 -1
  115. package/dist/elements/resizable.js +1 -1
  116. package/dist/elements/response-stream.js +1 -1
  117. package/dist/elements/screen.js +1 -1
  118. package/dist/elements/scroll-area.js +1 -1
  119. package/dist/elements/scroll-button.js +1 -1
  120. package/dist/elements/search.js +1 -1
  121. package/dist/elements/segmented.js +1 -1
  122. package/dist/elements/select.js +1 -1
  123. package/dist/elements/separator.js +1 -1
  124. package/dist/elements/setting-item.js +1 -1
  125. package/dist/elements/settings-group.js +1 -1
  126. package/dist/elements/skeleton.js +1 -1
  127. package/dist/elements/slider.js +1 -1
  128. package/dist/elements/source.js +1 -1
  129. package/dist/elements/status.js +1 -1
  130. package/dist/elements/switch.js +1 -1
  131. package/dist/elements/tabs.js +1 -1
  132. package/dist/elements/tasks.js +1 -1
  133. package/dist/elements/text-shimmer.js +1 -1
  134. package/dist/elements/thinking-bar.js +1 -1
  135. package/dist/elements/thread.js +1 -1
  136. package/dist/elements/toast.js +1 -1
  137. package/dist/elements/tool.js +1 -1
  138. package/dist/elements/tooltip.js +1 -1
  139. package/dist/elements/voice-input.js +1 -1
  140. package/dist/elements/voice-output.js +1 -1
  141. package/dist/elements.d.ts +20 -4
  142. package/dist/{ellipsis-DFr4Vqr3.js → ellipsis-CbOpJnU3.js} +1 -1
  143. package/dist/{embed-5s_vU4J0.js → embed-CrfjkbUG.js} +1 -1
  144. package/dist/engine-javascript-C1x7zo1_.js +1 -141
  145. package/dist/{external-link-u9d85ORQ.js → external-link-ByXAwBBQ.js} +1 -1
  146. package/dist/{file-text-CX7_x42o.js → file-text-DMib2qwt.js} +1 -1
  147. package/dist/{file-tree-D3kBjXI5.js → file-tree-CJqM2aP7.js} +1 -1
  148. package/dist/{folder-V-YdIL8f.js → folder-_BAb929C.js} +1 -1
  149. package/dist/{form-BRNUMCN2.js → form-DSZgZQZk.js} +1 -1
  150. package/dist/{hover-card-DaeiYrTA.js → hover-card-BQbul9eq.js} +1 -1
  151. package/dist/{icon-BpixdZNq.js → icon-CdcfRhYI.js} +1 -1
  152. package/dist/index.d.ts +3 -1
  153. package/dist/index.js +2842 -2703
  154. package/dist/index.server.js +2820 -2681
  155. package/dist/{info-8mFsIjS3.js → info-DsFjGuI_.js} +1 -1
  156. package/dist/{input-d1Yuu-hz.js → input-DKbmkMos.js} +1 -1
  157. package/dist/kai.es.js +1 -1
  158. package/dist/{kbd-961zMPFB.js → kbd-PvdGhX4s.js} +1 -1
  159. package/dist/{link-preview-DIIbV2Sd.js → link-preview-DbM1866N.js} +1 -1
  160. package/dist/{link-DlZZBGaR.js → link-zF8PzWfF.js} +1 -1
  161. package/dist/{loader-YQszHFaW.js → loader-BM4CEz4G.js} +1 -1
  162. package/dist/{markdown-CVk1MPsj.js → markdown-LMvmAyBk.js} +7 -7
  163. package/dist/mcp.es.js +79 -5
  164. package/dist/{message-CwKVEdZg.js → message-BSsgvHvf.js} +1 -1
  165. package/dist/{message-DS8lzHc1.js → message-BYZECyek.js} +1 -1
  166. package/dist/message-circle-DruwObfX.js +1 -0
  167. package/dist/message-square-BG6q6mlm.js +1 -0
  168. package/dist/{minimize-2-UEZmP2QT.js → minimize-2-BQRoBV1V.js} +1 -1
  169. package/dist/{model-switcher-Kk1jEQ5t.js → model-switcher-CMpCOYcB.js} +1 -1
  170. package/dist/{overlay-C1od6LOz.js → overlay-Cb-MkyDa.js} +1 -1
  171. package/dist/{panel-right-ryET0yyn.js → panel-right-i8warFxT.js} +1 -1
  172. package/dist/{paperclip-BDNoZFJP.js → paperclip-ByY3UVO6.js} +1 -1
  173. package/dist/play-BvKKq3fX.js +1 -0
  174. package/dist/primitives/conversation-store.d.ts +54 -0
  175. package/dist/{progress-bar-BvYX0aoy.js → progress-bar-jVAHvMUf.js} +1 -1
  176. package/dist/{prompt-suggestion-BRFu2lcu.js → prompt-suggestion-CD-qtNgC.js} +1 -1
  177. package/dist/{radio-DcL23cNJ.js → radio-BsoBMhkF.js} +1 -1
  178. package/dist/react/index.d.ts +393 -0
  179. package/dist/react.js +20 -20
  180. package/dist/{reasoning-Cackq4Rh.js → reasoning-4kBPtlTx.js} +1 -1
  181. package/dist/register-impl-B1hLkrI8.js +424 -0
  182. package/dist/{resizable-Cp9HUYih.js → resizable-uPmY9VY-.js} +1 -1
  183. package/dist/{rotate-ccw-0DLRDHH5.js → rotate-ccw-B2xn93py.js} +1 -1
  184. package/dist/{rotate-cw-DOB9IGcU.js → rotate-cw-CMVLoCyH.js} +1 -1
  185. package/dist/{scroll-area-emVmWP4K.js → scroll-area-BqLUo8ZZ.js} +1 -1
  186. package/dist/{scroll-button-CeP_gv1x.js → scroll-button-DslXiJyL.js} +1 -1
  187. package/dist/{select-CWmu00tS.js → select-2cLRtPGT.js} +1 -1
  188. package/dist/{separator-CE6vly6z.js → separator-BWQtNJcM.js} +1 -1
  189. package/dist/{settings-CE-78SvZ.js → settings-BBR63jLg.js} +1 -1
  190. package/dist/{settings-group-ZFWNxFQR.js → settings-group-B2ciy-Iw.js} +1 -1
  191. package/dist/{skeleton-BebdP4mf.js → skeleton-CkHI-HgC.js} +1 -1
  192. package/dist/{slider-BAKRYUlz.js → slider-DDR9U-i0.js} +1 -1
  193. package/dist/{solid-BE5ui6sy.js → solid-BzCFdL25.js} +7720 -7058
  194. package/dist/{solid-DFhsce3O.js → solid-DruVOXnf.js} +5864 -5283
  195. package/dist/solid.d.ts +6 -2
  196. package/dist/solid.js +217 -210
  197. package/dist/solid.server.js +217 -210
  198. package/dist/{source-B0FlguSx.js → source-GEnFF528.js} +1 -1
  199. package/dist/{star-CBMZvLuN.js → star-CilHq8GP.js} +1 -1
  200. package/dist/store-Ciyk6eZG.js +1 -0
  201. package/dist/{switch-CViARZCy.js → switch-KkeQIbuH.js} +1 -1
  202. package/dist/{tasks-card-MjCcOhR_.js → tasks-card-BrN4bggJ.js} +1 -1
  203. package/dist/{text-shimmer-DKlwRF2G.js → text-shimmer-Dcj1MHuq.js} +1 -1
  204. package/dist/{textarea-3ay2Me2-.js → textarea-Dpvbngbg.js} +1 -1
  205. package/dist/theme.tokens.css +28 -0
  206. package/dist/{thumbs-up-DQcu2HMO.js → thumbs-up-CsT9Wzb9.js} +1 -1
  207. package/dist/{toast-store-C6yKOhbk.js → toast-store-tgK6MuMv.js} +1 -1
  208. package/dist/{tool-BCYNlfKy.js → tool-DzUjIBT8.js} +1 -1
  209. package/dist/{tooltip-05zI4hjs.js → tooltip-Bkkg_4t0.js} +1 -1
  210. package/dist/{trash-2-BR1RxGky.js → trash-2-jBKxjGGQ.js} +1 -1
  211. package/dist/{triangle-alert-DHohDOCy.js → triangle-alert-DlQ68ppf.js} +1 -1
  212. package/dist/types.d.ts +48 -3
  213. package/dist/ui/dock.d.ts +29 -0
  214. package/dist/{upload-BbGW6A_u.js → upload-TcAHXv9W.js} +1 -1
  215. package/dist/{url-scheme-policy-DHpoTJwB.js → url-scheme-policy-DR5DgvkM.js} +1 -1
  216. package/dist/{use-card-resolution-CJW4grFa.js → use-card-resolution-DaZqAdWf.js} +1 -1
  217. package/dist/{variant-aurora-xiMPty8f.js → variant-aurora-BhLuYxJR.js} +1 -1
  218. package/dist/{variant-aurora-BUOVgPOB.js → variant-aurora-CNmfHhcx.js} +2 -2
  219. package/dist/{variant-aurora-CUsUJvFI.js → variant-aurora-D6GsdTPA.js} +2 -2
  220. package/dist/{variant-aurora-CW2i4bfr.js → variant-aurora-DbW_OWL2.js} +1 -1
  221. package/dist/{variant-custom-D91HjAKz.js → variant-custom-BRvaNHSi.js} +1 -1
  222. package/dist/{variant-custom-BQtOnmeO.js → variant-custom-BvYHR62b.js} +1 -1
  223. package/dist/{variant-custom-CAnzzppW.js → variant-custom-DMTrEO5w.js} +2 -2
  224. package/dist/{variant-custom-CAm9L-E5.js → variant-custom-DV2x254s.js} +2 -2
  225. package/dist/{variant-wave-Ca1Ls4_y.js → variant-wave-BNMGrDfj.js} +2 -2
  226. package/dist/{variant-wave-uY5crU_K.js → variant-wave-BpDd8t3Z.js} +1 -1
  227. package/dist/{variant-wave-CxX39DKd.js → variant-wave-CyBueXj9.js} +2 -2
  228. package/dist/{variant-wave-DYyzIIZv.js → variant-wave-sp-qwsdI.js} +1 -1
  229. package/dist/x-Z5UntkIJ.js +1 -0
  230. package/frameworks/react/index.tsx +14 -4
  231. package/llms-full.txt +7 -2
  232. package/package.json +16 -16
  233. package/src/elements/element-meta.json +49 -6
  234. package/theme.css +28 -0
  235. package/bin/route.test.js +0 -58
  236. package/dist/arrow-down-Br0qtpsz.js +0 -1
  237. package/dist/arrow-left-Dj7xgE12.js +0 -1
  238. package/dist/check-DPeeMUYx.js +0 -1
  239. package/dist/chevron-down-CHSWk7ZT.js +0 -1
  240. package/dist/chevron-right-B7l_fMgx.js +0 -1
  241. package/dist/circle-Bb0yOpqM.js +0 -1
  242. package/dist/circle-check-BGZpCiz7.js +0 -1
  243. package/dist/code-block-CUQ5mtv0.js +0 -1
  244. package/dist/controllable-D43BKmtX.js +0 -1
  245. package/dist/conversation-list-D4lLU_yS.js +0 -1
  246. package/dist/define-CGGX-7Vg.js +0 -1
  247. package/dist/message-circle-Xf8Q-vZp.js +0 -1
  248. package/dist/message-square-Cxnwgkns.js +0 -1
  249. package/dist/play-OFIvYXUQ.js +0 -1
  250. package/dist/register-impl-C7rENvPK.js +0 -424
  251. package/dist/store-7eoadydQ.js +0 -1
  252. package/dist/x-C5m1JFgi.js +0 -1
  253. package/src/agent-tooling/archetypes.ts +0 -205
  254. package/src/agent-tooling/catalog/README.md +0 -676
  255. package/src/agent-tooling/catalog/catalog-types.ts +0 -231
  256. package/src/agent-tooling/catalog/fabrications.ts +0 -96
  257. package/src/agent-tooling/catalog/invariants.ts +0 -284
  258. package/src/agent-tooling/catalog/labs-titles.ts +0 -114
  259. package/src/agent-tooling/catalog/scenarios.ts +0 -87
  260. package/src/agent-tooling/catalog/surfaces.ts +0 -347
  261. package/src/agent-tooling/construct/cli-entry.ts +0 -8
  262. package/src/agent-tooling/construct/cli.ts +0 -131
  263. package/src/agent-tooling/construct/codegen.ts +0 -1353
  264. package/src/agent-tooling/construct/construct.v1.schema.json +0 -250
  265. package/src/agent-tooling/construct/dev.ts +0 -148
  266. package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +0 -7
  267. package/src/agent-tooling/construct/fixtures/ops-console.construct.json +0 -44
  268. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +0 -23
  269. package/src/agent-tooling/construct/schema.ts +0 -371
  270. package/src/agent-tooling/integrations/anthropic.ts +0 -442
  271. package/src/agent-tooling/integrations/cloudflare.ts +0 -218
  272. package/src/agent-tooling/integrations/langgraph.ts +0 -133
  273. package/src/agent-tooling/integrations/mastra.ts +0 -182
  274. package/src/agent-tooling/integrations/mock.ts +0 -148
  275. package/src/agent-tooling/integrations/ollama.ts +0 -97
  276. package/src/agent-tooling/integrations/openai.ts +0 -95
  277. package/src/agent-tooling/integrations/openrouter.ts +0 -82
  278. package/src/agent-tooling/integrations/pi.ts +0 -176
  279. package/src/agent-tooling/integrations/pydantic-ai.ts +0 -108
  280. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +0 -398
  281. package/src/agent-tooling/mcp/css-raw.d.ts +0 -12
  282. package/src/agent-tooling/mcp/manifest.ts +0 -422
  283. package/src/agent-tooling/mcp/server.ts +0 -116
  284. package/src/agent-tooling/mcp/stdio.ts +0 -18
  285. package/src/agent-tooling/mcp/tools/construct.ts +0 -130
  286. package/src/agent-tooling/mcp/tools/debug.ts +0 -621
  287. package/src/agent-tooling/mcp/tools/reference.ts +0 -980
  288. package/src/agent-tooling/mcp/tools/scaffold.ts +0 -6708
  289. package/src/agent-tooling/mcp/tools/theme.ts +0 -456
  290. package/src/agent-tooling/mcp/tools/types.ts +0 -14
  291. package/src/agent-tooling/mcp/validate-args.ts +0 -141
  292. package/src/agent-tooling/recipes/composed-thread.ts +0 -714
  293. package/src/agent-tooling/recipes/index.ts +0 -22
  294. package/src/agent-tooling/recipes/types.ts +0 -32
  295. package/src/agent-tooling/registry.ts +0 -132
  296. package/src/agent-tooling/route-emit.ts +0 -305
  297. package/src/agent-tooling/types.ts +0 -390
  298. package/src/components/artifact-card.tsx +0 -120
  299. package/src/components/artifact.tsx +0 -914
  300. package/src/components/attachment-types.ts +0 -66
  301. package/src/components/attachments.tsx +0 -536
  302. package/src/components/audio-visualizer/audio-visualizer.voice-fixture.ts +0 -257
  303. package/src/components/audio-visualizer/aurora.glsl.ts +0 -330
  304. package/src/components/audio-visualizer/fit-scale.ts +0 -112
  305. package/src/components/audio-visualizer/index.tsx +0 -528
  306. package/src/components/audio-visualizer/labs/lab-choreography.ts +0 -187
  307. package/src/components/audio-visualizer/labs/lab-shaders.ts +0 -363
  308. package/src/components/audio-visualizer/labs/lab-visualizer.tsx +0 -102
  309. package/src/components/audio-visualizer/shader-canvas.tsx +0 -876
  310. package/src/components/audio-visualizer/sizes.ts +0 -54
  311. package/src/components/audio-visualizer/variant-aurora.tsx +0 -305
  312. package/src/components/audio-visualizer/variant-bar.tsx +0 -175
  313. package/src/components/audio-visualizer/variant-custom.tsx +0 -344
  314. package/src/components/audio-visualizer/variant-grid.tsx +0 -175
  315. package/src/components/audio-visualizer/variant-radial.tsx +0 -163
  316. package/src/components/audio-visualizer/variant-wave.tsx +0 -130
  317. package/src/components/audio-visualizer/wave.glsl.ts +0 -130
  318. package/src/components/card-fallback.tsx +0 -60
  319. package/src/components/card-renderer.tsx +0 -220
  320. package/src/components/card.tsx +0 -212
  321. package/src/components/chain-of-thought.tsx +0 -348
  322. package/src/components/chat-container.tsx +0 -89
  323. package/src/components/chat-scope-picker.tsx +0 -57
  324. package/src/components/chat-thread.tsx +0 -518
  325. package/src/components/checkpoint.tsx +0 -88
  326. package/src/components/choice-card.tsx +0 -743
  327. package/src/components/coachmark.tsx +0 -249
  328. package/src/components/code-block.tsx +0 -181
  329. package/src/components/composer-dom.ts +0 -159
  330. package/src/components/composer-highlight.ts +0 -242
  331. package/src/components/composer-history.ts +0 -82
  332. package/src/components/composer.tsx +0 -1075
  333. package/src/components/confirm-card.tsx +0 -402
  334. package/src/components/context.tsx +0 -377
  335. package/src/components/conversation-item.tsx +0 -218
  336. package/src/components/conversation-list.tsx +0 -429
  337. package/src/components/dismissed-stub.tsx +0 -80
  338. package/src/components/embed.tsx +0 -200
  339. package/src/components/empty.tsx +0 -177
  340. package/src/components/feedback-bar.tsx +0 -166
  341. package/src/components/file-tree.tsx +0 -530
  342. package/src/components/file-upload.tsx +0 -167
  343. package/src/components/form-widgets.tsx +0 -525
  344. package/src/components/form.tsx +0 -1296
  345. package/src/components/image.tsx +0 -65
  346. package/src/components/link-preview.tsx +0 -195
  347. package/src/components/loader.tsx +0 -367
  348. package/src/components/markdown.tsx +0 -162
  349. package/src/components/message-skills.tsx +0 -40
  350. package/src/components/message.tsx +0 -765
  351. package/src/components/model-switcher.tsx +0 -132
  352. package/src/components/prompt-input.tsx +0 -188
  353. package/src/components/prompt-suggestion.tsx +0 -150
  354. package/src/components/reasoning.tsx +0 -293
  355. package/src/components/response-compare-types.ts +0 -152
  356. package/src/components/response-compare.tsx +0 -455
  357. package/src/components/response-stream.tsx +0 -109
  358. package/src/components/screen.tsx +0 -181
  359. package/src/components/scroll-button.tsx +0 -93
  360. package/src/components/source.tsx +0 -192
  361. package/src/components/tasks-card.tsx +0 -801
  362. package/src/components/text-shimmer.tsx +0 -37
  363. package/src/components/thinking-bar.tsx +0 -50
  364. package/src/components/thread.tsx +0 -228
  365. package/src/components/toast.tsx +0 -503
  366. package/src/components/tool-classify.ts +0 -26
  367. package/src/components/tool-types.ts +0 -49
  368. package/src/components/tool.tsx +0 -190
  369. package/src/components/use-card-resolution.ts +0 -44
  370. package/src/components/voice-input.tsx +0 -222
  371. package/src/components/voice-output.tsx +0 -242
  372. package/src/components/workspace-shell.tsx +0 -285
  373. package/src/diagnostics/hook.ts +0 -352
  374. package/src/diagnostics/index.ts +0 -82
  375. package/src/diagnostics/report-request.ts +0 -296
  376. package/src/elements/agent-card.tsx +0 -67
  377. package/src/elements/artifact.tsx +0 -194
  378. package/src/elements/attachments.tsx +0 -140
  379. package/src/elements/audio-visualizer.tsx +0 -227
  380. package/src/elements/autoloader.ts +0 -89
  381. package/src/elements/avatar.tsx +0 -33
  382. package/src/elements/badge.tsx +0 -32
  383. package/src/elements/button.tsx +0 -149
  384. package/src/elements/card.tsx +0 -133
  385. package/src/elements/cards.tsx +0 -266
  386. package/src/elements/chain-of-thought.tsx +0 -141
  387. package/src/elements/chat-scope-picker.tsx +0 -65
  388. package/src/elements/chat-types.ts +0 -102
  389. package/src/elements/chat-workspace.tsx +0 -188
  390. package/src/elements/chat.tsx +0 -212
  391. package/src/elements/checkbox-group.tsx +0 -164
  392. package/src/elements/checkbox.tsx +0 -134
  393. package/src/elements/checkpoint.tsx +0 -47
  394. package/src/elements/choice.tsx +0 -100
  395. package/src/elements/coachmark.tsx +0 -90
  396. package/src/elements/code-block.tsx +0 -60
  397. package/src/elements/command.tsx +0 -197
  398. package/src/elements/compare.tsx +0 -111
  399. package/src/elements/compiled.css +0 -2
  400. package/src/elements/composer.tsx +0 -162
  401. package/src/elements/confirm-card.tsx +0 -76
  402. package/src/elements/context-meter.tsx +0 -107
  403. package/src/elements/conversation-item.tsx +0 -120
  404. package/src/elements/conversation-list.tsx +0 -203
  405. package/src/elements/css.ts +0 -5
  406. package/src/elements/default-input.tsx +0 -392
  407. package/src/elements/define-entry.ts +0 -12
  408. package/src/elements/define.tsx +0 -563
  409. package/src/elements/diagnostic-events.ts +0 -114
  410. package/src/elements/dialog.tsx +0 -145
  411. package/src/elements/disclosure.ts +0 -95
  412. package/src/elements/dock.tsx +0 -215
  413. package/src/elements/dropdown.tsx +0 -123
  414. package/src/elements/editable-label.tsx +0 -140
  415. package/src/elements/element-data-types.ts +0 -152
  416. package/src/elements/element-diagnostics.ts +0 -392
  417. package/src/elements/element-manifest.json +0 -354
  418. package/src/elements/element-nonscalar.json +0 -185
  419. package/src/elements/element-types.d.ts +0 -4337
  420. package/src/elements/embed.tsx +0 -35
  421. package/src/elements/empty.tsx +0 -29
  422. package/src/elements/feedback-bar.tsx +0 -66
  423. package/src/elements/file-tree.tsx +0 -62
  424. package/src/elements/file-upload.tsx +0 -44
  425. package/src/elements/form.tsx +0 -94
  426. package/src/elements/hover-card.tsx +0 -80
  427. package/src/elements/icon.tsx +0 -41
  428. package/src/elements/image.tsx +0 -32
  429. package/src/elements/input.tsx +0 -492
  430. package/src/elements/kbd.tsx +0 -45
  431. package/src/elements/link-preview.tsx +0 -34
  432. package/src/elements/loader.tsx +0 -25
  433. package/src/elements/markdown.tsx +0 -38
  434. package/src/elements/menu.tsx +0 -241
  435. package/src/elements/message-skills.tsx +0 -83
  436. package/src/elements/message.tsx +0 -361
  437. package/src/elements/model-switcher.tsx +0 -121
  438. package/src/elements/nav.tsx +0 -87
  439. package/src/elements/notice.tsx +0 -53
  440. package/src/elements/pane-grid.tsx +0 -111
  441. package/src/elements/pane-group.tsx +0 -119
  442. package/src/elements/pane.tsx +0 -129
  443. package/src/elements/popover.tsx +0 -81
  444. package/src/elements/progress-bar.tsx +0 -39
  445. package/src/elements/prompt-dock.tsx +0 -82
  446. package/src/elements/prompt-input.tsx +0 -240
  447. package/src/elements/prompt-suggestions.tsx +0 -113
  448. package/src/elements/radio-group.tsx +0 -129
  449. package/src/elements/reasoning.tsx +0 -71
  450. package/src/elements/register-impl.ts +0 -148
  451. package/src/elements/register.ts +0 -76
  452. package/src/elements/remote.tsx +0 -225
  453. package/src/elements/resizable.globals.d.ts +0 -36
  454. package/src/elements/resizable.tsx +0 -704
  455. package/src/elements/response-stream.tsx +0 -40
  456. package/src/elements/screen.tsx +0 -90
  457. package/src/elements/scroll-area.tsx +0 -33
  458. package/src/elements/scroll-button.tsx +0 -179
  459. package/src/elements/search.tsx +0 -185
  460. package/src/elements/segmented.tsx +0 -129
  461. package/src/elements/select.tsx +0 -165
  462. package/src/elements/separator.tsx +0 -36
  463. package/src/elements/setting-item.tsx +0 -50
  464. package/src/elements/settings-group.tsx +0 -37
  465. package/src/elements/skeleton.tsx +0 -45
  466. package/src/elements/slider.tsx +0 -171
  467. package/src/elements/slot-text.ts +0 -73
  468. package/src/elements/slots.ts +0 -787
  469. package/src/elements/source.tsx +0 -126
  470. package/src/elements/status.tsx +0 -42
  471. package/src/elements/styles.css +0 -328
  472. package/src/elements/switch.tsx +0 -118
  473. package/src/elements/tabs.tsx +0 -95
  474. package/src/elements/tasks.tsx +0 -103
  475. package/src/elements/text-shimmer.tsx +0 -28
  476. package/src/elements/thinking-bar.tsx +0 -43
  477. package/src/elements/thread.tsx +0 -139
  478. package/src/elements/toast.tsx +0 -106
  479. package/src/elements/tool.tsx +0 -78
  480. package/src/elements/tooltip.tsx +0 -85
  481. package/src/elements/validate-messages.ts +0 -76
  482. package/src/elements/voice-input.tsx +0 -100
  483. package/src/elements/voice-output.tsx +0 -82
  484. package/src/index.ts +0 -428
  485. package/src/primitives/audio-bands.ts +0 -174
  486. package/src/primitives/card-component-types.ts +0 -63
  487. package/src/primitives/card-contract.ts +0 -80
  488. package/src/primitives/card-data-types.ts +0 -361
  489. package/src/primitives/card-host.tsx +0 -37
  490. package/src/primitives/card-recovery.ts +0 -160
  491. package/src/primitives/card-registry.tsx +0 -78
  492. package/src/primitives/card-resolution.ts +0 -36
  493. package/src/primitives/card-routing.ts +0 -85
  494. package/src/primitives/card-schemas/artifact.schema.json +0 -92
  495. package/src/primitives/card-schemas/card-envelope.schema.json +0 -14
  496. package/src/primitives/card-schemas/card-event.schema.json +0 -12
  497. package/src/primitives/card-schemas/choice.schema.json +0 -75
  498. package/src/primitives/card-schemas/confirm.schema.json +0 -65
  499. package/src/primitives/card-schemas/embed.schema.json +0 -63
  500. package/src/primitives/card-schemas/form.result.schema.json +0 -7
  501. package/src/primitives/card-schemas/form.schema.json +0 -53
  502. package/src/primitives/card-schemas/link.schema.json +0 -54
  503. package/src/primitives/card-schemas/tasks.result.schema.json +0 -16
  504. package/src/primitives/card-schemas/tasks.schema.json +0 -83
  505. package/src/primitives/card-tags.ts +0 -61
  506. package/src/primitives/card-validate-cards.ts +0 -255
  507. package/src/primitives/card-validate-schemas.ts +0 -58
  508. package/src/primitives/card-validate.ts +0 -131
  509. package/src/primitives/chat-config.tsx +0 -103
  510. package/src/primitives/composer-model.ts +0 -49
  511. package/src/primitives/composer-triggers.ts +0 -35
  512. package/src/primitives/controllable.ts +0 -21
  513. package/src/primitives/create-kai-chat.ts +0 -66
  514. package/src/primitives/create-tween.ts +0 -266
  515. package/src/primitives/embed-providers.ts +0 -254
  516. package/src/primitives/field-mask.ts +0 -256
  517. package/src/primitives/field-semantics.ts +0 -115
  518. package/src/primitives/highlighter.ts +0 -157
  519. package/src/primitives/input-mask.ts +0 -853
  520. package/src/primitives/link-preview.ts +0 -87
  521. package/src/primitives/message-feedback.ts +0 -124
  522. package/src/primitives/pdf-preview.ts +0 -121
  523. package/src/primitives/toast-store.ts +0 -338
  524. package/src/primitives/url-scheme-policy.ts +0 -70
  525. package/src/primitives/use-audio-analysis.ts +0 -340
  526. package/src/primitives/use-auto-resize.ts +0 -31
  527. package/src/primitives/use-resize-observer.ts +0 -45
  528. package/src/primitives/use-sequencer.ts +0 -72
  529. package/src/primitives/use-speech-recognition.ts +0 -146
  530. package/src/primitives/use-stick-to-bottom.ts +0 -75
  531. package/src/primitives/use-text-stream.ts +0 -143
  532. package/src/primitives/use-voice-recorder.ts +0 -62
  533. package/src/primitives/visualizer-sequences.ts +0 -350
  534. package/src/remote/host-embed.ts +0 -345
  535. package/src/remote/index.ts +0 -2
  536. package/src/remote/origin.ts +0 -30
  537. package/src/remote/provider-runtime.ts +0 -262
  538. package/src/remote/provider.ts +0 -2
  539. package/src/remote/validate.ts +0 -22
  540. package/src/remote/version.ts +0 -12
  541. package/src/remote/wire.ts +0 -48
  542. package/src/schemas/from-tool-call.ts +0 -151
  543. package/src/schemas/index.ts +0 -341
  544. package/src/schemas/provider-subsets.ts +0 -538
  545. package/src/schemas/registry.ts +0 -355
  546. package/src/schemas/tool-defs.ts +0 -793
  547. package/src/solid.ts +0 -165
  548. package/src/state/index.ts +0 -44
  549. package/src/state/messages.ts +0 -53
  550. package/src/state/mock.ts +0 -297
  551. package/src/state/parts.ts +0 -295
  552. package/src/state/persistence.ts +0 -180
  553. package/src/state/stream.ts +0 -246
  554. package/src/state/suggestions.ts +0 -9
  555. package/src/state/threads.ts +0 -142
  556. package/src/test-utils/fake-clock.ts +0 -88
  557. package/src/types.ts +0 -53
  558. package/src/ui/action-icons.ts +0 -53
  559. package/src/ui/agent-card.tsx +0 -218
  560. package/src/ui/avatar.tsx +0 -23
  561. package/src/ui/badge.tsx +0 -21
  562. package/src/ui/button.tsx +0 -49
  563. package/src/ui/card.tsx +0 -245
  564. package/src/ui/checkbox-group.tsx +0 -153
  565. package/src/ui/checkbox.tsx +0 -63
  566. package/src/ui/collapsible.tsx +0 -163
  567. package/src/ui/command.tsx +0 -103
  568. package/src/ui/dialog.tsx +0 -223
  569. package/src/ui/dock.tsx +0 -584
  570. package/src/ui/dropdown.tsx +0 -636
  571. package/src/ui/editable-label.tsx +0 -112
  572. package/src/ui/hover-card.tsx +0 -345
  573. package/src/ui/icon.tsx +0 -167
  574. package/src/ui/input.tsx +0 -391
  575. package/src/ui/kbd.tsx +0 -118
  576. package/src/ui/nav.tsx +0 -282
  577. package/src/ui/notice.tsx +0 -84
  578. package/src/ui/overlay.tsx +0 -277
  579. package/src/ui/pane-grid.tsx +0 -117
  580. package/src/ui/pane-group.tsx +0 -291
  581. package/src/ui/pane.tsx +0 -193
  582. package/src/ui/popover.tsx +0 -106
  583. package/src/ui/progress-bar.tsx +0 -83
  584. package/src/ui/prompt-dock.tsx +0 -145
  585. package/src/ui/radio.tsx +0 -150
  586. package/src/ui/resizable.tsx +0 -693
  587. package/src/ui/scroll-area.tsx +0 -26
  588. package/src/ui/segmented.tsx +0 -109
  589. package/src/ui/select.tsx +0 -168
  590. package/src/ui/separator.tsx +0 -10
  591. package/src/ui/settings-group.tsx +0 -67
  592. package/src/ui/skeleton.tsx +0 -73
  593. package/src/ui/slider.tsx +0 -178
  594. package/src/ui/status.tsx +0 -48
  595. package/src/ui/switch.tsx +0 -119
  596. package/src/ui/tabs.tsx +0 -168
  597. package/src/ui/textarea.tsx +0 -21
  598. package/src/ui/tooltip.tsx +0 -118
  599. package/src/utils/cn.ts +0 -30
  600. package/src/wire/chunk.ts +0 -248
  601. package/src/wire/consume.ts +0 -599
  602. package/src/wire/diagnostics.ts +0 -727
  603. package/src/wire/encode-probe.ts +0 -214
  604. package/src/wire/encode.ts +0 -947
  605. package/src/wire/files.ts +0 -342
  606. package/src/wire/formats/anthropic.ts +0 -274
  607. package/src/wire/formats/openai.ts +0 -228
  608. package/src/wire/index.ts +0 -95
  609. package/src/wire/media-types.ts +0 -344
  610. package/src/wire/read.ts +0 -396
  611. package/src/wire/sink-helpers.ts +0 -50
  612. package/src/wire/sse.ts +0 -153
@@ -1,787 +0,0 @@
1
- /**
2
- * Composition slots for `kai-*` elements. A slot is a named region a consumer
3
- * fills with their own markup. This registry is the SINGLE SOURCE OF TRUTH:
4
- * the facade derives its detection from it (and, later, docs are generated
5
- * from it).
6
- */
7
-
8
- /** `inject` = additive (the built-in region still renders, your markup is added
9
- * in). `replace` = your markup stands in for the whole region — you own that
10
- * region's data + events (a slotted light-DOM node can't read the component's
11
- * reactive state). */
12
- export type SlotMode = 'inject' | 'replace';
13
-
14
- export interface SlotDef {
15
- /** Slot name (kebab-case). Also the `::part` name when `part` is true. */
16
- name: string;
17
- mode: SlotMode;
18
- /** Expose `::part(name)` on the region wrapper for consumer styling. */
19
- part?: boolean;
20
- /** One-line contract: what the consumer projects / owns. Feeds the docs. */
21
- doc: string;
22
- }
23
-
24
- /** Slots of `<kai-chat>`, in render order. */
25
- export const CHAT_SLOTS: SlotDef[] = [
26
- { name: 'header-start', mode: 'inject', doc: 'Leading header controls, left of the title.' },
27
- { name: 'header-end', mode: 'inject', doc: 'Trailing header controls.' },
28
- { name: 'header', mode: 'replace', part: true, doc: 'Full custom header; replaces the built-in title/model/context bar.' },
29
- { name: 'sidebar', mode: 'inject', part: true, doc: 'Left column (your nav / conversation list). Fixed width; use compose-your-own for resizable.' },
30
- { name: 'empty', mode: 'replace', doc: 'Custom zero-state rendered in the message area while the thread is empty. Replaces the empty message list only; the composer and any suggestions still render.' },
31
- { name: 'composer', mode: 'replace', doc: 'Full custom composer; you own submit + loading, drive the thread via messages.' },
32
- { name: 'composer-actions', mode: 'inject', doc: 'Accessory row above the composer.' },
33
- { name: 'footer', mode: 'inject', part: true, doc: 'Row below the composer (disclaimers, token meter).' },
34
- ];
35
-
36
- /** Slots of `<kai-prompt-input>` (and the default composer inside `<kai-chat>`). Native
37
- * shadow slots — an empty slot renders nothing, so no facade flag-gating is required.
38
- *
39
- * These are ONLY positions inside the card's shadow boundary — places a consumer
40
- * cannot reach from their own DOM. Content ABOVE/BELOW the whole card is the
41
- * consumer's own light-DOM layout (a sibling element), so there is intentionally
42
- * no outer block slot here. (When the input is nested inside `<kai-chat>`'s shadow,
43
- * that surrounding hole belongs to `kai-chat` — see `composer-actions`/`footer`.) */
44
- export const PROMPT_INPUT_SLOTS: SlotDef[] = [
45
- { name: 'input-top', mode: 'inject', doc: 'Inside the card, above the textarea (e.g. an inline status strip). For content above/below the whole card, use your own layout; that is light DOM you control.' },
46
- { name: 'toolbar-start', mode: 'inject', doc: 'Leading controls in the input toolbar, where a + menu goes.' },
47
- { name: 'toolbar-end', mode: 'inject', doc: 'Trailing controls in the toolbar, before the Send button.' },
48
- ];
49
-
50
- /** Slots of `<kai-conversations>` (also used inside `<kai-chat>`'s `sidebar`).
51
- * Names mirror `<kai-chat>`'s so the two compose with one vocabulary. */
52
- export const CONVERSATIONS_SLOTS: SlotDef[] = [
53
- { name: 'header', mode: 'replace', doc: 'Full custom title bar; replaces the built-in toggle / "Chats" / New-chat row.' },
54
- { name: 'empty', mode: 'replace', doc: 'Custom zero-state shown when there are no conversations; replaces the built-in "No conversations yet".' },
55
- { name: 'footer', mode: 'inject', doc: 'A row below the list: account, settings, or usage.' },
56
- ];
57
-
58
- /** Styleable `::part`s of `<kai-conversations>`. */
59
- export const CONVERSATIONS_PARTS: PartDef[] = [
60
- {
61
- name: 'trailing',
62
- 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.',
63
- recipe: 'kai-conversations::part(trailing) { color: var(--color-primary); font-variant-numeric: tabular-nums }',
64
- },
65
- {
66
- name: 'items',
67
- doc: 'The item-mode listbox region wrapping your slotted `<kai-conversation-item>` children.',
68
- recipe: 'kai-conversations::part(items) { gap: 2px }',
69
- },
70
- ];
71
-
72
- /** Slots of `<kai-conversation-item>` — one composed row of a consumer-owned
73
- * conversation loop (the default slot is the title). */
74
- export const CONVERSATION_ITEM_SLOTS: SlotDef[] = [
75
- { name: 'leading', mode: 'inject', part: true, doc: 'Leading region before the title (an icon or avatar).' },
76
- { name: 'meta', mode: 'inject', part: true, doc: 'Meta region under the title (a timestamp or status line).' },
77
- { name: 'menu', mode: 'inject', part: true, doc: 'Your own row menu (a popover trigger). Never selects the row.' },
78
- ];
79
-
80
- /** Styleable `::part`s of `<kai-conversation-item>`. (`leading`/`meta`/`menu`
81
- * are covered by their slot defs' `part: true` flags.) */
82
- export const CONVERSATION_ITEM_PARTS: PartDef[] = [
83
- {
84
- name: 'body',
85
- doc: 'The activation surface inside the row (button role; carries aria-current and the roving tabindex). The focus ring paints here.',
86
- recipe: 'kai-conversation-item::part(body) { outline-offset: 2px }',
87
- },
88
- {
89
- name: 'row',
90
- doc: 'The whole row surface. Carries `data-active` while selected.',
91
- recipe: 'kai-conversation-item::part(row) { border-radius: 0.5rem }',
92
- },
93
- {
94
- name: 'title',
95
- doc: 'The title line (the default slot renders inside it).',
96
- recipe: 'kai-conversation-item::part(title) { font-weight: 600 }',
97
- },
98
- ];
99
-
100
- /** Slots of `<kai-message>` — per-message composition seams. `before-body` and
101
- * `after-body` are INJECT regions inside the message's body column; `avatar`
102
- * REPLACES the built-in avatar rail (pair it with `avatar="none"` to omit the
103
- * rail entirely). These are the keystone of compose-your-own message lists. */
104
- export const MESSAGE_SLOTS: SlotDef[] = [
105
- { name: 'before-body', mode: 'inject', doc: 'A per-message header at the TOP of the body, above reasoning/tools/content: a model-name label, a role + timestamp line.' },
106
- { name: 'after-body', mode: 'inject', doc: 'A row at the BOTTOM of the body, below the action bar: a citation/sources row, a token-cost/latency line.' },
107
- { name: 'avatar', mode: 'replace', part: true, 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.' },
108
- ];
109
-
110
- /** Slots of `<kai-notice>`. The message is the default slot; these are the named seams. */
111
- export const NOTICE_SLOTS: SlotDef[] = [
112
- { name: 'action', mode: 'inject', doc: 'A trailing action beside the message: a link or button.' },
113
- { name: 'icon', mode: 'replace', doc: 'A custom leading icon (any inline SVG, inherits `currentColor`). Overrides the severity default and the `icon` prop, the same escape hatch as `kai-button`.' },
114
- ];
115
-
116
- /** Slots of `<kai-button>` (the label is the default slot). */
117
- export const BUTTON_SLOTS: SlotDef[] = [
118
- { name: 'icon', mode: 'replace', doc: 'A custom leading icon (any inline SVG, inherits `currentColor`). Wins over the `icon` prop.' },
119
- ];
120
-
121
- /** Slots of `<kai-hover-card>` (the trigger is the default slot). */
122
- export const HOVER_CARD_SLOTS: SlotDef[] = [
123
- { name: 'card', mode: 'inject', doc: 'The rich content shown in the floating hover card.' },
124
- ];
125
-
126
- /** Slots of `<kai-menu>` (the menu items come from the `items` prop). */
127
- export const MENU_SLOTS: SlotDef[] = [
128
- { name: 'trigger', mode: 'replace', doc: 'Your own trigger element; replaces the built-in button driven by the `trigger-icon` / `trigger-label` props.' },
129
- ];
130
-
131
- /** A styleable `::part` the kit renders (NOT a slot — you don't project into it;
132
- * you restyle it from outside via `::part(name)`). This registry is the source
133
- * of truth so the styling surface is discoverable: docs + the `kai` MCP
134
- * component reference are generated from it, the same way slots are. The
135
- * `recipe` is a copy-pasteable example — including the "just hide it" case that
136
- * is pure CSS and therefore intentionally NOT a prop. */
137
- export interface PartDef {
138
- /** `::part(name)` exposed for consumer styling. */
139
- name: string;
140
- /** One-line contract: what the part is. */
141
- doc: string;
142
- /** A copy-pasteable styling example for docs / the MCP reference. */
143
- recipe?: string;
144
- }
145
-
146
- /** Styleable `::part`s of `<kai-chat>` (beyond the slot-backed `header`/`sidebar`/
147
- * `footer` parts). */
148
- export const CHAT_PARTS: PartDef[] = [
149
- {
150
- name: 'header-bar',
151
- doc: 'The built-in header bar (the title / model-switcher / context row that hosts the header-start/header-end inject slots). Restyle its height, padding, or gap from outside without replacing the whole header via the `header` slot.',
152
- recipe: 'kai-chat::part(header-bar) { height: 3.5rem; padding-inline: 1rem; gap: 0.5rem }',
153
- },
154
- ];
155
-
156
- /** Styleable `::part`s of `<kai-prompt-input>`. */
157
- export const PROMPT_INPUT_PARTS: PartDef[] = [
158
- {
159
- name: 'send',
160
- doc: 'The send button. Restyle from outside, or hide it entirely (Enter-only). Hiding is pure CSS, which is why there is no `submit="never"`.',
161
- recipe: 'kai-prompt-input::part(send) { display: none } /* Enter-only; or restyle: background, border-radius, … */',
162
- },
163
- ];
164
-
165
- /** Styleable `::part`s of `<kai-button>`. */
166
- export const BUTTON_PARTS: PartDef[] = [
167
- {
168
- name: 'button',
169
- doc: 'The button element. Restyle radius, padding, colors, or weight from outside; the `variant`/`size` props set the defaults.',
170
- recipe: 'kai-button::part(button) { border-radius: 9999px; font-weight: 600 }',
171
- },
172
- ];
173
-
174
- /** Styleable `::part`s of `<kai-badge>`. */
175
- export const BADGE_PARTS: PartDef[] = [
176
- {
177
- name: 'badge',
178
- doc: 'The badge pill. Restyle its background, color, or shape; the `variant` prop (default/count/citation) sets the defaults.',
179
- recipe: 'kai-badge::part(badge) { background: var(--color-primary); color: var(--color-primary-foreground) }',
180
- },
181
- ];
182
-
183
- /** Styleable `::part`s of `<kai-icon>`. */
184
- export const ICON_PARTS: PartDef[] = [
185
- {
186
- name: 'icon',
187
- doc: 'The icon wrapper. Inherits `currentColor` and the `size` prop by default; recolor or resize it from outside.',
188
- recipe: 'kai-icon::part(icon) { color: var(--color-primary) }',
189
- },
190
- ];
191
-
192
- /** Styleable `::part`s of `<kai-separator>`. */
193
- export const SEPARATOR_PARTS: PartDef[] = [
194
- {
195
- name: 'separator',
196
- doc: 'The divider line. Restyle its color, thickness, or inset from outside.',
197
- recipe: 'kai-separator::part(separator) { background: var(--color-border) }',
198
- },
199
- ];
200
-
201
- /** Styleable `::part`s of `<kai-scroll-area>`. */
202
- export const SCROLL_AREA_PARTS: PartDef[] = [
203
- {
204
- name: 'viewport',
205
- doc: 'The scrolling container. Add padding or a max-height from outside; the thin scrollbar follows `--color-scrollbar-thumb`.',
206
- recipe: 'kai-scroll-area::part(viewport) { padding-right: 0.5rem }',
207
- },
208
- ];
209
-
210
- /** Styleable `::part`s of `<kai-skeleton>`. */
211
- export const SKELETON_PARTS: PartDef[] = [
212
- {
213
- name: 'skeleton',
214
- doc: 'The shimmer block(s). Recolor or change the opacity from outside; the default is a low-contrast foreground tint that reads in both light and dark.',
215
- recipe: 'kai-skeleton::part(skeleton) { background: var(--color-primary); opacity: 0.15 }',
216
- },
217
- ];
218
-
219
- /**
220
- * The parts of ONE attachment item, declared by `components/attachments.tsx`
221
- * and therefore surfaced by every element that renders an attachment — the
222
- * standalone `<kai-attachments>` AND the thread inside `<kai-message>` /
223
- * `<kai-chat>`. Shared rather than duplicated so the two can never document
224
- * different names for the same node.
225
- *
226
- * These are a styling seam and a TESTING seam, and the second is why they exist
227
- * at all. `examples/internal/openrouter-spike` proves "a user can see which file
228
- * was attached" by locating these; before they existed it pinned the chip by
229
- * `span.truncate` and broke the day the thread moved to the grid tile, while the
230
- * filename was still plainly on screen. A published part is what lets an
231
- * assertion name the thing rather than its current markup.
232
- */
233
- export const ATTACHMENT_ITEM_PARTS: PartDef[] = [
234
- {
235
- name: 'attachment',
236
- 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.',
237
- recipe: 'kai-chat::part(attachment) { border-radius: 0.25rem }',
238
- },
239
- {
240
- name: 'attachment-name',
241
- 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.',
242
- recipe: 'kai-chat::part(attachment-name) { font-size: 0.75rem }',
243
- },
244
- ];
245
-
246
- /** Styleable `::part`s of `<kai-message>`. (The `avatar` part is contributed by
247
- * the `avatar` slot's `part: true` flag, so it is not repeated here.) */
248
- export const MESSAGE_PARTS: PartDef[] = [
249
- {
250
- name: 'row',
251
- doc: 'The message row wrapper (avatar rail + body column). Restyle its gap or alignment from outside.',
252
- recipe: 'kai-message::part(row) { gap: 0.75rem }',
253
- },
254
- {
255
- name: 'bubble',
256
- doc: 'The content bubble wrapper. Restyle its background, radius, or padding; for a user message this is the rounded chat bubble.',
257
- recipe: 'kai-message::part(bubble) { background: var(--color-primary); color: var(--color-primary-foreground) }',
258
- },
259
- {
260
- name: 'content',
261
- doc: 'The rendered message text/markdown region (same node as `bubble`). Target it to tune typography from outside.',
262
- recipe: 'kai-message::part(content) { font-size: 0.9375rem }',
263
- },
264
- {
265
- name: 'actions',
266
- doc: 'The action-bar row (copy / like / regenerate …). Restyle its spacing or hide it entirely from outside.',
267
- recipe: 'kai-message::part(actions) { gap: 0.25rem }',
268
- },
269
- {
270
- name: 'citations',
271
- doc: 'The citation row rendered from the message’s `source` parts: a wrapped row of chips below the bubble, never inside it. Restyle its spacing or hide it entirely from outside.',
272
- recipe: 'kai-message::part(citations) { gap: 0.5rem }',
273
- },
274
- // A message renders its `file` parts through the same Attachment chrome
275
- // `<kai-attachments>` uses, so it exposes the same handles. Shared, not
276
- // restated — see ATTACHMENT_ITEM_PARTS.
277
- ...ATTACHMENT_ITEM_PARTS,
278
- ];
279
-
280
- /** Styleable `::part`s of `<kai-attachments>`. */
281
- export const ATTACHMENTS_PARTS: PartDef[] = [
282
- {
283
- name: 'preview',
284
- 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.',
285
- recipe: 'kai-attachments::part(preview) { max-width: 32rem; max-height: 24rem }',
286
- },
287
- ...ATTACHMENT_ITEM_PARTS,
288
- ];
289
-
290
- /** Styleable `::part`s of `<kai-status>`. */
291
- export const STATUS_PARTS: PartDef[] = [
292
- {
293
- name: 'dot',
294
- doc: 'The status dot. Recolor or resize it from outside; the `status` prop sets the default hue.',
295
- recipe: 'kai-status::part(dot) { background: var(--color-tool-green) }',
296
- },
297
- ];
298
-
299
- /** Styleable `::part`s of `<kai-tabs>`. */
300
- export const TABS_PARTS: PartDef[] = [
301
- {
302
- name: 'tablist',
303
- doc: 'The tab strip container (role="tablist"). Restyle its gap, padding, background, or radius from outside; the `variant` prop sets the segmented/underline defaults.',
304
- recipe: 'kai-tabs::part(tablist) { gap: 0.5rem; background: var(--color-card) }',
305
- },
306
- {
307
- name: 'tab',
308
- doc: 'A single tab button. Restyle from outside; the active tab carries a `[data-active]` attribute, so target `::part(tab)[data-active]` for the selected look.',
309
- recipe: 'kai-tabs::part(tab)[data-active] { color: var(--color-primary); font-weight: 600 }',
310
- },
311
- ];
312
-
313
- /** Styleable `::part`s of `<kai-voice-output>`. */
314
- export const VOICE_OUTPUT_PARTS: PartDef[] = [
315
- {
316
- name: 'button',
317
- doc: 'The speaker/play button. Restyle radius, size, padding, or colors from outside; it is a ghost icon button by default.',
318
- recipe: 'kai-voice-output::part(button) { border-radius: 9999px; color: var(--color-primary) }',
319
- },
320
- ];
321
-
322
- /** Slots of `<kai-screen>` (the default slot is the screen body). */
323
- export const SCREEN_SLOTS: SlotDef[] = [
324
- { name: 'title', mode: 'replace', part: true, doc: 'Rich header title; overrides the `headline` prop.' },
325
- { name: 'actions', mode: 'inject', doc: 'Header trailing cluster (e.g. an avatar or overflow menu).' },
326
- ];
327
-
328
- /** Styleable `::part`s of `<kai-screen>`. */
329
- export const SCREEN_PARTS: PartDef[] = [
330
- {
331
- name: 'header',
332
- doc: 'The back-header bar (back button + title + actions). Restyle its height, padding, or border from outside.',
333
- recipe: 'kai-screen::part(header) { height: 3.25rem; padding-inline: 1rem }',
334
- },
335
- {
336
- name: 'back',
337
- doc: 'The back button. Restyle or hide it from outside; `back="false"` removes it entirely.',
338
- recipe: 'kai-screen::part(back) { border-radius: 9999px }',
339
- },
340
- {
341
- name: 'body',
342
- doc: 'The full-bleed surface that fills the mount point and scrolls its content. Tune padding or background from outside.',
343
- recipe: 'kai-screen::part(body) { background: var(--color-card) }',
344
- },
345
- ];
346
-
347
- /** Slots of `<kai-card>` — structural regions only (the title/description are body
348
- * or `slot="header"` content you mark up). The body is the default slot. */
349
- export const CARD_SLOTS: SlotDef[] = [
350
- { name: 'media', mode: 'inject', doc: 'Full-bleed media (image/video/illustration) at the top (vertical) or start (horizontal). Clipped to the card corners.' },
351
- { name: 'header', mode: 'inject', doc: 'Header content, e.g. a title. Rendered above the body.' },
352
- { name: 'header-actions', mode: 'inject', doc: 'An actions cluster pinned to the end of the header row.' },
353
- { name: 'footer', mode: 'inject', doc: 'Footer content rendered below the body.' },
354
- { name: 'footer-actions', mode: 'inject', doc: 'Action buttons pinned to the end of the footer. Do NOT combine with a clickable/href card (nested interactive).' },
355
- ];
356
-
357
- /** Styleable `::part`s of `<kai-card>`. */
358
- export const CARD_PARTS: PartDef[] = [
359
- {
360
- name: 'card',
361
- doc: 'The card root (a div, or an a when href is set). Restyle its radius, border, or background; set --kai-card-spacing for padding/gaps (the dense prop sets the compact default).',
362
- recipe: 'kai-card::part(card) { border-radius: 1rem; --kai-card-spacing: 1.5rem }',
363
- },
364
- {
365
- name: 'media',
366
- doc: 'The full-bleed media region. Cap or crop it from outside (e.g. a fixed height with object-fit).',
367
- recipe: 'kai-card::part(media) { max-height: 12rem }',
368
- },
369
- {
370
- name: 'header',
371
- doc: 'The header row (header content + header-actions). Add a divider or adjust its alignment.',
372
- recipe: 'kai-card::part(header) { border-bottom: 1px solid var(--color-border) }',
373
- },
374
- {
375
- name: 'body',
376
- doc: 'The default-slot body region.',
377
- recipe: 'kai-card::part(body) { font-size: 0.9375rem }',
378
- },
379
- {
380
- name: 'footer',
381
- doc: 'The footer row (footer content + footer-actions).',
382
- recipe: 'kai-card::part(footer) { border-top: 1px solid var(--color-border) }',
383
- },
384
- {
385
- name: 'dismiss',
386
- doc: 'The dismiss (×) button shown when dismissible. Recolor or reposition it from outside.',
387
- recipe: 'kai-card::part(dismiss) { color: var(--color-muted-foreground) }',
388
- },
389
- ];
390
-
391
- /** Slots of `<kai-workspace>` (the five shell regions; main also takes the default slot). */
392
- export const WORKSPACE_SLOTS: SlotDef[] = [
393
- { name: 'header', mode: 'inject', part: true, doc: 'The top band across the full shell width (app bar, tabs, breadcrumbs).' },
394
- { name: 'start', mode: 'inject', part: true, doc: 'The inline-start aside column (a conversation rail, a nav, a file tree). Resizable and collapsible.' },
395
- { name: 'main', mode: 'inject', part: true, doc: 'The main region. Unnamed children project here too, via the default slot.' },
396
- { name: 'end', mode: 'inject', part: true, doc: 'The inline-end aside column (inspector, notes, preview). Resizable and collapsible.' },
397
- { name: 'footer', mode: 'inject', part: true, doc: 'The bottom band across the full shell width (status bar, disclaimers).' },
398
- ];
399
-
400
- /** Styleable `::part`s of `<kai-workspace>` (beyond the slot-backed header/start/main/end/footer parts). */
401
- export const WORKSPACE_PARTS: PartDef[] = [
402
- {
403
- name: 'aside',
404
- 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.',
405
- recipe: 'kai-workspace::part(aside) { background: var(--color-card) }',
406
- },
407
- ];
408
-
409
- /** Styleable `::part`s of `<kai-nav>`. */
410
- export const NAV_PARTS: PartDef[] = [
411
- {
412
- name: 'nav',
413
- doc: 'The nav list container. Restyle its gap or padding from outside.',
414
- recipe: 'kai-nav::part(nav) { gap: 0.25rem }',
415
- },
416
- {
417
- name: 'item',
418
- doc: 'A nav item button (leaf or group parent). The active leaf carries aria-current="page" and a group parent carries aria-expanded; target `::part(item)[aria-current]` for the selected look or `::part(item)[aria-expanded]` for a group row.',
419
- recipe: 'kai-nav::part(item)[aria-current] { background: var(--color-accent) }',
420
- },
421
- {
422
- name: 'group',
423
- doc: 'The nested child list rendered under an expanded group item. Add a left guide line or tune its indent from outside.',
424
- recipe: 'kai-nav::part(group) { border-left: 1px solid var(--color-border); margin-left: 1.1rem }',
425
- },
426
- {
427
- name: 'chevron',
428
- doc: 'The disclosure chevron on a group row (rotates when expanded). Recolor or resize it from outside.',
429
- recipe: 'kai-nav::part(chevron) { opacity: 1; color: var(--color-primary) }',
430
- },
431
- {
432
- name: 'status',
433
- doc: 'The per-item status cluster (a colored dot in the tone hue + an optional label). Shown only when an item carries a `status`; the `pulse` flag animates the dot. Restyle from outside.',
434
- recipe: 'kai-nav::part(status) { gap: 0.5rem }',
435
- },
436
- {
437
- name: 'meta',
438
- doc: 'The right-aligned muted trailing text on a row (e.g. a relative time). Shown only when an item carries `meta`; restyle from outside.',
439
- recipe: 'kai-nav::part(meta) { color: var(--color-foreground); font-variant-numeric: tabular-nums }',
440
- },
441
- {
442
- name: 'item-action',
443
- doc: 'The trailing per-item action / close button, a sibling of the item button. Shown only when an item carries `action` or `closable`; reveal it on hover or pin it visible from outside.',
444
- recipe: 'kai-nav::part(item-action) { opacity: 1 }',
445
- },
446
- ];
447
-
448
- /** Slots of `<kai-coachmark>` (the anchor/trigger is the default slot). */
449
- export const COACHMARK_SLOTS: SlotDef[] = [
450
- { name: 'content', mode: 'replace', doc: 'The bubble body text shown under the headline.' },
451
- ];
452
-
453
- /** Styleable `::part`s of `<kai-coachmark>`. */
454
- export const COACHMARK_PARTS: PartDef[] = [
455
- { name: 'bubble', doc: 'The hint bubble panel. Restyle its background, radius, or padding from outside; the default is bg-primary.', recipe: 'kai-coachmark::part(bubble) { border-radius: 1rem }' },
456
- { name: 'arrow', doc: 'The arrow pointing at the anchor. Inherits the bubble color; recolor it alongside the bubble.', recipe: 'kai-coachmark::part(arrow) { background: var(--color-accent) }' },
457
- { name: 'badge', doc: 'The small badge pill beside the headline (e.g. "New").', recipe: 'kai-coachmark::part(badge) { text-transform: none }' },
458
- { name: 'title', doc: 'The bold headline text.', recipe: 'kai-coachmark::part(title) { font-size: 0.9375rem }' },
459
- { name: 'dismiss', doc: 'The dismiss button. Recolor or reposition it from outside.', recipe: 'kai-coachmark::part(dismiss) { color: var(--color-primary-foreground) }' },
460
- ];
461
-
462
- /** Styleable `::part`s of `<kai-progress-bar>`. */
463
- export const PROGRESS_BAR_PARTS: PartDef[] = [
464
- { name: 'track', doc: 'The progress track (the background bar). Restyle its height, radius, or background from outside.', recipe: 'kai-progress-bar::part(track) { height: 0.5rem }' },
465
- { name: 'fill', doc: 'The filled portion; its width follows value/max. Recolor it from outside.', recipe: 'kai-progress-bar::part(fill) { background: var(--color-tool-green) }' },
466
- ];
467
-
468
- /** Styleable `::part`s of `<kai-context>`. The usage meter is the same shared
469
- * ProgressBar `<kai-progress-bar>` renders, mounted inside this element's own
470
- * shadow root, so `kai-context` exposes the same two names. Both sit inside the
471
- * hover-card breakdown and are in the DOM only while that card is open. */
472
- export const CONTEXT_PARTS: PartDef[] = [
473
- { name: 'track', doc: 'The usage meter track inside the hover-card breakdown. Carries `role="progressbar"` and is in the DOM only while the card is open. Restyle its height, radius, or background from outside.', recipe: 'kai-context::part(track) { height: 0.5rem }' },
474
- { name: 'fill', doc: 'The used-tokens portion of that meter. Its width follows `usedTokens / maxTokens`; its default color is the severity hue picked by `warnThreshold` / `dangerThreshold`, so recoloring it from outside replaces that signal.', recipe: 'kai-context::part(fill) { background: var(--color-tool-blue) }' },
475
- ];
476
-
477
- /** Styleable `::part`s of `<kai-file-tree>` — the changed-files / diff bits, shown
478
- * only when a file carries diff metadata (or the `summary` attribute is set). */
479
- export const FILE_TREE_PARTS: PartDef[] = [
480
- {
481
- name: 'summary',
482
- doc: 'The changed-files summary header (the file count, the summed +additions/-deletions, and the Collapse-all/Expand-all toggle). Rendered only when the `summary` attribute is set; restyle or hide it from outside.',
483
- recipe: 'kai-file-tree::part(summary) { border-bottom: none; padding-block: 0.5rem }',
484
- },
485
- {
486
- name: 'status',
487
- doc: 'The per-row change-status letter (A/M/D/R/U), shown when a file carries a `status`. Colored with the conventional VCS tool hues; restyle from outside.',
488
- recipe: 'kai-file-tree::part(status) { font-weight: 700 }',
489
- },
490
- {
491
- name: 'stat-additions',
492
- doc: 'The trailing `+N` additions stat on a file row (success/green tool hue, tabular-nums). Shown only when a file carries `additions`.',
493
- recipe: 'kai-file-tree::part(stat-additions) { color: var(--color-tool-green) }',
494
- },
495
- {
496
- name: 'stat-deletions',
497
- doc: 'The trailing `-N` deletions stat on a file row (error/red tool hue, tabular-nums). Shown only when a file carries `deletions`.',
498
- recipe: 'kai-file-tree::part(stat-deletions) { color: var(--color-tool-red) }',
499
- },
500
- ];
501
-
502
- /**
503
- * Per-element composition surface — the SINGLE registry the build extracts
504
- * (`scripts/gen-element-api.mjs`) into `element-meta.json`, the Custom Elements
505
- * Manifest (`cssParts`/`slots`), `docs/web-components.md`, and the `kai` MCP
506
- * `component_reference`. Each entry maps a `kai-*` tag to the slots it projects
507
- * and the `::part`s it exposes for styling. Slots flagged `part: true` are ALSO
508
- * styleable parts, so they surface in both places.
509
- *
510
- * Adding a `part="…"` in a facade/component without registering it here fails the
511
- * `slots.test.ts` drift guard — keep this in sync with the source.
512
- */
513
- export interface ElementComposition {
514
- slots?: SlotDef[];
515
- parts?: PartDef[];
516
- /**
517
- * What the element's DEFAULT (unnamed) `<slot>` projects — i.e. what a consumer
518
- * puts between the tags. Kept OUT of `slots` on purpose: those arrays are also
519
- * read at runtime by `readSlots()`, which would query a meaningless `[slot=""]`.
520
- * scripts/gen-element-api.mjs merges it back in as a slot with the empty name,
521
- * which is how the Custom Elements Manifest spells the default slot.
522
- *
523
- * Every facade that renders a bare `<slot />` needs one; guarded by
524
- * tests/elements/slot-registry-coverage.test.ts.
525
- */
526
- children?: string;
527
- }
528
-
529
- /** Slots + styleable `::part`s of `<kai-prompt-dock>`. */
530
- export const PROMPT_DOCK_SLOTS: SlotDef[] = [
531
- { name: 'top', mode: 'inject', part: true, doc: 'The top lip: a notice or banner above the input. Rendered only when filled.' },
532
- { name: 'bottom', mode: 'inject', part: true, doc: 'The bottom lip: a mode or controls row below the input. Rendered only when filled.' },
533
- ];
534
- export const PROMPT_DOCK_PARTS: PartDef[] = [
535
- {
536
- name: 'tray',
537
- doc: 'The recessed tray that frames the input. The `appearance`/`frame` props set the defaults; the --kai-prompt-dock-* tokens fine-tune surface/border/radius/inset.',
538
- recipe: 'kai-prompt-dock::part(tray) { --kai-prompt-dock-radius: 1rem }',
539
- },
540
- ];
541
-
542
- /** Slots + styleable `::part`s of `<kai-dock>` (the floating corner launcher — not
543
- * `<kai-prompt-dock>`, which is an in-flow tray around a prompt input). */
544
- export const DOCK_SLOTS: SlotDef[] = [
545
- { name: 'panel', mode: 'replace', part: true, 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.' },
546
- { name: 'launcher', mode: 'inject', 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.' },
547
- { name: 'launcher-open', mode: 'inject', 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.' },
548
- ];
549
- export const DOCK_PARTS: PartDef[] = [
550
- { name: 'launcher', 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.', recipe: 'kai-dock::part(launcher) { background: var(--color-info) }' },
551
- { name: 'badge', doc: 'The unread dot on the launcher, rendered only while closed and only when `unread` is set. Restyle its color or size.', recipe: 'kai-dock::part(badge) { background: var(--color-success) }' },
552
- ];
553
-
554
- /** Styleable `::part`s of `<kai-segmented>`. */
555
- export const SEGMENTED_PARTS: PartDef[] = [
556
- { name: 'track', doc: 'The segmented track (the pill container holding the segments). Restyle its background, radius, or padding.', recipe: 'kai-segmented::part(track) { border-radius: 9999px }' },
557
- { name: 'segment', doc: 'Each segment button. Restyle padding, font weight, or the selected look.', recipe: 'kai-segmented::part(segment) { font-weight: 600 }' },
558
- ];
559
-
560
- /** Styleable `::part`s of `<kai-settings-group>`. */
561
- export const SETTINGS_GROUP_PARTS: PartDef[] = [
562
- { name: 'header', doc: 'The group heading + description block. Restyle its spacing or typography.', recipe: 'kai-settings-group::part(header) { margin-bottom: 0.75rem }' },
563
- { name: 'body', doc: 'The bordered card holding the setting rows. Restyle its surface, border, or radius.', recipe: 'kai-settings-group::part(body) { border-radius: 1rem }' },
564
- ];
565
-
566
- /** Slots + styleable `::part`s of `<kai-setting-item>`. */
567
- export const SETTING_ITEM_SLOTS: SlotDef[] = [
568
- { name: 'control', mode: 'inject', part: true, doc: 'The row control (a switch, segmented, select, etc.), right-aligned. Omit it for a label-only row.' },
569
- ];
570
- export const SETTING_ITEM_PARTS: PartDef[] = [
571
- { name: 'label', doc: 'The label + description block on the left of the row. Restyle its typography or spacing.', recipe: 'kai-setting-item::part(label) { gap: 0.125rem }' },
572
- ];
573
-
574
- /** Slots + styleable `::part`s of `<kai-pane>` (the editor-group pane frame). */
575
- export const PANE_SLOTS: SlotDef[] = [
576
- { name: 'leading', mode: 'inject', doc: 'A glyph or avatar at the start of the pane header.' },
577
- { name: 'actions', mode: 'inject', doc: 'Extra header controls, before the built-in window controls.' },
578
- { name: 'footer', mode: 'inject', part: true, doc: 'A pinned row below the body (e.g. a composer).' },
579
- ];
580
- export const PANE_PARTS: PartDef[] = [
581
- { name: 'header', doc: 'The pane header bar (leading + title/status + actions + window controls).', recipe: 'kai-pane::part(header) { padding-inline: 0.75rem }' },
582
- { name: 'body', doc: 'The scrolling body region (the default slot).', recipe: 'kai-pane::part(body) { padding: 1rem }' },
583
- { name: 'controls', doc: 'The window-control cluster (maximize/close, and split/dock when enabled).', recipe: 'kai-pane::part(controls) { gap: 0.25rem }' },
584
- ];
585
-
586
- /** Styleable `::part`s of `<kai-agent-card>`. */
587
- export const AGENT_CARD_PARTS: PartDef[] = [
588
- { name: 'status', doc: 'The leading tone-colored status dot.', recipe: 'kai-agent-card::part(status) { width: 0.625rem; height: 0.625rem }' },
589
- { name: 'menu', doc: 'The trailing overflow ("...") menu button.', recipe: 'kai-agent-card::part(menu) { opacity: 1 }' },
590
- ];
591
-
592
- /** Styleable `::part`s of `<kai-code-block>` (one syntax-highlighted code block).
593
- * The code region itself is not a part — it is rebuilt when the highlight lands,
594
- * and its look is owned by the Shiki theme (`code-theme`). */
595
- export const CODE_BLOCK_PARTS: PartDef[] = [
596
- { name: 'copy', doc: 'The copy-to-clipboard button in the header row. Hide it with `copy="false"` rather than CSS.', recipe: 'kai-code-block::part(copy) { color: var(--color-primary) }' },
597
- ];
598
-
599
- /** Slots + styleable `::part`s of `<kai-dialog>` (the centered modal). */
600
- export const DIALOG_SLOTS: SlotDef[] = [
601
- { name: 'header', mode: 'inject', part: true, doc: 'Optional title region at the top of the panel.' },
602
- { name: 'footer', mode: 'inject', part: true, doc: 'Optional actions region at the bottom of the panel.' },
603
- ];
604
- export const DIALOG_PARTS: PartDef[] = [
605
- { name: 'backdrop', doc: 'The full-area scrim behind the panel. Restyle its color/blur.', recipe: 'kai-dialog::part(backdrop) { background: rgb(0 0 0 / 0.6) }' },
606
- { name: 'panel', doc: 'The centered modal panel. Restyle width, radius, padding.', recipe: 'kai-dialog::part(panel) { max-width: 32rem }' },
607
- { name: 'body', doc: 'The scrolling content region (the default slot).', recipe: 'kai-dialog::part(body) { padding: 1.25rem }' },
608
- ];
609
-
610
- /** Styleable `::part`s of `<kai-pane-group>` (the editor group: a tab strip over
611
- * the active tab's pane). The per-tab content slots are NAMED DYNAMICALLY by tab
612
- * id (`slot="<tab id>"`) plus a default slot, so they are not enumerable here —
613
- * only the styleable parts are registered. */
614
- export const PANE_GROUP_PARTS: PartDef[] = [
615
- { name: 'tabs', doc: 'The tab strip (role="tablist"). Restyle its background, height, padding, or gap from outside.', recipe: 'kai-pane-group::part(tabs) { background: var(--color-card); gap: 0.25rem }' },
616
- { name: 'tab', doc: 'A single tab button. The active tab carries `[aria-selected="true"]`; target `::part(tab)[aria-selected="true"]` for the selected look.', recipe: 'kai-pane-group::part(tab)[aria-selected="true"] { background: var(--color-accent) }' },
617
- { name: 'body', doc: 'The active tab\'s content region (the named/default slot host).', recipe: 'kai-pane-group::part(body) { padding: 0.75rem }' },
618
- { name: 'menu', doc: 'The per-tab "…" overflow button. Reveal it on hover or pin it visible from outside.', recipe: 'kai-pane-group::part(menu) { opacity: 1 }' },
619
- { name: 'close', doc: 'The per-tab close ("×") button. Recolor, resize, or hide it from outside.', recipe: 'kai-pane-group::part(close) { color: var(--color-muted-foreground) }' },
620
- ];
621
-
622
- /** Affix slots + styleable `::part`s of `<kai-input>` (the field shell). */
623
- export const INPUT_SLOTS: SlotDef[] = [
624
- { name: 'leading', mode: 'inject', doc: 'A glyph, prefix, or affix at the start of the field, inside the border.' },
625
- { name: 'trailing', mode: 'inject', doc: 'A button, unit, or affix at the end of the field, inside the border.' },
626
- ];
627
- export const INPUT_PARTS: PartDef[] = [
628
- { name: 'field', doc: 'The bordered control box (the row wrapping any affixes plus the input). Restyle its border, radius, surface, or focus ring.', recipe: 'kai-input::part(field) { border-radius: 0.75rem }' },
629
- { name: 'input', doc: 'The inner input element. Restyle its text, padding, or placeholder.', recipe: 'kai-input::part(input) { font-variant-numeric: tabular-nums }' },
630
- { name: 'label', doc: 'The field label above the control. Restyle its typography or spacing.', recipe: 'kai-input::part(label) { font-weight: 600 }' },
631
- { name: 'hint', doc: 'The hint or error line below the control. Restyle its typography.', recipe: 'kai-input::part(hint) { font-style: italic }' },
632
- ];
633
-
634
- /** Styleable `::part`s of `<kai-search>` (the debounced filter field; composes the
635
- * kai-input field plus a clear button). */
636
- export const SEARCH_PARTS: PartDef[] = [
637
- { name: 'field', doc: 'The bordered control box (the row wrapping the search icon, input, and clear button).', recipe: 'kai-search::part(field) { border-radius: 9999px }' },
638
- { name: 'input', doc: 'The inner search input element.', recipe: 'kai-search::part(input) { font-size: 0.875rem }' },
639
- { name: 'clear', doc: 'The trailing clear ("x") button, shown when the field is non-empty.', recipe: 'kai-search::part(clear) { opacity: 1 }' },
640
- ];
641
-
642
- /** Styleable `::part`s of `<kai-editable-label>` (inline rename; the edit field is the kai-input field). */
643
- export const EDITABLE_LABEL_PARTS: PartDef[] = [
644
- { name: 'text', doc: 'The read-mode label text. Restyle its typography; it swaps to the input on edit.', recipe: 'kai-editable-label::part(text) { font-weight: 600 }' },
645
- { name: 'input', doc: 'The edit-mode input (the composed kai-input field).', recipe: 'kai-editable-label::part(input) { font: inherit }' },
646
- ];
647
-
648
- /** Styleable `::part`s of `<kai-kbd>` (the keyboard-shortcut display). */
649
- export const KBD_PARTS: PartDef[] = [
650
- { name: 'key', doc: 'Each key cap. Restyle its surface, border, radius, or font.', recipe: 'kai-kbd::part(key) { border-radius: 0.375rem }' },
651
- { name: 'separator', doc: 'The gap between key caps. Inject a literal joiner (e.g. a plus sign) from outside.', recipe: 'kai-kbd::part(separator)::after { content: "+" }' },
652
- ];
653
-
654
- /** Styleable `::part`s of `<kai-command>` (the command palette). */
655
- export const COMMAND_PARTS: PartDef[] = [
656
- { name: 'shortcut', doc: 'The right-aligned per-row keyboard shortcut, rendered as kai-kbd key caps. Shown only when a row carries a `shortcut`.', recipe: 'kai-command::part(shortcut) { opacity: 0.8 }' },
657
- ];
658
-
659
- /** Styleable `::part`s of `<kai-menu>` (the actions dropdown). */
660
- export const MENU_PARTS: PartDef[] = [
661
- { name: 'shortcut', doc: 'The right-aligned per-item keyboard shortcut, rendered as kai-kbd key caps. Shown only when an item carries a `shortcut`.', recipe: 'kai-menu::part(shortcut) { opacity: 0.8 }' },
662
- ];
663
-
664
- /** Slots of `<kai-thread>` (the standalone scrolling message list; messages come
665
- * from the `messages` prop). */
666
- export const THREAD_SLOTS: SlotDef[] = [
667
- { name: 'empty', mode: 'replace', doc: 'Custom zero-state rendered in the message area while the thread is empty; replaces the built-in default.' },
668
- ];
669
-
670
- /** Slots of `<kai-empty>`. The body is the default slot; `media` is the named seam. */
671
- export const EMPTY_SLOTS: SlotDef[] = [
672
- { name: 'media', mode: 'replace', doc: 'The leading illustration or icon above the title (any inline SVG or <img>). Replaces the built-in media box.' },
673
- ];
674
-
675
- /** Slots of `<kai-popover>`. The panel body is the default slot; `trigger` is the
676
- * control the panel anchors to and opens from. */
677
- export const POPOVER_SLOTS: SlotDef[] = [
678
- { name: 'trigger', mode: 'replace', doc: 'The control that opens the popover (a button, an avatar, …). The panel anchors to it.' },
679
- ];
680
-
681
- /** Slots of `<kai-dropdown>`. The menu body is the default slot; `trigger` is the
682
- * VISUAL content of the built-in trigger button (never your own `<button>`/`<a>`,
683
- * which would nest interactive elements — the `kai-menu` rule). */
684
- export const DROPDOWN_SLOTS: SlotDef[] = [
685
- { name: 'trigger', mode: 'replace', doc: 'Visual content of the trigger button (an icon, text, an `<svg>`). Replaces the built-in trigger* content; name it with `label`.' },
686
- ];
687
-
688
- /** Styleable `::part`s of `<kai-audio-visualizer>`. Every DOM variant (`bar`,
689
- * `grid`, `radial`) shares the `bar`/`cell` markup pattern; the shader variants
690
- * (`wave`, `aurora`) share the `canvas` part. Lit items ALSO carry the
691
- * `highlighted` part token, so `::part(bar highlighted)`/`::part(cell
692
- * highlighted)` selects only the lit ones. `::part(bar)[data-kai-highlighted=
693
- * "true"]` looks plausible but is invalid CSS: a CSS attribute selector
694
- * cannot follow a pseudo-element (`CSS.supports(selector(...))` returns
695
- * `false` for it in Chromium, and `insertRule` throws). `data-kai-index` /
696
- * `data-kai-highlighted` still exist on the element for consumers reading
697
- * them from INSIDE the shadow root or via the Solid render-prop; they are
698
- * just not reachable from an external `::part()` selector. */
699
- export const AUDIO_VISUALIZER_PARTS: PartDef[] = [
700
- {
701
- name: 'bar',
702
- doc: 'A single bar in the `bar` variant, or a single spoke in the `radial` variant. Also carries `data-kai-index` and `data-kai-highlighted` ("true"/"false") for use inside the shadow root; to style the lit state from OUTSIDE, combine with the `highlighted` part below rather than an attribute selector.',
703
- recipe: 'kai-audio-visualizer::part(bar) { border-radius: 2px }\nkai-audio-visualizer::part(bar highlighted) { background: var(--brand) }',
704
- },
705
- {
706
- name: 'cell',
707
- doc: 'A single dot in the `grid` variant. Also carries `data-kai-index` and `data-kai-highlighted` ("true"/"false") for use inside the shadow root; to style the lit state from OUTSIDE, combine with the `highlighted` part below rather than an attribute selector.',
708
- recipe: 'kai-audio-visualizer::part(cell) { border-radius: 9999px }\nkai-audio-visualizer::part(cell highlighted) { background: var(--brand) }',
709
- },
710
- {
711
- name: 'highlighted',
712
- doc: 'A second part TOKEN present on a `bar` or `cell` exactly when the sequencer or live audio has it lit, not a standalone styleable element. Combine it in the same `::part()` argument: `::part(bar highlighted)` or `::part(cell highlighted)`. This is the external equivalent of the internal `data-kai-highlighted="true"` attribute, which a `::part()` selector cannot reach (an attribute selector cannot follow a pseudo-element).',
713
- recipe: 'kai-audio-visualizer::part(bar highlighted) { background: var(--brand) }\nkai-audio-visualizer::part(cell highlighted) { background: var(--brand) }',
714
- },
715
- {
716
- name: 'canvas',
717
- doc: 'The WebGL canvas backing the `wave` and `aurora` variants. Restyle its size or radius, or layer a mask/filter, from outside.',
718
- recipe: 'kai-audio-visualizer::part(canvas) { border-radius: 0.75rem }',
719
- },
720
- ];
721
-
722
- export const ELEMENT_COMPOSITION: Record<string, ElementComposition> = {
723
- 'kai-chat': { slots: CHAT_SLOTS, parts: CHAT_PARTS },
724
- 'kai-command': { parts: COMMAND_PARTS },
725
- 'kai-conversations': { slots: CONVERSATIONS_SLOTS, parts: CONVERSATIONS_PARTS, children: 'Your own `<kai-conversation-item>` rows (item mode: the consumer-owned loop). Data rows do not render while any are present.' },
726
- 'kai-conversation-item': { slots: CONVERSATION_ITEM_SLOTS, parts: CONVERSATION_ITEM_PARTS, children: 'The row title. `leading`, `meta` and `menu` are the named regions around it.' },
727
- 'kai-message': { slots: MESSAGE_SLOTS, parts: MESSAGE_PARTS },
728
- 'kai-thread': { slots: THREAD_SLOTS },
729
- 'kai-prompt-input': { slots: PROMPT_INPUT_SLOTS, parts: PROMPT_INPUT_PARTS },
730
- 'kai-button': { slots: BUTTON_SLOTS, parts: BUTTON_PARTS, children: 'The button\'s label. Omit it for an icon-only button (pair with `aria-label`).' },
731
- 'kai-badge': { parts: BADGE_PARTS, children: 'The badge\'s label: text, or a small inline icon plus text.' },
732
- 'kai-icon': { parts: ICON_PARTS },
733
- 'kai-separator': { parts: SEPARATOR_PARTS },
734
- 'kai-scroll-area': { parts: SCROLL_AREA_PARTS, children: 'The scrollable content.' },
735
- 'kai-notice': { slots: NOTICE_SLOTS, children: 'The notice message. `icon` and `action` are the named seams around it.' },
736
- 'kai-hover-card': { slots: HOVER_CARD_SLOTS, children: 'The TRIGGER the card hovers off. The card body is the `card` slot.' },
737
- 'kai-menu': { slots: MENU_SLOTS, parts: MENU_PARTS },
738
- 'kai-skeleton': { parts: SKELETON_PARTS },
739
- 'kai-attachments': { parts: ATTACHMENTS_PARTS },
740
- 'kai-status': { parts: STATUS_PARTS },
741
- 'kai-tabs': { parts: TABS_PARTS },
742
- 'kai-voice-output': { parts: VOICE_OUTPUT_PARTS },
743
- 'kai-screen': { slots: SCREEN_SLOTS, parts: SCREEN_PARTS, children: 'The screen body, below the title bar.' },
744
- 'kai-card': { slots: CARD_SLOTS, parts: CARD_PARTS, children: 'The card body, below the header/media regions.' },
745
- 'kai-workspace': { slots: WORKSPACE_SLOTS, parts: WORKSPACE_PARTS, children: 'The main region content (same region as the `main` slot): your `<kai-chat>`, or any app view.' },
746
- 'kai-nav': { parts: NAV_PARTS },
747
- 'kai-coachmark': { slots: COACHMARK_SLOTS, parts: COACHMARK_PARTS, children: 'The ANCHOR the coachmark points at: the element it attaches to and positions against. The bubble body is the `content` slot.' },
748
- 'kai-progress-bar': { parts: PROGRESS_BAR_PARTS },
749
- 'kai-context': { parts: CONTEXT_PARTS },
750
- 'kai-file-tree': { parts: FILE_TREE_PARTS },
751
- 'kai-prompt-dock': { slots: PROMPT_DOCK_SLOTS, parts: PROMPT_DOCK_PARTS, children: 'The input the dock wraps, typically a `<kai-prompt-input>`. The `top`/`bottom` slots are the lips around it.' },
752
- 'kai-segmented': { parts: SEGMENTED_PARTS },
753
- 'kai-settings-group': { parts: SETTINGS_GROUP_PARTS, children: 'The `<kai-setting-item>` rows in this group.' },
754
- 'kai-setting-item': { slots: SETTING_ITEM_SLOTS, parts: SETTING_ITEM_PARTS },
755
- 'kai-pane': { slots: PANE_SLOTS, parts: PANE_PARTS, children: 'The pane body, below the header row.' },
756
- 'kai-pane-group': { parts: PANE_GROUP_PARTS, children: 'Content shown for every tab. Use it INSTEAD of the per-tab `slot="<tab id>"` seams when you swap the content yourself.' },
757
- 'kai-agent-card': { parts: AGENT_CARD_PARTS },
758
- 'kai-dialog': { slots: DIALOG_SLOTS, parts: DIALOG_PARTS, children: 'The dialog body, between the `header` and `footer` slots.' },
759
- 'kai-dock': { slots: DOCK_SLOTS, parts: DOCK_PARTS, children: 'The panel body, the same region as `slot="panel"`.' },
760
- 'kai-input': { slots: INPUT_SLOTS, parts: INPUT_PARTS },
761
- 'kai-search': { parts: SEARCH_PARTS },
762
- 'kai-kbd': { parts: KBD_PARTS, children: 'Literal key text, when you are not using the `keys` prop to render key caps.' },
763
- 'kai-editable-label': { parts: EDITABLE_LABEL_PARTS },
764
- 'kai-empty': { slots: EMPTY_SLOTS, children: 'The empty-state body below the title/description, usually the call to action.' },
765
- 'kai-file-upload': { children: 'Custom dropzone content, replacing the default label (the `label` prop is the fallback).' },
766
- 'kai-popover': { slots: POPOVER_SLOTS, children: 'The popover panel body. The control that opens it is the `trigger` slot.' },
767
- 'kai-dropdown': { slots: DROPDOWN_SLOTS, children: 'The menu body: your own rows. Give each `role="menuitem"`. The control that opens it is the `trigger` slot.' },
768
- 'kai-resizable': { children: 'The `<kai-resizable-item>` panels, in order. Dividers are inserted between them.' },
769
- 'kai-resizable-item': { children: 'This panel\'s content.' },
770
- 'kai-tooltip': { children: 'The TRIGGER the tooltip describes. The tip text is the `text` prop.' },
771
- 'kai-code-block': { parts: CODE_BLOCK_PARTS },
772
- 'kai-audio-visualizer': { parts: AUDIO_VISUALIZER_PARTS },
773
- };
774
-
775
- /**
776
- * Which slots have projected light-DOM content — a DIRECT child of `host`
777
- * carrying the matching `slot` attribute. Pure and synchronous; safe in jsdom
778
- * and SSR (returns all-false when `host` has no matching children). The facade
779
- * calls this on mount and on every childList mutation.
780
- */
781
- export function readSlots(host: Element, defs: SlotDef[] = CHAT_SLOTS): Record<string, boolean> {
782
- const out: Record<string, boolean> = {};
783
- for (const def of defs) {
784
- out[def.name] = !!host.querySelector(`:scope > [slot="${def.name}"]`);
785
- }
786
- return out;
787
- }