@kitn.ai/ui 0.17.0 → 0.18.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 (494) hide show
  1. package/README.md +28 -5
  2. package/dist/components/artifact.d.ts +39 -1
  3. package/dist/components/attachment-types.d.ts +12 -0
  4. package/dist/components/attachments.d.ts +2 -10
  5. package/dist/components/card.d.ts +27 -0
  6. package/dist/components/chain-of-thought.d.ts +78 -2
  7. package/dist/components/chat-scope-picker.d.ts +7 -0
  8. package/dist/components/chat-thread.d.ts +37 -12
  9. package/dist/components/choice-card.d.ts +26 -0
  10. package/dist/components/coachmark.d.ts +49 -0
  11. package/dist/components/composer-dom.d.ts +35 -0
  12. package/dist/components/composer-highlight.d.ts +48 -0
  13. package/dist/components/composer-history.d.ts +34 -0
  14. package/dist/components/composer.d.ts +86 -0
  15. package/dist/components/confirm-card.d.ts +17 -0
  16. package/dist/components/conversation-item.d.ts +9 -0
  17. package/dist/components/conversation-list.d.ts +36 -1
  18. package/dist/components/file-tree.d.ts +15 -0
  19. package/dist/components/form.d.ts +34 -0
  20. package/dist/components/markdown.d.ts +3 -0
  21. package/dist/components/message.d.ts +12 -0
  22. package/dist/components/model-switcher.d.ts +7 -0
  23. package/dist/components/prompt-input.d.ts +13 -4
  24. package/dist/components/prompt-suggestion.d.ts +9 -1
  25. package/dist/components/reasoning.d.ts +14 -1
  26. package/dist/components/response-compare.d.ts +14 -0
  27. package/dist/components/screen.d.ts +46 -0
  28. package/dist/components/tasks-card.d.ts +49 -1
  29. package/dist/components/toast.d.ts +12 -2
  30. package/dist/components/tool-types.d.ts +10 -0
  31. package/dist/components/tool.d.ts +8 -8
  32. package/dist/components/voice-input.d.ts +27 -0
  33. package/dist/components/voice-output.d.ts +33 -0
  34. package/dist/core-C8fzo39E.js +12 -0
  35. package/dist/custom-elements.json +8392 -1860
  36. package/dist/elements/agent-card.d.ts +1 -0
  37. package/dist/elements/agent-card.js +1 -0
  38. package/dist/elements/artifact.js +1 -1
  39. package/dist/elements/attachments.js +1 -1
  40. package/dist/elements/autoloader.js +1 -1
  41. package/dist/elements/avatar.d.ts +1 -0
  42. package/dist/elements/avatar.js +1 -0
  43. package/dist/elements/badge.d.ts +1 -0
  44. package/dist/elements/badge.js +1 -0
  45. package/dist/elements/button.d.ts +1 -0
  46. package/dist/elements/button.js +1 -0
  47. package/dist/elements/card.js +1 -1
  48. package/dist/elements/cards.js +1 -1
  49. package/dist/elements/chain-of-thought.js +1 -1
  50. package/dist/elements/chat-scope-picker.js +1 -1
  51. package/dist/elements/chat-types.d.ts +47 -0
  52. package/dist/elements/chat-workspace.js +1 -1
  53. package/dist/elements/chat.js +1 -1
  54. package/dist/elements/checkpoint.js +1 -1
  55. package/dist/elements/choice.js +1 -1
  56. package/dist/elements/chunks/Icon-DLLBeLG5.js +1 -0
  57. package/dist/elements/chunks/action-icons-UB4V5FNq.js +1 -0
  58. package/dist/elements/chunks/arrow-left-C-gwlUmx.js +1 -0
  59. package/dist/elements/chunks/attachments-CgbErf1r.js +1 -0
  60. package/dist/elements/chunks/badge-DTQpgB6N.js +1 -0
  61. package/dist/elements/chunks/button-XDUM6lXs.js +1 -0
  62. package/dist/elements/chunks/card-CBlFZ-7I.js +1 -0
  63. package/dist/elements/chunks/chat-thread-BIhmqwNL.js +1 -0
  64. package/dist/elements/chunks/check-hGUoVIKb.js +1 -0
  65. package/dist/elements/chunks/chevron-down-DDoaSUtO.js +1 -0
  66. package/dist/elements/chunks/chevron-right-CdGEUakB.js +1 -0
  67. package/dist/elements/chunks/circle-BKAZdmzb.js +1 -0
  68. package/dist/elements/chunks/circle-check-CmYG-y3I.js +1 -0
  69. package/dist/elements/chunks/circle-x-DewgAEym.js +1 -0
  70. package/dist/elements/chunks/cn-CU7UAWzk.js +1 -0
  71. package/dist/elements/chunks/code-block-DedwxwFI.js +1 -0
  72. package/dist/elements/chunks/collapsible-FfgmTHtM.js +1 -0
  73. package/dist/elements/chunks/composer-Cfbw5HKT.js +65 -0
  74. package/dist/elements/chunks/context-DwJmxlRE.js +1 -0
  75. package/dist/elements/chunks/conversation-list-DsCQMfPq.js +1 -0
  76. package/dist/elements/chunks/default-input-BuqsoENC.js +1 -0
  77. package/dist/elements/chunks/define-rGsaWsLL.js +1 -0
  78. package/dist/elements/chunks/disclosure-CwoAkpMH.js +1 -0
  79. package/dist/elements/chunks/download-DJ06G3Bz.js +1 -0
  80. package/dist/elements/chunks/dropdown-BFg8ri_R.js +1 -0
  81. package/dist/elements/chunks/ellipsis-dlN6YvGw.js +1 -0
  82. package/dist/elements/chunks/external-link-DBX2lc_R.js +1 -0
  83. package/dist/elements/chunks/file-text-HfwUx4F9.js +1 -0
  84. package/dist/elements/chunks/file-tree-C6Toj71u.js +1 -0
  85. package/dist/elements/chunks/folder-MYuqa9Xp.js +1 -0
  86. package/dist/elements/chunks/hover-card-gE7iyXdW.js +1 -0
  87. package/dist/elements/chunks/icon-Vqz4ivrY.js +1 -0
  88. package/dist/elements/chunks/{index-CTBEJeo6.js → index-BCRhi84a.js} +1 -1
  89. package/dist/elements/chunks/info-B_toFS0l.js +1 -0
  90. package/dist/elements/chunks/input-gzbHYZvQ.js +1 -0
  91. package/dist/elements/chunks/kbd-n49c4KZm.js +1 -0
  92. package/dist/elements/chunks/link-CKPs9yM0.js +1 -0
  93. package/dist/elements/chunks/loader-q6MamGus.js +1 -0
  94. package/dist/elements/chunks/{markdown-CMTGx9r8.js → markdown-DBrcqq4S.js} +9 -9
  95. package/dist/elements/chunks/message-CTqaYI0s.js +1 -0
  96. package/dist/elements/chunks/message-feedback-Cvzm03w0.js +1 -0
  97. package/dist/elements/chunks/message-square-CUg9eRCi.js +1 -0
  98. package/dist/elements/chunks/minimize-2-l2klxP6K.js +1 -0
  99. package/dist/elements/chunks/model-switcher-CmyjiHO1.js +1 -0
  100. package/dist/elements/chunks/overlay-C8sOYqjT.js +1 -0
  101. package/dist/elements/chunks/paperclip-42Ia7xHD.js +1 -0
  102. package/dist/elements/chunks/progress-bar-tzKMWAwO.js +1 -0
  103. package/dist/elements/chunks/prompt-suggestion-D3F6vP_A.js +1 -0
  104. package/dist/elements/chunks/reasoning-BJNmmyov.js +1 -0
  105. package/dist/elements/chunks/resizable-BRsk19qI.js +1 -0
  106. package/dist/elements/chunks/rotate-cw-BgcggLHC.js +1 -0
  107. package/dist/elements/chunks/scroll-area-CgGbFFbT.js +1 -0
  108. package/dist/elements/chunks/separator-8hM4GdHE.js +1 -0
  109. package/dist/elements/chunks/settings-CaUIYOg-.js +1 -0
  110. package/dist/elements/chunks/settings-group-CYjOVIZQ.js +1 -0
  111. package/dist/elements/chunks/share-BTYM3Ddt.js +1 -0
  112. package/dist/elements/chunks/skeleton-DsTYrPUe.js +1 -0
  113. package/dist/elements/chunks/slots-DkZ-Cmha.js +1 -0
  114. package/dist/elements/chunks/star-9R3LBQ9n.js +1 -0
  115. package/dist/elements/chunks/store-CYl5Y0_u.js +1 -0
  116. package/dist/elements/chunks/text-shimmer-CaYGv8Se.js +1 -0
  117. package/dist/elements/chunks/textarea-NEr2SLcD.js +1 -0
  118. package/dist/elements/chunks/thumbs-up-DZYZkFfc.js +1 -0
  119. package/dist/elements/chunks/toast-store-ClxVZRcc.js +1 -0
  120. package/dist/elements/chunks/tool-CHZOmoe9.js +1 -0
  121. package/dist/elements/chunks/tooltip-WpHElELC.js +1 -0
  122. package/dist/elements/chunks/triangle-alert-BlS80PUg.js +1 -0
  123. package/dist/elements/chunks/use-card-resolution-VSVoxDeJ.js +1 -0
  124. package/dist/elements/chunks/video-DxTPZqT8.js +1 -0
  125. package/dist/elements/chunks/x-C1qtndxn.js +1 -0
  126. package/dist/elements/coachmark.d.ts +1 -0
  127. package/dist/elements/coachmark.js +1 -0
  128. package/dist/elements/code-block.js +1 -1
  129. package/dist/elements/command.d.ts +1 -0
  130. package/dist/elements/command.js +1 -0
  131. package/dist/elements/compare.js +1 -1
  132. package/dist/elements/composer.d.ts +1 -0
  133. package/dist/elements/composer.js +1 -0
  134. package/dist/elements/confirm-card.js +1 -1
  135. package/dist/elements/context-meter.js +1 -1
  136. package/dist/elements/conversation-list.js +1 -1
  137. package/dist/elements/css.d.ts +1 -0
  138. package/dist/elements/default-input.d.ts +51 -0
  139. package/dist/elements/define.d.ts +53 -0
  140. package/dist/elements/dialog.d.ts +1 -0
  141. package/dist/elements/dialog.js +1 -0
  142. package/dist/elements/disclosure.d.ts +37 -0
  143. package/dist/elements/editable-label.d.ts +1 -0
  144. package/dist/elements/editable-label.js +1 -0
  145. package/dist/elements/embed.js +1 -1
  146. package/dist/elements/empty.js +1 -1
  147. package/dist/elements/feedback-bar.js +1 -1
  148. package/dist/elements/file-tree.js +1 -1
  149. package/dist/elements/file-upload.js +1 -1
  150. package/dist/elements/form.js +1 -1
  151. package/dist/elements/hover-card.d.ts +1 -0
  152. package/dist/elements/hover-card.js +1 -0
  153. package/dist/elements/icon.d.ts +1 -0
  154. package/dist/elements/icon.js +1 -0
  155. package/dist/elements/image.js +1 -1
  156. package/dist/elements/input.d.ts +1 -0
  157. package/dist/elements/input.js +1 -0
  158. package/dist/elements/kbd.d.ts +1 -0
  159. package/dist/elements/kbd.js +1 -0
  160. package/dist/elements/link-preview.js +1 -1
  161. package/dist/elements/loader.js +1 -1
  162. package/dist/elements/markdown.js +1 -1
  163. package/dist/elements/menu.d.ts +1 -0
  164. package/dist/elements/menu.js +1 -0
  165. package/dist/elements/message-skills.js +1 -1
  166. package/dist/elements/message.js +1 -1
  167. package/dist/elements/model-switcher.js +1 -1
  168. package/dist/elements/nav.d.ts +1 -0
  169. package/dist/elements/nav.js +1 -0
  170. package/dist/elements/notice.d.ts +1 -0
  171. package/dist/elements/notice.js +1 -0
  172. package/dist/elements/pane-group.d.ts +1 -0
  173. package/dist/elements/pane-group.js +1 -0
  174. package/dist/elements/pane.d.ts +1 -0
  175. package/dist/elements/pane.js +1 -0
  176. package/dist/elements/popover.js +1 -1
  177. package/dist/elements/progress-bar.d.ts +1 -0
  178. package/dist/elements/progress-bar.js +1 -0
  179. package/dist/elements/prompt-dock.d.ts +1 -0
  180. package/dist/elements/prompt-dock.js +1 -0
  181. package/dist/elements/prompt-input.js +1 -1
  182. package/dist/elements/prompt-suggestions.js +1 -1
  183. package/dist/elements/reasoning.js +1 -1
  184. package/dist/elements/register-impl.d.ts +0 -0
  185. package/dist/elements/register.d.ts +13 -0
  186. package/dist/elements/remote.d.ts +1 -0
  187. package/dist/elements/remote.js +1 -0
  188. package/dist/elements/resizable.js +1 -1
  189. package/dist/elements/response-stream.js +2 -2
  190. package/dist/elements/screen.d.ts +1 -0
  191. package/dist/elements/screen.js +1 -0
  192. package/dist/elements/scroll-area.d.ts +1 -0
  193. package/dist/elements/scroll-area.js +1 -0
  194. package/dist/elements/scroll-button.js +1 -1
  195. package/dist/elements/search.d.ts +1 -0
  196. package/dist/elements/search.js +1 -0
  197. package/dist/elements/segmented.d.ts +1 -0
  198. package/dist/elements/segmented.js +1 -0
  199. package/dist/elements/separator.d.ts +1 -0
  200. package/dist/elements/separator.js +1 -0
  201. package/dist/elements/setting-item.d.ts +1 -0
  202. package/dist/elements/setting-item.js +1 -0
  203. package/dist/elements/settings-group.d.ts +1 -0
  204. package/dist/elements/settings-group.js +1 -0
  205. package/dist/elements/skeleton.d.ts +1 -0
  206. package/dist/elements/skeleton.js +1 -0
  207. package/dist/elements/slots.d.ts +176 -0
  208. package/dist/elements/source.js +1 -1
  209. package/dist/elements/status.d.ts +1 -0
  210. package/dist/elements/status.js +1 -0
  211. package/dist/elements/switch.js +1 -1
  212. package/dist/elements/tabs.d.ts +1 -0
  213. package/dist/elements/tabs.js +1 -0
  214. package/dist/elements/tasks.js +1 -1
  215. package/dist/elements/text-shimmer.js +1 -1
  216. package/dist/elements/thinking-bar.js +1 -1
  217. package/dist/elements/toast.js +1 -1
  218. package/dist/elements/tool.js +1 -1
  219. package/dist/elements/tooltip.d.ts +1 -0
  220. package/dist/elements/tooltip.js +1 -0
  221. package/dist/elements/voice-input.js +1 -1
  222. package/dist/elements/voice-output.d.ts +1 -0
  223. package/dist/elements/voice-output.js +1 -0
  224. package/dist/elements.d.ts +733 -58
  225. package/dist/engine-javascript-C1x7zo1_.js +141 -0
  226. package/dist/index.d.ts +3 -2
  227. package/dist/index.js +8256 -5703
  228. package/dist/kai.es.js +1 -0
  229. package/dist/llms/llms-full.txt +1146 -64
  230. package/dist/llms/llms.txt +4 -4
  231. package/dist/mcp.es.js +62 -7
  232. package/dist/primitives/composer-model.d.ts +22 -0
  233. package/dist/primitives/composer-triggers.d.ts +19 -0
  234. package/dist/primitives/create-kai-chat.d.ts +38 -0
  235. package/dist/primitives/toast-store.d.ts +32 -2
  236. package/dist/primitives/use-speech-recognition.d.ts +26 -0
  237. package/dist/react/index.d.ts +1085 -97
  238. package/dist/react/runtime.d.ts +9 -2
  239. package/dist/react/use-kai-chat.d.ts +41 -0
  240. package/dist/react.js +572 -193
  241. package/dist/register-impl-CYWGkgbI.js +141 -0
  242. package/dist/schemas/tasks.schema.json +2 -2
  243. package/dist/state/index.d.ts +4 -0
  244. package/dist/state/messages.d.ts +11 -0
  245. package/dist/state/stream.d.ts +22 -0
  246. package/dist/state/suggestions.d.ts +4 -0
  247. package/dist/state.js +117 -0
  248. package/dist/theme.tokens.css +87 -0
  249. package/dist/types.d.ts +4 -0
  250. package/dist/ui/agent-card.d.ts +61 -0
  251. package/dist/ui/button.d.ts +5 -2
  252. package/dist/ui/card.d.ts +61 -0
  253. package/dist/ui/collapsible.d.ts +15 -1
  254. package/dist/ui/command.d.ts +33 -0
  255. package/dist/ui/dialog.d.ts +42 -0
  256. package/dist/ui/dropdown.d.ts +95 -1
  257. package/dist/ui/editable-label.d.ts +26 -0
  258. package/dist/ui/hover-card.d.ts +13 -1
  259. package/dist/ui/icon.d.ts +18 -0
  260. package/dist/ui/input.d.ts +33 -0
  261. package/dist/ui/kbd.d.ts +21 -0
  262. package/dist/ui/nav.d.ts +62 -0
  263. package/dist/ui/notice.d.ts +31 -0
  264. package/dist/ui/overlay.d.ts +12 -0
  265. package/dist/ui/pane-grid.d.ts +58 -0
  266. package/dist/ui/pane-group.d.ts +75 -0
  267. package/dist/ui/pane.d.ts +78 -0
  268. package/dist/ui/popover.d.ts +11 -1
  269. package/dist/ui/progress-bar.d.ts +23 -0
  270. package/dist/ui/prompt-dock.d.ts +96 -0
  271. package/dist/ui/resizable.d.ts +12 -0
  272. package/dist/ui/scroll-area.d.ts +4 -0
  273. package/dist/ui/segmented.d.ts +28 -0
  274. package/dist/ui/settings-group.d.ts +32 -0
  275. package/dist/ui/skeleton.d.ts +12 -0
  276. package/dist/ui/stat.d.ts +16 -0
  277. package/dist/ui/status.d.ts +13 -0
  278. package/dist/ui/switch.d.ts +8 -1
  279. package/dist/ui/tabs.d.ts +35 -0
  280. package/dist/ui/tooltip.d.ts +19 -1
  281. package/frameworks/react/index.tsx +1042 -157
  282. package/frameworks/react/runtime.tsx +30 -1
  283. package/frameworks/react/use-kai-chat.tsx +87 -0
  284. package/llms-full.txt +1146 -64
  285. package/llms.txt +4 -4
  286. package/package.json +23 -8
  287. package/src/agent-tooling/mcp/manifest.ts +14 -0
  288. package/src/agent-tooling/mcp/tools/debug.ts +10 -6
  289. package/src/agent-tooling/mcp/tools/reference.ts +32 -0
  290. package/src/agent-tooling/mcp/tools/scaffold.ts +30 -1
  291. package/src/components/artifact.tsx +98 -13
  292. package/src/components/attachment-types.ts +13 -0
  293. package/src/components/attachments.tsx +4 -14
  294. package/src/components/card.tsx +109 -15
  295. package/src/components/chain-of-thought.tsx +210 -1
  296. package/src/components/chat-scope-picker.tsx +13 -3
  297. package/src/components/chat-thread.tsx +225 -116
  298. package/src/components/choice-card.tsx +103 -11
  299. package/src/components/coachmark.tsx +245 -0
  300. package/src/components/component-meta.json +691 -102
  301. package/src/components/composer-dom.ts +159 -0
  302. package/src/components/composer-highlight.ts +242 -0
  303. package/src/components/composer-history.ts +82 -0
  304. package/src/components/composer.tsx +979 -0
  305. package/src/components/confirm-card.tsx +54 -1
  306. package/src/components/conversation-item.tsx +69 -7
  307. package/src/components/conversation-list.tsx +134 -37
  308. package/src/components/file-tree.tsx +197 -47
  309. package/src/components/form-widgets.tsx +9 -7
  310. package/src/components/form.tsx +140 -17
  311. package/src/components/image.tsx +3 -5
  312. package/src/components/link-preview.tsx +5 -4
  313. package/src/components/markdown.tsx +5 -2
  314. package/src/components/message.tsx +23 -4
  315. package/src/components/model-switcher.tsx +19 -4
  316. package/src/components/prompt-input.tsx +46 -75
  317. package/src/components/prompt-suggestion.tsx +48 -16
  318. package/src/components/reasoning.tsx +29 -6
  319. package/src/components/response-compare.tsx +31 -2
  320. package/src/components/screen.tsx +176 -0
  321. package/src/components/tasks-card.tsx +342 -21
  322. package/src/components/toast.tsx +119 -31
  323. package/src/components/tool-types.ts +10 -0
  324. package/src/components/tool.tsx +22 -16
  325. package/src/components/voice-input.tsx +102 -19
  326. package/src/components/voice-output.tsx +202 -0
  327. package/src/elements/agent-card.tsx +67 -0
  328. package/src/elements/artifact.tsx +53 -4
  329. package/src/elements/attachments.tsx +1 -0
  330. package/src/elements/avatar.tsx +33 -0
  331. package/src/elements/badge.tsx +32 -0
  332. package/src/elements/button.tsx +126 -0
  333. package/src/elements/card-media.jpg +0 -0
  334. package/src/elements/card.tsx +124 -31
  335. package/src/elements/cards.tsx +81 -7
  336. package/src/elements/chain-of-thought.tsx +77 -32
  337. package/src/elements/chat-scope-picker.tsx +35 -8
  338. package/src/elements/chat-types.ts +2 -2
  339. package/src/elements/chat-workspace.tsx +153 -41
  340. package/src/elements/chat.tsx +45 -23
  341. package/src/elements/choice.tsx +71 -19
  342. package/src/elements/coachmark.tsx +90 -0
  343. package/src/elements/command.tsx +209 -0
  344. package/src/elements/compare.tsx +24 -2
  345. package/src/elements/compiled.css +1 -1
  346. package/src/elements/composer.tsx +151 -0
  347. package/src/elements/confirm-card.tsx +36 -11
  348. package/src/elements/conversation-list.tsx +80 -11
  349. package/src/elements/default-input.tsx +75 -53
  350. package/src/elements/define.tsx +47 -6
  351. package/src/elements/dialog.tsx +98 -0
  352. package/src/elements/disclosure.ts +73 -0
  353. package/src/elements/editable-label.tsx +125 -0
  354. package/src/elements/element-manifest.json +129 -1
  355. package/src/elements/element-meta.json +5562 -1336
  356. package/src/elements/element-types.d.ts +732 -57
  357. package/src/elements/file-tree.tsx +12 -2
  358. package/src/elements/file-upload.tsx +1 -1
  359. package/src/elements/form.tsx +54 -11
  360. package/src/elements/hover-card.tsx +80 -0
  361. package/src/elements/icon-names.json +48 -0
  362. package/src/elements/icon.tsx +41 -0
  363. package/src/elements/input.tsx +203 -0
  364. package/src/elements/kbd.tsx +45 -0
  365. package/src/elements/menu.tsx +217 -0
  366. package/src/elements/message.tsx +58 -11
  367. package/src/elements/model-switcher.tsx +27 -1
  368. package/src/elements/nav.tsx +87 -0
  369. package/src/elements/notice.tsx +53 -0
  370. package/src/elements/pane-group.tsx +119 -0
  371. package/src/elements/pane.tsx +129 -0
  372. package/src/elements/popover.tsx +39 -17
  373. package/src/elements/progress-bar.tsx +39 -0
  374. package/src/elements/prompt-dock.tsx +81 -0
  375. package/src/elements/prompt-input.tsx +112 -63
  376. package/src/elements/prompt-suggestions.tsx +25 -9
  377. package/src/elements/reasoning.tsx +30 -9
  378. package/src/elements/register-impl.ts +38 -3
  379. package/src/elements/register.ts +11 -3
  380. package/src/elements/resizable.tsx +48 -11
  381. package/src/elements/screen.tsx +90 -0
  382. package/src/elements/scroll-area.tsx +33 -0
  383. package/src/elements/search.tsx +180 -0
  384. package/src/elements/segmented.tsx +135 -0
  385. package/src/elements/separator.tsx +36 -0
  386. package/src/elements/setting-item.tsx +50 -0
  387. package/src/elements/settings-group.tsx +37 -0
  388. package/src/elements/skeleton.tsx +45 -0
  389. package/src/elements/slots.ts +607 -0
  390. package/src/elements/source.tsx +13 -6
  391. package/src/elements/status.tsx +42 -0
  392. package/src/elements/switch.tsx +89 -14
  393. package/src/elements/tabs.tsx +95 -0
  394. package/src/elements/tasks.tsx +70 -14
  395. package/src/elements/toast.tsx +17 -2
  396. package/src/elements/tool.tsx +43 -9
  397. package/src/elements/tooltip.tsx +85 -0
  398. package/src/elements/video-poster.jpg +0 -0
  399. package/src/elements/voice-input.tsx +66 -16
  400. package/src/elements/voice-output.tsx +69 -0
  401. package/src/index.ts +5 -2
  402. package/src/primitives/card-schemas/tasks.schema.json +2 -2
  403. package/src/primitives/composer-model.ts +49 -0
  404. package/src/primitives/composer-triggers.ts +35 -0
  405. package/src/primitives/create-kai-chat.ts +66 -0
  406. package/src/primitives/toast-store.ts +43 -2
  407. package/src/primitives/use-speech-recognition.ts +135 -0
  408. package/src/state/index.ts +6 -0
  409. package/src/state/messages.ts +36 -0
  410. package/src/state/stream.ts +92 -0
  411. package/src/state/suggestions.ts +9 -0
  412. package/src/types.ts +4 -0
  413. package/src/ui/agent-card.tsx +212 -0
  414. package/src/ui/button.tsx +16 -5
  415. package/src/ui/card.tsx +245 -0
  416. package/src/ui/collapsible.tsx +30 -4
  417. package/src/ui/command.tsx +99 -0
  418. package/src/ui/dialog.tsx +217 -0
  419. package/src/ui/dropdown.tsx +375 -13
  420. package/src/ui/editable-label.tsx +112 -0
  421. package/src/ui/hover-card.tsx +28 -5
  422. package/src/ui/icon.tsx +110 -0
  423. package/src/ui/input.tsx +132 -0
  424. package/src/ui/kbd.tsx +118 -0
  425. package/src/ui/nav.tsx +282 -0
  426. package/src/ui/notice.tsx +84 -0
  427. package/src/ui/overlay.tsx +108 -2
  428. package/src/ui/pane-grid.tsx +116 -0
  429. package/src/ui/pane-group.tsx +280 -0
  430. package/src/ui/pane.tsx +193 -0
  431. package/src/ui/popover.tsx +16 -2
  432. package/src/ui/progress-bar.tsx +83 -0
  433. package/src/ui/prompt-dock.tsx +145 -0
  434. package/src/ui/resizable.tsx +69 -1
  435. package/src/ui/scroll-area.tsx +14 -3
  436. package/src/ui/segmented.tsx +109 -0
  437. package/src/ui/settings-group.tsx +67 -0
  438. package/src/ui/skeleton.tsx +62 -5
  439. package/src/ui/stat.tsx +41 -0
  440. package/src/ui/status.tsx +48 -0
  441. package/src/ui/switch.tsx +49 -23
  442. package/src/ui/tabs.tsx +168 -0
  443. package/src/ui/tooltip.tsx +52 -8
  444. package/theme.css +113 -0
  445. package/dist/components/slash-command.d.ts +0 -15
  446. package/dist/elements/chunks/Icon-D_Zmwmwh.js +0 -1
  447. package/dist/elements/chunks/action-icons-PVfIvcuG.js +0 -1
  448. package/dist/elements/chunks/attachments-Dp6vqtrc.js +0 -1
  449. package/dist/elements/chunks/button-CKyYD9G4.js +0 -1
  450. package/dist/elements/chunks/card-Cjho-PYk.js +0 -1
  451. package/dist/elements/chunks/chat-thread-RT808iPf.js +0 -1
  452. package/dist/elements/chunks/check-CDYaMYrM.js +0 -1
  453. package/dist/elements/chunks/chevron-down-3SBiq8HF.js +0 -1
  454. package/dist/elements/chunks/chevron-right-k2UFlIVK.js +0 -1
  455. package/dist/elements/chunks/cn-Dogu6PbV.js +0 -1
  456. package/dist/elements/chunks/code-block-BYUmfFSd.js +0 -1
  457. package/dist/elements/chunks/collapsible-BiNwdOn6.js +0 -1
  458. package/dist/elements/chunks/context-18g6oi4J.js +0 -1
  459. package/dist/elements/chunks/conversation-list-D9Y0NVdo.js +0 -1
  460. package/dist/elements/chunks/default-input-CSAoYYMd.js +0 -1
  461. package/dist/elements/chunks/download-D8K0Je8r.js +0 -1
  462. package/dist/elements/chunks/dropdown-bUs2iTia.js +0 -1
  463. package/dist/elements/chunks/external-link-6mA0wxab.js +0 -1
  464. package/dist/elements/chunks/file-text-DnaYk3Dm.js +0 -1
  465. package/dist/elements/chunks/file-tree-CgtRLlxK.js +0 -1
  466. package/dist/elements/chunks/hover-card-CIGw62gP.js +0 -1
  467. package/dist/elements/chunks/link-BlGSeoPy.js +0 -1
  468. package/dist/elements/chunks/loader-DvhR4qa0.js +0 -1
  469. package/dist/elements/chunks/message-CDZwXjhL.js +0 -1
  470. package/dist/elements/chunks/message-feedback-CYx81QiA.js +0 -1
  471. package/dist/elements/chunks/model-switcher-O_tUhoOT.js +0 -1
  472. package/dist/elements/chunks/overlay-DydXYMQW.js +0 -1
  473. package/dist/elements/chunks/prompt-suggestion-ldlWV5kd.js +0 -1
  474. package/dist/elements/chunks/reasoning-2PUnHlmr.js +0 -1
  475. package/dist/elements/chunks/resizable-B5WNbSeb.js +0 -1
  476. package/dist/elements/chunks/star-t9tI-P0q.js +0 -1
  477. package/dist/elements/chunks/store-C6rIooZz.js +0 -1
  478. package/dist/elements/chunks/text-shimmer-uh9V_KUh.js +0 -1
  479. package/dist/elements/chunks/textarea-3nm6Ia9U.js +0 -1
  480. package/dist/elements/chunks/thumbs-up-BBtguGld.js +0 -1
  481. package/dist/elements/chunks/toast-store-D8cL3fWl.js +0 -1
  482. package/dist/elements/chunks/tool-GJ3vwp1U.js +0 -1
  483. package/dist/elements/chunks/tooltip-DwKAz4XR.js +0 -1
  484. package/dist/elements/chunks/triangle-alert-Ct1zt2JL.js +0 -1
  485. package/dist/elements/chunks/use-card-resolution-D-_0Alzy.js +0 -1
  486. package/dist/elements/chunks/video-mVYiM99-.js +0 -1
  487. package/dist/elements/chunks/x-CzxL27Ch.js +0 -1
  488. package/dist/kitn-chat.es.js +0 -1
  489. package/dist/register-JyTglR6m.js +0 -1
  490. package/dist/register-impl-C6wlSsts.js +0 -77
  491. package/src/components/slash-command.tsx +0 -232
  492. package/src/elements/framework-usage.json +0 -588
  493. /package/dist/{kitn-chat-provider.d.ts → kai-provider.d.ts} +0 -0
  494. /package/dist/{kitn-chat-provider.es.js → kai-provider.es.js} +0 -0
@@ -22,6 +22,7 @@ interface CollapsibleCtx {
22
22
  open: Accessor<boolean>;
23
23
  toggle: () => void;
24
24
  contentId: string;
25
+ disabled: Accessor<boolean>;
25
26
  }
26
27
 
27
28
  const Ctx = createContext<CollapsibleCtx>();
@@ -32,25 +33,48 @@ const useCollapsible = () => {
32
33
  return c;
33
34
  };
34
35
 
36
+ /** Imperative open controller, handed to a parent (e.g. the kai-tool facade)
37
+ * via `controllerRef` so it can drive/observe open state — mirrors
38
+ * HoverCardController. Only available when the Collapsible is UNCONTROLLED
39
+ * (no `open` prop); in controlled mode the parent already owns the state. */
40
+ export interface CollapsibleController { open: Accessor<boolean>; setOpen: (v: boolean) => void; }
41
+
35
42
  export function Collapsible(props: {
36
43
  open?: boolean;
37
44
  defaultOpen?: boolean;
38
45
  onOpenChange?: (open: boolean) => void;
46
+ /** When true, the trigger no longer toggles (programmatic show/hide still work
47
+ * via the controller; this only gates the user-facing trigger). */
48
+ disabled?: boolean;
49
+ /** Receive the open controller (open accessor + setOpen) once mounted.
50
+ * Only meaningful in uncontrolled mode (no `open` prop). */
51
+ controllerRef?: (api: CollapsibleController) => void;
39
52
  children: JSX.Element;
40
53
  class?: string;
41
54
  }) {
42
- const [local, rest] = splitProps(props, ['open', 'defaultOpen', 'onOpenChange', 'children', 'class']);
55
+ const [local, rest] = splitProps(props, ['open', 'defaultOpen', 'onOpenChange', 'disabled', 'controllerRef', 'children', 'class']);
43
56
  const [uncontrolled, setUncontrolled] = createSignal(local.defaultOpen ?? false);
44
57
  const isControlled = () => local.open !== undefined;
45
58
  const open = () => (isControlled() ? !!local.open : uncontrolled());
46
- const toggle = () => {
47
- const next = !open();
59
+ const disabled = () => !!local.disabled;
60
+ // setOpen drives the open state and notifies onOpenChange — the single mutate
61
+ // path shared by the trigger and the imperative controller.
62
+ const setOpen = (next: boolean) => {
63
+ if (open() === next) return;
48
64
  if (!isControlled()) setUncontrolled(next);
49
65
  local.onOpenChange?.(next);
50
66
  };
67
+ const toggle = () => {
68
+ if (disabled()) return;
69
+ setOpen(!open());
70
+ };
71
+ // Hand the controller up once. setOpen is NOT gated by disabled — disabled only
72
+ // suppresses the user trigger; programmatic show/hide remain available (the
73
+ // facade's wireDisclosure applies its own disabled-gating on show/toggle).
74
+ local.controllerRef?.({ open, setOpen });
51
75
  const contentId = createUniqueId();
52
76
  return (
53
- <Ctx.Provider value={{ open, toggle, contentId }}>
77
+ <Ctx.Provider value={{ open, toggle, contentId, disabled }}>
54
78
  <div
55
79
  class={local.class}
56
80
  {...rest}
@@ -78,10 +102,12 @@ export function CollapsibleTrigger(props: {
78
102
  type: 'button' as const,
79
103
  'aria-expanded': ctx.open(),
80
104
  'aria-controls': ctx.contentId,
105
+ disabled: ctx.disabled() || undefined,
81
106
  'data-expanded': ctx.open() ? '' : undefined,
82
107
  'data-closed': ctx.open() ? undefined : '',
83
108
  'data-state': ctx.open() ? 'open' : 'closed',
84
109
  onClick: (e: MouseEvent) => {
110
+ if (ctx.disabled()) return;
85
111
  if (typeof local.onClick === 'function') {
86
112
  (local.onClick as (e: MouseEvent) => void)(e);
87
113
  }
@@ -0,0 +1,99 @@
1
+ import { For, Show, type JSX } from 'solid-js';
2
+ import { cn } from '../utils/cn';
3
+ import { renderIcon } from './icon';
4
+ import { Kbd } from './kbd';
5
+
6
+ export interface CommandRow {
7
+ id: string;
8
+ label: string;
9
+ icon?: string;
10
+ description?: string;
11
+ /** Optional keyboard shortcut shown as right-aligned key caps; uses the
12
+ * kai-kbd `keys` syntax (e.g. "Mod+K", "Alt+1"). */
13
+ shortcut?: string;
14
+ }
15
+
16
+ export interface CommandGroup {
17
+ group?: string;
18
+ items: CommandRow[];
19
+ }
20
+
21
+ export interface CommandListProps {
22
+ groups: CommandGroup[];
23
+ activeId?: string;
24
+ onSelect: (id: string) => void;
25
+ emptyLabel?: string;
26
+ /** Accessible label for the listbox container. Defaults to 'Command palette'. */
27
+ ariaLabel?: string;
28
+ /** id applied to the listbox container, for aria-controls wiring. */
29
+ id?: string;
30
+ }
31
+
32
+ /**
33
+ * `CommandList` — a presentational grouped listbox for command/mention palettes.
34
+ *
35
+ * Renders a `role="listbox"` container. Groups with a `group` name get a muted
36
+ * section header. Each row is a `role="option"` button with icon, label, and
37
+ * optional description. Clicking a row calls `onSelect(id)`. When there are no
38
+ * groups/items it renders `emptyLabel` (default "No results").
39
+ */
40
+ export function CommandList(props: CommandListProps): JSX.Element {
41
+ const hasItems = () => props.groups.some((g) => g.items.length > 0);
42
+
43
+ return (
44
+ <div role="listbox" aria-label={props.ariaLabel ?? 'Command palette'} id={props.id}>
45
+ <Show
46
+ when={hasItems()}
47
+ fallback={
48
+ <div class="px-3 py-4 text-center text-sm text-muted-foreground select-none">
49
+ {props.emptyLabel ?? 'No results'}
50
+ </div>
51
+ }
52
+ >
53
+ <For each={props.groups}>
54
+ {(group) => (
55
+ <Show when={group.items.length > 0}>
56
+ <>
57
+ <Show when={group.group}>
58
+ <div class="px-3 pt-2 pb-1 text-xs font-medium text-muted-foreground select-none">
59
+ {group.group}
60
+ </div>
61
+ </Show>
62
+ <For each={group.items}>
63
+ {(row) => (
64
+ <button
65
+ role="option"
66
+ aria-selected={row.id === props.activeId}
67
+ class={cn(
68
+ 'flex w-full items-center gap-2 px-3 py-1.5 text-left text-sm transition-colors',
69
+ row.id === props.activeId
70
+ ? 'bg-muted text-foreground'
71
+ : 'text-foreground hover:bg-muted',
72
+ )}
73
+ // Prevent blur on the search input so keyboard nav keeps working.
74
+ onMouseDown={(e) => e.preventDefault()}
75
+ onClick={() => props.onSelect(row.id)}
76
+ >
77
+ <Show when={row.icon}>{(icon) => renderIcon(icon(), { imgClass: 'size-4 shrink-0 rounded object-cover', spanClass: 'flex size-4 shrink-0 items-center justify-center text-sm', ariaHidden: true })}</Show>
78
+ <span class="font-medium whitespace-nowrap shrink-0">{row.label}</span>
79
+ <Show when={row.description}>
80
+ <span class="min-w-0 truncate text-muted-foreground">{row.description}</span>
81
+ </Show>
82
+ <Show when={row.shortcut}>
83
+ {(sc) => (
84
+ <span part="shortcut" class="ml-auto shrink-0 pl-3">
85
+ <Kbd keys={sc()} platform="auto" size="sm" />
86
+ </span>
87
+ )}
88
+ </Show>
89
+ </button>
90
+ )}
91
+ </For>
92
+ </>
93
+ </Show>
94
+ )}
95
+ </For>
96
+ </Show>
97
+ </div>
98
+ );
99
+ }
@@ -0,0 +1,217 @@
1
+ import {
2
+ createEffect, createSignal, createUniqueId, Show, type Accessor, type JSX,
3
+ } from 'solid-js';
4
+ import { Portal } from 'solid-js/web';
5
+ import { cn } from '../utils/cn';
6
+ import { useChatConfig } from '../primitives/chat-config';
7
+ import { createPresence } from './overlay';
8
+
9
+ /** Imperative open controller, handed to a parent (e.g. the kai-dialog facade)
10
+ * via `controllerRef` so it can drive/observe open state with `wireDisclosure`. */
11
+ export interface DialogController { open: Accessor<boolean>; setOpen: (v: boolean) => void; }
12
+
13
+ export interface DialogProps {
14
+ /** Dialog body — the default slot / main content. */
15
+ children?: JSX.Element;
16
+ /** Optional header region (e.g. a title). Rendered above the body with a divider. */
17
+ header?: JSX.Element;
18
+ /** Optional footer region (e.g. action buttons). Rendered below the body with a divider. */
19
+ footer?: JSX.Element;
20
+ /** Controlled open state. When set, the component never changes it itself —
21
+ * drive it from `onOpenChange`. Omit for uncontrolled (internal) state. */
22
+ open?: boolean;
23
+ /** Initial open state when uncontrolled. */
24
+ defaultOpen?: boolean;
25
+ /** Fires whenever the dialog wants to open or close (Escape / backdrop / method). */
26
+ onOpenChange?: (open: boolean) => void;
27
+ /** Receive the open controller (open accessor + setOpen) once mounted. */
28
+ controllerRef?: (api: DialogController) => void;
29
+ /** Receive the focusable panel node so a facade's `focus()` can target it. */
30
+ panelRef?: (el: HTMLElement) => void;
31
+ /** Accessible name for the dialog when no `header` is provided. */
32
+ 'aria-label'?: string;
33
+ /** Extra class applied to the panel (e.g. a wider `max-w-*`). */
34
+ class?: string;
35
+ }
36
+
37
+ /** Focusable-element selector for the Tab focus trap. */
38
+ const FOCUSABLE_SELECTOR = [
39
+ 'a[href]', 'button:not([disabled])', 'input:not([disabled])',
40
+ 'select:not([disabled])', 'textarea:not([disabled])',
41
+ 'audio[controls]', 'video[controls]', '[contenteditable]:not([contenteditable="false"])',
42
+ '[tabindex]:not([tabindex="-1"])',
43
+ ].join(',');
44
+
45
+ /** Roughly "rendered + not visibility:hidden" — skips display:none / hidden nodes. */
46
+ function isVisible(el: HTMLElement): boolean {
47
+ return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length)
48
+ && getComputedStyle(el).visibility !== 'hidden';
49
+ }
50
+
51
+ /**
52
+ * Tabbable descendants of `panel`, in tab order. Crosses `<slot>` boundaries:
53
+ * when used as a web-component facade the panel's real content is light-DOM nodes
54
+ * assigned to its slots, not panel descendants, so a plain querySelectorAll would
55
+ * miss them. We walk the tree and expand each slot to its assigned elements.
56
+ */
57
+ function getTabbables(panel: HTMLElement): HTMLElement[] {
58
+ const out: HTMLElement[] = [];
59
+ const walk = (node: Element) => {
60
+ for (const child of Array.from(node.children)) {
61
+ if (child instanceof HTMLSlotElement) {
62
+ for (const assigned of child.assignedElements()) {
63
+ if (assigned instanceof HTMLElement) {
64
+ if (assigned.matches(FOCUSABLE_SELECTOR)) out.push(assigned);
65
+ walk(assigned);
66
+ }
67
+ }
68
+ } else if (child instanceof HTMLElement) {
69
+ if (child.matches(FOCUSABLE_SELECTOR)) out.push(child);
70
+ walk(child);
71
+ }
72
+ }
73
+ };
74
+ walk(panel);
75
+ return out.filter(isVisible);
76
+ }
77
+
78
+ /** The deepest active element, drilling through nested shadow roots (so a focused
79
+ * node inside a shadow tree resolves to the real element, not its host). */
80
+ function deepActiveElement(): HTMLElement | null {
81
+ let el = document.activeElement as HTMLElement | null;
82
+ while (el?.shadowRoot?.activeElement) el = el.shadowRoot.activeElement as HTMLElement;
83
+ return el;
84
+ }
85
+
86
+ /**
87
+ * Dialog is the presentational centered modal surface. It renders through a Portal
88
+ * (so it escapes any clipping/stacking ancestor), dims the page with a backdrop,
89
+ * and centers a panel with a sensible max width/height and internal scroll. It
90
+ * closes on Escape and on a backdrop click (never on a panel click), moves focus
91
+ * into the panel on open and restores it on close, and runs a basic Tab focus
92
+ * trap so keyboard focus cycles within the panel while open. The developer owns
93
+ * when it opens (drive `open` / `defaultOpen`); this owns being the modal.
94
+ *
95
+ * Styleable parts: `backdrop` · `panel` · `header` · `body` · `footer`.
96
+ */
97
+ export function Dialog(props: DialogProps) {
98
+ const config = useChatConfig();
99
+ const [internalOpen, setInternalOpen] = createSignal(props.defaultOpen ?? false);
100
+ const headerId = `kai-dialog-title-${createUniqueId()}`;
101
+
102
+ const isControlled = () => props.open !== undefined;
103
+ const isOpen = () => (isControlled() ? !!props.open : internalOpen());
104
+ const setOpen = (v: boolean) => {
105
+ if (!isControlled()) setInternalOpen(v);
106
+ props.onOpenChange?.(v);
107
+ };
108
+
109
+ // Hand the open controller up to a parent (e.g. the kai-dialog facade) so it can
110
+ // drive/observe open state via wireDisclosure.
111
+ props.controllerRef?.({ open: isOpen, setOpen });
112
+
113
+ const presence = createPresence(isOpen);
114
+
115
+ let backdrop: HTMLElement | undefined;
116
+ let panel: HTMLElement | undefined;
117
+ // The element that had focus before we opened, restored on close.
118
+ let restoreFocus: HTMLElement | null = null;
119
+ // Track where a click started so a drag that ends on the backdrop (e.g. a text
120
+ // selection begun inside the panel) does not falsely dismiss.
121
+ let pointerDownOnBackdrop = false;
122
+
123
+ // Move focus into the panel on open; restore it on close. Seeded prev=false so a
124
+ // `defaultOpen` (open-at-mount) still runs the open branch.
125
+ createEffect((wasOpen: boolean) => {
126
+ const open = isOpen();
127
+ if (open && !wasOpen) {
128
+ restoreFocus = deepActiveElement();
129
+ queueMicrotask(() => panel?.focus());
130
+ } else if (!open && wasOpen) {
131
+ const target = restoreFocus;
132
+ restoreFocus = null;
133
+ if (target && target.isConnected) queueMicrotask(() => target.focus());
134
+ }
135
+ return open;
136
+ }, false);
137
+
138
+ const onKeyDown = (e: KeyboardEvent) => {
139
+ if (e.key === 'Escape') {
140
+ e.stopPropagation();
141
+ setOpen(false);
142
+ return;
143
+ }
144
+ if (e.key !== 'Tab' || !panel) return;
145
+ // Basic focus trap: keep Tab / Shift+Tab cycling within the panel.
146
+ const items = getTabbables(panel);
147
+ if (!items.length) {
148
+ e.preventDefault();
149
+ panel.focus();
150
+ return;
151
+ }
152
+ const active = deepActiveElement();
153
+ const idx = active ? items.indexOf(active) : -1;
154
+ if (e.shiftKey) {
155
+ if (idx <= 0) { e.preventDefault(); items[items.length - 1].focus(); }
156
+ } else if (idx === -1 || idx === items.length - 1) {
157
+ e.preventDefault();
158
+ items[0].focus();
159
+ }
160
+ };
161
+
162
+ const onClick = (e: MouseEvent) => {
163
+ if (pointerDownOnBackdrop && e.target === backdrop) setOpen(false);
164
+ pointerDownOnBackdrop = false;
165
+ };
166
+
167
+ return (
168
+ <Show when={presence.present()}>
169
+ <Portal mount={config.portalMount()}>
170
+ <div
171
+ ref={(el) => { backdrop = el; presence.setRef(el); }}
172
+ part="backdrop"
173
+ data-expanded={presence.state() === 'open' ? '' : undefined}
174
+ data-closed={presence.state() === 'closed' ? '' : undefined}
175
+ onPointerDown={(e) => { pointerDownOnBackdrop = e.target === e.currentTarget; }}
176
+ onClick={onClick}
177
+ onKeyDown={onKeyDown}
178
+ class={cn(
179
+ 'fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4',
180
+ 'animate-in fade-in-0 data-[closed]:animate-out data-[closed]:fade-out-0 motion-reduce:animate-none',
181
+ )}
182
+ >
183
+ <div
184
+ ref={(el) => { panel = el; props.panelRef?.(el); }}
185
+ part="panel"
186
+ role="dialog"
187
+ aria-modal="true"
188
+ aria-labelledby={props.header ? headerId : undefined}
189
+ aria-label={props.header ? undefined : props['aria-label']}
190
+ tabindex={-1}
191
+ data-expanded={presence.state() === 'open' ? '' : undefined}
192
+ data-closed={presence.state() === 'closed' ? '' : undefined}
193
+ class={cn(
194
+ 'flex max-h-[85vh] w-full max-w-lg flex-col overflow-hidden rounded-xl border border-border bg-background text-foreground shadow-xl outline-none',
195
+ 'animate-in fade-in-0 zoom-in-95 data-[closed]:animate-out data-[closed]:fade-out-0 data-[closed]:zoom-out-95 motion-reduce:animate-none',
196
+ props.class,
197
+ )}
198
+ >
199
+ <Show when={props.header}>
200
+ <header part="header" id={headerId} class="shrink-0 border-b border-border px-5 py-4 text-base font-semibold text-foreground">
201
+ {props.header}
202
+ </header>
203
+ </Show>
204
+ <div part="body" class="min-h-0 flex-1 overflow-auto px-5 py-4 text-sm text-foreground">
205
+ {props.children}
206
+ </div>
207
+ <Show when={props.footer}>
208
+ <footer part="footer" class="flex shrink-0 items-center justify-end gap-2 border-t border-border px-5 py-3">
209
+ {props.footer}
210
+ </footer>
211
+ </Show>
212
+ </div>
213
+ </div>
214
+ </Portal>
215
+ </Show>
216
+ );
217
+ }