@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,112 +0,0 @@
1
- import { createSignal, onCleanup, type Accessor } from 'solid-js';
2
-
3
- /**
4
- * Fit-to-container scaling: the size tiers are fixed
5
- * px by design (`sizes.ts`), so a container narrower than a tier's natural
6
- * footprint used to CLIP the picture at its edges. The dispatcher now scales
7
- * the WHOLE visualization down proportionally to fit, and renders byte-equal
8
- * to the designed px metrics whenever the container is at least natural size.
9
- *
10
- * Why a transform-scale wrapper rather than relative units or reflow:
11
- * - The px tiers ARE the design (LiveKit parity); switching the geometry to
12
- * relative units would change rendering at every container size, not just
13
- * the overflowing ones.
14
- * - Reflowing (fewer bars, smaller gaps) changes what the animation MEANS;
15
- * proportional scale keeps the exact picture, just smaller.
16
- * - A transform also covers the shader variants for free: their canvases size
17
- * their backing store from layout size (`clientWidth`), which a transform
18
- * does not change, so the bitmap stays at full natural resolution and only
19
- * the composited output shrinks. No variant needs an exception.
20
- *
21
- * Both sizes are MEASURED (one ResizeObserver watching both wrappers), never
22
- * restated from `sizes.ts`: the natural footprint depends on variant, size
23
- * tier, barCount/count/radius and the consumer's own part styling, and a
24
- * hand-derived width table would rot the day any of those moved.
25
- *
26
- * Where ResizeObserver does not exist (SSR, jsdom) this is inert: scale stays
27
- * 1 and nothing is written, which is exactly the pre-fix rendering.
28
- */
29
- export function computeFitScale(
30
- available: number | undefined,
31
- natural: number | undefined,
32
- ): number {
33
- if (
34
- available === undefined || natural === undefined ||
35
- !Number.isFinite(available) || !Number.isFinite(natural) ||
36
- available <= 0 || natural <= 0
37
- ) {
38
- return 1;
39
- }
40
- return Math.min(1, available / natural);
41
- }
42
-
43
- export interface FitScale {
44
- /** Ref for the outer wrapper (the host box, clamped by `max-width: 100%`). */
45
- observeOuter: (el: HTMLElement) => void;
46
- /** Ref for the inner wrapper (the natural-size content that gets scaled). */
47
- observeInner: (el: HTMLElement) => void;
48
- /** 1 when the content fits; the proportional shrink factor when it does not. */
49
- scale: Accessor<number>;
50
- /** The scaled content height in px while shrunk, else undefined: the outer
51
- * wrapper adopts it so the page never reserves the unscaled height. */
52
- scaledHeight: Accessor<number | undefined>;
53
- }
54
-
55
- /**
56
- * One ResizeObserver over both wrappers. ResizeObserver reports layout
57
- * (border-box/content-box) sizes, which CSS transforms do not affect, so the
58
- * inner wrapper keeps reporting its NATURAL size even while scaled, and the
59
- * outer wrapper (whose `max-width: 100%` is what lets a narrow parent
60
- * actually constrain it) reports the width the container is offering. The
61
- * ratio of the two is the scale, with `computeFitScale` guarding the
62
- * unmeasured/degenerate cases to 1 so a bad reading can never blank the
63
- * element.
64
- */
65
- export function createFitScale(): FitScale {
66
- const [availableWidth, setAvailableWidth] = createSignal<number>();
67
- const [naturalWidth, setNaturalWidth] = createSignal<number>();
68
- const [naturalHeight, setNaturalHeight] = createSignal<number>();
69
-
70
- let outerEl: HTMLElement | undefined;
71
- let innerEl: HTMLElement | undefined;
72
- let observer: ResizeObserver | undefined;
73
-
74
- const ensureObserver = (): ResizeObserver | undefined => {
75
- if (observer) return observer;
76
- if (typeof ResizeObserver === 'undefined') return undefined;
77
- observer = new ResizeObserver((entries) => {
78
- for (const entry of entries) {
79
- // contentRect, not borderBoxSize: identical for these padding-less
80
- // wrappers and present everywhere this runs.
81
- if (entry.target === outerEl) setAvailableWidth(entry.contentRect.width);
82
- if (entry.target === innerEl) {
83
- setNaturalWidth(entry.contentRect.width);
84
- setNaturalHeight(entry.contentRect.height);
85
- }
86
- }
87
- });
88
- return observer;
89
- };
90
-
91
- onCleanup(() => observer?.disconnect());
92
-
93
- const scale = () => computeFitScale(availableWidth(), naturalWidth());
94
- const scaledHeight = () => {
95
- const k = scale();
96
- const h = naturalHeight();
97
- return k < 1 && h !== undefined && h > 0 ? h * k : undefined;
98
- };
99
-
100
- return {
101
- observeOuter: (el) => {
102
- outerEl = el;
103
- ensureObserver()?.observe(el);
104
- },
105
- observeInner: (el) => {
106
- innerEl = el;
107
- ensureObserver()?.observe(el);
108
- },
109
- scale,
110
- scaledHeight,
111
- };
112
- }
@@ -1,528 +0,0 @@
1
- import {
2
- createSignal, createEffect, onCleanup, Show, Switch, Match,
3
- type Accessor, type Component, type JSX,
4
- } from 'solid-js';
5
- import { cn } from '../../utils/cn';
6
- import { useAudioAnalysis } from '../../primitives/use-audio-analysis';
7
- import { mirrorBandsCenterOut, mirrorBandsAroundRing } from '../../primitives/audio-bands';
8
- import { normalizeState, type VisualizerState } from '../../primitives/visualizer-sequences';
9
- import { BarVisualizer, type VariantProps } from './variant-bar';
10
- import { createFitScale } from './fit-scale';
11
- import { GridVisualizer } from './variant-grid';
12
- import { RadialVisualizer } from './variant-radial';
13
- import { defaultBarCount, defaultGridCount, defaultRadialBarCount, type VisualizerSize } from './sizes';
14
- import type { UniformType } from './shader-canvas';
15
-
16
- export type VisualizerVariant = 'bar' | 'grid' | 'radial' | 'wave' | 'aurora' | 'custom';
17
-
18
- const KNOWN_VARIANTS: readonly VisualizerVariant[] = ['bar', 'grid', 'radial', 'wave', 'aurora', 'custom'];
19
-
20
- /**
21
- * `aura` is LiveKit's name for this look. Ours is `aurora`. Accept theirs so
22
- * markup ported from LiveKit works unchanged, the same way `normalizeState`
23
- * accepts their room-lifecycle state names.
24
- */
25
- const VARIANT_ALIASES: Record<string, VisualizerVariant> = { aura: 'aurora' };
26
-
27
- export function normalizeVariant(input: string | undefined): VisualizerVariant {
28
- if (!input) return 'bar';
29
- if ((KNOWN_VARIANTS as readonly string[]).includes(input)) return input as VisualizerVariant;
30
- return VARIANT_ALIASES[input] ?? 'bar';
31
- }
32
-
33
- /** A consumer-supplied fragment shader, for `variant="custom"`. */
34
- export interface ShaderSpec {
35
- /**
36
- * GLSL source defining `mainImage(out vec4 fragColor, in vec2 fragCoord)`.
37
- *
38
- * MUST output premultiplied colour: `fragColor = vec4(rgb * alpha, alpha);`,
39
- * never `vec4(rgb, alpha)`. The canvas composites using the browser's
40
- * default `premultipliedAlpha: true`; a translucent edge written the
41
- * natural (straight-alpha) way gets a dark fringe where it meets a light
42
- * page background.
43
- */
44
- fragment: string;
45
- /**
46
- * Custom uniforms. The canvas DECLARES these for you; declaring them in the
47
- * shader too is a compile error.
48
- *
49
- * `type` is narrowed to `UniformType`, not a bare string: an unrecognized
50
- * type here is caught by TypeScript for a TS-authored `shader` prop, before
51
- * it can produce `uniform undefined <name>;` in the assembled source (a
52
- * confusing compile error). A consumer reaching this through the
53
- * `<kai-audio-visualizer>` custom element or an attribute-driven wrapper
54
- * bypasses this check entirely (it is JS at that boundary, not TS) --
55
- * `variant-custom.tsx`'s `customUniforms` re-checks `type` at runtime for
56
- * exactly that reason.
57
- */
58
- uniforms?: Record<string, { type: UniformType; value: number | number[] }>;
59
- }
60
-
61
- export interface AudioVisualizerProps {
62
- variant?: VisualizerVariant;
63
- state?: string;
64
- size?: VisualizerSize;
65
- barCount?: number;
66
- /** Grid only: rows and columns of the square grid. */
67
- count?: number;
68
- /** Radial only: distance from center, in px. */
69
- radius?: number;
70
- /** Grid only: ring distance for the connecting animation, in cells. */
71
- spread?: number;
72
- /** Grid only: ms between scripted frames. */
73
- interval?: number;
74
- color?: string;
75
- /** Shader variants only: pattern density, 0..1. */
76
- complexity?: number;
77
- /** Setting this makes the element an announced image instead of decorative. */
78
- label?: string;
79
- /** Live audio to analyze. NOTE: amplitude renders only while
80
- * `state === 'speaking'` unless `listeningAmplitude` is set; every other
81
- * state plays its scripted animation and the analysis output is unused. */
82
- stream?: MediaStream;
83
- /** Same speaking-only amplitude rule as `stream`: see `listeningAmplitude`. */
84
- audioElement?: HTMLMediaElement;
85
- /** Pre-computed levels. Set this and no AudioContext is ever constructed.
86
- * Same speaking-only amplitude rule as `stream`: see `listeningAmplitude`. */
87
- bands?: number[];
88
- /**
89
- * Opt in to rendering live amplitude during `listening` as well, using the
90
- * same presentation as `speaking`. Default off, which keeps LiveKit parity:
91
- * amplitude (from `stream`, `audioElement` or `bands`) renders only while
92
- * `state === 'speaking'`. Set this to show a real mic-level picture while
93
- * the USER is the one talking. Forwarded to every variant; see
94
- * `amplitudeRenderState` in variant-bar for the single mapping they share.
95
- */
96
- listeningAmplitude?: boolean;
97
- /**
98
- * Custom fragment shader for `variant="custom"`. See `ShaderSpec` for the
99
- * full contract -- most importantly, `fragment` MUST output premultiplied
100
- * colour (`vec4(rgb * alpha, alpha)`, not `vec4(rgb, alpha)`), or
101
- * translucent edges get dark fringes on light backgrounds.
102
- */
103
- shader?: ShaderSpec;
104
- /**
105
- * Shader variants only (`wave`/`aurora`/`custom`): keep animating while the
106
- * element is scrolled off screen. Default `false`, which stops the draw loop
107
- * and releases the WebGL context until it comes back -- see `ShaderCanvas`'s
108
- * `animateWhenNotVisible` for the context-budget reasoning and the cost of
109
- * opting out. Does not override `prefers-reduced-motion`.
110
- */
111
- animateWhenNotVisible?: boolean;
112
- class?: string;
113
- /**
114
- * Render each DOM variant's items yourself -- the same render-prop the
115
- * underlying bar/grid/radial component takes, imported rather than
116
- * redeclared so the two cannot drift. Not used by the shader variants
117
- * (`wave`/`aurora`/`custom`): a fragment shader has no per-item DOM for it
118
- * to replace.
119
- */
120
- children?: VariantProps['children'];
121
- /**
122
- * Explicit `'light'` or `'dark'` wins; `'auto'` (the default) follows a
123
- * live `prefers-color-scheme` listener -- the same rule
124
- * `elements/define.tsx`'s `createDarkMode` applies for every `kai-*`
125
- * element. Only the shader variants read this (aurora/wave pick a colour
126
- * pipeline with it): the three DOM variants already get dark-mode styling
127
- * for free via CSS custom properties, which a shader baking colour into a
128
- * GLSL uniform cannot do. `<kai-audio-visualizer>` forwards its own
129
- * already-resolved `theme` attribute through this prop; a bare
130
- * `<AudioVisualizer>` with no wrapping element needs it set directly.
131
- */
132
- theme?: 'light' | 'dark' | 'auto';
133
- }
134
-
135
- /** Tracks `prefers-reduced-motion`, live. */
136
- export function usePrefersReducedMotion(): Accessor<boolean> {
137
- const [reduced, setReduced] = createSignal(false);
138
-
139
- createEffect(() => {
140
- if (typeof matchMedia !== 'function') return;
141
- const mq = matchMedia('(prefers-reduced-motion: reduce)');
142
- setReduced(mq.matches);
143
- const onChange = (e: MediaQueryListEvent) => setReduced(e.matches);
144
- mq.addEventListener?.('change', onChange);
145
- onCleanup(() => mq.removeEventListener?.('change', onChange));
146
- });
147
-
148
- return reduced;
149
- }
150
-
151
- /**
152
- * Resolves `theme` (`'light' | 'dark' | 'auto'`) to a boolean, mirroring
153
- * `elements/define.tsx`'s `createDarkMode` rule exactly: an explicit value
154
- * wins, `'auto'` (the default) follows a live `prefers-color-scheme`
155
- * listener.
156
- *
157
- * This is a SEPARATE implementation of that rule, not an import of it:
158
- * `components/` is the framework-agnostic layer `elements/` wraps (see the
159
- * kit's architecture), so it cannot depend on `elements/define.tsx` without
160
- * inverting that direction. When driven through `<kai-audio-visualizer>`,
161
- * the facade has already resolved `'auto'` against its OWN listener (the one
162
- * already wired to the visible `.dark` class) before handing this an
163
- * explicit `'light'`/`'dark'` -- so this hook's own listener only ever
164
- * actually decides anything for a bare `<AudioVisualizer>` used directly,
165
- * with no wrapping element at all.
166
- */
167
- export function useResolvedDark(theme: () => string | undefined): Accessor<boolean> {
168
- const [systemDark, setSystemDark] = createSignal(false);
169
-
170
- createEffect(() => {
171
- if (typeof matchMedia !== 'function') return;
172
- const mq = matchMedia('(prefers-color-scheme: dark)');
173
- setSystemDark(mq.matches);
174
- const onChange = (e: MediaQueryListEvent) => setSystemDark(e.matches);
175
- mq.addEventListener?.('change', onChange);
176
- onCleanup(() => mq.removeEventListener?.('change', onChange));
177
- });
178
-
179
- return () => {
180
- const t = theme() ?? 'auto';
181
- return t === 'dark' || (t === 'auto' && systemDark());
182
- };
183
- }
184
-
185
- /**
186
- * Props a shader variant (`wave`, `aurora`, `custom`) receives from the
187
- * dispatcher: everything a DOM variant gets, minus `children` (a fragment
188
- * shader has no per-item DOM for a render-prop to replace, so the field is
189
- * dropped rather than inherited-but-unused), plus the scalar `volume` reading
190
- * (shaders read one number, not per-band levels) and the shader-specific
191
- * knobs. This is the compile-time contract Tasks 12 to 15 build against --
192
- * keep it honest rather than casting around a looser type at the render site.
193
- */
194
- export interface ShaderVariantProps extends Omit<VariantProps, 'children'> {
195
- volume: number;
196
- /** Pattern density, 0..1. */
197
- complexity?: number;
198
- /** Only meaningful for `variant="custom"`. */
199
- shader?: ShaderSpec;
200
- /**
201
- * Already-resolved: `true` selects the dark colour pipeline, `false`
202
- * selects light -- matching `elements/define.tsx`'s `createDarkMode`
203
- * output exactly (`classList={{ dark: isDark() }}`). This is that SAME
204
- * resolved value forwarded down, not a re-derivation, so a shader baking
205
- * colour into a GLSL uniform never needs its own `prefers-color-scheme`
206
- * listener for the common case. Optional: a shader mounted standalone (no
207
- * dispatcher resolving `theme` above it) may fall back to reading the
208
- * media query itself.
209
- */
210
- dark?: boolean;
211
- /**
212
- * Keep animating while off screen instead of releasing the WebGL context.
213
- * Relayed straight through to `ShaderCanvas`, which owns the behaviour and
214
- * documents the trade-off; the variants are pure conduits for it.
215
- */
216
- animateWhenNotVisible?: boolean;
217
- /**
218
- * Call this if the shader cannot render at all -- most commonly
219
- * `canvas.getContext('webgl')` returning null. Permanent for this mount:
220
- * the dispatcher swaps to the bar fallback and will not retry the shader
221
- * on any later reactive update, only on switching to a different variant.
222
- */
223
- onUnavailable: () => void;
224
- }
225
-
226
- /**
227
- * Shader variants live behind a dynamic import so the WebGL runtime and the
228
- * GLSL strings (about 25 to 30 KB) never reach a consumer who does not ask for
229
- * them.
230
- *
231
- * This MUST stay dynamic. `vite.config.ts` disables tree-shaking on the
232
- * register-all bundle by design, so a static import here would put the whole
233
- * shader path into `kai.es.js` for everyone, including a `<kai-chat>`-only
234
- * user. A dynamic import splits into its own chunk under `treeshake: false`;
235
- * a static one does not (verified empirically). Never convert these entries
236
- * to static imports.
237
- */
238
- const SHADER_VARIANTS: Record<string, () => Promise<{ default: Component<ShaderVariantProps> }>> = {
239
- wave: () => import('./variant-wave'),
240
- aurora: () => import('./variant-aurora'),
241
- custom: () => import('./variant-custom'),
242
- };
243
-
244
- export function AudioVisualizer(props: AudioVisualizerProps): JSX.Element {
245
- const variant = () => normalizeVariant(props.variant);
246
- const size = () => props.size ?? 'md';
247
- const state = (): VisualizerState => normalizeState(props.state);
248
- const reduced = usePrefersReducedMotion();
249
- // Only the shader match arm below reads this; the three DOM variants get
250
- // dark-mode styling for free via CSS custom properties.
251
- const resolvedDark = useResolvedDark(() => props.theme);
252
-
253
- const isShader = () => variant() in SHADER_VARIANTS;
254
-
255
- // How many elements the active variant actually renders. Grid keys off its
256
- // own column default (each column shares one band across every row -- see
257
- // GridVisualizer), radial off its own bar-count default, everything else
258
- // off the bar count -- pulled from `sizes.ts` rather than re-derived here,
259
- // so this stays in sync with what each variant actually renders.
260
- const elementCount = () => {
261
- if (variant() === 'grid') return props.count ?? defaultGridCount(size());
262
- if (variant() === 'radial') return props.barCount ?? defaultRadialBarCount(size());
263
- return props.barCount ?? defaultBarCount(size());
264
- };
265
-
266
- // Only ceil(n/2) bands are requested from the analyser, not one per
267
- // element: useAudioAnalysis's output is mirrored back out to the full
268
- // elementCount below (centre-out for bar/grid, across the ring's vertical
269
- // axis for radial), which is what turns a real voice's natural
270
- // low-to-high spectral tilt into a shape that grows from the centre
271
- // outward instead of always ramping in one direction. See
272
- // mirrorBandsCenterOut / mirrorBandsAroundRing in primitives/audio-bands.ts
273
- // for the full rationale and the real-clip measurements behind it.
274
- const bandCount = () => Math.ceil(elementCount() / 2);
275
-
276
- // A caller-supplied `bands` array short-circuits Web Audio entirely, which is
277
- // what keeps the headless and SSR paths free of an AudioContext.
278
- const source = () => (props.bands ? undefined : props.stream ?? props.audioElement);
279
- // Pass the ACCESSOR, not its current value: useAudioAnalysis reads it inside
280
- // its own effect, so a later variant/size/barCount change rebuilds the
281
- // analyser at the new count instead of leaving it wired to whatever the
282
- // count happened to be at mount.
283
- const analysis = useAudioAnalysis(source, { bands: bandCount });
284
-
285
- // A caller-supplied `bands` array is used exactly as given -- it already
286
- // has whatever shape the caller intends, mirrored or not, and mirroring it
287
- // again here would be a second, unwanted transform on data we don't own.
288
- // The analyser's own output is only ceil(n/2) values (bandCount above);
289
- // mirror it back out to the FULL elementCount so it lines up EXACTLY with
290
- // what each variant's own `normalizeVolumeBands(props.bands, count())`
291
- // expects. Matching the count exactly here, rather than leaning on that
292
- // pad-by-repeating-the-last-value, matters specifically because the mirror
293
- // makes a length mismatch look like a plausible (but wrong) shape instead
294
- // of an obviously broken one.
295
- const bands = () => {
296
- if (props.bands) return props.bands;
297
- return variant() === 'radial'
298
- ? mirrorBandsAroundRing(analysis.bands(), elementCount())
299
- : mirrorBandsCenterOut(analysis.bands(), elementCount());
300
- };
301
-
302
- // The shader variants read `volume`, a scalar, not `bands`. When
303
- // caller-supplied `bands` short-circuits Web Audio above, `analysis.volume()`
304
- // sits at its initial 0 forever (nothing ever computes it), so a shader
305
- // fed `bands` would otherwise look static despite the DOM variants next to
306
- // it correctly animating. Derive it from the same `bands` this component
307
- // is already using -- root-mean-square, matching how `reduceToVolume` in
308
- // `primitives/audio-bands.ts` reduces real analyser output to a scalar, so
309
- // the two paths agree in character. Not reused directly: `reduceToVolume`
310
- // takes a `Uint8Array` of byte frequency data (0..255), not a `number[]` of
311
- // already-normalized 0..1 levels, so contorting it to accept both shapes
312
- // would be worse than the few lines below.
313
- const volume = () => {
314
- if (!props.bands) return analysis.volume();
315
- if (props.bands.length === 0) return 0;
316
- let sum = 0;
317
- for (const b of props.bands) sum += b * b;
318
- return Math.sqrt(sum / props.bands.length);
319
- };
320
-
321
- // Lazily loaded shader component, or undefined until it resolves. Failure is
322
- // not fatal: the bar fallback below stays on screen.
323
- const [Shader, setShader] = createSignal<Component<ShaderVariantProps> | undefined>();
324
- // A mounted shader can ALSO fail after its chunk loads fine -- most notably
325
- // WebGL being unavailable, which only a mounted component can discover (it
326
- // is the one calling `canvas.getContext('webgl')`). This is a separate flag
327
- // from `Shader` itself: `Shader()` staying undefined already makes a failed
328
- // *import* permanent (nothing ever sets it), but a shader that DID load and
329
- // mount needs its own signal to force the fallback despite `Shader()` being
330
- // truthy. `onUnavailable` below is what a mounted shader calls to set it.
331
- const [unavailable, setUnavailable] = createSignal(false);
332
- createEffect(() => {
333
- const v = variant();
334
- const load = SHADER_VARIANTS[v];
335
- setShader(undefined);
336
- // Switching variants gets a fresh attempt: a failure on `aurora` must not
337
- // carry over and permanently block `wave` too.
338
- setUnavailable(false);
339
- if (!load) return;
340
- let cancelled = false;
341
- void load()
342
- .then((m) => { if (!cancelled) setShader(() => m.default); })
343
- .catch((err) => {
344
- // Same `cancelled` check as the `.then` above. The two handlers were
345
- // asymmetric: a rejection arriving after this effect was disposed
346
- // still warned, even though there is no longer a component to fall
347
- // back to and nothing the message could usefully tell anyone. Worse,
348
- // the warning surfaces against whatever is running by the time the
349
- // rejection lands rather than against the mount that asked for the
350
- // chunk, so it reads as a fault in unrelated code -- in a test run,
351
- // in an unrelated test.
352
- if (cancelled) return;
353
- console.warn(
354
- `<kai-audio-visualizer variant="${v}">: failed to load the shader chunk, falling back to bars.`,
355
- err,
356
- );
357
- });
358
- onCleanup(() => { cancelled = true; });
359
- });
360
-
361
- // Props every variant shares, MINUS `bands` -- deliberately. Solid compiles
362
- // a component spread (`{...shared()}` below) into per-key getters that all
363
- // call this SAME function: reading ANY one key re-invokes the whole thing,
364
- // so if `bands()` lived in here, reading `state` (or `size`/`frozen`/
365
- // `color`) would transitively subscribe the reader to `bands()` too, which
366
- // updates ~31 times a second with live or synthetic audio. That is exactly
367
- // what caused two real bugs downstream: `use-sequencer.ts`'s effect reading
368
- // `frozen`/`state` re-ran at band cadence and called `setTick(0)` on every
369
- // run, so the tick could never advance (every scripted animation looked
370
- // dead); `shader-canvas.tsx`'s compile effect reading `precision`/`fragment`
371
- // re-ran the same way and recompiled the GL program 65-70 times in 4
372
- // seconds while restamping its animation clock (`iTime` pinned under 0.33s,
373
- // periodically negative). Both were patched locally with memos in those
374
- // files (kept -- defence in depth, cheap, and they document the hazard),
375
- // but the leak was still here for the next reader: `variant-wave.tsx`,
376
- // `variant-aurora.tsx`, and `variant-custom.tsx` each have their OWN
377
- // state/frozen-driven tween effect with no local memo at all, so they were
378
- // live instances of the identical bug (`.to()` restarts a tween's clock on
379
- // every call -- see `create-tween.ts` -- so a 31Hz re-run means a tween
380
- // never visibly progresses). Fixing it here, at the one place the bundling
381
- // happens, closes all of those at once rather than requiring every current
382
- // and future reader to remember to memoize defensively.
383
- //
384
- // `bands` GENUINELY must stay reactive -- this split is about not dragging
385
- // it into unrelated reads, not about freezing it. It is passed explicitly,
386
- // `bands={bands()}`, at every call site below, exactly like `volume`,
387
- // `complexity`, etc. already are: an explicit prop gets its OWN getter,
388
- // entirely independent of this one.
389
- // `listeningAmplitude` is safe inside this bundle (unlike `bands`): it is a
390
- // boolean a caller sets once, not a signal driven at audio cadence, so
391
- // reading it through the shared getters cannot drag in a hot subscription.
392
- const shared = (): Omit<VariantProps, 'bands'> => ({
393
- state: state(),
394
- size: size(),
395
- frozen: reduced(),
396
- color: props.color,
397
- listeningAmplitude: props.listeningAmplitude,
398
- });
399
-
400
- // The three DOM variants (bar/grid/radial), including the bar fallback
401
- // shown while a shader chunk loads or fails, additionally get the
402
- // caller's render-prop. `children` is bundled here (unlike `bands`) because
403
- // it does not churn -- it is a callback reference a caller sets once, not a
404
- // signal driven by audio, so reading it cannot drag in anything that does.
405
- const domShared = (): Omit<VariantProps, 'bands'> => ({ ...shared(), children: props.children });
406
-
407
- const a11y = () =>
408
- props.label
409
- ? { role: 'img' as const, 'aria-label': props.label }
410
- : { 'aria-hidden': 'true' as const };
411
-
412
- // Fit-to-container: measured by createFitScale (see fit-scale.ts for the
413
- // full design rationale). At or above the natural width this contributes
414
- // nothing but the `max-width` clamp, so the designed px metrics render
415
- // exactly; below it, the inner wrapper scales the whole picture down and
416
- // the outer adopts the scaled height so layout follows the visual.
417
- const fit = createFitScale();
418
-
419
- return (
420
- <div
421
- class={cn('inline-flex', props.class)}
422
- {...a11y()}
423
- ref={fit.observeOuter}
424
- style={{
425
- // What lets a narrow container actually constrain this element: the
426
- // content is fixed-px, so without the clamp the host box would just
427
- // overflow (and clip at the viewport edge, the reported defect).
428
- 'max-width': '100%',
429
- // While shrunk, the inner wrapper's LAYOUT box deliberately keeps its
430
- // natural size (that is what keeps the measurement honest above), so
431
- // it overhangs this box below/right of the scaled visual. `hidden`
432
- // clips that overhang for BOTH painting and hit-testing -- without it
433
- // the stale layout box covered a sibling button and ate its pointer
434
- // events (W5 live finding, mechanism 2). Nothing visible is clipped:
435
- // the scaled visual is exactly this box by construction.
436
- // `vertical-align: top` rides along with `overflow: hidden`, which is
437
- // what makes it necessary: hidden overflow moves an inline-flex box's
438
- // baseline to its bottom border edge, so the surrounding line box
439
- // grows by the font strut's descent below it and the host measures
440
- // ~6px taller than the box (measured in headed Chromium: 107.2 vs
441
- // 101.2). Top alignment opts out of baseline layout entirely. Scoped
442
- // to the scaled state so default (unscaled) inline placement beside
443
- // text keeps its original baseline behavior.
444
- ...(fit.scaledHeight() !== undefined
445
- ? { height: `${fit.scaledHeight()}px`, overflow: 'hidden', 'vertical-align': 'top' }
446
- : {}),
447
- }}
448
- >
449
- <div
450
- ref={fit.observeInner}
451
- style={{
452
- // THE FEEDBACK-LOOP GUARD (W5 live finding, mechanism 1). The inner
453
- // wrapper is a flex item of the outer, and a flex item's default
454
- // `align-self: stretch` makes its LAYOUT height follow the outer's
455
- // -- including the scaled height this component itself adopts below.
456
- // The ResizeObserver measuring this element for its NATURAL size
457
- // then reads back the adopted height, k multiplies in again, and
458
- // the element spirals (measured in headed Chromium: 224px -> 45.7
459
- // -> 0.85 -> 0.38). `flex-start` + `flex: none` pin this box to its
460
- // intrinsic content size in BOTH axes, so the measurement can never
461
- // see anything this component wrote. Unconditional: at scale 1 both
462
- // are visually identical to the defaults for a single item that
463
- // defines its container's size.
464
- flex: '0 0 auto',
465
- 'align-self': 'flex-start',
466
- ...(fit.scale() < 1
467
- ? { transform: `scale(${fit.scale()})`, 'transform-origin': 'top left' }
468
- : {}),
469
- }}
470
- >
471
- <Switch
472
- fallback={<BarVisualizer {...domShared()} bands={bands()} barCount={props.barCount} />}
473
- >
474
- <Match when={variant() === 'grid'}>
475
- <GridVisualizer
476
- {...domShared()}
477
- bands={bands()}
478
- count={props.count}
479
- spread={props.spread}
480
- interval={props.interval}
481
- />
482
- </Match>
483
- <Match when={variant() === 'radial'}>
484
- <RadialVisualizer
485
- {...domShared()}
486
- bands={bands()}
487
- barCount={props.barCount}
488
- radius={props.radius}
489
- />
490
- </Match>
491
- <Match when={isShader()}>
492
- {/*
493
- Bars stand in until the chunk resolves, and permanently if it
494
- cannot -- either because the import itself failed (`Shader()`
495
- never becomes truthy) or because the mounted shader called
496
- `onUnavailable` (checked here via `!unavailable()`, since
497
- `Shader()` alone cannot tell a working component from one that
498
- loaded fine but can't actually render, e.g. no WebGL). Both cases
499
- fall back to the same `BarVisualizer`, and `when` still narrows to
500
- the component reference on the success path, matching the
501
- `(Comp) => ...` extraction below.
502
- */}
503
- <Show
504
- when={!unavailable() && Shader()}
505
- fallback={<BarVisualizer {...domShared()} bands={bands()} barCount={props.barCount} />}
506
- >
507
- {(Comp) => {
508
- const C = Comp();
509
- return (
510
- <C
511
- {...shared()}
512
- bands={bands()}
513
- volume={volume()}
514
- complexity={props.complexity}
515
- shader={props.shader}
516
- dark={resolvedDark()}
517
- animateWhenNotVisible={props.animateWhenNotVisible}
518
- onUnavailable={() => setUnavailable(true)}
519
- />
520
- );
521
- }}
522
- </Show>
523
- </Match>
524
- </Switch>
525
- </div>
526
- </div>
527
- );
528
- }