@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,102 +0,0 @@
1
- import type { ToolPart, RawOrigin } from '../components/tool-types';
2
- import type { AttachmentData } from '../components/attachment-types';
3
- import type { CardEnvelope } from '../primitives/card-contract';
4
-
5
- /** Re-exported so consumers of chat-types (and MessagePart) can keep using
6
- * RawOrigin unqualified. It is defined in components/tool-types.ts, not here,
7
- * to keep the components -> elements import direction one-way. */
8
- export type { RawOrigin };
9
-
10
- /** The five built-in action buttons (each carries its own curated icon + label). */
11
- export type ChatMessageAction = 'copy' | 'like' | 'dislike' | 'regenerate' | 'edit';
12
-
13
- /** A like/dislike feedback vote on an assistant message. */
14
- export type FeedbackVote = 'like' | 'dislike';
15
-
16
- /** A host-defined action button. `icon` is a curated registry name (see
17
- * `src/ui/action-icons.ts`); unknown/absent icons render label-only. */
18
- export interface CustomAction {
19
- /** Emitted as the `kai-message-action` detail `action` when clicked. */
20
- id: string;
21
- /** Visible/`aria-label` text. */
22
- label: string;
23
- /** A curated icon name from the action-icon registry. */
24
- icon?: string;
25
- /** Tooltip text shown on hover. Defaults to `label` when omitted. */
26
- tooltip?: string;
27
- }
28
-
29
- /** The speaker avatar for a message row. (Mirrors the `…Data` convention of
30
- * `AttachmentData`; named to avoid clashing with the `MessageAvatar` component.) */
31
- export interface AvatarData {
32
- /** Image URL. When present, renders an `<img>`. */
33
- src?: string;
34
- /** Initials/short text shown when there is no `src`. */
35
- fallback?: string;
36
- /** Alt text for the image. */
37
- alt?: string;
38
- }
39
-
40
- /** A citation the model produced. */
41
- export interface Source {
42
- id?: string;
43
- url?: string;
44
- title?: string;
45
- snippet?: string;
46
- /** Citation marker number, when the model numbers its citations. */
47
- index?: number;
48
- }
49
-
50
- /** The public name for the citation carried by a `source` part, and the argument
51
- * type of `AssistantStream.addSource`. The bare `Source` name is already taken
52
- * on the public entry by the citation-chip COMPONENT (`./components/source`),
53
- * so exporting this interface unaliased would be a duplicate identifier and the
54
- * type would be unnameable from `@kitn.ai/ui`. */
55
- export type MessageSource = Source;
56
-
57
- /** One ordered piece of message content. Closed union: extension happens at the CARD
58
- * layer via the card registry, not by adding variants here. */
59
- export type MessagePart =
60
- | { type: 'text'; text: string; raw?: RawOrigin }
61
- | {
62
- type: 'reasoning';
63
- text: string;
64
- label?: string;
65
- /** Provider block index. Keeps parallel reasoning blocks distinct. */
66
- index?: number;
67
- /** Which provider RESPONSE STREAM `index` was counted in. Anthropic restarts
68
- * content-block indices at 0 for every message, and a multi-round tool loop
69
- * folds several of those messages into ONE assistant turn, so `index` alone
70
- * is not unique within `parts`. Set by the wire adapter, one value per
71
- * `consumeModelStream` call. See `appendReasoningPart`. */
72
- streamId?: string;
73
- /** Load-bearing on the OpenAI wire, informational on the Anthropic one.
74
- * `toOpenAIMessages({ reasoning: 'include' })` REBUILDS a signed
75
- * `reasoning_details` entry from `text` plus this, because `raw` after a
76
- * streamed turn is a textless fragment: only the final frame carries the
77
- * signature and it has no text, and `appendReasoningPart` resolves `raw`
78
- * last-write-wins. `toAnthropicMessages` ignores this field and echoes
79
- * `raw.payload` verbatim — a thinking block rebuilt from text plus
80
- * signature is a hard 400. */
81
- signature?: string;
82
- raw?: RawOrigin;
83
- }
84
- | { type: 'tool'; tool: ToolPart; raw?: RawOrigin }
85
- | { type: 'card'; envelope: CardEnvelope; raw?: RawOrigin }
86
- | { type: 'source'; source: Source; raw?: RawOrigin }
87
- | { type: 'file'; attachment: AttachmentData; raw?: RawOrigin };
88
-
89
- export interface ChatMessage {
90
- id: string;
91
- role: 'user' | 'assistant';
92
- /** The ONLY content channel. Ordered. */
93
- parts: MessagePart[];
94
- /** Action buttons under the message. Chrome, not content. */
95
- actions?: (ChatMessageAction | CustomAction)[];
96
- /** Optional speaker avatar shown to the left of the message column. */
97
- avatar?: AvatarData;
98
- /** Controlled feedback vote. When set, it wins over the facade's internal
99
- * optimistic state (`m.feedback ?? feedbackMap[m.id]`), so a host that
100
- * persists votes can re-hydrate them. */
101
- feedback?: FeedbackVote;
102
- }
@@ -1,188 +0,0 @@
1
- import { createSignal, onMount, onCleanup, untrack } from 'solid-js';
2
- import { defineWebComponent } from './define';
3
- import { readSlots, WORKSPACE_SLOTS } from './slots';
4
- import {
5
- WorkspaceShell,
6
- type WorkspaceShellController,
7
- type WorkspaceAsideSide,
8
- type WorkspaceAsideToggleDetail,
9
- type WorkspaceAsideResizeDetail,
10
- } from '../components/workspace-shell';
11
-
12
- interface Props extends Record<string, unknown> {
13
- /** Controlled collapsed state of the start aside. Set this as a JS property
14
- * (`el.startCollapsed = true`) to drive the aside from your app, updating it
15
- * in response to the `kai-aside-toggle` event. Omit for uncontrolled (the
16
- * element manages it). */
17
- startCollapsed?: boolean;
18
- /** Initial collapsed state of the start aside when uncontrolled (default
19
- * false). Use the `default-start-collapsed` attribute to start collapsed in
20
- * plain HTML. */
21
- defaultStartCollapsed?: boolean;
22
- /** Controlled collapsed state of the end aside. Set this as a JS property
23
- * (`el.endCollapsed = true`) to drive the aside from your app, updating it
24
- * in response to the `kai-aside-toggle` event. Omit for uncontrolled (the
25
- * element manages it). */
26
- endCollapsed?: boolean;
27
- /** Initial collapsed state of the end aside when uncontrolled (default
28
- * false). Use the `default-end-collapsed` attribute to start collapsed in
29
- * plain HTML. */
30
- defaultEndCollapsed?: boolean;
31
- /** Auto-collapse both asides when the shell's own width drops below this many
32
- * px, and re-expand when it grows back above. Applies to uncontrolled asides
33
- * only (it never fights an app-driven collapsed prop); omit to disable.
34
- * Fires `kai-aside-toggle`. Attribute: `collapse-below`. */
35
- collapseBelow?: number;
36
- /** Below this shell width in px, an expanded aside renders as an overlay
37
- * drawer over the main region instead of a column beside it. Escape inside
38
- * the drawer closes it and returns focus to the element focused before it
39
- * opened. Omit to disable. Attribute: `drawer-below`. */
40
- drawerBelow?: number;
41
- /** Density hint. Reflected as a `data-compact` hook on the root (and as the
42
- * `compact` attribute on the element) for your CSS and slotted content; the
43
- * shell itself keeps no other opinion about density. */
44
- compact?: boolean;
45
- }
46
-
47
- /** Events fired by `<kai-workspace>`. Layout only: every chat event now belongs
48
- * to the part that fires it, inside your own markup. */
49
- interface Events {
50
- /** An aside collapsed or expanded (a method, the breakpoint, the drawer's Escape). */
51
- 'kai-aside-toggle': WorkspaceAsideToggleDetail;
52
- /** The aside was resized (fires per drag step, keyboard nudge, or a handle double-click reset), width in px. */
53
- 'kai-aside-resize': WorkspaceAsideResizeDetail;
54
- }
55
-
56
- /**
57
- * `<kai-workspace>` — the chat-agnostic layout shell: five slots (`header` ·
58
- * `start` · `main` · `end` · `footer`), resize handles between the columns,
59
- * per-aside collapse, collapse-below-breakpoint, and a mobile drawer mode for
60
- * the asides. It knows nothing about chat: a file tree in `start` is as valid
61
- * as `<kai-conversations>`, and the workspace app slots `<kai-conversations>`
62
- * and `<kai-chat>` into it.
63
- *
64
- * ```html
65
- * <kai-workspace collapse-below="720" drawer-below="640">
66
- * <kai-conversations slot="start"></kai-conversations>
67
- * <kai-chat></kai-chat>
68
- * </kai-workspace>
69
- * ```
70
- *
71
- * Aside geometry is CSS custom properties, not props (the `kai-dock` rule):
72
- * `--kai-workspace-start-width` (280px) · `--kai-workspace-start-min-width`
73
- * (200px) · `--kai-workspace-start-max-width` (480px) · `--kai-workspace-end-width`
74
- * (320px) · `--kai-workspace-end-min-width` (200px) · `--kai-workspace-end-max-width`
75
- * (480px). Read once at upgrade. Parts: `header` · `start` · `main` · `end` ·
76
- * `footer` (the asides also match `::part(aside)`).
77
- *
78
- * **BREAKING (0.24):** this element was a chat
79
- * preset; it is now a layout shell, and everything chat-shaped is gone from its
80
- * surface. Where each removed prop went:
81
- *
82
- * - `conversations` / `activeId` / `groups` / `noConversations`: set them on your
83
- * own `<kai-conversations slot="start">`.
84
- * - `messages` / `loading` / `proseSize` / `codeTheme` / `codeHighlight` /
85
- * `chatTitle` / `scrollButton` / `cardTypes` / `cardSchemas`: set them on your
86
- * own `<kai-chat>` in the main region.
87
- * - `value` / `placeholder` / `suggestions` / `suggestionMode` / `voice` /
88
- * `triggers` / `kindIcons` and the renamed `webSearch` (was `search`): the
89
- * composer surface on `<kai-chat>` or `<kai-prompt-input>`.
90
- * - `models` / `currentModel` / `context`: header chrome you slot (a model
91
- * picker is a part in a slot, not three orchestrator props).
92
- * - `sidebarWidth` / `sidebarMinWidth` / `sidebarMaxWidth`: the
93
- * `--kai-workspace-start-*` custom properties above.
94
- * - `sidebarCollapsed` / `defaultSidebarCollapsed`: `startCollapsed` /
95
- * `defaultStartCollapsed` (per-aside; the end aside has its own pair).
96
- * - `collapseBelow`: kept, now collapsing both asides.
97
- * - `compact`: kept as a reflected density hint; the rail's row density is
98
- * `<kai-conversations>`' own `compact`.
99
- * - Chat events (`kai-submit`, `kai-conversation-select`, `kai-message-action`,
100
- * `kai-model-change`, `kai-search`, `kai-voice`, `kai-value-change`,
101
- * `kai-suggestion-click`): listen on the part that fires them.
102
- * `kai-sidebar-toggle` is now `kai-aside-toggle` with a `side`.
103
- * - Methods: `toggleSidebar()` / `collapseSidebar()` / `expandSidebar()` are now
104
- * `toggleAside(side)` / `collapseAside(side)` / `expandAside(side)`; the
105
- * thread methods (`focus`/`clear`/`send`/`scrollToBottom`) live on your
106
- * `<kai-chat>`.
107
- *
108
- * The migration path for a full app is the `workspace` block scaffold (the kai
109
- * MCP `scaffold` tool), which emits this composition wired.
110
- */
111
- defineWebComponent<Props, Events>('kai-workspace', {
112
- startCollapsed: undefined,
113
- defaultStartCollapsed: undefined,
114
- endCollapsed: undefined,
115
- defaultEndCollapsed: undefined,
116
- collapseBelow: undefined,
117
- drawerBelow: undefined,
118
- compact: undefined,
119
- }, (props, { dispatch, flag, expose, element, reflectFlag }) => {
120
- // Which slots the consumer has filled. A bare <slot> is always a truthy JSX
121
- // node, so each optional region renders ONLY when readSlots reports projected
122
- // light-DOM content (re-read on childList mutation). Main always renders.
123
- const [slots, setSlots] = createSignal<Record<string, boolean>>({});
124
- onMount(() => {
125
- const read = () => setSlots(readSlots(element, WORKSPACE_SLOTS));
126
- read();
127
- const observer = new MutationObserver(read);
128
- observer.observe(element, { childList: true });
129
- onCleanup(() => observer.disconnect());
130
- });
131
-
132
- // Reflect the read-back flags (the G-05 rule: a bare attribute parses to
133
- // `undefined`, so without this the property would contradict the attribute).
134
- reflectFlag('compact');
135
- reflectFlag('defaultStartCollapsed');
136
- reflectFlag('defaultEndCollapsed');
137
-
138
- // Aside geometry from the element's CSS custom properties, read once at
139
- // upgrade (inline style first so jsdom, which does not resolve custom
140
- // properties through getComputedStyle, still honors a direct set).
141
- const readVar = (name: string, fallback: number): number => {
142
- const inline = element.style.getPropertyValue(name).trim();
143
- const computed = inline || getComputedStyle(element).getPropertyValue(name).trim();
144
- const n = parseFloat(computed);
145
- return Number.isFinite(n) ? n : fallback;
146
- };
147
- const geometry = untrack(() => ({
148
- startWidth: readVar('--kai-workspace-start-width', 280),
149
- startMinWidth: readVar('--kai-workspace-start-min-width', 200),
150
- startMaxWidth: readVar('--kai-workspace-start-max-width', 480),
151
- endWidth: readVar('--kai-workspace-end-width', 320),
152
- endMinWidth: readVar('--kai-workspace-end-min-width', 200),
153
- endMaxWidth: readVar('--kai-workspace-end-max-width', 480),
154
- }));
155
-
156
- let controller: WorkspaceShellController | undefined;
157
- expose({
158
- /** Collapse/expand one aside (fires `kai-aside-toggle`). */
159
- toggleAside: (side: WorkspaceAsideSide) => controller?.toggleAside(side),
160
- /** Force one aside collapsed (fires `kai-aside-toggle`). */
161
- collapseAside: (side: WorkspaceAsideSide) => controller?.collapseAside(side),
162
- /** Force one aside expanded (fires `kai-aside-toggle`). */
163
- expandAside: (side: WorkspaceAsideSide) => controller?.expandAside(side),
164
- });
165
-
166
- return (
167
- <WorkspaceShell
168
- header={slots()['header'] ? <slot name="header" /> : undefined}
169
- start={slots()['start'] ? <slot name="start" /> : undefined}
170
- end={slots()['end'] ? <slot name="end" /> : undefined}
171
- footer={slots()['footer'] ? <slot name="footer" /> : undefined}
172
- startCollapsed={props.startCollapsed as boolean | undefined}
173
- defaultStartCollapsed={flag('defaultStartCollapsed')}
174
- endCollapsed={props.endCollapsed as boolean | undefined}
175
- defaultEndCollapsed={flag('defaultEndCollapsed')}
176
- collapseBelow={props.collapseBelow as number | undefined}
177
- drawerBelow={props.drawerBelow as number | undefined}
178
- compact={flag('compact')}
179
- {...geometry}
180
- onAsideToggle={(detail) => dispatch('kai-aside-toggle', detail)}
181
- onAsideResize={(detail) => dispatch('kai-aside-resize', detail)}
182
- controllerRef={(c) => (controller = c)}
183
- >
184
- <slot name="main" />
185
- <slot />
186
- </WorkspaceShell>
187
- );
188
- });
@@ -1,212 +0,0 @@
1
- import { createSignal, onCleanup, onMount } from 'solid-js';
2
- import { defineWebComponent } from './define';
3
- import { CHAT_SLOTS, readSlots } from './slots';
4
- import { ChatThread, type ChatThreadProps, type ChatThreadContextUsage, type ChatThreadController } from '../components/chat-thread';
5
- import { cardComponentsFromTags } from './message';
6
- import { createMessagesGuard } from './validate-messages';
7
- import type { AttachmentData } from '../components/attachments';
8
- import type { RejectedAttachment } from './default-input';
9
- import type { ChatMessage } from './chat-types';
10
- import type { TriggerDef } from '../components/composer';
11
- import type { ComposerDoc } from '../primitives/composer-model';
12
- import type { ProseSize } from '../primitives/chat-config';
13
- import type { ModelOption } from '../types';
14
-
15
- type Props = Omit<ChatThreadProps,
16
- 'class' | 'onValueChange' | 'onSubmit' | 'onAttachmentsChange' | 'onSuggestionClick' | 'onModelChange'
17
- | 'onMessageAction' | 'onWebSearch' | 'onVoice' | 'controllerRef' | 'cardTypes' | 'cardSchemas' | 'cardHostElement' | 'messages'
18
- | 'accept' | 'onAttachmentsRejected'
19
- // `headerEndContent`/`emptyContent` are JSX.Element escape hatches for a caller
20
- // composing `ChatThread` directly as a Solid component (see their doc comments in
21
- // chat-thread.tsx — the construct-engine's emitted App is the motivating case).
22
- // `<kai-chat>` is the OPPOSITE shape: a custom element crossing the shadow-DOM
23
- // boundary, where a `JSX.Element` value cannot exist for a consumer to construct
24
- // (React/Vue/plain HTML have no such type) and the facade already has its own
25
- // working mechanism for both regions — `slot="header-end"` and `slot="empty"`.
26
- // Omitted here rather than left to flow through `Omit`'s default pass-through:
27
- // without this, `gen-element-api.mjs` picked them up and put a JSX.Element type
28
- // (which it stringifies as Solid's internal array-like union — meaningless to a
29
- // web-component consumer) into `<kai-chat>`'s public prop surface and docs.
30
- | 'headerEndContent' | 'emptyContent'> & Record<string, unknown> & {
31
- /** Which attachment media types the user may stage, in HTML `accept` syntax:
32
- * `<kai-chat accept="image/*,application/pdf">`. A plain string, so unlike
33
- * `messages` it DOES work as an attribute. Omitted means no filter.
34
- *
35
- * MEDIA TYPES ONLY -- exact (`image/png`) or subtype wildcard (`text/*`).
36
- * HTML allows a file extension here and this does not: `accept=".py"` THROWS
37
- * with the entry named, rather than silently resolving to a picker that
38
- * accepts nothing.
39
- *
40
- * It can only NARROW what the kit can already encode: `accept="image/*"`
41
- * resolves to the four image formats both APIs take, not to every image type
42
- * the OS offers. Pass the SAME string to `toOpenAIMessages(msgs, { accept })`
43
- * and the picker and the wire cannot disagree -- both resolve it through
44
- * `resolveMediaPolicy` against one declaration. That declaration is readable
45
- * as `encodableMediaTypes()` from `@kitn.ai/ui/wire`, if you would rather
46
- * build your own picker than use this prop. */
47
- accept?: string;
48
- /** The full message thread to render, newest last. Each entry carries its
49
- * role, ordered `parts`, and optional actions/avatar/feedback. Set as a JS
50
- * property (`el.messages = [...]`); a NEW array reference per streaming
51
- * chunk re-renders (mutating in place does not). Omit for an empty thread.
52
- *
53
- * Re-declared here (rather than inherited from `ChatThreadProps`) because
54
- * the ELEMENT registers a `[]` default and renders the empty state without
55
- * it, while the SolidJS `<ChatThread>` component still requires it. The
56
- * facade hands it a validated array either way. Matches `<kai-thread>`. */
57
- messages?: ChatMessage[];
58
- /** Optional card type -> custom-element tag overrides/additions for `card`
59
- * parts (merged over the built-ins). Property: `el.cardTypes`. Typed as a
60
- * plain string map (not the `CardTagMap` alias) so the generated React
61
- * wrapper inlines it instead of emitting an unresolved named type. */
62
- cardTypes?: Record<string, string>;
63
- /** JSON Schemas for the card types this app renders, keyed by envelope type. The
64
- * companion of `cardTypes`, which says what DRAWS a card while this says what a
65
- * VALID one looks like. An OBJECT, so it is a JS property only: `el.cardSchemas
66
- * = { 'pricing-table': pricingSchema }`, never an attribute.
67
- * `createCardRegistry(...).validationSchemas` is exactly this shape.
68
- *
69
- * Without it the kit validates its own seven built-ins and leaves your own card
70
- * type, the one your app actually cares about, as the only unchecked thing on
71
- * screen. A schema here WINS over a built-in of the same name.
72
- *
73
- * Typed `Record<string, object>` rather than `Record<string, JsonSchema>`
74
- * deliberately: an imported `.json` schema widens `"type"` to `string`, and an
75
- * authored one carries `$schema`/`title`/`description`/`additionalProperties`,
76
- * so the tighter type would reject both of the normal ways to supply one. */
77
- cardSchemas?: Record<string, object>;
78
- };
79
-
80
- interface Events {
81
- /** User submitted a message. */
82
- 'kai-submit': { value: string; attachments: AttachmentData[] };
83
- /** Fired on every input change. */
84
- 'kai-value-change': { value: string };
85
- /** The staged attachments changed (file added or removed). Carries the full
86
- * current list so a consumer can react in real time. */
87
- 'kai-attachments-change': { attachments: AttachmentData[] };
88
- /** One or more picked files were refused because `accept` excluded them. The
89
- * element renders NO message of its own: it reports the facts (name, media
90
- * type, whether the kit could have sent it) and what the user should see is
91
- * the application's call. Only ever fires when `accept` is set. */
92
- 'kai-attachments-rejected': { rejected: RejectedAttachment[] };
93
- /** A suggestion chip was clicked (only in `suggestion-mode="fill"`). */
94
- 'kai-suggestion-click': { value: string };
95
- /** An action button on a message was clicked. `action` is the built-in name or
96
- * custom id. `state` is present only for the toggleable feedback votes:
97
- * `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
98
- 'kai-message-action': { messageId: string; action: string; state?: 'on' | 'off' };
99
- /** The header model switcher changed. */
100
- 'kai-model-change': { modelId: string };
101
- /** The web-search (Globe) toolbar button was clicked. */
102
- 'kai-web-search': Record<string, never>;
103
- /** The Mic / voice button was clicked. */
104
- 'kai-voice': Record<string, never>;
105
- }
106
-
107
- defineWebComponent<Props, Events>('kai-chat', {
108
- messages: [], value: undefined, placeholder: 'Send a message...', loading: false,
109
- suggestions: undefined, suggestionMode: 'submit', persistSuggestions: false, proseSize: 'sm',
110
- codeTheme: 'github-dark-dimmed', codeHighlight: true, chatTitle: undefined,
111
- models: undefined, currentModel: undefined, context: undefined, scrollButton: true,
112
- attach: true, webSearch: false, voice: false, triggers: undefined, kindIcons: undefined,
113
- actionsReveal: 'always', cardTypes: undefined, cardSchemas: undefined, accept: undefined,
114
- reasoning: undefined, reasoningOpen: undefined,
115
- }, (props, { dispatch, flag, reflectFlag, element, expose }) => {
116
- // `messages` is an untyped boundary: a consumer can hand it anything at
117
- // runtime (a pre-0.20.0 `{ id, role, content }` array, in particular). Skip
118
- // the invalid entries rather than let `groupMessageParts` throw deep inside a
119
- // render pass, which would blank the whole chat instead of one message.
120
- const validMessages = createMessagesGuard('kai-chat');
121
-
122
- // Slot detection is driven by the CHAT_SLOTS registry (single source of truth)
123
- // so slot names never drift between the view, the facade, and the docs.
124
- const [slots, setSlots] = createSignal<Record<string, boolean>>({});
125
- const slot = (name: string) => slots()[name] === true;
126
- onMount(() => {
127
- const read = () => setSlots(readSlots(element, CHAT_SLOTS));
128
- read();
129
- const observer = new MutationObserver(read);
130
- observer.observe(element, { childList: true });
131
- onCleanup(() => observer.disconnect());
132
- });
133
-
134
- // Reflect streaming state to a host attribute so slotted composer/notice CSS
135
- // can react without reading internals (e.g. :host([loading]) ::slotted(...)).
136
- // reflectFlag, not a hand-rolled toggleAttribute effect: the reflection is what
137
- // makes the property read back `undefined`, so the two belong in one call. See
138
- // WebComponentContext.reflectFlag.
139
- reflectFlag('loading');
140
-
141
- // Imperative method API — forward the chat-thread controller onto the host
142
- // (focus the composer, clear it, send programmatically, scroll the thread).
143
- let controller: ChatThreadController | undefined;
144
- expose({
145
- /** Focus the composer, meaning the contenteditable (or textarea) inside the
146
- * shadow root. A native `focus()` on the host lands on the host itself and
147
- * never reaches it, so this is the only way to focus the input
148
- * programmatically. */
149
- focus: (options?: FocusOptions) => controller?.focus(options),
150
- /** Blur whatever currently holds focus inside the shadow root. The companion
151
- * to `focus()`, for the same reason: a native `blur()` on the host misses
152
- * the real focus target. */
153
- blur: () => (element.shadowRoot?.activeElement as HTMLElement | null)?.blur(),
154
- /** Empty the COMPOSER: drops the draft text and every staged attachment, then
155
- * fires `kai-value-change` with `''`. It does NOT touch the thread. `messages`
156
- * is the consumer's own state, so clearing history stays the consumer's call. */
157
- clear: () => controller?.clear(),
158
- /** Submit whatever the composer currently holds, on the same path as Enter or
159
- * the send button: fires `kai-submit` with that value plus the staged
160
- * attachments, then drops the attachments. It takes no argument, so to send
161
- * text the user never typed, set `el.value` first. There is no empty-check,
162
- * so an empty composer still fires. The draft is cleared afterwards only when
163
- * `value` is uncontrolled; a controlled host owns its value and clears it
164
- * itself. Named `send`, not `submit`, to match the shared vocabulary. */
165
- send: () => controller?.send(),
166
- /** Scroll the message viewport to the newest message. Defaults to `'smooth'`;
167
- * pass `'instant'` to jump without animating. */
168
- scrollToBottom: (behavior?: ScrollBehavior) => controller?.scrollToBottom(behavior),
169
- });
170
-
171
- return (
172
- <ChatThread
173
- messages={validMessages(props.messages)} value={props.value as string | ComposerDoc | undefined} placeholder={props.placeholder as string}
174
- loading={flag('loading')} suggestions={props.suggestions as string[] | undefined}
175
- suggestionMode={props.suggestionMode as 'submit' | 'fill'} persistSuggestions={flag('persistSuggestions')}
176
- proseSize={props.proseSize as ProseSize}
177
- codeTheme={props.codeTheme as string} codeHighlight={flag('codeHighlight')}
178
- chatTitle={props.chatTitle as string | undefined} models={props.models as ModelOption[] | undefined}
179
- currentModel={props.currentModel as string | undefined} context={props.context as ChatThreadContextUsage | undefined}
180
- scrollButton={props.scrollButton !== false} attach={flag('attach')} webSearch={flag('webSearch')} voice={flag('voice')}
181
- reasoning={props.reasoning as 'full' | 'compact' | 'off' | undefined}
182
- reasoningOpen={flag('reasoningOpen')}
183
- triggers={props.triggers as TriggerDef[] | undefined}
184
- kindIcons={props.kindIcons as Record<string, string> | undefined}
185
- actionsReveal={props.actionsReveal as 'always' | 'hover'}
186
- cardTypes={cardComponentsFromTags(props.cardTypes as Record<string, string> | undefined, (props as { theme?: string }).theme)}
187
- cardSchemas={props.cardSchemas as Record<string, object> | undefined}
188
- /* F-26: card parts emit off THIS element as the bubbling `kai-card` event,
189
- so `listenForCardEvents(el)` / addEventListener('kai-card') work. */
190
- cardHostElement={element}
191
- onValueChange={(value) => dispatch('kai-value-change', { value })}
192
- onSubmit={(detail) => dispatch('kai-submit', detail)}
193
- accept={props.accept as string | undefined}
194
- onAttachmentsChange={(attachments) => dispatch('kai-attachments-change', { attachments })}
195
- onAttachmentsRejected={(rejected) => dispatch('kai-attachments-rejected', { rejected })}
196
- onSuggestionClick={(value) => dispatch('kai-suggestion-click', { value })}
197
- onModelChange={(modelId) => dispatch('kai-model-change', { modelId })}
198
- onMessageAction={(detail) => dispatch('kai-message-action', detail)}
199
- onWebSearch={() => dispatch('kai-web-search', {})}
200
- onVoice={() => dispatch('kai-voice', {})}
201
- controllerRef={(c) => (controller = c)}
202
- headerStart={slot('header-start')}
203
- headerEnd={slot('header-end')}
204
- headerFull={slot('header')}
205
- sidebar={slot('sidebar')}
206
- empty={slot('empty')}
207
- composer={slot('composer')}
208
- composerActions={slot('composer-actions')}
209
- footer={slot('footer')}
210
- />
211
- );
212
- });
@@ -1,164 +0,0 @@
1
- import { createEffect, createSignal, untrack } from 'solid-js';
2
- import { defineWebComponent } from './define';
3
- import { CheckboxGroup } from '../ui/checkbox-group';
4
- // Public shape of the `options` prop; lives in ./element-data-types so the ROOT
5
- // entry can re-export it (see that file's header).
6
- import type { KaiCheckboxOption } from './element-data-types';
7
-
8
- interface Props extends Record<string, unknown> {
9
- /** The choices, top to bottom. Set as a JS PROPERTY (array), never an attribute.
10
- * Rendered in full: the kit never truncates, re-orders or de-duplicates them. */
11
- options: KaiCheckboxOption[];
12
- /** The FIRST selected value. Settable and reflected to the `value` attribute, so
13
- * `:host([value])` and `el.value` see live state, and a seed can be written in
14
- * markup. Writing it makes that the whole selection; to read or drive the rest,
15
- * use `el.values`. */
16
- value?: string;
17
- /**
18
- * The shared form-control name every box carries, so `FormData.getAll(name)` reads
19
- * the whole selection back under one key.
20
- *
21
- * NO DEFAULT, unlike `<kai-radio-group>`. A radio set needs a shared `name` for the
22
- * browser to make it exclusive and arrow-navigable, so one is generated when none is
23
- * given; checkboxes are independent controls and behave correctly with no name at
24
- * all. Generating one here would submit the selection under a random key, which is
25
- * worse than submitting nothing.
26
- *
27
- * The element is NOT form-associated (no `ElementInternals`, no `setFormValue()`),
28
- * the same known gap `<kai-input>` records: the boxes live in a shadow root, so a
29
- * surrounding `<form>` collects nothing from them whether or not `name` is set. Read
30
- * `el.values`. The name still lands on every inner input, so it is right the day form
31
- * association arrives.
32
- */
33
- name?: string;
34
- /** Disable every row. Individual rows carry their own `disabled`. */
35
- disabled?: boolean;
36
- /** Accessible name for the group. */
37
- label?: string;
38
- }
39
-
40
- /** Events fired by `<kai-checkbox-group>`. */
41
- interface Events {
42
- /** A row was ticked or unticked. `values` is the whole selection after the change,
43
- * which is what a multi-select control needs; `value` is the first of them (empty
44
- * when nothing is selected). Both are always present, so neither shape silently
45
- * loses the other. This is `<kai-select>`'s detail, deliberately. */
46
- 'kai-change': { value: string; values: string[] };
47
- }
48
-
49
- /**
50
- * `<kai-checkbox-group>` — the kit's "pick any number" control, and
51
- * `<kai-radio-group>`'s sibling: the same options shape and the same divided row
52
- * chrome over real `<input type="checkbox">`es, multi-value instead of exclusive. A
53
- * box per tab stop, Space to toggle and correct announcement are the browser's, not a
54
- * reimplementation.
55
- *
56
- * Feed it `options` (a JS-property array of `{ value, label, description?, disabled? }`),
57
- * drive and read the selection with the `values` property, and listen for `kai-change`.
58
- * `value` is the first selected option and is reflected to the `value` attribute.
59
- *
60
- * Re-rendering follows the kit's reactivity contract: hand it a NEW array reference,
61
- * and a new object for any option whose content changed — the rows are a
62
- * reference-keyed list, so mutating an option in place changes nothing on screen.
63
- *
64
- * No validation and no limits: "at least one", "at most three" and anything else that
65
- * lands in a policy document is the application's rule, not the kit's.
66
- *
67
- * ```html
68
- * <kai-checkbox-group label="Environments" name="env"></kai-checkbox-group>
69
- * <script type="module">
70
- * import '@kitn.ai/ui/elements';
71
- * const group = document.querySelector('kai-checkbox-group');
72
- * // ARRAY prop — a JS property, never an attribute.
73
- * group.options = [
74
- * { value: 'prod', label: 'Production', description: 'Pages the on-call' },
75
- * { value: 'staging', label: 'Staging' },
76
- * { value: 'dev', label: 'Development' },
77
- * ];
78
- * group.addEventListener('kai-change', (e) => console.log(e.detail.values));
79
- * group.values = ['prod', 'dev']; // drive it (no kai-change — the host already knows)
80
- * </script>
81
- * ```
82
- */
83
- defineWebComponent<Props, Events>('kai-checkbox-group', {
84
- options: [],
85
- value: undefined,
86
- name: undefined,
87
- disabled: undefined,
88
- label: undefined,
89
- }, (props, ctx) => {
90
- const { element, dispatch, flag, expose } = ctx;
91
-
92
- // Lift the selection into the facade and drive CheckboxGroup CONTROLLED so the host
93
- // can read it (`el.values` / `:host([value])`) and set it after mount. Seed from the
94
- // `value` property/attribute present on mount; nothing is auto-selected, because
95
- // `options` normally arrives as a property AFTER upgrade (kai-select's structure).
96
- const seed = (props.value as string | undefined) ?? element.getAttribute('value') ?? '';
97
- const [values, setValues] = createSignal<string[]>(seed ? [seed] : []);
98
- const first = () => values()[0] ?? '';
99
-
100
- // Coerce anything arriving through the `value` setter (a JS assignment, or the
101
- // attributeChangedCallback write-back the reflect effect below triggers) to a string,
102
- // falling back to the live attribute when nullish so the write-back equals the signal
103
- // and the guard absorbs it — no attr⇄prop feedback loop.
104
- const coerce = (v: unknown): string =>
105
- v == null ? (element.getAttribute('value') ?? '') : String(v);
106
-
107
- // Apply a new selection and fire kai-change once (the user-toggle path).
108
- const apply = (next: string[]) => {
109
- const prev = untrack(values);
110
- if (prev.length === next.length && prev.every((v, i) => v === next[i])) return;
111
- setValues(next);
112
- dispatch('kai-change', { value: next[0] ?? '', values: next });
113
- };
114
-
115
- Object.defineProperty(element, 'value', {
116
- get: () => first(),
117
- set: (v: unknown) => {
118
- const next = coerce(v);
119
- if (untrack(first) !== next) setValues(next ? [next] : []);
120
- },
121
- configurable: true,
122
- enumerable: true,
123
- });
124
-
125
- // The multi-selection read/write side, spelled exactly as `<kai-select multiple>`
126
- // spells it. `value` alone cannot represent a checkbox group's selection, and
127
- // returning only the first ticked box would be a silent drop.
128
- Object.defineProperty(element, 'values', {
129
- get: () => values(),
130
- set: (v: unknown) => setValues(Array.isArray(v) ? v.map(String) : []),
131
- configurable: true,
132
- enumerable: true,
133
- });
134
-
135
- // Reflect the first value → the `[value]` host attribute (for `:host([value])`).
136
- createEffect(() => {
137
- const v = first();
138
- if (v) {
139
- if (element.getAttribute('value') !== v) element.setAttribute('value', v);
140
- } else if (element.hasAttribute('value')) {
141
- element.removeAttribute('value');
142
- }
143
- });
144
-
145
- expose({
146
- /** Focus the group's first box. Not "the first ticked one", which is
147
- * `<kai-radio-group>`'s rule: a radio group is ONE tab stop that lands on the
148
- * selection, while every checkbox here is its own tab stop, so the entry point is
149
- * simply the top of the list. */
150
- focus: (options?: FocusOptions) =>
151
- element.shadowRoot?.querySelector<HTMLInputElement>('input[type="checkbox"]')?.focus(options),
152
- });
153
-
154
- return (
155
- <CheckboxGroup
156
- options={(props.options ?? []) as KaiCheckboxOption[]}
157
- value={values()}
158
- name={props.name as string | undefined}
159
- disabled={flag('disabled')}
160
- label={props.label as string | undefined}
161
- onChange={(next) => apply(next)}
162
- />
163
- );
164
- });