@kitn.ai/ui 0.17.0 → 0.18.1

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-C2LTALdM.js +1 -0
  57. package/dist/elements/chunks/action-icons-Dtl8Ox5D.js +1 -0
  58. package/dist/elements/chunks/arrow-left-GbBceGBE.js +1 -0
  59. package/dist/elements/chunks/attachments-DLJcWCDV.js +1 -0
  60. package/dist/elements/chunks/badge-BTNZTODL.js +1 -0
  61. package/dist/elements/chunks/button-DBDZebGr.js +1 -0
  62. package/dist/elements/chunks/card-YfCyI4fH.js +1 -0
  63. package/dist/elements/chunks/chat-thread-Dz2qbzvI.js +1 -0
  64. package/dist/elements/chunks/check-fhmRksq_.js +1 -0
  65. package/dist/elements/chunks/chevron-down-DcRg1aRU.js +1 -0
  66. package/dist/elements/chunks/chevron-right-ChzBcNJ-.js +1 -0
  67. package/dist/elements/chunks/circle-B4fTe9v6.js +1 -0
  68. package/dist/elements/chunks/circle-check-CJV-3Rem.js +1 -0
  69. package/dist/elements/chunks/circle-x-pDtzlghQ.js +1 -0
  70. package/dist/elements/chunks/cn-CU7UAWzk.js +1 -0
  71. package/dist/elements/chunks/code-block-DZ6mz6vs.js +1 -0
  72. package/dist/elements/chunks/collapsible-CWUAShMC.js +1 -0
  73. package/dist/elements/chunks/composer-BZyPU6gD.js +65 -0
  74. package/dist/elements/chunks/context-Cx6eQA_G.js +1 -0
  75. package/dist/elements/chunks/conversation-list-C4xTQSpT.js +1 -0
  76. package/dist/elements/chunks/default-input-BZcwyKcP.js +1 -0
  77. package/dist/elements/chunks/define-CNSKFZCd.js +1 -0
  78. package/dist/elements/chunks/disclosure-BcBs--Jf.js +1 -0
  79. package/dist/elements/chunks/download-BDQwcFav.js +1 -0
  80. package/dist/elements/chunks/dropdown-wgs8xCJZ.js +1 -0
  81. package/dist/elements/chunks/ellipsis-CUiEJ6R1.js +1 -0
  82. package/dist/elements/chunks/external-link-DJUmC7g2.js +1 -0
  83. package/dist/elements/chunks/file-text-DOYfYvrh.js +1 -0
  84. package/dist/elements/chunks/file-tree-DQzNQrbr.js +1 -0
  85. package/dist/elements/chunks/folder-DBDUBANz.js +1 -0
  86. package/dist/elements/chunks/hover-card-BQGdGAQ3.js +1 -0
  87. package/dist/elements/chunks/icon-CAyRqVrg.js +1 -0
  88. package/dist/elements/chunks/{index-CTBEJeo6.js → index-BCRhi84a.js} +1 -1
  89. package/dist/elements/chunks/info-DBQl-m6e.js +1 -0
  90. package/dist/elements/chunks/input-DZD67EvW.js +1 -0
  91. package/dist/elements/chunks/kbd-DbyVrlnU.js +1 -0
  92. package/dist/elements/chunks/link-vko7AttA.js +1 -0
  93. package/dist/elements/chunks/loader-Cg6rO8tQ.js +1 -0
  94. package/dist/elements/chunks/{markdown-CMTGx9r8.js → markdown-n3Xbj3PR.js} +9 -9
  95. package/dist/elements/chunks/message-CgKytiSB.js +1 -0
  96. package/dist/elements/chunks/message-feedback-Ds3-US0e.js +1 -0
  97. package/dist/elements/chunks/message-square-MmRkvc-M.js +1 -0
  98. package/dist/elements/chunks/minimize-2-3kCdE0q3.js +1 -0
  99. package/dist/elements/chunks/model-switcher-BMtXGwLU.js +1 -0
  100. package/dist/elements/chunks/overlay-B1-MBI6h.js +1 -0
  101. package/dist/elements/chunks/paperclip-DDEfmkHc.js +1 -0
  102. package/dist/elements/chunks/progress-bar-Dwbiyv3s.js +1 -0
  103. package/dist/elements/chunks/prompt-suggestion-9lvgFcEa.js +1 -0
  104. package/dist/elements/chunks/reasoning-DzHWsdAJ.js +1 -0
  105. package/dist/elements/chunks/resizable-Bq_eHxUm.js +1 -0
  106. package/dist/elements/chunks/rotate-cw-jpisOdOV.js +1 -0
  107. package/dist/elements/chunks/scroll-area-g5Ze3K6f.js +1 -0
  108. package/dist/elements/chunks/separator-Bmjc5XyX.js +1 -0
  109. package/dist/elements/chunks/settings-Cz1bMJP9.js +1 -0
  110. package/dist/elements/chunks/settings-group-9imY3kRA.js +1 -0
  111. package/dist/elements/chunks/share-BdenF0wQ.js +1 -0
  112. package/dist/elements/chunks/skeleton-Pjc5jiaY.js +1 -0
  113. package/dist/elements/chunks/slots-DkZ-Cmha.js +1 -0
  114. package/dist/elements/chunks/star-DY6z1UUH.js +1 -0
  115. package/dist/elements/chunks/store-th4VyJXM.js +1 -0
  116. package/dist/elements/chunks/text-shimmer-CEi-tlXr.js +1 -0
  117. package/dist/elements/chunks/textarea-CboigarR.js +1 -0
  118. package/dist/elements/chunks/thumbs-up-BR33KLfA.js +1 -0
  119. package/dist/elements/chunks/toast-store-BEMda0fv.js +1 -0
  120. package/dist/elements/chunks/tool-TMued3WO.js +1 -0
  121. package/dist/elements/chunks/tooltip-Cft_Rxiw.js +1 -0
  122. package/dist/elements/chunks/triangle-alert-B07fX3Q8.js +1 -0
  123. package/dist/elements/chunks/use-card-resolution-M36zVciB.js +1 -0
  124. package/dist/elements/chunks/video-MKp3LmNT.js +1 -0
  125. package/dist/elements/chunks/x-Ckwicf6g.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 +8255 -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-cKscku5m.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 +77 -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 +31 -10
  287. package/src/agent-tooling/mcp/manifest.ts +14 -0
  288. package/src/agent-tooling/mcp/tools/debug.ts +11 -7
  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 +249 -0
  300. package/src/components/component-meta.json +699 -110
  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 +341 -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 +2 -2
  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 +87 -7
  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 +218 -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 +117 -0
  429. package/src/ui/pane-group.tsx +291 -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
@@ -8,18 +8,20 @@ import {
8
8
  createMemo,
9
9
  createEffect,
10
10
  on,
11
+ onMount,
11
12
  ErrorBoundary,
12
13
  createUniqueId,
13
14
  } from 'solid-js';
14
15
  import { cn } from '../utils/cn';
15
16
  import { Button } from '../ui/button';
17
+ import { ProgressBar } from '../ui/progress-bar';
16
18
  import { Card } from './card';
17
19
  import { DismissedStub } from './dismissed-stub';
18
20
  import type { CardEnvelope, CardEvent, CardHost, CardResolution } from '../primitives/card-contract';
19
21
  import { useCardResolution } from './use-card-resolution';
20
22
  import { emitCardEvent } from '../primitives/card-routing';
21
23
  import { useCardHost } from '../primitives/card-host';
22
- import { Check, X } from 'lucide-solid';
24
+ import { Check, Circle, CircleCheck, X } from 'lucide-solid';
23
25
 
24
26
  // ─────────────────────────────────────────────────────────────────────────────
25
27
  // Types (tasks.schema.json) — see src/primitives/card-schemas/tasks.schema.json
@@ -34,7 +36,15 @@ export interface TasksTask {
34
36
  }
35
37
 
36
38
  export interface TasksCardData {
37
- mode?: 'select'; // future: 'select' | 'progress'
39
+ /**
40
+ * `select` (default) = checkbox rows + a confirm button that emits the contract
41
+ * `submit`. `progress` = an onboarding/checklist look: a header `done / total`
42
+ * count, circular indicators, per-item title + muted description, and NO confirm
43
+ * button (checking a row is itself the terminal action). Both share the same
44
+ * selection model (toggle by id, the `max` gate, `kai-value-change`); `progress`
45
+ * is purely a presentational variant.
46
+ */
47
+ mode?: 'select' | 'progress';
38
48
  heading?: string;
39
49
  tasks: TasksTask[]; // >=1
40
50
  selectAll?: boolean;
@@ -123,6 +133,16 @@ export function showSelectAll(data: TasksCardData, tasks: TasksTask[]): boolean
123
133
  return true;
124
134
  }
125
135
 
136
+ /** Whether the card is in the onboarding-checklist `progress` look (no confirm). */
137
+ export function isProgressMode(data: TasksCardData): boolean {
138
+ return data.mode === 'progress';
139
+ }
140
+
141
+ /** The header progress count (`done` checked / `total` rows) for `progress` mode. */
142
+ export function progressCount(tasks: TasksTask[], selected: Set<string>): { done: number; total: number } {
143
+ return { done: tasks.filter((t) => selected.has(t.id)).length, total: tasks.length };
144
+ }
145
+
126
146
  /** Whether confirm is enabled for the current selection count. */
127
147
  export function canConfirm(data: TasksCardData, count: number): boolean {
128
148
  const min = data.min ?? (data.allowEmpty ? 0 : 1);
@@ -149,6 +169,24 @@ export function confirmReason(data: TasksCardData, count: number): string | unde
149
169
  // The <TasksCard> component.
150
170
  // ─────────────────────────────────────────────────────────────────────────────
151
171
 
172
+ /** Imperative handle exposed via `controllerRef` — surfaces the tasks card's latent
173
+ * selection model (set the checked ids, toggle one, confirm, focus the group,
174
+ * dismiss/reopen) so the `<kai-tasks>` facade can forward them as instance methods. */
175
+ export interface TasksCardController {
176
+ /** Set the checked ids (local-only, no emit), respecting disabled/max. No arg = select all toggleable rows. */
177
+ select(taskIds?: string[]): void;
178
+ /** Toggle one task by id, honoring the max gate. */
179
+ toggle(taskId: string, checked?: boolean): void;
180
+ /** Confirm the current selection (only when allowed) — emits `submit` + resolves. */
181
+ send(): void;
182
+ /** Focus the task group (select-all checkbox if shown, else the first row). */
183
+ focus(options?: FocusOptions): void;
184
+ /** Trigger the dismiss path (emit `dismiss` + collapse to the re-openable stub). */
185
+ dismiss(): void;
186
+ /** Re-open a dismissed card from its stub (emit `reopen`). */
187
+ reopen(): void;
188
+ }
189
+
152
190
  export interface TasksCardProps {
153
191
  /** The tasks definition (CardEnvelope.data). */
154
192
  data?: TasksCardData;
@@ -164,6 +202,20 @@ export interface TasksCardProps {
164
202
  class?: string;
165
203
  /** When set, render the chromed read-only summary instead of the interactive controls. */
166
204
  resolution?: CardResolution;
205
+ /** Controlled selection (task ids) — when set, this wins over internal state. */
206
+ value?: string[];
207
+ /** Uncontrolled initial selection (task ids), overlaying per-task `checked`. */
208
+ defaultValue?: string[];
209
+ /** Freeze the whole list + Confirm. */
210
+ disabled?: boolean;
211
+ /** Display-only: rows can't be toggled and show the default cursor (no pointer,
212
+ * no hover background, no focus ring). Keeps the visual content as-is — this only
213
+ * drops the interactive affordances + a11y exposure. */
214
+ readonly?: boolean;
215
+ /** Fires on every selection change with the selected ids (distinct from submit). */
216
+ onValueChange?: (payload: { value: string[] }) => void;
217
+ /** Receive the imperative controller once mounted. */
218
+ controllerRef?: (controller: TasksCardController) => void;
167
219
  }
168
220
 
169
221
  const DEFAULT_DATA: TasksCardData = { tasks: [] };
@@ -177,7 +229,10 @@ const DEFAULT_DATA: TasksCardData = { tasks: [] };
177
229
  */
178
230
  export function TasksCard(props: TasksCardProps): JSX.Element {
179
231
  const merged = mergeProps({ cardId: 'kai-tasks' }, props);
180
- const [local] = splitProps(merged, ['data', 'cardId', 'heading', 'host', 'hostElement', 'class', 'resolution']);
232
+ const [local] = splitProps(merged, [
233
+ 'data', 'cardId', 'heading', 'host', 'hostElement', 'class', 'resolution',
234
+ 'value', 'defaultValue', 'disabled', 'readonly', 'onValueChange', 'controllerRef',
235
+ ]);
181
236
 
182
237
  const ctxHost = useCardHost();
183
238
  const uid = createUniqueId();
@@ -198,16 +253,37 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
198
253
 
199
254
  const res = useCardResolution({ prop: () => local.resolution, data: () => local.data });
200
255
 
201
- // Seed selection from the tasks' initial checked state when a NEW definition arrives.
256
+ // Only ids that exist in the current task list (drop unknown ids defensively).
257
+ const validIds = (ids: string[]): string[] => {
258
+ const known = new Set(tasks().map((t) => t.id));
259
+ return ids.filter((id) => known.has(id));
260
+ };
261
+
262
+ // Seed selection from `value` (controlled) > `defaultValue` > per-task `checked`,
263
+ // when a NEW definition arrives.
202
264
  createEffect(
203
265
  on(
204
266
  () => local.data,
205
267
  () => {
206
- setSelected(new Set(initialSelected(tasks())));
268
+ const seedIds = local.value ?? local.defaultValue ?? initialSelected(tasks());
269
+ setSelected(new Set(validIds(seedIds)));
207
270
  },
208
271
  ),
209
272
  );
210
273
 
274
+ // Controlled selection: when the consumer drives `value`, mirror it into the set
275
+ // (the controlled prop wins). Deferred so mount's seed runs first.
276
+ createEffect(on(() => local.value, (v) => {
277
+ if (!v) return;
278
+ setSelected(new Set(validIds(v)));
279
+ }, { defer: true }));
280
+
281
+ // Fire the live change signal whenever the selection set changes (distinct from
282
+ // the terminal submit). Deferred so the initial seed doesn't emit.
283
+ createEffect(on(selected, (s) => {
284
+ local.onValueChange?.({ value: selectedInOrder(tasks(), s) });
285
+ }, { defer: true }));
286
+
211
287
  // ready / error lifecycle emits.
212
288
  createEffect(
213
289
  on(valid, (ok) => {
@@ -216,28 +292,41 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
216
292
  }),
217
293
  );
218
294
 
295
+ const groupDisabled = (): boolean => local.disabled === true;
296
+ // Display-only: block all toggling/confirm and drop the interactive affordances,
297
+ // without the dimmed/`disabled` look.
298
+ const readOnly = (): boolean => local.readonly === true;
299
+
219
300
  const count = createMemo(() => selected().size);
301
+ // `progress` mode = the onboarding-checklist look: a header `done / total`
302
+ // count, circular indicators, no confirm button. Same selection model.
303
+ const progress = createMemo(() => isProgressMode(data()));
304
+ const progressN = createMemo(() => progressCount(tasks(), selected()));
220
305
  const confirmLabel = () => data().confirmLabel ?? 'Confirm';
221
306
  const masterState = createMemo(() => selectAllState(tasks(), selected()));
222
307
  const showMaster = createMemo(() => showSelectAll(data(), tasks()));
223
308
  const reason = createMemo(() => confirmReason(data(), count()));
224
- const confirmEnabled = createMemo(() => canConfirm(data(), count()) && !res.isResolved());
309
+ const confirmEnabled = createMemo(() => canConfirm(data(), count()) && !res.isResolved() && !groupDisabled() && !readOnly());
225
310
 
226
- const toggle = (id: string, on: boolean): void => {
227
- if (res.isResolved()) return;
228
- const next = new Set(selected());
311
+ // Apply one id to a selection set, honoring the max gate (mutates+returns `next`).
312
+ const applyToggle = (next: Set<string>, id: string, on: boolean): Set<string> => {
229
313
  if (on) {
230
314
  // Respect max: block adding past max.
231
- if (isMaxReached(data(), next.size) && !next.has(id)) return;
315
+ if (isMaxReached(data(), next.size) && !next.has(id)) return next;
232
316
  next.add(id);
233
317
  } else {
234
318
  next.delete(id);
235
319
  }
236
- setSelected(next);
320
+ return next;
321
+ };
322
+
323
+ const toggle = (id: string, on: boolean): void => {
324
+ if (res.isResolved() || groupDisabled() || readOnly()) return;
325
+ setSelected(applyToggle(new Set(selected()), id, on));
237
326
  };
238
327
 
239
328
  const toggleAll = (on: boolean): void => {
240
- if (res.isResolved()) return;
329
+ if (res.isResolved() || groupDisabled() || readOnly()) return;
241
330
  const next = new Set(selected());
242
331
  for (const id of toggleableIds(tasks())) {
243
332
  if (on) next.add(id);
@@ -262,6 +351,43 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
262
351
  };
263
352
  const onReopen = (): void => emit({ kind: 'reopen', cardId: local.cardId });
264
353
 
354
+ // Imperative controller (Pattern C): hand the facade a handle over the tasks
355
+ // card's latent selection model. select sets the checked ids local-only (no
356
+ // submit); toggle drives one row; send confirms (same path as Confirm); focus
357
+ // targets the group; dismiss/reopen drive the stub.
358
+ onMount(() => {
359
+ local.controllerRef?.({
360
+ select: (taskIds) => {
361
+ if (res.isResolved() || groupDisabled() || readOnly()) return;
362
+ if (taskIds === undefined) { toggleAll(true); return; }
363
+ // Build the set fresh, honoring max + disabled per id (skip disabled rows).
364
+ const next = new Set<string>();
365
+ const toggleable = new Set(toggleableIds(tasks()));
366
+ for (const id of validIds(taskIds)) {
367
+ if (!toggleable.has(id)) continue; // skip per-task-disabled rows
368
+ applyToggle(next, id, true);
369
+ }
370
+ setSelected(next);
371
+ },
372
+ toggle: (taskId, checked) => {
373
+ // No explicit `checked` → flip the current state.
374
+ const on = checked ?? !selected().has(taskId);
375
+ toggle(taskId, on);
376
+ },
377
+ send: () => onConfirm(),
378
+ focus: (options) => {
379
+ const root = local.hostElement?.shadowRoot ?? document;
380
+ const group = root.querySelector<HTMLElement>('[role="group"]');
381
+ // Prefer the select-all checkbox (it's the first labelled input), else the
382
+ // first row's checkbox; fall back to the group container itself.
383
+ const firstInput = group?.querySelector<HTMLElement>('input[type="checkbox"]');
384
+ (firstInput ?? group)?.focus(options);
385
+ },
386
+ dismiss: () => onDismiss(),
387
+ reopen: () => onReopen(),
388
+ });
389
+ });
390
+
265
391
  // Surface the resolved state for host styling. Only a `submit` resolution is the
266
392
  // "submitted" state; a deferred `dismissed` (or `expired`) is not.
267
393
  createEffect(() => {
@@ -283,6 +409,9 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
283
409
 
284
410
  const reasonId = `kai-tl-reason-${uid}`;
285
411
  const countId = `kai-tl-count-${uid}`;
412
+ const progressCountId = `kai-tl-progress-${uid}`;
413
+ const progressHeadingId = `kai-tl-heading-${uid}`;
414
+ const headingText = () => local.heading ?? local.data?.heading;
286
415
 
287
416
  return (
288
417
  <Show when={valid()} fallback={<Card heading={local.heading} errorMessage={errorMessage()} />}>
@@ -299,9 +428,14 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
299
428
  }
300
429
  >
301
430
  <Card
302
- heading={local.heading ?? local.data?.heading}
431
+ // In `progress` mode the heading + count render as a custom in-body row
432
+ // (so the count can sit right-aligned beside the heading), so the Card
433
+ // chrome's own heading is suppressed.
434
+ heading={progress() ? undefined : headingText()}
303
435
  actions={
304
- res.isResolved() ? undefined : (
436
+ // `progress` mode is confirm-less: checking a row IS the action.
437
+ // `readonly` is display-only, so there's no confirm/dismiss row either.
438
+ progress() || res.isResolved() || readOnly() ? undefined : (
305
439
  <div class="flex w-full flex-wrap items-center justify-between gap-2">
306
440
  <Show when={local.data?.dismissible === true}>
307
441
  <Button
@@ -340,9 +474,31 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
340
474
  when={!res.isResolved()}
341
475
  fallback={<TasksResolved summary={resolvedSummary()!} optimistic={res.isOptimistic()} />}
342
476
  >
477
+ <Show when={progress()}>
478
+ <ProgressChecklist
479
+ heading={headingText()}
480
+ headingId={progressHeadingId}
481
+ countId={progressCountId}
482
+ done={progressN().done}
483
+ total={progressN().total}
484
+ tasks={tasks()}
485
+ uid={uid}
486
+ isChecked={(id) => selected().has(id)}
487
+ isBlocked={(task) =>
488
+ groupDisabled() || task.disabled === true ||
489
+ (!selected().has(task.id) && isMaxReached(data(), count()))
490
+ }
491
+ onToggle={(id, on) => toggle(id, on)}
492
+ groupClass={local.class}
493
+ maxNote={data().max !== undefined ? data().max : undefined}
494
+ readonly={readOnly()}
495
+ />
496
+ </Show>
497
+ <Show when={!progress()}>
343
498
  <div
344
499
  role="group"
345
500
  aria-label={local.heading ?? local.data?.heading ?? 'Tasks'}
501
+ aria-readonly={readOnly() ? 'true' : undefined}
346
502
  class={cn('flex flex-col', local.class)}
347
503
  onKeyDown={(e) => {
348
504
  // Enter anywhere in the card (off a checkbox) confirms when enabled.
@@ -359,16 +515,20 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
359
515
  return (
360
516
  <label
361
517
  class={cn(
362
- 'flex cursor-pointer items-center gap-3 px-3 py-2.5 text-sm font-medium transition-colors',
518
+ 'flex items-center gap-3 px-3 py-2.5 text-sm font-medium transition-colors',
519
+ readOnly() ? 'cursor-default' : 'cursor-pointer',
363
520
  masterState() === 'checked'
364
521
  ? 'bg-accent text-accent-foreground'
365
- : 'text-foreground hover:bg-muted/50',
522
+ : readOnly()
523
+ ? 'text-foreground'
524
+ : 'text-foreground hover:bg-muted/50',
366
525
  )}
367
526
  >
368
527
  <input
369
528
  type="checkbox"
370
529
  class="kai-checkbox"
371
530
  checked={masterState() === 'checked'}
531
+ disabled={groupDisabled() || readOnly()}
372
532
  aria-checked={indeterminate() ? 'mixed' : masterState() === 'checked'}
373
533
  ref={(el) => {
374
534
  createEffect(() => {
@@ -387,15 +547,17 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
387
547
  {(task) => {
388
548
  const checked = () => selected().has(task.id);
389
549
  const blocked = () =>
390
- task.disabled || (!checked() && isMaxReached(data(), count()));
550
+ groupDisabled() || task.disabled || (!checked() && isMaxReached(data(), count()));
391
551
  const descId = `kai-tl-desc-${uid}-${task.id}`;
392
552
  return (
393
553
  <label
394
554
  class={cn(
395
555
  'flex items-start gap-3 px-3 py-2.5 text-sm transition-colors',
396
- blocked()
397
- ? 'cursor-not-allowed opacity-60'
398
- : 'cursor-pointer hover:bg-muted/50',
556
+ readOnly()
557
+ ? 'cursor-default'
558
+ : blocked()
559
+ ? 'cursor-not-allowed opacity-60'
560
+ : 'cursor-pointer hover:bg-muted/50',
399
561
  checked() && !blocked()
400
562
  ? 'bg-accent font-medium text-accent-foreground'
401
563
  : 'text-foreground',
@@ -406,7 +568,7 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
406
568
  type="checkbox"
407
569
  class="kai-checkbox mt-0.5"
408
570
  checked={checked()}
409
- disabled={blocked()}
571
+ disabled={blocked() || readOnly()}
410
572
  aria-disabled={blocked() ? 'true' : undefined}
411
573
  aria-describedby={task.description ? descId : undefined}
412
574
  onChange={(e) => toggle(task.id, e.currentTarget.checked)}
@@ -429,6 +591,7 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
429
591
  <p class="pt-1 text-xs text-muted-foreground">Up to {data().max} selected.</p>
430
592
  </Show>
431
593
  </div>
594
+ </Show>
432
595
  </Show>
433
596
  </Card>
434
597
  </Show>
@@ -437,6 +600,163 @@ export function TasksCard(props: TasksCardProps): JSX.Element {
437
600
  );
438
601
  }
439
602
 
603
+ // ─────────────────────────────────────────────────────────────────────────────
604
+ // Onboarding-checklist (`mode: 'progress'`) presenter: a header `done / total`
605
+ // count + circular indicators + per-item title/description, no confirm button.
606
+ // Drives the same selection model, where toggling a row IS the action.
607
+ // ─────────────────────────────────────────────────────────────────────────────
608
+
609
+ function ProgressChecklist(props: {
610
+ heading?: string;
611
+ headingId: string;
612
+ countId: string;
613
+ done: number;
614
+ total: number;
615
+ tasks: TasksTask[];
616
+ uid: string;
617
+ isChecked: (id: string) => boolean;
618
+ isBlocked: (task: TasksTask) => boolean;
619
+ onToggle: (id: string, on: boolean) => void;
620
+ groupClass?: string;
621
+ maxNote?: number;
622
+ /** Display-only: rows aren't focusable/toggleable and show the default cursor. */
623
+ readonly?: boolean;
624
+ }): JSX.Element {
625
+ return (
626
+ <div class={cn('flex flex-col gap-3', props.groupClass)}>
627
+ <Show when={props.heading}>
628
+ <div class="flex items-center justify-between gap-3">
629
+ <span id={props.headingId} class="text-sm font-medium text-foreground">
630
+ {props.heading}
631
+ </span>
632
+ <span
633
+ id={props.countId}
634
+ aria-live="polite"
635
+ class="shrink-0 text-sm font-medium tabular-nums text-muted-foreground"
636
+ >
637
+ {props.done} / {props.total}
638
+ </span>
639
+ </div>
640
+ </Show>
641
+
642
+ {/* Thin progress bar under the heading: filled to done / total. Named off the
643
+ checklist heading (no duplicate caption), or a generic label when headless. */}
644
+ <ProgressBar
645
+ value={props.done}
646
+ max={props.total}
647
+ tone="success"
648
+ aria-labelledby={props.heading ? props.headingId : undefined}
649
+ aria-label={props.heading ? undefined : 'Task progress'}
650
+ />
651
+
652
+ <ul
653
+ aria-labelledby={props.heading ? props.headingId : undefined}
654
+ aria-label={props.heading ? undefined : 'Checklist'}
655
+ class="flex flex-col gap-1"
656
+ >
657
+ <For each={props.tasks}>
658
+ {(task) => {
659
+ const checked = () => props.isChecked(task.id);
660
+ const blocked = () => props.isBlocked(task);
661
+ const descId = `kai-tl-pdesc-${props.uid}-${task.id}`;
662
+ return (
663
+ <li>
664
+ <label
665
+ class={cn(
666
+ 'group flex items-start gap-3 rounded-lg px-2.5 py-2 text-sm transition-colors',
667
+ // Keyboard focus ring (kit standard, inset so it stays within the
668
+ // row). focus-visible only, so a mouse click that parks focus on the
669
+ // row doesn't leave a noisy persistent outline — and it makes a
670
+ // Tab-focused completed row's open description perceivable. Dropped
671
+ // entirely when readonly (the row isn't focusable then).
672
+ !props.readonly &&
673
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring',
674
+ props.readonly
675
+ ? 'cursor-default'
676
+ : blocked()
677
+ ? 'cursor-not-allowed opacity-60'
678
+ : 'cursor-pointer hover:bg-muted/50',
679
+ )}
680
+ data-task-id={task.id}
681
+ // Completed rows hide their description until hover/focus, so make the
682
+ // row itself focusable to drive the focus-reveal (group-focus-within).
683
+ // Incomplete rows — and every row when readonly — stay unfocusable.
684
+ // Expose the label + description to AT.
685
+ tabindex={!props.readonly && checked() ? 0 : undefined}
686
+ aria-label={checked() ? task.label : undefined}
687
+ aria-describedby={checked() && task.description ? descId : undefined}
688
+ >
689
+ <input
690
+ type="checkbox"
691
+ class="sr-only"
692
+ checked={checked()}
693
+ disabled={blocked() || props.readonly}
694
+ aria-disabled={blocked() ? 'true' : undefined}
695
+ aria-describedby={task.description ? descId : undefined}
696
+ onChange={(e) => props.onToggle(task.id, e.currentTarget.checked)}
697
+ />
698
+ <span
699
+ class={cn(
700
+ 'mt-0.5 shrink-0 text-muted-foreground',
701
+ // Completed rows: the check gently scales on hover.
702
+ checked() && 'motion-safe:transition-transform motion-safe:group-hover:scale-110',
703
+ )}
704
+ aria-hidden="true"
705
+ >
706
+ <Show
707
+ when={checked()}
708
+ fallback={<Circle size={18} />}
709
+ >
710
+ <CircleCheck size={18} class="text-foreground" />
711
+ </Show>
712
+ </span>
713
+ <span class="flex min-w-0 flex-col gap-0.5">
714
+ <span
715
+ class={cn(
716
+ 'font-medium text-foreground',
717
+ // Completed: strike through + muted, brightening on hover.
718
+ checked() && 'line-through opacity-70 motion-safe:transition-opacity motion-safe:group-hover:opacity-100',
719
+ )}
720
+ >
721
+ {task.label}
722
+ </span>
723
+ <Show when={task.description}>
724
+ <Show
725
+ when={checked()}
726
+ fallback={
727
+ <span id={descId} class="text-xs font-normal text-muted-foreground">
728
+ {task.description}
729
+ </span>
730
+ }
731
+ >
732
+ {/* Completed: collapse the description and reveal it on hover or
733
+ keyboard focus via the grid-rows height trick. Height-collapse
734
+ keeps the text in the DOM + a11y tree (unlike display:none). */}
735
+ <div class="grid grid-rows-[0fr] group-hover:grid-rows-[1fr] group-focus-within:grid-rows-[1fr] motion-safe:transition-[grid-template-rows] motion-safe:duration-200">
736
+ <span
737
+ id={descId}
738
+ class="overflow-hidden text-xs font-normal text-muted-foreground opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 motion-safe:transition-opacity"
739
+ >
740
+ {task.description}
741
+ </span>
742
+ </div>
743
+ </Show>
744
+ </Show>
745
+ </span>
746
+ </label>
747
+ </li>
748
+ );
749
+ }}
750
+ </For>
751
+ </ul>
752
+
753
+ <Show when={props.maxNote !== undefined}>
754
+ <p class="text-xs text-muted-foreground">Up to {props.maxNote} selected.</p>
755
+ </Show>
756
+ </div>
757
+ );
758
+ }
759
+
440
760
  // ─────────────────────────────────────────────────────────────────────────────
441
761
  // Read-only resolved summary presenter.
442
762
  // ─────────────────────────────────────────────────────────────────────────────