@kitn.ai/ui 0.27.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 (266) hide show
  1. package/README.md +10 -2
  2. package/dist/{Icon-BnFKqqtY.js → Icon-DObhsRtm.js} +1 -1
  3. package/dist/{action-icons-CBskfBMz.js → action-icons-CcgNN2oT.js} +1 -1
  4. package/dist/arrow-down-CjRU3JgV.js +1 -0
  5. package/dist/arrow-left-Bnpb1UEW.js +1 -0
  6. package/dist/{artifact-CvXEm1lS.js → artifact-Bwt7OgcR.js} +1 -1
  7. package/dist/{attachments-C43ZegEq.js → attachments-Qr4kg-2b.js} +1 -1
  8. package/dist/{audio-visualizer-B-79y1Tj.js → audio-visualizer-DToYdfSc.js} +1 -1
  9. package/dist/{badge-BpUbq8c0.js → badge-CdEu_jn2.js} +1 -1
  10. package/dist/{bell-sn17Ip9v.js → bell-DQAAOpDz.js} +1 -1
  11. package/dist/{button-BH6rN0U-.js → button-DkuOnGLy.js} +1 -1
  12. package/dist/{card-renderer-Cb1gQmth.js → card-renderer-Jx70m6_l.js} +1 -1
  13. package/dist/{card-routing-DifQgS7n.js → card-routing-0YidER_3.js} +1 -1
  14. package/dist/check-njkVdZu2.js +1 -0
  15. package/dist/{checkbox-Dc9Yov_B.js → checkbox-D7iRB3nL.js} +1 -1
  16. package/dist/{checkbox-group-B1kDLLYk.js → checkbox-group-B2_rpoPM.js} +1 -1
  17. package/dist/chevron-down-B72s6PXR.js +1 -0
  18. package/dist/chevron-right-BatuHzUm.js +1 -0
  19. package/dist/{choice-card-BT3c1S8g.js → choice-card-m0BYqqOK.js} +1 -1
  20. package/dist/circle-check-B62pODB3.js +1 -0
  21. package/dist/{circle-x-wobWkoSx.js → circle-x-BPG0iPst.js} +1 -1
  22. package/dist/circle-zx0ByzY9.js +1 -0
  23. package/dist/code-block-ClMLKb7C.js +1 -0
  24. package/dist/{collapsible-CPJbf6FM.js → collapsible-B4DlWicL.js} +1 -1
  25. package/dist/components/chat-thread.d.ts +89 -1
  26. package/dist/components/conversation-item.d.ts +16 -0
  27. package/dist/components/conversation-panel.d.ts +29 -0
  28. package/dist/components/home-panel.d.ts +34 -0
  29. package/dist/components/widget-tab-bar.d.ts +16 -0
  30. package/dist/{composer-CjngLzal.js → composer-sQ0HcvyG.js} +3 -3
  31. package/dist/{confirm-card-DCx_A4bU.js → confirm-card-rQWDQsnC.js} +1 -1
  32. package/dist/construct-cli.es.js +182 -14
  33. package/dist/{context-BY8V-Nlp.js → context-0kg4ZX1J.js} +1 -1
  34. package/dist/controllable-CnGpMF6r.js +1 -0
  35. package/dist/conversation-item-BxwQLaFJ.js +1 -0
  36. package/dist/conversation-list-BCfGN1JU.js +1 -0
  37. package/dist/{copy-B6DO4PqB.js → copy-n9u9rqpi.js} +1 -1
  38. package/dist/{create-tween-CnMHviKB.js → create-tween-C-q-JCM-.js} +1 -1
  39. package/dist/{create-tween-D1aiGZZh.js → create-tween-CRrJXxBd.js} +1 -1
  40. package/dist/{create-tween-BPzaefTp.js → create-tween-DZ3RRDHD.js} +1 -1
  41. package/dist/{create-tween-DUSQUKpr.js → create-tween-uPkArjIG.js} +1 -1
  42. package/dist/custom-elements.json +51 -2
  43. package/dist/{default-input-CucQEOqH.js → default-input-CaMrJkgH.js} +1 -1
  44. package/dist/define-By-uL588.js +1 -0
  45. package/dist/define.js +2 -2
  46. package/dist/define.server.js +2 -2
  47. package/dist/{disclosure-CbLtajUQ.js → disclosure-WUImBbDv.js} +1 -1
  48. package/dist/{dropdown-BwhViJFd.js → dropdown-wZVeJOMd.js} +1 -1
  49. package/dist/elements/agent-card.js +1 -1
  50. package/dist/elements/artifact.js +1 -1
  51. package/dist/elements/attachments.js +1 -1
  52. package/dist/elements/audio-visualizer.js +1 -1
  53. package/dist/elements/avatar.js +1 -1
  54. package/dist/elements/badge.js +1 -1
  55. package/dist/elements/button.js +1 -1
  56. package/dist/elements/card.js +1 -1
  57. package/dist/elements/cards.js +1 -1
  58. package/dist/elements/chain-of-thought.js +1 -1
  59. package/dist/elements/chat-scope-picker.js +1 -1
  60. package/dist/elements/chat-workspace.js +1 -1
  61. package/dist/elements/chat.js +1 -1
  62. package/dist/elements/checkbox-group.js +1 -1
  63. package/dist/elements/checkbox.js +1 -1
  64. package/dist/elements/checkpoint.js +1 -1
  65. package/dist/elements/choice.js +1 -1
  66. package/dist/elements/coachmark.js +1 -1
  67. package/dist/elements/code-block.js +1 -1
  68. package/dist/elements/command.js +1 -1
  69. package/dist/elements/compare.js +1 -1
  70. package/dist/elements/composer.js +1 -1
  71. package/dist/elements/confirm-card.js +1 -1
  72. package/dist/elements/context-meter.js +1 -1
  73. package/dist/elements/conversation-item.js +1 -1
  74. package/dist/elements/conversation-list.js +1 -1
  75. package/dist/elements/dialog.js +1 -1
  76. package/dist/elements/dock.js +3 -3
  77. package/dist/elements/dropdown.js +1 -1
  78. package/dist/elements/editable-label.js +1 -1
  79. package/dist/elements/embed.js +1 -1
  80. package/dist/elements/empty.js +1 -1
  81. package/dist/elements/feedback-bar.js +1 -1
  82. package/dist/elements/file-tree.js +1 -1
  83. package/dist/elements/file-upload.js +1 -1
  84. package/dist/elements/form.js +1 -1
  85. package/dist/elements/hover-card.js +1 -1
  86. package/dist/elements/icon.js +1 -1
  87. package/dist/elements/image.js +1 -1
  88. package/dist/elements/input.js +1 -1
  89. package/dist/elements/kbd.js +1 -1
  90. package/dist/elements/link-preview.js +1 -1
  91. package/dist/elements/loader.js +1 -1
  92. package/dist/elements/markdown.js +1 -1
  93. package/dist/elements/menu.js +1 -1
  94. package/dist/elements/message-skills.js +1 -1
  95. package/dist/elements/message.js +1 -1
  96. package/dist/elements/model-switcher.js +1 -1
  97. package/dist/elements/nav.js +1 -1
  98. package/dist/elements/notice.js +1 -1
  99. package/dist/elements/pane-grid.js +1 -1
  100. package/dist/elements/pane-group.js +1 -1
  101. package/dist/elements/pane.js +1 -1
  102. package/dist/elements/popover.js +1 -1
  103. package/dist/elements/progress-bar.js +1 -1
  104. package/dist/elements/prompt-dock.js +1 -1
  105. package/dist/elements/prompt-input.js +1 -1
  106. package/dist/elements/prompt-suggestions.js +1 -1
  107. package/dist/elements/radio-group.js +1 -1
  108. package/dist/elements/reasoning.js +1 -1
  109. package/dist/elements/remote.js +1 -1
  110. package/dist/elements/resizable.js +1 -1
  111. package/dist/elements/response-stream.js +1 -1
  112. package/dist/elements/screen.js +1 -1
  113. package/dist/elements/scroll-area.js +1 -1
  114. package/dist/elements/scroll-button.js +1 -1
  115. package/dist/elements/search.js +1 -1
  116. package/dist/elements/segmented.js +1 -1
  117. package/dist/elements/select.js +1 -1
  118. package/dist/elements/separator.js +1 -1
  119. package/dist/elements/setting-item.js +1 -1
  120. package/dist/elements/settings-group.js +1 -1
  121. package/dist/elements/skeleton.js +1 -1
  122. package/dist/elements/slider.js +1 -1
  123. package/dist/elements/source.js +1 -1
  124. package/dist/elements/status.js +1 -1
  125. package/dist/elements/switch.js +1 -1
  126. package/dist/elements/tabs.js +1 -1
  127. package/dist/elements/tasks.js +1 -1
  128. package/dist/elements/text-shimmer.js +1 -1
  129. package/dist/elements/thinking-bar.js +1 -1
  130. package/dist/elements/thread.js +1 -1
  131. package/dist/elements/toast.js +1 -1
  132. package/dist/elements/tool.js +1 -1
  133. package/dist/elements/tooltip.js +1 -1
  134. package/dist/elements/voice-input.js +1 -1
  135. package/dist/elements/voice-output.js +1 -1
  136. package/dist/elements.d.ts +20 -4
  137. package/dist/{ellipsis-DFr4Vqr3.js → ellipsis-CbOpJnU3.js} +1 -1
  138. package/dist/{embed-5s_vU4J0.js → embed-CrfjkbUG.js} +1 -1
  139. package/dist/{external-link-u9d85ORQ.js → external-link-ByXAwBBQ.js} +1 -1
  140. package/dist/{file-text-CX7_x42o.js → file-text-DMib2qwt.js} +1 -1
  141. package/dist/{file-tree-D3kBjXI5.js → file-tree-CJqM2aP7.js} +1 -1
  142. package/dist/{folder-V-YdIL8f.js → folder-_BAb929C.js} +1 -1
  143. package/dist/{form-BRNUMCN2.js → form-DSZgZQZk.js} +1 -1
  144. package/dist/{hover-card-DaeiYrTA.js → hover-card-BQbul9eq.js} +1 -1
  145. package/dist/{icon-BpixdZNq.js → icon-CdcfRhYI.js} +1 -1
  146. package/dist/index.d.ts +3 -1
  147. package/dist/index.js +2842 -2703
  148. package/dist/index.server.js +2820 -2681
  149. package/dist/{info-8mFsIjS3.js → info-DsFjGuI_.js} +1 -1
  150. package/dist/{input-d1Yuu-hz.js → input-DKbmkMos.js} +1 -1
  151. package/dist/kai.es.js +1 -1
  152. package/dist/{kbd-961zMPFB.js → kbd-PvdGhX4s.js} +1 -1
  153. package/dist/{link-preview-DIIbV2Sd.js → link-preview-DbM1866N.js} +1 -1
  154. package/dist/{link-DlZZBGaR.js → link-zF8PzWfF.js} +1 -1
  155. package/dist/{loader-YQszHFaW.js → loader-BM4CEz4G.js} +1 -1
  156. package/dist/{markdown-CVk1MPsj.js → markdown-LMvmAyBk.js} +7 -7
  157. package/dist/mcp.es.js +78 -4
  158. package/dist/{message-CwKVEdZg.js → message-BSsgvHvf.js} +1 -1
  159. package/dist/{message-DS8lzHc1.js → message-BYZECyek.js} +1 -1
  160. package/dist/message-circle-DruwObfX.js +1 -0
  161. package/dist/message-square-BG6q6mlm.js +1 -0
  162. package/dist/{minimize-2-UEZmP2QT.js → minimize-2-BQRoBV1V.js} +1 -1
  163. package/dist/{model-switcher-Kk1jEQ5t.js → model-switcher-CMpCOYcB.js} +1 -1
  164. package/dist/{overlay-C1od6LOz.js → overlay-Cb-MkyDa.js} +1 -1
  165. package/dist/{panel-right-ryET0yyn.js → panel-right-i8warFxT.js} +1 -1
  166. package/dist/{paperclip-BDNoZFJP.js → paperclip-ByY3UVO6.js} +1 -1
  167. package/dist/play-BvKKq3fX.js +1 -0
  168. package/dist/primitives/conversation-store.d.ts +54 -0
  169. package/dist/{progress-bar-BvYX0aoy.js → progress-bar-jVAHvMUf.js} +1 -1
  170. package/dist/{prompt-suggestion-BRFu2lcu.js → prompt-suggestion-CD-qtNgC.js} +1 -1
  171. package/dist/{radio-DcL23cNJ.js → radio-BsoBMhkF.js} +1 -1
  172. package/dist/react/index.d.ts +393 -0
  173. package/dist/react.js +20 -20
  174. package/dist/{reasoning-Cackq4Rh.js → reasoning-4kBPtlTx.js} +1 -1
  175. package/dist/register-impl-B1hLkrI8.js +424 -0
  176. package/dist/{resizable-Cp9HUYih.js → resizable-uPmY9VY-.js} +1 -1
  177. package/dist/{rotate-ccw-0DLRDHH5.js → rotate-ccw-B2xn93py.js} +1 -1
  178. package/dist/{rotate-cw-DOB9IGcU.js → rotate-cw-CMVLoCyH.js} +1 -1
  179. package/dist/{scroll-area-emVmWP4K.js → scroll-area-BqLUo8ZZ.js} +1 -1
  180. package/dist/{scroll-button-CeP_gv1x.js → scroll-button-DslXiJyL.js} +1 -1
  181. package/dist/{select-CWmu00tS.js → select-2cLRtPGT.js} +1 -1
  182. package/dist/{separator-CE6vly6z.js → separator-BWQtNJcM.js} +1 -1
  183. package/dist/{settings-CE-78SvZ.js → settings-BBR63jLg.js} +1 -1
  184. package/dist/{settings-group-ZFWNxFQR.js → settings-group-B2ciy-Iw.js} +1 -1
  185. package/dist/{skeleton-BebdP4mf.js → skeleton-CkHI-HgC.js} +1 -1
  186. package/dist/{slider-BAKRYUlz.js → slider-DDR9U-i0.js} +1 -1
  187. package/dist/{solid-BE5ui6sy.js → solid-BzCFdL25.js} +7720 -7058
  188. package/dist/{solid-DFhsce3O.js → solid-DruVOXnf.js} +5864 -5283
  189. package/dist/solid.d.ts +6 -2
  190. package/dist/solid.js +217 -210
  191. package/dist/solid.server.js +217 -210
  192. package/dist/{source-B0FlguSx.js → source-GEnFF528.js} +1 -1
  193. package/dist/{star-CBMZvLuN.js → star-CilHq8GP.js} +1 -1
  194. package/dist/store-Ciyk6eZG.js +1 -0
  195. package/dist/{switch-CViARZCy.js → switch-KkeQIbuH.js} +1 -1
  196. package/dist/{tasks-card-MjCcOhR_.js → tasks-card-BrN4bggJ.js} +1 -1
  197. package/dist/{text-shimmer-DKlwRF2G.js → text-shimmer-Dcj1MHuq.js} +1 -1
  198. package/dist/{textarea-3ay2Me2-.js → textarea-Dpvbngbg.js} +1 -1
  199. package/dist/theme.tokens.css +28 -0
  200. package/dist/{thumbs-up-DQcu2HMO.js → thumbs-up-CsT9Wzb9.js} +1 -1
  201. package/dist/{toast-store-C6yKOhbk.js → toast-store-tgK6MuMv.js} +1 -1
  202. package/dist/{tool-BCYNlfKy.js → tool-DzUjIBT8.js} +1 -1
  203. package/dist/{tooltip-05zI4hjs.js → tooltip-Bkkg_4t0.js} +1 -1
  204. package/dist/{trash-2-BR1RxGky.js → trash-2-jBKxjGGQ.js} +1 -1
  205. package/dist/{triangle-alert-DHohDOCy.js → triangle-alert-DlQ68ppf.js} +1 -1
  206. package/dist/types.d.ts +48 -3
  207. package/dist/ui/dock.d.ts +29 -0
  208. package/dist/{upload-BbGW6A_u.js → upload-TcAHXv9W.js} +1 -1
  209. package/dist/{url-scheme-policy-DHpoTJwB.js → url-scheme-policy-DR5DgvkM.js} +1 -1
  210. package/dist/{use-card-resolution-CJW4grFa.js → use-card-resolution-DaZqAdWf.js} +1 -1
  211. package/dist/{variant-aurora-xiMPty8f.js → variant-aurora-BhLuYxJR.js} +1 -1
  212. package/dist/{variant-aurora-BUOVgPOB.js → variant-aurora-CNmfHhcx.js} +2 -2
  213. package/dist/{variant-aurora-CUsUJvFI.js → variant-aurora-D6GsdTPA.js} +2 -2
  214. package/dist/{variant-aurora-CW2i4bfr.js → variant-aurora-DbW_OWL2.js} +1 -1
  215. package/dist/{variant-custom-D91HjAKz.js → variant-custom-BRvaNHSi.js} +1 -1
  216. package/dist/{variant-custom-BQtOnmeO.js → variant-custom-BvYHR62b.js} +1 -1
  217. package/dist/{variant-custom-CAnzzppW.js → variant-custom-DMTrEO5w.js} +2 -2
  218. package/dist/{variant-custom-CAm9L-E5.js → variant-custom-DV2x254s.js} +2 -2
  219. package/dist/{variant-wave-Ca1Ls4_y.js → variant-wave-BNMGrDfj.js} +2 -2
  220. package/dist/{variant-wave-uY5crU_K.js → variant-wave-BpDd8t3Z.js} +1 -1
  221. package/dist/{variant-wave-CxX39DKd.js → variant-wave-CyBueXj9.js} +2 -2
  222. package/dist/{variant-wave-DYyzIIZv.js → variant-wave-sp-qwsdI.js} +1 -1
  223. package/dist/x-Z5UntkIJ.js +1 -0
  224. package/frameworks/react/index.tsx +14 -4
  225. package/llms-full.txt +7 -2
  226. package/package.json +1 -1
  227. package/src/agent-tooling/README.md +192 -0
  228. package/src/agent-tooling/catalog/invariants.ts +2 -2
  229. package/src/agent-tooling/construct/cli.ts +16 -0
  230. package/src/agent-tooling/construct/codegen.ts +309 -27
  231. package/src/agent-tooling/construct/construct.v1.schema.json +69 -0
  232. package/src/agent-tooling/construct/fixtures/owner-widget.construct.json +11 -2
  233. package/src/agent-tooling/construct/schema.ts +81 -0
  234. package/src/components/chat-thread.tsx +532 -36
  235. package/src/components/conversation-item.tsx +23 -0
  236. package/src/components/conversation-panel.tsx +118 -0
  237. package/src/components/home-panel.tsx +159 -0
  238. package/src/components/widget-tab-bar.tsx +73 -0
  239. package/src/elements/chat.tsx +94 -2
  240. package/src/elements/compiled.css +1 -1
  241. package/src/elements/element-meta.json +49 -6
  242. package/src/elements/element-nonscalar.json +2 -0
  243. package/src/elements/element-types.d.ts +20 -4
  244. package/src/index.ts +3 -1
  245. package/src/primitives/conversation-store.ts +248 -0
  246. package/src/solid.ts +10 -2
  247. package/src/types.ts +45 -3
  248. package/src/ui/dock.tsx +47 -1
  249. package/theme.css +28 -0
  250. package/dist/arrow-down-Br0qtpsz.js +0 -1
  251. package/dist/arrow-left-Dj7xgE12.js +0 -1
  252. package/dist/check-DPeeMUYx.js +0 -1
  253. package/dist/chevron-down-CHSWk7ZT.js +0 -1
  254. package/dist/chevron-right-B7l_fMgx.js +0 -1
  255. package/dist/circle-Bb0yOpqM.js +0 -1
  256. package/dist/circle-check-BGZpCiz7.js +0 -1
  257. package/dist/code-block-CUQ5mtv0.js +0 -1
  258. package/dist/controllable-D43BKmtX.js +0 -1
  259. package/dist/conversation-list-D4lLU_yS.js +0 -1
  260. package/dist/define-CGGX-7Vg.js +0 -1
  261. package/dist/message-circle-Xf8Q-vZp.js +0 -1
  262. package/dist/message-square-Cxnwgkns.js +0 -1
  263. package/dist/play-OFIvYXUQ.js +0 -1
  264. package/dist/register-impl-C7rENvPK.js +0 -424
  265. package/dist/store-7eoadydQ.js +0 -1
  266. package/dist/x-C5m1JFgi.js +0 -1
package/src/types.ts CHANGED
@@ -37,10 +37,29 @@ export interface ConversationSummary {
37
37
  /** Fallback for the auto relative time when updatedAt is absent. */
38
38
  lastMessageAt?: string;
39
39
  updatedAt: string;
40
- /** Right-aligned trailing text on the row a count, status, or "days ago".
41
- * When omitted, a short relative time is auto-derived from `updatedAt`
42
- * (fallback `lastMessageAt`). */
40
+ /** Trailing text describing the row's content, read differently by the two
41
+ * built-in list surfaces (both optional, same field no widened shape):
42
+ * the desktop `ConversationList`/`ConversationItem` renders it right-aligned
43
+ * as a count/status/"days ago" and auto-derives a short relative time from
44
+ * `updatedAt` (fallback `lastMessageAt`) when it's absent; the widget-box
45
+ * `ConversationPanel` list view (owner rework, 2026-08-26) renders it as the
46
+ * one-line last-message preview under the title instead — that view always
47
+ * computes its own right-aligned relative time from `updatedAt` separately,
48
+ * since a box that size has no room for a third line. `localStorageStore`
49
+ * writes it as the ~80-char truncated last-message preview on every save
50
+ * (`primitives/conversation-store.ts`). */
43
51
  trailing?: string;
52
+ /** ISO timestamp of when this conversation was last SEEN by the visitor
53
+ * (widened additively, 2026-08-26 — unread indicators; no existing field
54
+ * fit, since `trailing`/`lastMessageAt`/`updatedAt` are all content-timing
55
+ * facts, not viewing-state). Unread = `updatedAt` is later than this.
56
+ * Written by `ConversationStore.markRead` (see that doc for exactly when
57
+ * and for the decide-loudly default when a store never implements it —
58
+ * an absent `lastReadAt` reads as "not unread," never as "definitely
59
+ * unread," so a store that doesn't support the concept at all simply
60
+ * never shows an indicator rather than guessing). Round-tripped through
61
+ * `list()`/`save()`; never author this by hand. */
62
+ lastReadAt?: string;
44
63
  }
45
64
 
46
65
  export interface ConversationGroup {
@@ -51,3 +70,26 @@ export interface ConversationGroup {
51
70
  sortOrder: number;
52
71
  createdAt: string;
53
72
  }
73
+
74
+ /** One row in a `HomeConfig.links` list — a "docs" / "talk to sales" style
75
+ * entry. `href` is optional: with it, the row renders as a link (subject to
76
+ * `isSafeUrl`); without it, the row is a button that emits itself via
77
+ * `HomePanelProps.onLink`. `icon` is either a `renderIcon` name or a safe
78
+ * URL, same resolution `renderIcon` already does for every other icon prop
79
+ * in the kit. */
80
+ export interface HomeLinkEntry {
81
+ label: string;
82
+ href?: string;
83
+ description?: string;
84
+ icon?: string;
85
+ }
86
+
87
+ /** The widget home screen's JSON-shaped config (Intercom-pattern home tab).
88
+ * Consumed by `ChatThread`'s `home` prop, which wires it into `HomePanel`/
89
+ * `WidgetTabBar` and, from there, into `<kai-chat>`'s own `home` property. */
90
+ export interface HomeConfig {
91
+ greeting?: { title?: string; subtitle?: string };
92
+ recentConversation?: boolean;
93
+ newConversation?: { label?: string };
94
+ links?: HomeLinkEntry[];
95
+ }
package/src/ui/dock.tsx CHANGED
@@ -92,6 +92,52 @@ export function DockCloseGlyph(): JSX.Element {
92
92
  return <X size={24} />;
93
93
  }
94
94
 
95
+ export interface DockLauncherImageProps {
96
+ /** The icon URL. */
97
+ src: string;
98
+ /** Alt text — usually left empty: the launcher BUTTON already carries the
99
+ * accessible name (Dock derives it from `label`/`openLabel`/`closeLabel`),
100
+ * so a second name on the icon inside it would be redundant, not missing. */
101
+ alt?: string;
102
+ }
103
+
104
+ /**
105
+ * A branded launcher icon with a built-in fallback to {@link DockLauncherGlyph}
106
+ * on load failure — a dead link, or a placeholder URL nobody swapped for a
107
+ * real asset yet (exactly what shipped in `kai dev`'s own `owner-widget`
108
+ * fixture: `launcherIcon: "https://example.com/logo.png"`, which never
109
+ * resolves, so the FAB rendered a permanently broken image). Decides loudly
110
+ * with one `console.warn` naming the failing URL, then swaps — never a
111
+ * silent broken-image icon sitting in the corner of someone's page.
112
+ *
113
+ * Lives here, not on {@link Dock} itself: `Dock`'s `launcher` prop is
114
+ * deliberately ANY content (an emoji, a "Support" text pill, this image,
115
+ * whatever a consumer slots in) and the dock never inspects what it's
116
+ * holding — teaching it to specifically understand "this might be an
117
+ * `<img>` that can 404" would be the one prop where that boundary breaks.
118
+ * This is a plain sibling component a `launcher` value can be built FROM,
119
+ * same relationship `DockLauncherGlyph`/`DockCloseGlyph` already have to
120
+ * `Dock`. The construct engine's `emitDockLauncher` (codegen.ts) renders
121
+ * `<DockLauncherImage src={...} />` for a construct-authored `launcherIcon`
122
+ * rather than hand-rolling the same onError dance in emitted output.
123
+ */
124
+ export function DockLauncherImage(props: DockLauncherImageProps) {
125
+ const [failed, setFailed] = createSignal(false);
126
+ return (
127
+ <Show when={!failed()} fallback={<DockLauncherGlyph />}>
128
+ <img
129
+ src={props.src}
130
+ alt={props.alt ?? ''}
131
+ style={{ width: '24px', height: '24px', 'border-radius': '9999px' }}
132
+ onError={() => {
133
+ console.warn(`[kai] Dock launcher icon failed to load (${props.src}); falling back to the default glyph.`);
134
+ setFailed(true);
135
+ }}
136
+ />
137
+ </Show>
138
+ );
139
+ }
140
+
95
141
  /**
96
142
  * The dock's own stylesheet, scoped to its shadow root.
97
143
  *
@@ -245,7 +291,7 @@ const DOCK_CSS = `
245
291
  inline-size: 0.75rem;
246
292
  block-size: 0.75rem;
247
293
  border-radius: 9999px;
248
- background: var(--color-destructive);
294
+ background: var(--color-unread);
249
295
  box-shadow: 0 0 0 2px var(--color-primary);
250
296
  }
251
297
 
package/theme.css CHANGED
@@ -74,6 +74,29 @@
74
74
  added at the bottom. */
75
75
  --color-hover: var(--kai-color-hover, color-mix(in oklab, var(--color-muted) 60%, var(--color-background)));
76
76
  --color-selected: var(--kai-color-selected, color-mix(in oklab, var(--color-primary) 8%, var(--color-background)));
77
+ /* UNREAD indicator — a dedicated token (owner ruling, 2026-08-26), not a
78
+ reuse of --color-destructive: unread is notification semantics, not
79
+ error, so a consumer re-theming "danger" red must not also move every
80
+ unread dot. Used identically by all three places an unread conversation
81
+ surfaces: the list-row trailing dot (ConversationPanel), the header
82
+ toggle's badge (ChatThread), and Dock's own closed-launcher badge.
83
+ A vivid "messenger red" (Tailwind red-500 territory, the Intercom/iOS
84
+ badge convention) rather than the darker --color-destructive hue: the
85
+ first pass at this token picked a color that read as legible-on-paper
86
+ but visually flat/dark next to the launcher's near-black ring. This one
87
+ value is used in BOTH light and dark (no .dark override below) because
88
+ it independently clears 3:1 (WCAG 1.4.11, non-text) against every real
89
+ surface an unread dot sits on in EITHER mode: light row/card background
90
+ (white) 3.78:1, light Dock-launcher ring (--color-primary, near-black)
91
+ 4.68:1, dark row/card background (near-black) 4.73–4.35:1, dark
92
+ Dock-launcher ring (--color-primary, near-white) 3.62:1. (Measured via
93
+ the WCAG relative-luminance formula against this file's own light/dark
94
+ --color-background/-card/-primary values — see
95
+ .superpowers/sdd/2026-08-26-conversations/rework-report.md Round 4 for
96
+ the worked numbers.) Override via --kai-color-unread; a construct author
97
+ can also set it per-widget through `theme.unreadColor` (construct
98
+ vocabulary — see agent-tooling/construct/schema.ts). */
99
+ --color-unread: var(--kai-color-unread, hsl(0 84% 60%));
77
100
  /* MARKED text — the fill behind a keyword the app has flagged (the composer's
78
101
  `highlights` rules, decorated through the CSS Custom Highlight API). This is
79
102
  `<mark>`, not a selection and not a status: a warm yellow, the convention
@@ -241,6 +264,11 @@
241
264
  --color-destructive-soft: var(--kai-color-destructive-soft, color-mix(in oklab, var(--color-destructive) 14%, var(--color-background)));
242
265
  --color-hover: var(--kai-color-hover, color-mix(in oklab, var(--color-muted) 60%, var(--color-background)));
243
266
  --color-selected: var(--kai-color-selected, color-mix(in oklab, var(--color-primary) 8%, var(--color-background)));
267
+ /* Unread indicator — dark. Same value as light (see the light block for the
268
+ full contrast note): one vivid red independently clears 3:1 against both
269
+ modes' real surfaces, so there is nothing to flip here. Still redeclared
270
+ for override symmetry with every other semantic color in this file. */
271
+ --color-unread: var(--kai-color-unread, hsl(0 84% 60%));
244
272
  /* Marked text — dark. A deep warm amber rather than the light yellow: a pale
245
273
  highlighter on a near-black field would blow out and force the text to flip
246
274
  colour. See the light block for the full note. */
@@ -1 +0,0 @@
1
- import{I as o}from"./Icon-BnFKqqtY.js";import{c as r,q as e}from"./define-CGGX-7Vg.js";var m=[["path",{d:"M12 5v14",key:"s699le"}],["path",{d:"m19 12-7 7-7-7",key:"1idqje"}]],p=a=>r(o,e(a,{name:"ArrowDown",iconNode:m})),t=p;export{t as a};
@@ -1 +0,0 @@
1
- import{I as o}from"./Icon-BnFKqqtY.js";import{c as r,q as e}from"./define-CGGX-7Vg.js";var m=[["path",{d:"m12 19-7-7 7-7",key:"1l729n"}],["path",{d:"M19 12H5",key:"x3x0zl"}]],t=a=>r(o,e(a,{name:"ArrowLeft",iconNode:m})),p=t;export{p as a};
@@ -1 +0,0 @@
1
- import{I as o}from"./Icon-BnFKqqtY.js";import{c as m,q as r}from"./define-CGGX-7Vg.js";var c=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],e=a=>m(o,r(a,{name:"Check",iconNode:c})),f=e;export{f as c};
@@ -1 +0,0 @@
1
- import{I as r}from"./Icon-BnFKqqtY.js";import{c as a,q as m}from"./define-CGGX-7Vg.js";var e=[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]],n=o=>a(r,m(o,{name:"ChevronDown",iconNode:e})),p=n;export{p as c};
@@ -1 +0,0 @@
1
- import{I as a}from"./Icon-BnFKqqtY.js";import{c as m,q as r}from"./define-CGGX-7Vg.js";var t=[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]],e=o=>m(a,r(o,{name:"ChevronRight",iconNode:t})),h=e;export{h as c};
@@ -1 +0,0 @@
1
- import{I as c}from"./Icon-BnFKqqtY.js";import{c as o,q as a}from"./define-CGGX-7Vg.js";var e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],m=r=>o(c,a(r,{name:"Circle",iconNode:e})),i=m;export{i as c};
@@ -1 +0,0 @@
1
- import{I as m}from"./Icon-BnFKqqtY.js";import{c as r,q as a}from"./define-CGGX-7Vg.js";var e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],o=c=>r(m,a(c,{name:"CircleCheck",iconNode:e})),i=o;export{i as c};
@@ -1 +0,0 @@
1
- import{s as f,p as d,q as p,i as u,c as s,S as b,A as $,J,t as g,g as L,h as P,a as q,d as A,b as E,e as M}from"./define-CGGX-7Vg.js";import{c as m}from"./cn-DN5AWfiS.js";import{c as R}from"./check-DPeeMUYx.js";import{c as B}from"./copy-B6DO4PqB.js";const D={bash:()=>import("./bash-InADTalH.js"),javascript:()=>import("./javascript-C25yR2R2.js"),typescript:()=>import("./typescript-RycA9KXf.js"),tsx:()=>import("./tsx-B8rCNbgL.js"),html:()=>import("./html-CPZ3oZQ7.js"),css:()=>import("./css-M7EaDHN_.js"),json:()=>import("./json-DxJze_jm.js"),vue:()=>import("./vue-BmIZj4XD.js"),svelte:()=>import("./svelte--5p79yCD.js")},F={"github-dark-dimmed":()=>import("./github-dark-dimmed-DUshB20C.js"),"github-light":()=>import("./github-light-JYsPkUQd.js")},G={js:"javascript",ts:"typescript",jsx:"tsx",sh:"bash",shell:"bash"},w="github-dark-dimmed";let I={...D},K={...F},N={...G},v=null;const y=new Set,T=new Set;function O(){return v||(v=(async()=>{const[{createHighlighterCore:e},{createJavaScriptRegexEngine:t}]=await Promise.all([import("./core-AYMC6_lb.js"),import("./engine-javascript-vq0WuIJl.js")]);return e({themes:[],langs:[],engine:t()})})()),v}function j(e){return N[e]??e}async function Q(e,t){const n=j(t);if(y.has(n))return!0;const r=I[n];return r?(await e.loadLanguage(r()),y.add(n),!0):!1}async function k(e,t){if(T.has(t))return!0;const n=K[t];return n?(await e.loadTheme(n()),T.add(t),!0):!1}function U(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function h(e){return`<pre><code>${U(e)}</code></pre>`}async function V(e,t,n){if(!e)return h(e);try{const r=await O();if(!await Q(r,t))return h(e);const a=await k(r,n)?n:await k(r,w)?w:null;return a?r.codeToHtml(e,{lang:j(t),theme:a}):h(e)}catch{return h(e)}}var W=g("<button type=button part=copy>"),C=g("<div>"),X=g("<div tabindex=0>"),Y=g("<div tabindex=0><pre><code>");const Z=2e3;function _(e){const[t,n]=L(!1);let r;return P(()=>clearTimeout(r)),(()=>{var a=W();return a.$$click=()=>{var i;Promise.resolve((i=navigator.clipboard)==null?void 0:i.writeText(e.text)).catch(()=>{}),n(!0),clearTimeout(r),r=setTimeout(()=>n(!1),Z)},u(a,s(b,{get when(){return t()},get fallback(){return s(B,{size:14,"aria-hidden":"true"})},get children(){return s(R,{size:14,"aria-hidden":"true",class:"text-emerald-500"})}})),q(i=>{var l=t()?"Copied":"Copy code",c=m("inline-flex items-center justify-center rounded-md p-1.5","text-muted-foreground transition-colors hover:bg-muted hover:text-foreground","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring");return l!==i.e&&A(a,"aria-label",i.e=l),c!==i.t&&E(a,i.t=c),i},{e:void 0,t:void 0}),a})()}function ee(e){const[t,n]=f(e,["children","class","copy","copyText"]);return(()=>{var r=C();return d(r,p({get class(){return m("not-prose flex w-full flex-col overflow-clip border","border-border bg-card text-card-foreground","rounded-[var(--kai-code-radius,0.75rem)]",t.class)}},n),!1,!0),u(r,s(b,{get when(){return t.copy},get children(){return s(re,{class:"justify-end border-b border-border px-2 py-1",get children(){return s(_,{get text(){return t.copyText??""}})}})}}),null),u(r,()=>t.children,null),r})()}function te(e){const[t,n]=f(e,["code","language","theme","class"]),r=$(),a=()=>t.language??"tsx",i=()=>t.theme??r.codeTheme(),l=()=>r.codeHighlight(),[c]=J(()=>l()?{code:t.code,lang:a(),theme:i()}:null,o=>V(o.code,o.lang,o.theme)),S=()=>{switch(r.proseSize()){case"xs":return"text-caption";case"sm":return"text-compact";case"base":return"text-sm";case"lg":return"text-base"}},x=()=>m("w-full overflow-x-auto kai-focus-inset [&>pre]:px-4 [&>pre]:py-4",S(),t.class);return s(b,{get when(){return c()},get fallback(){return(()=>{var o=Y(),H=o.firstChild,z=H.firstChild;return d(o,p({get class(){return x()}},n),!1,!0),u(z,()=>t.code),o})()},get children(){var o=X();return d(o,p({get class(){return x()},get innerHTML(){return c()}},n),!1,!1),o}})}function re(e){const[t,n]=f(e,["children","class"]);return(()=>{var r=C();return d(r,p({get class(){return m("flex items-center justify-between",t.class)}},n),!1,!0),u(r,()=>t.children),r})()}M(["click"]);export{ee as C,te as a};
@@ -1 +0,0 @@
1
- import{g as c}from"./define-CGGX-7Vg.js";function i(t,o){const[r,n]=c(o);return[()=>t()??r(),a=>n(a)]}export{i as c};
@@ -1 +0,0 @@
1
- import{c as i,q as K,s as I,i as u,S as p,a as y,d as b,b as k,t as h,k as C,e as D,g as B,o as L,u as P,F as $,m as R}from"./define-CGGX-7Vg.js";import{c as w}from"./cn-DN5AWfiS.js";import{a as T,b as U,C as F}from"./collapsible-CPJbf6FM.js";import{B as M}from"./button-BH6rN0U-.js";import{B as H}from"./badge-BpUbq8c0.js";import{S as E}from"./scroll-area-emVmWP4K.js";import{m as G}from"./message-square-Cxnwgkns.js";import{I as J}from"./Icon-BnFKqqtY.js";var Q=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M9 3v18",key:"fh3hqa"}],["path",{d:"m14 9 3 3-3 3",key:"8010ee"}]],V=s=>i(J,K(s,{name:"PanelLeftOpen",iconNode:Q})),W=V,X=h('<span part=leading class="flex shrink-0 items-center text-muted-foreground">'),Y=h('<div part=meta class="mt-0.5 truncate text-xs text-muted-foreground">'),Z=h('<span part=menu data-kai-item-menu class="ml-auto flex shrink-0 items-center">'),_=h('<div part=row><div part=body role=button data-kai-item-body class="flex min-w-0 flex-1 cursor-pointer items-center gap-2.5 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"><div class="min-w-0 flex-1"><div part=title>'),z=h('<span part=trailing class="ml-auto shrink-0 text-xs text-muted-foreground">'),ee=h('<div class="flex items-center gap-2.5"><span>'),te=h("<button>"),re=h('<div class="flex items-center gap-2"><div>'),ne=h("<div> messages");function oe(s,e=Date.now()){if(!s)return"";const g=Date.parse(s);if(Number.isNaN(g))return"";const l=Math.max(0,Math.round((e-g)/1e3));if(l<60)return"just now";const o=Math.floor(l/60);if(o<60)return`${o}m ago`;const v=Math.floor(o/60);return v<24?`${v}h ago`:`${Math.floor(v/24)}d ago`}function ae(s){const[e]=I(s,["conversationId","active","compact","leading","meta","menu","children","hostSemantics","onActivate","class"]);return(()=>{var g=_(),l=g.firstChild,o=l.firstChild,v=o.firstChild;return l.$$keydown=t=>{e.onActivate&&(t.key==="Enter"||t.key===" ")&&(t.preventDefault(),e.onActivate())},l.$$click=()=>{var t;return(t=e.onActivate)==null?void 0:t.call(e)},u(l,i(p,{get when(){return e.leading},get children(){var t=X();return u(t,()=>e.leading),t}}),o),u(v,()=>e.children),u(o,i(p,{get when(){return e.meta},get children(){var t=Y();return u(t,()=>e.meta),t}}),null),u(g,i(p,{get when(){return e.menu},get children(){var t=Z();return u(t,()=>e.menu),t}}),null),y(t=>{var a=e.hostSemantics?"presentation":"listitem",n=e.active?"":void 0,f=e.conversationId,m=w("flex w-full items-center gap-2.5 rounded-lg text-left transition-colors",e.compact?"px-2.5 py-1.5":"px-2.5 py-2",e.active?"bg-muted":"hover:bg-muted/50",e.class),c=e.active?"true":"false",r=e.onActivate?0:void 0,d=w("truncate text-sm",e.active?"font-medium text-foreground":"text-foreground/80");return a!==t.e&&b(g,"role",t.e=a),n!==t.t&&b(g,"data-active",t.t=n),f!==t.a&&b(g,"data-conversation-id",t.a=f),m!==t.o&&k(g,t.o=m),c!==t.i&&b(l,"aria-current",t.i=c),r!==t.n&&b(l,"tabindex",t.n=r),d!==t.s&&k(v,t.s=d),t},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0}),g})()}function j(s){const[e]=I(s,["conversation","isActive","onSelect","compact","class"]),g=C(()=>e.conversation.trailing??oe(e.conversation.updatedAt??e.conversation.lastMessageAt));return(()=>{var l=te();return l.$$click=()=>e.onSelect(e.conversation.id),u(l,i(p,{get when(){return e.compact},get fallback(){return[(()=>{var o=re(),v=o.firstChild;return u(v,()=>e.conversation.title),u(o,i(p,{get when(){return g()},get children(){var t=z();return u(t,g),t}}),null),y(()=>k(v,w("min-w-0 flex-1 truncate text-sm",e.isActive?"font-medium text-foreground":"text-foreground/80"))),o})(),(()=>{var o=ne(),v=o.firstChild;return u(o,()=>e.conversation.messageCount,v),y(()=>k(o,w("mt-0.5 truncate text-xs",e.isActive?"text-foreground/70":"text-muted-foreground"))),o})()]},get children(){var o=ee(),v=o.firstChild;return u(o,i(G,{get class(){return w("size-3.5 shrink-0",e.isActive?"text-foreground":"text-muted-foreground")}}),v),u(v,()=>e.conversation.title),u(o,i(p,{get when(){return g()},get children(){var t=z();return u(t,g),t}}),null),y(()=>k(v,w("min-w-0 flex-1 truncate text-sm",e.isActive?"font-medium text-foreground":"text-foreground/80"))),o}})),y(o=>{var v=e.conversation.id,t=e.isActive?"true":void 0,a=w("w-full rounded-lg text-left transition-colors",e.compact?"px-2.5 py-1.5":"px-2.5 py-2",e.isActive?"bg-muted":"hover:bg-muted/50",e.class);return v!==o.e&&b(l,"data-conversation-id",o.e=v),t!==o.t&&b(l,"aria-current",o.t=t),a!==o.a&&k(l,o.a=a),o},{e:void 0,t:void 0,a:void 0}),l})()}D(["click","keydown"]);var ie=h('<div class="px-3 pb-2"><div class="flex items-center gap-2 rounded-md bg-surface-strong px-2.5 py-1.5"><svg width=13 height=13 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2 class=text-muted-foreground><circle cx=11 cy=11 r=8></circle><line x1=21 y1=21 x2=16.65 y2=16.65></line></svg><input type=text placeholder="Search chats..."aria-label="Search chats"class="bg-transparent text-compact text-foreground placeholder:text-muted-foreground rounded-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring w-full">'),se=h('<div role=list aria-label=Conversations part=items class="space-y-0.5 py-1">'),ce=h('<div class="flex flex-1 flex-col items-center justify-center gap-1 p-6 text-center text-sm text-muted-foreground">No conversations match your search'),le=h('<div class="space-y-0.5 py-1">'),ue=h('<div class="shrink-0 border-t border-border">'),de=h("<div>"),ge=h('<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><line x1=3 y1=12 x2=21 y2=12></line><line x1=3 y1=6 x2=21 y2=6></line><line x1=3 y1=18 x2=21 y2=18>'),ve=h('<svg width=16 height=16 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><line x1=12 y1=5 x2=12 y2=19></line><line x1=5 y1=12 x2=19 y2=12>'),fe=h('<div class="flex items-center justify-between p-3 pb-2"><div class="flex items-center gap-2"><span class="text-sm font-semibold text-foreground">Chats'),me=h('<div class="flex flex-1 flex-col items-center justify-center gap-1 p-6 text-center text-sm text-muted-foreground">No conversations yet'),he=h('<svg width=10 height=10 viewBox="0 0 24 24"fill=none stroke=currentColor stroke-width=2><polyline points="6 9 12 15 18 9">'),pe=h("<span>"),xe=h('<div class="pl-2 mt-0.5 space-y-0.5">');function we(s){return i(M,{variant:"ghost",size:"icon-sm","aria-label":"Open sidebar",get class(){return w("rounded-full bg-card/80 shadow-sm backdrop-blur",s.class)},get onClick(){return s.onExpand},get children(){return i(W,{class:"size-4"})}})}function A(s){const e=s.conversationId;return typeof e=="string"&&e?e:s.getAttribute("conversation-id")??s.id}function ye(s){var e;return((e=s.parentElement)==null?void 0:e.localName)!=="kai-conversations"}function be(s){const e=a=>{const n=s.getItems();return a.composedPath().find(f=>n.includes(f))},g=a=>{var n;return((n=a.shadowRoot)==null?void 0:n.querySelector("[data-kai-item-body]"))??a},l=a=>a.composedPath().some(n=>n instanceof Element&&(n.hasAttribute("data-kai-item-menu")||n.getAttribute("slot")==="menu")),o=(a,n,f)=>{a.getAttribute(n)!==f&&a.setAttribute(n,f)},v=a=>{const n=new Map;for(const f of a){const m=g(f);m===f&&f.localName.includes("-")||n.set(f,m)}return n},t=(a,n)=>{for(const[f,m]of v(a))o(m,"tabindex",f===n?"0":"-1")};return{sync:()=>{const a=s.getItems(),n=s.getActiveId(),f=v(a);let m;for(const[c,r]of f){const d=n!==void 0&&A(c)===n;r.hasAttribute("role")||r.setAttribute("role","button"),o(r,"aria-current",d?"true":"false");const x=c;x.active!==d&&(x.active=d),d&&(m=c)}t(a,m??f.keys().next().value)},handleClick(a){const n=e(a);!n||l(a)||s.onSelect(A(n))},handleKeyDown(a){const n=s.getItems();if(n.length===0)return;const f=e(a);if(a.key==="Enter"||a.key===" "){if(!f||l(a))return;a.preventDefault(),s.onSelect(A(f));return}let m;const c=f?n.indexOf(f):n.findIndex(r=>g(r).getAttribute("tabindex")==="0");a.key==="ArrowDown"?m=n[Math.min(c+1,n.length-1)]:a.key==="ArrowUp"?m=n[Math.max(c-1,0)]:a.key==="Home"?m=n[0]:a.key==="End"&&(m=n[n.length-1]),m&&(a.preventDefault(),t(n,m),g(m).focus())}}}function ke(s){const[e]=I(s,["groups","conversations","activeId","onSelect","onNewChat","onToggleSidebar","header","footer","empty","compact","onSearchChange","controllerRef","items","itemsKeyDown","itemsClick","class"]),[g,l]=B(""),o=C(()=>e.items!=null),v=C(()=>e.conversations.length===0);let t;const a=c=>{var r;l(c),(r=e.onSearchChange)==null||r.call(e,c)};L(()=>{var c;(c=e.controllerRef)==null||c.call(e,{focus:r=>t?.focus(r),clearSearch:()=>a("")})});const n=C(()=>{const c=g().toLowerCase();return c?e.conversations.filter(r=>r.title.toLowerCase().includes(c)):e.conversations}),f=C(()=>{const c=new Map;for(const r of n()){const d=r.groupId;c.has(d)||c.set(d,[]),c.get(d).push(r)}return c}),m=C(()=>{const c=new Set((e.groups??[]).map(r=>r.id));return n().filter(r=>r.groupId==null||!c.has(r.groupId))});return(()=>{var c=de();return u(c,i(p,{get when(){return e.header},get fallback(){return(()=>{var r=fe(),d=r.firstChild,x=d.firstChild;return u(d,i(M,{variant:"ghost",size:"icon-sm","aria-label":"Toggle sidebar",get onClick(){return e.onToggleSidebar},get children(){return ge()}}),x),u(r,i(M,{variant:"ghost",size:"icon-sm","aria-label":"New chat",get onClick(){return e.onNewChat},get children(){return ve()}}),null),r})()},get children(){return e.header}}),null),u(c,i(p,{get when(){return o()||!v()},get children(){var r=ie(),d=r.firstChild,x=d.firstChild,S=x.nextSibling;S.$$input=q=>a(q.currentTarget.value);var N=t;return typeof N=="function"?P(N,S):t=S,y(()=>S.value=g()),r}}),null),u(c,i(p,{get when(){return o()},get children(){return i(E,{class:"flex-1 px-2",get children(){var r=se();return r.$$click=d=>{var x;return(x=e.itemsClick)==null?void 0:x.call(e,d)},r.$$keydown=d=>{var x;return(x=e.itemsKeyDown)==null?void 0:x.call(e,d)},u(r,()=>e.items),r}})}}),null),u(c,i(p,{get when(){return R(()=>!o())()&&!v()},get fallback(){return i(p,{get when(){return!o()},get children(){return i(p,{get when(){return e.empty},get fallback(){return me()},get children(){return e.empty}})}})},get children(){return[i(p,{get when(){return n().length===0},get children(){return ce()}}),i(p,{get when(){return n().length>0},get children(){return i(E,{class:"flex-1 px-2",get children(){return[i($,{get each(){return e.groups},children:r=>{const d=C(()=>f().get(r.id)??[]);return i(p,{get when(){return d().length>0},get children(){return i(O,{get name(){return r.name},get count(){return d().length},get conversations(){return d()},get activeId(){return e.activeId},get onSelect(){return e.onSelect},get compact(){return e.compact}})}})}}),i(p,{get when(){return m().length>0},get children(){return i(p,{get when(){return e.compact},get fallback(){return i(O,{name:"Ungrouped",get count(){return m().length},get conversations(){return m()},get activeId(){return e.activeId},get onSelect(){return e.onSelect}})},get children(){var r=le();return u(r,i($,{get each(){return m()},children:d=>i(j,{conversation:d,get isActive(){return d.id===e.activeId},get onSelect(){return e.onSelect},compact:!0})})),r}})}})]}})}})]}}),null),u(c,i(p,{get when(){return e.footer},get children(){var r=ue();return u(r,()=>e.footer),r}}),null),y(()=>k(c,w("flex flex-col h-full bg-sidebar",e.class))),c})()}function O(s){const[e,g]=B(!0);return i(F,{get open(){return e()},onOpenChange:g,get children(){return[i(T,{class:"flex items-center gap-1.5 w-full px-1.5 py-1 rounded-md text-compact text-muted-foreground font-medium hover:bg-muted/30 transition-colors cursor-pointer mt-1.5",get children(){return[(()=>{var l=he();return y(()=>b(l,"class",w("transition-transform",!e()&&"-rotate-90"))),l})(),(()=>{var l=pe();return u(l,()=>s.name),l})(),i(H,{variant:"count",class:"ml-auto text-caption",get children(){return s.count}})]}}),i(U,{get children(){var l=xe();return u(l,i($,{get each(){return s.conversations},children:o=>i(j,{conversation:o,get isActive(){return o.id===s.activeId},get onSelect(){return s.onSelect},get compact(){return s.compact}})})),l}})]}})}D(["input","keydown","click"]);export{ke as C,ae as S,we as a,be as c,ye as i,A as r};