@kitn.ai/ui 0.26.0 → 0.28.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 (488) hide show
  1. package/README.md +25 -6
  2. package/bin/mcp.js +16 -3
  3. package/bin/route.js +23 -0
  4. package/bin/route.test.js +58 -0
  5. package/dist/{elements/chunks/Icon--Y8vsFal.js → Icon-DObhsRtm.js} +1 -1
  6. package/dist/action-icons-CcgNN2oT.js +1 -0
  7. package/dist/arrow-down-CjRU3JgV.js +1 -0
  8. package/dist/arrow-left-Bnpb1UEW.js +1 -0
  9. package/dist/artifact-Bwt7OgcR.js +1 -0
  10. package/dist/assets/dev-5XzXYR21.js +91 -0
  11. package/dist/attachments-Qr4kg-2b.js +1 -0
  12. package/dist/{elements/chunks/audio-visualizer-D7lB6mvR.js → audio-visualizer-DToYdfSc.js} +1 -1
  13. package/dist/badge-CdEu_jn2.js +1 -0
  14. package/dist/bash-InADTalH.js +1 -6
  15. package/dist/bell-DQAAOpDz.js +1 -0
  16. package/dist/{elements/chunks/button-flUbeufF.js → button-DkuOnGLy.js} +1 -1
  17. package/dist/card-renderer-Jx70m6_l.js +1 -0
  18. package/dist/card-routing-0YidER_3.js +1 -0
  19. package/dist/check-njkVdZu2.js +1 -0
  20. package/dist/checkbox-D7iRB3nL.js +1 -0
  21. package/dist/checkbox-group-B2_rpoPM.js +1 -0
  22. package/dist/chevron-down-B72s6PXR.js +1 -0
  23. package/dist/chevron-right-BatuHzUm.js +1 -0
  24. package/dist/choice-card-m0BYqqOK.js +1 -0
  25. package/dist/circle-check-B62pODB3.js +1 -0
  26. package/dist/circle-x-BPG0iPst.js +1 -0
  27. package/dist/circle-zx0ByzY9.js +1 -0
  28. package/dist/{elements/chunks/cn-CU7UAWzk.js → cn-DN5AWfiS.js} +1 -1
  29. package/dist/code-block-ClMLKb7C.js +1 -0
  30. package/dist/{elements/chunks/collapsible-BzbXpPzr.js → collapsible-B4DlWicL.js} +1 -1
  31. package/dist/components/attachment-types.d.ts +7 -0
  32. package/dist/components/audio-visualizer/fit-scale.d.ts +1 -1
  33. package/dist/components/card-renderer.d.ts +13 -0
  34. package/dist/components/card.d.ts +4 -0
  35. package/dist/components/chat-thread.d.ts +135 -2
  36. package/dist/components/conversation-item.d.ts +35 -7
  37. package/dist/components/conversation-list.d.ts +17 -5
  38. package/dist/components/conversation-panel.d.ts +29 -0
  39. package/dist/components/form-widgets.d.ts +67 -2
  40. package/dist/components/form.d.ts +48 -1
  41. package/dist/components/home-panel.d.ts +34 -0
  42. package/dist/components/message.d.ts +25 -3
  43. package/dist/components/reasoning.d.ts +6 -0
  44. package/dist/components/scroll-button.d.ts +11 -0
  45. package/dist/components/thread.d.ts +5 -0
  46. package/dist/components/tool-types.d.ts +9 -0
  47. package/dist/components/widget-tab-bar.d.ts +16 -0
  48. package/dist/composer-sQ0HcvyG.js +106 -0
  49. package/dist/confirm-card-rQWDQsnC.js +1 -0
  50. package/dist/construct-cli.es.js +1337 -0
  51. package/dist/{elements/chunks/context-VLIL3sJ-.js → context-0kg4ZX1J.js} +1 -1
  52. package/dist/controllable-CnGpMF6r.js +1 -0
  53. package/dist/conversation-item-BxwQLaFJ.js +1 -0
  54. package/dist/conversation-list-BCfGN1JU.js +1 -0
  55. package/dist/copy-n9u9rqpi.js +1 -0
  56. package/dist/core-AYMC6_lb.js +12 -5874
  57. package/dist/{create-tween-BFT6c-Y8.js → create-tween-C-q-JCM-.js} +1 -1
  58. package/dist/{create-tween-CJNlzoaO.js → create-tween-CRrJXxBd.js} +1 -1
  59. package/dist/{create-tween-CQED4T0g.js → create-tween-DZ3RRDHD.js} +1 -1
  60. package/dist/{elements/chunks/create-tween-c4Z8TDYz.js → create-tween-uPkArjIG.js} +2 -2
  61. package/dist/css-M7EaDHN_.js +1 -6
  62. package/dist/custom-elements.json +1433 -202
  63. package/dist/default-input-CaMrJkgH.js +1 -0
  64. package/dist/define-By-uL588.js +1 -0
  65. package/dist/define.d.ts +4 -0
  66. package/dist/define.js +510 -0
  67. package/dist/define.server.d.ts +5 -0
  68. package/dist/define.server.js +506 -0
  69. package/dist/{elements/chunks/disclosure-CcNbyLy0.js → disclosure-WUImBbDv.js} +1 -1
  70. package/dist/{elements/chunks/dropdown-BgWTthUx.js → dropdown-wZVeJOMd.js} +1 -1
  71. package/dist/elements/agent-card.js +1 -1
  72. package/dist/elements/artifact.js +1 -1
  73. package/dist/elements/attachments.js +1 -1
  74. package/dist/elements/audio-visualizer.js +1 -1
  75. package/dist/elements/autoloader.js +1 -1
  76. package/dist/elements/avatar.js +1 -1
  77. package/dist/elements/badge.js +1 -1
  78. package/dist/elements/button.js +1 -1
  79. package/dist/elements/card.js +1 -1
  80. package/dist/elements/cards.js +1 -1
  81. package/dist/elements/chain-of-thought.js +1 -1
  82. package/dist/elements/chat-scope-picker.js +1 -1
  83. package/dist/elements/chat-workspace.js +1 -1
  84. package/dist/elements/chat.js +1 -1
  85. package/dist/elements/checkbox-group.d.ts +1 -0
  86. package/dist/elements/checkbox-group.js +1 -0
  87. package/dist/elements/checkbox.d.ts +1 -0
  88. package/dist/elements/checkbox.js +1 -0
  89. package/dist/elements/checkpoint.js +1 -1
  90. package/dist/elements/choice.js +1 -1
  91. package/dist/elements/coachmark.js +1 -1
  92. package/dist/elements/code-block.js +1 -1
  93. package/dist/elements/command.js +1 -1
  94. package/dist/elements/compare.js +1 -1
  95. package/dist/elements/composer.js +1 -1
  96. package/dist/elements/confirm-card.js +1 -1
  97. package/dist/elements/context-meter.js +1 -1
  98. package/dist/elements/conversation-item.js +1 -1
  99. package/dist/elements/conversation-list.js +1 -1
  100. package/dist/elements/define-entry.d.ts +12 -0
  101. package/dist/elements/dialog.js +1 -1
  102. package/dist/elements/dock.js +102 -8
  103. package/dist/elements/dropdown.js +1 -1
  104. package/dist/elements/editable-label.js +1 -1
  105. package/dist/elements/element-data-types.d.ts +37 -0
  106. package/dist/elements/embed.js +1 -1
  107. package/dist/elements/empty.js +1 -1
  108. package/dist/elements/feedback-bar.js +1 -1
  109. package/dist/elements/file-tree.js +1 -1
  110. package/dist/elements/file-upload.js +1 -1
  111. package/dist/elements/form.js +1 -1
  112. package/dist/elements/hover-card.js +1 -1
  113. package/dist/elements/icon.js +1 -1
  114. package/dist/elements/image.js +1 -1
  115. package/dist/elements/input.js +1 -1
  116. package/dist/elements/kbd.js +1 -1
  117. package/dist/elements/link-preview.js +1 -1
  118. package/dist/elements/loader.js +1 -1
  119. package/dist/elements/markdown.js +1 -1
  120. package/dist/elements/menu.js +1 -1
  121. package/dist/elements/message-skills.js +1 -1
  122. package/dist/elements/message.js +1 -1
  123. package/dist/elements/model-switcher.js +1 -1
  124. package/dist/elements/nav.js +1 -1
  125. package/dist/elements/notice.js +1 -1
  126. package/dist/elements/pane-grid.d.ts +1 -0
  127. package/dist/elements/pane-grid.js +1 -0
  128. package/dist/elements/pane-group.js +1 -1
  129. package/dist/elements/pane.js +1 -1
  130. package/dist/elements/popover.js +1 -1
  131. package/dist/elements/progress-bar.js +1 -1
  132. package/dist/elements/prompt-dock.js +1 -1
  133. package/dist/elements/prompt-input.js +1 -1
  134. package/dist/elements/prompt-suggestions.js +1 -1
  135. package/dist/elements/radio-group.d.ts +1 -0
  136. package/dist/elements/radio-group.js +1 -0
  137. package/dist/elements/reasoning.js +1 -1
  138. package/dist/elements/remote.js +1 -1
  139. package/dist/elements/resizable.js +1 -1
  140. package/dist/elements/response-stream.js +2 -2
  141. package/dist/elements/screen.js +1 -1
  142. package/dist/elements/scroll-area.js +1 -1
  143. package/dist/elements/scroll-button.js +1 -1
  144. package/dist/elements/search.js +1 -1
  145. package/dist/elements/segmented.js +1 -1
  146. package/dist/elements/select.d.ts +1 -0
  147. package/dist/elements/select.js +1 -0
  148. package/dist/elements/separator.js +1 -1
  149. package/dist/elements/setting-item.js +1 -1
  150. package/dist/elements/settings-group.js +1 -1
  151. package/dist/elements/skeleton.js +1 -1
  152. package/dist/elements/slider.d.ts +1 -0
  153. package/dist/elements/slider.js +1 -0
  154. package/dist/elements/slots.d.ts +1 -1
  155. package/dist/elements/source.js +1 -1
  156. package/dist/elements/status.js +1 -1
  157. package/dist/elements/switch.js +1 -1
  158. package/dist/elements/tabs.js +1 -1
  159. package/dist/elements/tasks.js +1 -1
  160. package/dist/elements/text-shimmer.js +1 -1
  161. package/dist/elements/thinking-bar.js +1 -1
  162. package/dist/elements/thread.js +1 -1
  163. package/dist/elements/toast.js +1 -1
  164. package/dist/elements/tool.js +1 -1
  165. package/dist/elements/tooltip.js +1 -1
  166. package/dist/elements/voice-input.js +1 -1
  167. package/dist/elements/voice-output.js +1 -1
  168. package/dist/elements.d.ts +380 -26
  169. package/dist/{elements/chunks/ellipsis-7gU33mL2.js → ellipsis-CbOpJnU3.js} +1 -1
  170. package/dist/embed-CrfjkbUG.js +1 -0
  171. package/dist/engine-javascript-vq0WuIJl.js +14 -2516
  172. package/dist/{elements/chunks/external-link-CSOEsNlx.js → external-link-ByXAwBBQ.js} +1 -1
  173. package/dist/file-text-DMib2qwt.js +1 -0
  174. package/dist/{elements/chunks/file-tree-zvB2i7P9.js → file-tree-CJqM2aP7.js} +1 -1
  175. package/dist/folder-_BAb929C.js +1 -0
  176. package/dist/form-DSZgZQZk.js +1 -0
  177. package/dist/github-dark-dimmed-DUshB20C.js +1 -4
  178. package/dist/github-light-JYsPkUQd.js +1 -4
  179. package/dist/hover-card-BQbul9eq.js +1 -0
  180. package/dist/html-CPZ3oZQ7.js +1 -10
  181. package/dist/icon-CdcfRhYI.js +1 -0
  182. package/dist/{elements/chunks/index-BCRhi84a.js → index-xu_pdcPi.js} +1 -1
  183. package/dist/index.d.ts +4 -2
  184. package/dist/index.js +7474 -5857
  185. package/dist/index.server.js +5965 -4762
  186. package/dist/info-DsFjGuI_.js +1 -0
  187. package/dist/input-DKbmkMos.js +1 -0
  188. package/dist/javascript-C25yR2R2.js +1 -6
  189. package/dist/json-DxJze_jm.js +1 -6
  190. package/dist/kai.es.js +1 -1
  191. package/dist/kbd-PvdGhX4s.js +1 -0
  192. package/dist/{elements/chunks/link-preview-OQ9IEq0f.js → link-preview-DbM1866N.js} +1 -1
  193. package/dist/link-zF8PzWfF.js +1 -0
  194. package/dist/loader-BM4CEz4G.js +1 -0
  195. package/dist/{elements/chunks/markdown-DgBFaGAz.js → markdown-LMvmAyBk.js} +7 -7
  196. package/dist/mcp.es.js +1361 -81
  197. package/dist/message-BSsgvHvf.js +1 -0
  198. package/dist/message-BYZECyek.js +1 -0
  199. package/dist/message-circle-DruwObfX.js +1 -0
  200. package/dist/message-square-BG6q6mlm.js +1 -0
  201. package/dist/{elements/chunks/minimize-2-DPIUKTrT.js → minimize-2-BQRoBV1V.js} +1 -1
  202. package/dist/{elements/chunks/model-switcher-DsT8tFB0.js → model-switcher-CMpCOYcB.js} +1 -1
  203. package/dist/{elements/chunks/overlay-DuiwdXjm.js → overlay-Cb-MkyDa.js} +1 -1
  204. package/dist/panel-right-i8warFxT.js +1 -0
  205. package/dist/paperclip-ByY3UVO6.js +1 -0
  206. package/dist/play-BvKKq3fX.js +1 -0
  207. package/dist/primitives/card-data-types.d.ts +49 -0
  208. package/dist/primitives/card-routing.d.ts +1 -33
  209. package/dist/primitives/card-validate.d.ts +2 -2
  210. package/dist/primitives/chat-config.d.ts +29 -2
  211. package/dist/primitives/conversation-store.d.ts +54 -0
  212. package/dist/primitives/field-mask.d.ts +96 -0
  213. package/dist/primitives/field-semantics.d.ts +36 -0
  214. package/dist/primitives/input-mask.d.ts +46 -0
  215. package/dist/primitives/url-scheme-policy.d.ts +34 -0
  216. package/dist/primitives/use-resize-observer.d.ts +2 -2
  217. package/dist/progress-bar-jVAHvMUf.js +1 -0
  218. package/dist/prompt-suggestion-CD-qtNgC.js +1 -0
  219. package/dist/radio-BsoBMhkF.js +1 -0
  220. package/dist/react/index.d.ts +586 -19
  221. package/dist/react.js +223 -187
  222. package/dist/reasoning-4kBPtlTx.js +1 -0
  223. package/dist/register-impl-B1hLkrI8.js +424 -0
  224. package/dist/{elements/chunks/resizable-D181b4fM.js → resizable-uPmY9VY-.js} +1 -1
  225. package/dist/rotate-ccw-B2xn93py.js +1 -0
  226. package/dist/rotate-cw-CMVLoCyH.js +1 -0
  227. package/dist/schemas/form.schema.json +21 -1
  228. package/dist/schemas/tool-defs.d.ts +11 -1
  229. package/dist/schemas.js +81 -81
  230. package/dist/scroll-area-BqLUo8ZZ.js +1 -0
  231. package/dist/scroll-button-DslXiJyL.js +1 -0
  232. package/dist/select-2cLRtPGT.js +1 -0
  233. package/dist/{elements/chunks/separator-CeJHQqLW.js → separator-BWQtNJcM.js} +1 -1
  234. package/dist/{elements/chunks/settings-CqaHgJF9.js → settings-BBR63jLg.js} +1 -1
  235. package/dist/{elements/chunks/settings-group-CjqjLCOn.js → settings-group-B2ciy-Iw.js} +1 -1
  236. package/dist/{elements/chunks/skeleton-D8akBnKS.js → skeleton-CkHI-HgC.js} +1 -1
  237. package/dist/slider-DDR9U-i0.js +1 -0
  238. package/dist/{solid-BtdqNZI7.js → solid-BzCFdL25.js} +9771 -7594
  239. package/dist/{solid-CnavwBye.js → solid-DruVOXnf.js} +7893 -6183
  240. package/dist/solid.d.ts +16 -2
  241. package/dist/solid.js +256 -243
  242. package/dist/solid.server.js +256 -243
  243. package/dist/source-GEnFF528.js +1 -0
  244. package/dist/star-CilHq8GP.js +1 -0
  245. package/dist/state/index.d.ts +1 -1
  246. package/dist/state/mock.d.ts +32 -2
  247. package/dist/state.js +133 -108
  248. package/dist/store-Ciyk6eZG.js +1 -0
  249. package/dist/svelte--5p79yCD.js +1 -15
  250. package/dist/switch-KkeQIbuH.js +1 -0
  251. package/dist/tasks-card-BrN4bggJ.js +1 -0
  252. package/dist/text-shimmer-Dcj1MHuq.js +1 -0
  253. package/dist/textarea-Dpvbngbg.js +1 -0
  254. package/dist/theme.tokens.css +110 -13
  255. package/dist/{elements/chunks/thumbs-up-DX2Ijk3H.js → thumbs-up-CsT9Wzb9.js} +1 -1
  256. package/dist/toast-store-tgK6MuMv.js +1 -0
  257. package/dist/{elements/chunks/tool-DKQ2D1DP.js → tool-DzUjIBT8.js} +1 -1
  258. package/dist/{elements/chunks/tooltip-B0G99y8w.js → tooltip-Bkkg_4t0.js} +1 -1
  259. package/dist/trash-2-jBKxjGGQ.js +1 -0
  260. package/dist/{elements/chunks/triangle-alert-F9cyUEyy.js → triangle-alert-DlQ68ppf.js} +1 -1
  261. package/dist/tsx-B8rCNbgL.js +1 -6
  262. package/dist/types.d.ts +48 -3
  263. package/dist/typescript-RycA9KXf.js +1 -6
  264. package/dist/ui/checkbox-group.d.ts +83 -0
  265. package/dist/ui/checkbox.d.ts +40 -0
  266. package/dist/ui/dock.d.ts +51 -0
  267. package/dist/ui/icon.d.ts +3 -0
  268. package/dist/ui/input.d.ts +48 -2
  269. package/dist/ui/radio.d.ts +85 -0
  270. package/dist/ui/select.d.ts +71 -0
  271. package/dist/ui/slider.d.ts +65 -0
  272. package/dist/ui/switch.d.ts +9 -2
  273. package/dist/upload-TcAHXv9W.js +1 -0
  274. package/dist/url-scheme-policy-DR5DgvkM.js +1 -0
  275. package/dist/use-card-resolution-DaZqAdWf.js +1 -0
  276. package/dist/{elements/chunks/variant-aurora-qt6Zct8M.js → variant-aurora-BhLuYxJR.js} +1 -1
  277. package/dist/{variant-aurora-B8II3-I1.js → variant-aurora-CNmfHhcx.js} +2 -2
  278. package/dist/{variant-aurora-CMNWOSJR.js → variant-aurora-D6GsdTPA.js} +2 -2
  279. package/dist/{variant-aurora-CcuDMWwQ.js → variant-aurora-DbW_OWL2.js} +1 -1
  280. package/dist/{elements/chunks/variant-custom-tJp22_BQ.js → variant-custom-BRvaNHSi.js} +1 -1
  281. package/dist/{variant-custom-L16JLLZy.js → variant-custom-BvYHR62b.js} +1 -1
  282. package/dist/{variant-custom-BdvYC7af.js → variant-custom-DMTrEO5w.js} +2 -2
  283. package/dist/{variant-custom-C714mqKl.js → variant-custom-DV2x254s.js} +2 -2
  284. package/dist/{variant-wave-ecwykeyL.js → variant-wave-BNMGrDfj.js} +2 -2
  285. package/dist/{variant-wave-2S4La2Ka.js → variant-wave-BpDd8t3Z.js} +1 -1
  286. package/dist/{variant-wave-D7ruiA1W.js → variant-wave-CyBueXj9.js} +2 -2
  287. package/dist/{elements/chunks/variant-wave-CaQ5ti39.js → variant-wave-sp-qwsdI.js} +1 -1
  288. package/dist/vue-BmIZj4XD.js +1 -33
  289. package/dist/x-Z5UntkIJ.js +1 -0
  290. package/frameworks/react/index.tsx +210 -22
  291. package/llms-full.txt +1184 -22
  292. package/llms.txt +6 -3
  293. package/package.json +17 -4
  294. package/src/agent-tooling/README.md +192 -0
  295. package/src/agent-tooling/catalog/invariants.ts +3 -3
  296. package/src/agent-tooling/catalog/surfaces.ts +72 -0
  297. package/src/agent-tooling/construct/cli-entry.ts +8 -0
  298. package/src/agent-tooling/construct/cli.ts +147 -0
  299. package/src/agent-tooling/construct/codegen.ts +1635 -0
  300. package/src/agent-tooling/construct/construct.v1.schema.json +319 -0
  301. package/src/agent-tooling/construct/dev.ts +148 -0
  302. package/src/agent-tooling/construct/fixtures/demo-widget.construct.json +7 -0
  303. package/src/agent-tooling/construct/fixtures/ops-console.construct.json +44 -0
  304. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +32 -0
  305. package/src/agent-tooling/construct/schema.ts +452 -0
  306. package/src/agent-tooling/mcp/server.ts +2 -1
  307. package/src/agent-tooling/mcp/tools/construct.ts +130 -0
  308. package/src/agent-tooling/mcp/tools/debug.ts +126 -4
  309. package/src/agent-tooling/mcp/tools/reference.ts +104 -3
  310. package/src/agent-tooling/recipes/composed-thread.ts +714 -0
  311. package/src/agent-tooling/recipes/index.ts +22 -0
  312. package/src/agent-tooling/recipes/types.ts +32 -0
  313. package/src/agent-tooling/registry.ts +5 -0
  314. package/src/components/attachment-types.ts +7 -0
  315. package/src/components/audio-visualizer/fit-scale.ts +1 -1
  316. package/src/components/card-renderer.tsx +39 -8
  317. package/src/components/card.tsx +10 -2
  318. package/src/components/chat-scope-picker.tsx +2 -2
  319. package/src/components/chat-thread.tsx +602 -43
  320. package/src/components/choice-card.tsx +102 -37
  321. package/src/components/coachmark.tsx +1 -1
  322. package/src/components/code-block.tsx +2 -2
  323. package/src/components/composer.tsx +89 -15
  324. package/src/components/confirm-card.tsx +20 -4
  325. package/src/components/conversation-item.tsx +56 -9
  326. package/src/components/conversation-list.tsx +25 -10
  327. package/src/components/conversation-panel.tsx +118 -0
  328. package/src/components/empty.tsx +14 -3
  329. package/src/components/file-tree.tsx +5 -1
  330. package/src/components/form-widgets.tsx +257 -195
  331. package/src/components/form.tsx +297 -9
  332. package/src/components/home-panel.tsx +159 -0
  333. package/src/components/loader.tsx +12 -5
  334. package/src/components/message-skills.tsx +1 -1
  335. package/src/components/message.tsx +71 -11
  336. package/src/components/prompt-input.tsx +7 -1
  337. package/src/components/prompt-suggestion.tsx +4 -1
  338. package/src/components/reasoning.tsx +30 -3
  339. package/src/components/response-compare.tsx +2 -2
  340. package/src/components/scroll-button.tsx +56 -4
  341. package/src/components/source.tsx +6 -1
  342. package/src/components/tasks-card.tsx +58 -16
  343. package/src/components/thread.tsx +10 -1
  344. package/src/components/toast.tsx +1 -1
  345. package/src/components/tool-types.ts +9 -0
  346. package/src/components/widget-tab-bar.tsx +73 -0
  347. package/src/elements/attachments.tsx +3 -1
  348. package/src/elements/chat-workspace.tsx +1 -1
  349. package/src/elements/chat.tsx +115 -5
  350. package/src/elements/checkbox-group.tsx +164 -0
  351. package/src/elements/checkbox.tsx +134 -0
  352. package/src/elements/compiled.css +1 -1
  353. package/src/elements/composer.tsx +12 -1
  354. package/src/elements/conversation-item.tsx +62 -22
  355. package/src/elements/conversation-list.tsx +2 -2
  356. package/src/elements/define-entry.ts +12 -0
  357. package/src/elements/dock.tsx +11 -0
  358. package/src/elements/element-data-types.ts +40 -0
  359. package/src/elements/element-manifest.json +24 -0
  360. package/src/elements/element-meta.json +767 -34
  361. package/src/elements/element-nonscalar.json +17 -0
  362. package/src/elements/element-types.d.ts +380 -26
  363. package/src/elements/feedback-bar.tsx +5 -0
  364. package/src/elements/icon-names.json +29 -0
  365. package/src/elements/input.tsx +312 -23
  366. package/src/elements/message.tsx +2 -0
  367. package/src/elements/pane-grid.tsx +111 -0
  368. package/src/elements/prompt-input.tsx +8 -2
  369. package/src/elements/radio-group.tsx +129 -0
  370. package/src/elements/register-impl.ts +6 -0
  371. package/src/elements/scroll-button.tsx +54 -6
  372. package/src/elements/select.tsx +165 -0
  373. package/src/elements/slider.tsx +171 -0
  374. package/src/elements/slots.ts +1 -1
  375. package/src/elements/styles.css +89 -3
  376. package/src/elements/thread.tsx +2 -0
  377. package/src/elements/toast.tsx +14 -1
  378. package/src/index.ts +5 -2
  379. package/src/primitives/card-data-types.ts +49 -0
  380. package/src/primitives/card-host.tsx +4 -2
  381. package/src/primitives/card-routing.ts +7 -56
  382. package/src/primitives/card-schemas/form.schema.json +21 -1
  383. package/src/primitives/card-validate.ts +10 -2
  384. package/src/primitives/chat-config.tsx +33 -6
  385. package/src/primitives/conversation-store.ts +248 -0
  386. package/src/primitives/field-mask.ts +256 -0
  387. package/src/primitives/field-semantics.ts +115 -0
  388. package/src/primitives/input-mask.ts +853 -0
  389. package/src/primitives/toast-store.ts +66 -4
  390. package/src/primitives/url-scheme-policy.ts +70 -0
  391. package/src/primitives/use-resize-observer.ts +2 -2
  392. package/src/schemas/tool-defs.ts +12 -2
  393. package/src/solid.ts +20 -2
  394. package/src/state/index.ts +1 -1
  395. package/src/state/mock.ts +92 -6
  396. package/src/types.ts +45 -3
  397. package/src/ui/agent-card.tsx +2 -2
  398. package/src/ui/avatar.tsx +1 -1
  399. package/src/ui/checkbox-group.tsx +153 -0
  400. package/src/ui/checkbox.tsx +63 -0
  401. package/src/ui/dock.tsx +192 -7
  402. package/src/ui/icon.tsx +53 -0
  403. package/src/ui/input.tsx +249 -9
  404. package/src/ui/kbd.tsx +1 -1
  405. package/src/ui/nav.tsx +1 -1
  406. package/src/ui/pane-group.tsx +2 -2
  407. package/src/ui/radio.tsx +150 -0
  408. package/src/ui/select.tsx +168 -0
  409. package/src/ui/slider.tsx +178 -0
  410. package/src/ui/switch.tsx +49 -18
  411. package/src/utils/cn.ts +11 -5
  412. package/theme.css +112 -13
  413. package/dist/elements/chunks/action-icons-D9u3OzYW.js +0 -1
  414. package/dist/elements/chunks/arrow-left-CVh1TeN7.js +0 -1
  415. package/dist/elements/chunks/artifact-BkYcfIlZ.js +0 -1
  416. package/dist/elements/chunks/attachments-DwfNlubq.js +0 -1
  417. package/dist/elements/chunks/badge-Q0-Cmwzz.js +0 -1
  418. package/dist/elements/chunks/bash-InADTalH.js +0 -1
  419. package/dist/elements/chunks/card-renderer-3Dyl-FpN.js +0 -1
  420. package/dist/elements/chunks/card-routing-BK09BdmL.js +0 -1
  421. package/dist/elements/chunks/check-B5kBPKeo.js +0 -1
  422. package/dist/elements/chunks/chevron-down-DZ1GS39h.js +0 -1
  423. package/dist/elements/chunks/chevron-right-CvP7OUd2.js +0 -1
  424. package/dist/elements/chunks/choice-card-D4QUIOWZ.js +0 -1
  425. package/dist/elements/chunks/circle-CDf9g6MQ.js +0 -1
  426. package/dist/elements/chunks/circle-check-CA47Nqbz.js +0 -1
  427. package/dist/elements/chunks/circle-x-CJ_HVbC8.js +0 -1
  428. package/dist/elements/chunks/code-block-BdLiTitd.js +0 -1
  429. package/dist/elements/chunks/composer-Byve-n8K.js +0 -69
  430. package/dist/elements/chunks/confirm-card-B0flE3MN.js +0 -1
  431. package/dist/elements/chunks/controllable-DTwTIlwp.js +0 -1
  432. package/dist/elements/chunks/conversation-item-BDztezOG.js +0 -1
  433. package/dist/elements/chunks/copy-Nf-kqxXH.js +0 -1
  434. package/dist/elements/chunks/core-AYMC6_lb.js +0 -12
  435. package/dist/elements/chunks/css-M7EaDHN_.js +0 -1
  436. package/dist/elements/chunks/default-input-C2iLFq0b.js +0 -1
  437. package/dist/elements/chunks/define-wjHR1MkU.js +0 -1
  438. package/dist/elements/chunks/download-C4V7tBdb.js +0 -1
  439. package/dist/elements/chunks/embed-D3KewsIJ.js +0 -1
  440. package/dist/elements/chunks/engine-javascript-vq0WuIJl.js +0 -141
  441. package/dist/elements/chunks/file-text-D1G8khle.js +0 -1
  442. package/dist/elements/chunks/folder-WW2LGLid.js +0 -1
  443. package/dist/elements/chunks/form-CQirdC4W.js +0 -1
  444. package/dist/elements/chunks/github-dark-dimmed-DUshB20C.js +0 -1
  445. package/dist/elements/chunks/github-light-JYsPkUQd.js +0 -1
  446. package/dist/elements/chunks/hover-card-CJJkfHTK.js +0 -1
  447. package/dist/elements/chunks/html-CPZ3oZQ7.js +0 -1
  448. package/dist/elements/chunks/icon-Cfgmf4fa.js +0 -1
  449. package/dist/elements/chunks/info-DX3YMOt6.js +0 -1
  450. package/dist/elements/chunks/input-BtW9U6Sq.js +0 -1
  451. package/dist/elements/chunks/javascript-C25yR2R2.js +0 -1
  452. package/dist/elements/chunks/json-DxJze_jm.js +0 -1
  453. package/dist/elements/chunks/kbd-LGXwuT_V.js +0 -1
  454. package/dist/elements/chunks/link-2My69BqT.js +0 -1
  455. package/dist/elements/chunks/loader-iOxc_Tu-.js +0 -1
  456. package/dist/elements/chunks/message-VMZohrXx.js +0 -1
  457. package/dist/elements/chunks/message-circle-CpXMM-_n.js +0 -1
  458. package/dist/elements/chunks/message-square-DxcWtETQ.js +0 -1
  459. package/dist/elements/chunks/message-tZmV2A3p.js +0 -1
  460. package/dist/elements/chunks/paperclip-CRZVp4z_.js +0 -1
  461. package/dist/elements/chunks/progress-bar-DNy66e_E.js +0 -1
  462. package/dist/elements/chunks/prompt-suggestion-Bn64Nl7L.js +0 -1
  463. package/dist/elements/chunks/reasoning-Emn9N4-T.js +0 -1
  464. package/dist/elements/chunks/rotate-cw-CPWe37D9.js +0 -1
  465. package/dist/elements/chunks/scroll-area-ClZkZxIk.js +0 -1
  466. package/dist/elements/chunks/scroll-button-DPE-t3x_.js +0 -1
  467. package/dist/elements/chunks/share-CyfnNEqp.js +0 -1
  468. package/dist/elements/chunks/source-UWCvmVak.js +0 -1
  469. package/dist/elements/chunks/star-DoHFAikQ.js +0 -1
  470. package/dist/elements/chunks/store-Cjq0qwYN.js +0 -1
  471. package/dist/elements/chunks/svelte--5p79yCD.js +0 -1
  472. package/dist/elements/chunks/tasks-card-CmZ5xh6v.js +0 -1
  473. package/dist/elements/chunks/text-shimmer-DYn09zrz.js +0 -1
  474. package/dist/elements/chunks/textarea-skiGHURM.js +0 -1
  475. package/dist/elements/chunks/toast-store-CFnQpThX.js +0 -1
  476. package/dist/elements/chunks/tsx-B8rCNbgL.js +0 -1
  477. package/dist/elements/chunks/typescript-RycA9KXf.js +0 -1
  478. package/dist/elements/chunks/use-card-resolution-DoA2f_EU.js +0 -1
  479. package/dist/elements/chunks/vue-BmIZj4XD.js +0 -1
  480. package/dist/elements/chunks/x-B6UnOiLw.js +0 -1
  481. package/dist/llms/llms-full.txt +0 -2949
  482. package/dist/llms/llms.txt +0 -156
  483. package/dist/register-impl-DpE7icIb.js +0 -293
  484. package/dist/ui/stat.d.ts +0 -16
  485. package/src/ui/stat.tsx +0 -41
  486. /package/dist/{elements/chunks/card-tags-D8lZ-C_U.js → card-tags-D8lZ-C_U.js} +0 -0
  487. /package/dist/{elements/chunks/link-preview-DNILK391.js → link-preview-DNILK391.js} +0 -0
  488. /package/dist/{elements/chunks/slots-DaNjX0rc.js → slots-DaNjX0rc.js} +0 -0
@@ -1,5 +1,18 @@
1
- /* Element-bundle stylesheet. Compiled to compiled.css and injected into each
2
- custom element's shadow root. Mirrors .storybook/styles.css but scans src/. */
1
+ /* Element-bundle stylesheet, and the SOURCE OF TRUTH for element CSS. Compiled to
2
+ compiled.css and injected into each custom element's shadow root;
3
+ .storybook/styles.css @imports this file rather than restating it, so a rule
4
+ added here reaches the shadow roots AND the light-DOM Solid stories at once.
5
+
6
+ It used to be the other way round — Storybook hand-copied a few of these rules
7
+ under "Mirror the shipped ..." comments. Nothing enforced the copy, so
8
+ .kai-radio, .kai-checkbox, .kai-range and .kai-focus-inset were simply missing
9
+ there: three form controls rendered as raw OS chrome in every story while the
10
+ shipped element rendered them fully designed, and an agent and the owner each
11
+ concluded the kit had unstyled controls. Never copy a rule from here into the
12
+ Storybook sheet; add it here.
13
+
14
+ The one thing that cannot cross is :host, which selects nothing in the light
15
+ DOM. Its defaults are re-stated on `body` in the Storybook sheet's shim. */
3
16
  @import "tailwindcss";
4
17
  /* tw-animate-css supplies the animate-in/animate-out + slide/fade/zoom utilities
5
18
  the kit uses for every overlay enter/exit (toast, popover, tooltip, dropdown,
@@ -16,10 +29,19 @@
16
29
  /* Base typography is token-driven so a theme can restyle it. --kai-font-base is
17
30
  the family for ALL text/UI (named "base", not "sans", so a serif body works);
18
31
  --kai-tracking is global letter-spacing. Both pierce the Shadow DOM via the
19
- var() fallback, exactly like the --kai-color-* tokens. */
32
+ var() fallback, exactly like the --kai-color-* tokens.
33
+
34
+ font-size is the third: without it every shadow root inherited the DOCUMENT's
35
+ size (16px in a stock page), so any surface that never set an explicit text-*
36
+ class rendered a step larger than the rest of the kit and looked like a bug in
37
+ that one component. --text-body is the scale's primary reading size and itself
38
+ resolves through --kai-text-body, so overriding that one token still moves the
39
+ default. The literal fallback matches theme.css's --text-body so the rule is
40
+ still correct if this sheet is ever used without the @theme block. */
20
41
  :host {
21
42
  display: block;
22
43
  font-family: var(--kai-font-base, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);
44
+ font-size: var(--text-body, var(--kai-text-body, 0.875rem));
23
45
  letter-spacing: var(--kai-tracking, normal);
24
46
  }
25
47
  /* Code/monospace surfaces use --kai-font-code (named for its ROLE — code — not
@@ -83,6 +105,40 @@
83
105
  *::-webkit-scrollbar-thumb:hover { background-color: var(--color-scrollbar-thumb-hover); }
84
106
  *::-webkit-scrollbar-corner { background: transparent; }
85
107
 
108
+ /* SELECTED text, kit-owned. Scoped to the shadow root — deliberately, and this
109
+ is the whole design decision, so read it before "simplifying" it into
110
+ theme.css.
111
+
112
+ WHY THE KIT OWNS IT AT ALL: left to the UA, the browser's blue selection was
113
+ visually stronger than the kit's OWN deliberate emphasis (the composer's
114
+ --color-highlight mark), so an incidental drag-select outranked a keyword the
115
+ app had flagged on purpose. How selected text reads is a fact about the
116
+ medium, which is the kit's call.
117
+
118
+ WHY ONLY HERE, AND NOT IN theme.css: theme.css is imported into a CONSUMER's
119
+ Tailwind build, so a bare ::selection there would restyle every paragraph on
120
+ their page — the kit deciding for the app's own content, which is not ours to
121
+ decide. The shadow root IS the kit's DOM, so the same rule is unambiguous
122
+ here. Identical reasoning to the scrollbar and :focus-visible rules above,
123
+ which are scoped the same way and for the same reason. theme.css therefore
124
+ carries the TOKENS only, and a Solid-layer consumer rendering our components
125
+ into their own light DOM opts in with one rule of their own:
126
+ `.my-chat ::selection { background-color: var(--color-selection); … }`.
127
+
128
+ WHY THE RULE MUST BE IN THIS SHEET AND NOT INHERITED: ::selection does NOT
129
+ cross the shadow boundary the way ordinary inherited properties do — a
130
+ document-level ::selection leaves shadow content on the UA default. The
131
+ --kai-color-selection TOKEN does pierce (custom properties inherit normally),
132
+ which is what keeps a consumer override working.
133
+
134
+ Both background AND color are set; see the theme.css note for why the
135
+ foreground is load-bearing rather than cosmetic (coloured text falls under
136
+ WCAG AA on this fill if it keeps its own colour). */
137
+ ::selection {
138
+ background-color: var(--color-selection);
139
+ color: var(--color-selection-foreground);
140
+ }
141
+
86
142
  /* Respect a user's reduced-motion preference: disable the tw-animate-css
87
143
  enter/exit keyframe animations (toasts, overlays, cards) so they appear and
88
144
  disappear instantly instead of sliding/fading. Targets the utility classes
@@ -169,6 +225,36 @@
169
225
  .kai-checkbox:checked {
170
226
  box-shadow: 0 1px 4px color-mix(in srgb, var(--color-primary) 26%, transparent);
171
227
  }
228
+ /* The mixed state ("some of the children below are ticked"). `indeterminate` is a
229
+ DOM property with no HTML attribute, so a rule is the ONLY way it can be seen —
230
+ without one a mixed box paints pixel-identically to an unchecked one and lies
231
+ about its state. That was live: `<kai-tasks>` in `select` mode puts an
232
+ indeterminate select-all above a partial selection, and it read as "none
233
+ selected".
234
+
235
+ Same fill and the same masked `::after` as `:checked`, with the tick mask
236
+ swapped for a bar, so the two states are siblings of one technique rather than
237
+ two: the bar is `--color-primary-foreground` on `--color-primary`, exactly the
238
+ pair the tick already uses, so it themes and contrasts identically in both
239
+ themes and stays consumer-themable through the same tokens.
240
+
241
+ Ordered AFTER the `:checked` rules on purpose. `indeterminate` is independent of
242
+ `checked`, so a box can be both; specificity is equal, so source order decides,
243
+ and mixed-wins is what the browser's own native rendering does.
244
+
245
+ Scoped to `.kai-checkbox` on purpose: `:indeterminate` also matches every radio
246
+ in a group with nothing selected, and an empty radio group must go on reading as
247
+ empty rather than sprouting a third state. */
248
+ .kai-checkbox:indeterminate {
249
+ background-color: var(--color-primary);
250
+ border-color: var(--color-primary);
251
+ box-shadow: 0 1px 4px color-mix(in srgb, var(--color-primary) 26%, transparent);
252
+ }
253
+ .kai-checkbox:indeterminate::after {
254
+ transform: scale(1);
255
+ -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E") center / contain no-repeat;
256
+ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E") center / contain no-repeat;
257
+ }
172
258
  .kai-radio:disabled,
173
259
  .kai-checkbox:disabled { opacity: 0.5; cursor: not-allowed; }
174
260
 
@@ -128,6 +128,8 @@ defineWebComponent<Props, Events>('kai-thread', {
128
128
  scrollButton={props.scrollButton !== false}
129
129
  cardTypes={cardComponentsFromTags(props.cardTypes as Record<string, string> | undefined, (props as { theme?: string }).theme)}
130
130
  cardSchemas={props.cardSchemas as Record<string, object> | undefined}
131
+ /* F-26: card parts emit off THIS element as the bubbling `kai-card` event. */
132
+ cardHostElement={element}
131
133
  empty={slots()['empty'] ? <slot name="empty" /> : undefined}
132
134
  onMessageAction={(detail) => dispatch('kai-message-action', detail)}
133
135
  controllerRef={(c) => (controller = c)}
@@ -5,7 +5,11 @@ import { toast as toastStore, type ToastItem } from '../primitives/toast-store';
5
5
  interface Props extends Record<string, unknown> {
6
6
  /** The toasts to render. Newest is shown on top. Set as a JS property (array);
7
7
  * pass a new array reference to update. Omit for an empty region, which is
8
- * the normal resting state and how the imperative `toast()` API starts. */
8
+ * the normal resting state and how the imperative `toast()` API starts.
9
+ * Note the handover: the first `toast()` call ADOPTS a region you placed in
10
+ * markup (no second region mounts) and binds the imperative store to this
11
+ * property, replacing any array you set. Drive a region as data OR via
12
+ * `toast()`, not both at once. */
9
13
  toasts?: ToastItem[];
10
14
  /** Stack anchor: `'top-center'` (default), `'top-right'`, `'bottom-center'`, … */
11
15
  position?: ToastPosition;
@@ -41,6 +45,15 @@ interface Events {
41
45
  * also usable declaratively — set `el.toasts = [...]` (a JS property, never an
42
46
  * attribute) and listen for `kai-dismiss` / `kai-action`.
43
47
  *
48
+ * The two modes meet gracefully: `toast()` ADOPTS the first connected
49
+ * `<kai-toast-region>` already in the document instead of mounting a second
50
+ * one, and creates its own on `document.body` only when none exists. Adoption
51
+ * keeps your authored attributes (position/stack/appearance) but binds the
52
+ * imperative store to `toasts`, replacing an array you were driving as data —
53
+ * so within one app, either own the array or call `toast()`, not both. With
54
+ * two or more regions placed, the first in document order is adopted and a
55
+ * one-time console.warn flags the ambiguity.
56
+ *
44
57
  * Because it is a real `kai-*` element it carries its own shadow root + the
45
58
  * shared kit stylesheet, so it is viewport-positioned AND kit-styled.
46
59
  *
package/src/index.ts CHANGED
@@ -22,7 +22,7 @@
22
22
  // Type-only exports are free (fully erased by the build) and may live in either.
23
23
 
24
24
  // Shared types (folded in from @tab-zen/shared)
25
- export type { ModelOption, SearchFilters, ConversationScope, ConversationSummary, ConversationGroup } from './types';
25
+ export type { ModelOption, SearchFilters, ConversationScope, ConversationSummary, ConversationGroup, HomeConfig, HomeLinkEntry } from './types';
26
26
 
27
27
  // Utilities
28
28
  export { cn } from './utils/cn';
@@ -42,6 +42,8 @@ export { configureCodeHighlighting, isCodeHighlightingEnabled } from './primitiv
42
42
  export type { CodeHighlightingOptions } from './primitives/highlighter';
43
43
  export { configurePdfPreview, isPdfPreviewEnabled } from './primitives/pdf-preview';
44
44
  export type { PdfPreviewOptions } from './primitives/pdf-preview';
45
+ export { localStorageStore, fetchStore, byRecency, LEGACY_THREAD_MIGRATED_TITLE } from './primitives/conversation-store';
46
+ export type { ConversationStore } from './primitives/conversation-store';
45
47
 
46
48
  // Toasts: imperative `toast()` API + the reactive store behind <kai-toast-region>
47
49
  export { toast, configureToasts, ensureMounted as ensureToastRegion, getToasts } from './primitives/toast-store';
@@ -419,7 +421,8 @@ export type { KaiTabItem } from './ui/tabs';
419
421
  export type { PaneStatus } from './ui/pane';
420
422
  export type { PaneTab } from './ui/pane-group';
421
423
  export type {
422
- KaiCommandItem, KaiContextUsage, KaiMenuItem, KaiSegmentedOption, KaiSourceItem,
424
+ KaiCheckboxOption, KaiCommandItem, KaiContextUsage, KaiMenuItem, KaiRadioOption, KaiSegmentedOption, KaiSelectOption,
425
+ KaiSourceItem,
423
426
  } from './elements/element-data-types';
424
427
  // `kai-audio-visualizer.shader` takes a ShaderSpec. The element arrived from main
425
428
  // after this block was written, and prop-types-exported.test.ts caught it, which
@@ -207,6 +207,55 @@ export type FormField = {
207
207
  | 'switch';
208
208
  'x-kai-placeholder'?: string;
209
209
  'x-kai-step'?: number;
210
+ /**
211
+ * Display format for a string field. `tel` / `ssn` / `credit-card`
212
+ * apply that type's standard mask and submit digits only; `custom` masks with
213
+ * `x-kai-mask` and submits the formatted value.
214
+ *
215
+ * NOT the JSON Schema `format` keyword, and deliberately not an extension of it:
216
+ * `format` has a registered vocabulary with assertion semantics, `widgetFor()`
217
+ * already switches on it to pick a widget, and `toJsonSchema()` turns it into a
218
+ * validation pattern. This is a UI hint, so it lives in the `x-kai-*` namespace
219
+ * with the other UI hints — and it selects FORMATTING, never a widget.
220
+ *
221
+ * Typed as the semantic-type union for a consumer authoring a form definition by
222
+ * hand. A value arriving from a MODEL is untrusted and may be anything at all;
223
+ * `resolveFieldMask()` degrades an unrecognised one to an unmasked text field with
224
+ * a console warning rather than trusting this declaration.
225
+ *
226
+ * SPELLED OUT HERE RATHER THAN IMPORTED, and that is not laziness. `FieldSemanticType`
227
+ * is declared in `./field-semantics`, which carries the semantics TABLE and its
228
+ * `console.warn` — and this file's whole reason for existing is that a Node/no-DOM
229
+ * backend can name a card payload with `lib: ["ESNext"]` and `types: []`, where
230
+ * `console` does not exist (measured: TS2584, by
231
+ * `tests/schemas/card-data-types-node-safe.test.ts`, which is what caught the import).
232
+ * A type import still has to RESOLVE, so importing the union would drag the engine into
233
+ * the server-safe entry's graph.
234
+ *
235
+ * AN APP CANNOT PIN THIS ON THE MODEL TODAY.
236
+ * `cardTools({ require })` narrows a projected tool schema by dot-path, but there is
237
+ * no path that reaches a form FIELD: a form card's payload is itself a JSON Schema, so
238
+ * `form.schema.json` describes `properties` as a map of field definitions rather than
239
+ * as a node per field, and `require: { form: [{ path: 'properties.ticketId' }] }` is a
240
+ * TypeError naming a path that does not resolve. "Force the model to mask the ticket
241
+ * field" is therefore not expressible; the enum above is what makes it LIKELY, and an
242
+ * app that needs a guarantee validates the arriving envelope itself.
243
+ *
244
+ * It is therefore a REGISTERED COPY of `FIELD_SEMANTIC_TYPES`: the two are pinned
245
+ * mutually assignable at compile time in
246
+ * `tests/components/form-field-formats.test.tsx`, so adding a fifth token to the enum
247
+ * without adding it here fails `nx typecheck ui` rather than shipping a form card that
248
+ * cannot name it.
249
+ */
250
+ 'x-kai-format'?: 'tel' | 'ssn' | 'credit-card' | 'custom';
251
+ /** The mask pattern, read only when `x-kai-format` is `custom`: `#` a digit, `@` an
252
+ * alphanumeric, `*` an obscurable alphanumeric, everything else a literal
253
+ * (`CHG-####`). Capped at the mask engine's own limit; a longer one is refused. */
254
+ 'x-kai-mask'?: string;
255
+ /** Placeholder text for the mask's unfilled positions, aligned character for
256
+ * character with the pattern (`mm/dd/yyyy`). Derived from the pattern when absent;
257
+ * a misaligned one is dropped, loudly, and the mask survives. */
258
+ 'x-kai-mask-guide'?: string;
210
259
  };
211
260
 
212
261
  /** The form definition = CardEnvelope.data for type:'form'. */
@@ -1,8 +1,10 @@
1
1
  // src/primitives/card-host.tsx
2
2
  // The native transport: a Solid context exposing a CardHost (context() + emit()).
3
3
  // emit() routes through the contract policy via the shared routeCardEvent. Cards
4
- // inside <kai-chat>/<CardProvider> use this; bare cards fall back to the bubbling
5
- // kai-card event (see card-routing.listenForCardEvents).
4
+ // inside a <CardProvider> use this; cards inside <kai-chat>/<kai-message>/
5
+ // <kai-thread> (and bare cards given a hostElement) fall back to the bubbling
6
+ // kai-card event off the host element (see card-routing.listenForCardEvents and
7
+ // CardRenderer's hostElement prop).
6
8
  import { createContext, useContext, type JSX } from 'solid-js';
7
9
  import type { CardContext, CardEvent, CardHost, CardPolicy } from './card-contract';
8
10
  import { routeCardEvent } from './card-routing';
@@ -3,6 +3,13 @@
3
3
  // policy router (used by BOTH the native listener and the remote transport), and a
4
4
  // host-side listener helper for the bare-element path.
5
5
  import type { CardEvent, CardPolicy } from './card-contract';
6
+ // isSafeUrl/isScriptUrl live in their own DOM-free file so schema.ts
7
+ // (agent-tooling/construct, checked under tsconfig.mcp.json's Node-only pass)
8
+ // can import isSafeUrl without dragging this file's HTMLElement/window/
9
+ // CustomEvent references into a no-DOM-lib compile. Re-exported here so this
10
+ // module's own public surface is unchanged.
11
+ import { isSafeUrl, isScriptUrl } from './url-scheme-policy';
12
+ export { isSafeUrl, isScriptUrl } from './url-scheme-policy';
6
13
 
7
14
  /** The single contract event name. */
8
15
  export const CARD_EVENT_NAME = 'kai-card';
@@ -16,62 +23,6 @@ export function emitCardEvent(element: HTMLElement, event: CardEvent): void {
16
23
  );
17
24
  }
18
25
 
19
- const SAFE_SCHEMES = ['http:', 'https:', 'mailto:'];
20
- const SCRIPT_SCHEMES = ['javascript:', 'vbscript:'];
21
-
22
- /** The scheme the WHATWG parser reads out of `url`, resolved against a base so a
23
- * relative input inherits `http:`. `undefined` when it will not parse at all.
24
- *
25
- * ONE parser for the two questions below, deliberately: the parsing is where
26
- * the subtlety lives (it strips embedded tabs/newlines and trims surrounding
27
- * whitespace before reading the scheme, so `java\nscript:` and
28
- * ` javascript:... ` are both read as `javascript:` -- which a regex over the
29
- * raw string would miss). Two predicates over one parse cannot drift on that;
30
- * two hand-rolled parsers would. */
31
- function schemeOf(url: string): string | undefined {
32
- try { return new URL(url, 'http://_invalid_base').protocol; } catch { return undefined; }
33
- }
34
-
35
- /** True when `url` is safe to put in an href / hand to `window.open`.
36
- *
37
- * Exported so the MARKDOWN renderer and the ARTIFACT viewer reuse this exact
38
- * guard rather than growing a second scheme list that can drift from this one.
39
- *
40
- * Resolving against a base is deliberate and is what makes it correct for
41
- * markdown: a relative or fragment link (`/docs`, `#section`, `./rel`) is
42
- * ordinary markdown, and resolving it inherits the base's `http:` so it
43
- * passes, while `javascript:`/`data:`/`vbscript:` keep their own protocol and
44
- * fail. It is correct for the artifact viewer for the same reason: a file with
45
- * no `src` to resolve against yields a bare relative path (`docs/report.pdf`),
46
- * which is a legitimate artifact address. Contrast `isRenderableLink` in
47
- * `primitives/link-preview.ts`, which takes NO base and so demands an absolute
48
- * http(s) URL: that is the right guard for a model-supplied citation -- a
49
- * reference to a page on the public web -- this one for markdown body links and
50
- * artifact file addresses. */
51
- export function isSafeUrl(url: string): boolean {
52
- const scheme = schemeOf(url);
53
- return scheme !== undefined && SAFE_SCHEMES.includes(scheme);
54
- }
55
-
56
- /** True when navigating to `url` would EXECUTE it as script in the initiating
57
- * document's origin.
58
- *
59
- * Strictly narrower than `!isSafeUrl(url)`, and not a competing policy: it
60
- * answers a different question, for the one sink where the allowlist is the
61
- * wrong tool. An `<iframe src>` legitimately takes `data:` and `blob:` (a
62
- * `data:` blob artifact is a documented `<kai-artifact>` use -- it is what
63
- * `displayUrl` exists for) and both get an OPAQUE origin in every modern
64
- * browser, so neither can reach the host page. `javascript:`/`vbscript:` are
65
- * the schemes that run in the EMBEDDER's origin, and they are the whole risk:
66
- * the default sandbox (no `allow-same-origin`) already makes the browser refuse
67
- * them, but a consumer who sets `allow-same-origin` turns a model-supplied
68
- * `src` into host-origin script execution. The artifact viewer used to suggest
69
- * that setting for "an artifact you trust"; it no longer does, and this guard
70
- * is what protects the consumers who took the old advice. */
71
- export function isScriptUrl(url: string): boolean {
72
- const scheme = schemeOf(url);
73
- return scheme !== undefined && SCRIPT_SCHEMES.includes(scheme);
74
- }
75
26
  function warnNoHandler(kind: string): void {
76
27
  // eslint-disable-next-line no-console
77
28
  console.warn(`[kai-card] no policy handler for "${kind}"`);
@@ -11,7 +11,27 @@
11
11
  "description": { "type": "string" },
12
12
  "required": { "type": "array", "items": { "type": "string" } },
13
13
  "properties": {
14
- "type": "object"
14
+ "type": "object",
15
+ "description": "The fields to collect, keyed by property name. Each value is a JSON Schema field definition (type, title, description, enum, minimum/maximum, minLength/maxLength, pattern, items) plus optional x-kai-* UI hints. Only the display-format hints are spelled out below; the rest of a field definition is ordinary JSON Schema.",
16
+ "additionalProperties": {
17
+ "type": "object",
18
+ "properties": {
19
+ "x-kai-format": {
20
+ "description": "Display format for a string field. `tel`, `ssn` and `credit-card` apply that type's standard mask and submit digits only; `custom` masks with `x-kai-mask` and submits the formatted value. Omit it for a plain text field.",
21
+ "enum": ["tel", "ssn", "credit-card", "custom"]
22
+ },
23
+ "x-kai-mask": {
24
+ "description": "The mask pattern, used only with `x-kai-format: \"custom\"`: `#` one digit, `@` one letter or digit, `*` one letter or digit that may be obscured; every other character is a literal shown as typed, e.g. `CHG-####`.",
25
+ "type": "string",
26
+ "maxLength": 64
27
+ },
28
+ "x-kai-mask-guide": {
29
+ "description": "Placeholder text shown at the unfilled positions of the mask, aligned character for character with the pattern (`mm/dd/yyyy` for `##/##/####`). Derived from the pattern when omitted.",
30
+ "type": "string",
31
+ "maxLength": 64
32
+ }
33
+ }
34
+ }
15
35
  },
16
36
  "x-kai-order": { "type": "array", "items": { "type": "string" } },
17
37
  "x-kai-inlineMax": { "type": "integer", "minimum": 1 },
@@ -6,8 +6,16 @@
6
6
  export interface JsonSchema {
7
7
  type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null';
8
8
  const?: unknown;
9
- enum?: unknown[];
10
- required?: string[];
9
+ // `readonly`: a construct's card schema is emitted `as const` (codegen.ts,
10
+ // emitCardsRegistry) so its literal types survive into CardTools' input —
11
+ // that turns array-valued fields into readonly tuples, which a mutable
12
+ // `T[]` does not structurally accept even under a `Readonly<Record<...>>`
13
+ // wrapper. JsonSchema is read-only data everywhere it is consumed (no
14
+ // caller mutates `.required`/`.enum` in place — see the callers in
15
+ // tool-defs.ts and form.tsx, which all build a fresh array via spread/
16
+ // filter/Set before assigning), so widening these two costs nothing.
17
+ enum?: readonly unknown[];
18
+ required?: readonly string[];
11
19
  properties?: Record<string, JsonSchema>;
12
20
  items?: JsonSchema;
13
21
  minimum?: number; maximum?: number;
@@ -55,22 +55,49 @@ export function useChatConfig(): ChatConfigValue {
55
55
  return useContext(ChatConfigContext)!;
56
56
  }
57
57
 
58
- /** Maps prose size to Tailwind prose class */
58
+ /**
59
+ * Maps prose size to the Tailwind Typography *size modifier* for consumers who
60
+ * render their own `prose` block.
61
+ *
62
+ * The `prose-*` names are deliberately NOT re-pointed at the --kai-text-* scale.
63
+ * They are not font sizes: each is a plugin-generated bundle of proportional
64
+ * margins, list indents, heading ratios and line-heights for every nested
65
+ * element, keyed to hardcoded rems, and they only do anything alongside `prose`
66
+ * itself. There is no `prose-body` to alias them to, and collapsing them to a
67
+ * bare font-size would throw away the vertical rhythm that is their whole job.
68
+ * The kit's own markdown does not go through them at all — it renders through
69
+ * `.chat-markdown` (theme.css), which is em-relative and therefore already
70
+ * scales off whatever `textClass` sets.
71
+ *
72
+ * The one raw font-size here (`xs`) DOES join the semantic scale, so it stays in
73
+ * step with `textClass('xs')`.
74
+ */
59
75
  export function proseClass(size: ProseSize): string {
60
76
  switch (size) {
61
- case 'xs': return 'prose-sm text-xs';
77
+ case 'xs': return 'prose-sm text-meta';
62
78
  case 'sm': return 'prose-sm';
63
79
  case 'base': return '';
64
80
  case 'lg': return 'prose-lg';
65
81
  }
66
82
  }
67
83
 
68
- /** Maps prose size to a text class for non-prose elements (sidebar, input) */
84
+ /**
85
+ * Maps prose size to a text class for message content, markdown, and non-prose
86
+ * chrome (sidebar, input).
87
+ *
88
+ * These are the kit's SEMANTIC type-scale utilities, not Tailwind's raw scale:
89
+ * each resolves through a namespaced --kai-text-* token in theme.css, so a
90
+ * consumer setting `--kai-text-body` moves the reading text. The public
91
+ * `proseSize` strings ('xs' | 'sm' | 'base' | 'lg') are unchanged — this is an
92
+ * internal re-point only. Sizes are byte-identical to the Tailwind classes they
93
+ * replace (text-meta ≡ text-xs, text-body ≡ text-sm, text-title ≡ text-base),
94
+ * so nothing moves until a token is actually overridden.
95
+ */
69
96
  export function textClass(size: ProseSize): string {
70
97
  switch (size) {
71
- case 'xs': return 'text-xs';
72
- case 'sm': return 'text-sm';
73
- case 'base': return 'text-base';
98
+ case 'xs': return 'text-meta';
99
+ case 'sm': return 'text-body';
100
+ case 'base': return 'text-title';
74
101
  case 'lg': return 'text-lg';
75
102
  }
76
103
  }