@signalflare-ai/ui 1.0.0 → 1.2.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 (300) hide show
  1. package/CHANGELOG.md +37 -4
  2. package/README.md +1 -1
  3. package/ai/component-registry.json +1047 -183
  4. package/ai/component-registry.md +4241 -50
  5. package/ai/schemas.ts +99 -502
  6. package/dist/.build-complete +1 -1
  7. package/dist/ai/schemas.d.ts +76 -58
  8. package/dist/ai/schemas.d.ts.map +1 -1
  9. package/dist/{ai-actions-DSVeQn4e.js → ai-actions-BdUZI3Gk.js} +3 -3
  10. package/dist/{ai-actions-DSVeQn4e.js.map → ai-actions-BdUZI3Gk.js.map} +1 -1
  11. package/dist/{ai-agent-card-BXHwhWAU.js → ai-agent-card-BR2NIYhi.js} +1 -1
  12. package/dist/{ai-agent-card-BXHwhWAU.js.map → ai-agent-card-BR2NIYhi.js.map} +1 -1
  13. package/dist/{ai-approval-aa0qvjFN.js → ai-approval-Ba7mrKba.js} +2 -2
  14. package/dist/{ai-approval-aa0qvjFN.js.map → ai-approval-Ba7mrKba.js.map} +1 -1
  15. package/dist/{ai-code-block-BgtIxtZZ.js → ai-code-block-CZtoL73R.js} +3 -3
  16. package/dist/{ai-code-block-BgtIxtZZ.js.map → ai-code-block-CZtoL73R.js.map} +1 -1
  17. package/dist/ai-conversation-Cc7WlaBg.js +242 -0
  18. package/dist/ai-conversation-Cc7WlaBg.js.map +1 -0
  19. package/dist/{ai-info-banner-uFxHHwBA.js → ai-info-banner-C7EWPBj7.js} +7 -3
  20. package/dist/ai-info-banner-C7EWPBj7.js.map +1 -0
  21. package/dist/{ai-message-BjnFznXy.js → ai-message-Bp7L68U_.js} +27 -8
  22. package/dist/ai-message-Bp7L68U_.js.map +1 -0
  23. package/dist/{ai-mission-header-08__gULL.js → ai-mission-header-TiCJfTNt.js} +1 -1
  24. package/dist/{ai-mission-header-08__gULL.js.map → ai-mission-header-TiCJfTNt.js.map} +1 -1
  25. package/dist/{ai-part-group-DBtgTgAn.js → ai-part-group-DNb9I446.js} +3 -3
  26. package/dist/{ai-part-group-DBtgTgAn.js.map → ai-part-group-DNb9I446.js.map} +1 -1
  27. package/dist/{ai-prompt-input-Dy1LfxPk.js → ai-prompt-input-BVvov_KF.js} +467 -25
  28. package/dist/ai-prompt-input-BVvov_KF.js.map +1 -0
  29. package/dist/{ai-question-CHHoDJMg.js → ai-question-GPPMk7YM.js} +2 -2
  30. package/dist/{ai-question-CHHoDJMg.js.map → ai-question-GPPMk7YM.js.map} +1 -1
  31. package/dist/{ai-reasoning-CnL6ZSr5.js → ai-reasoning-_feFjk56.js} +2 -2
  32. package/dist/{ai-reasoning-CnL6ZSr5.js.map → ai-reasoning-_feFjk56.js.map} +1 -1
  33. package/dist/{ai-response-BEUg3xvd.js → ai-response-CvjV3WhV.js} +8 -3
  34. package/dist/ai-response-CvjV3WhV.js.map +1 -0
  35. package/dist/{ai-shimmer-By5_L05p.js → ai-shimmer-j6lKIrjj.js} +1 -1
  36. package/dist/{ai-shimmer-By5_L05p.js.map → ai-shimmer-j6lKIrjj.js.map} +1 -1
  37. package/dist/{ai-status-badge-BGYGWYF6.js → ai-status-badge-CSU_QOdz.js} +1 -1
  38. package/dist/{ai-status-badge-BGYGWYF6.js.map → ai-status-badge-CSU_QOdz.js.map} +1 -1
  39. package/dist/{ai-streaming-text-CMfoThV0.js → ai-streaming-text-IWW1BhvZ.js} +44 -16
  40. package/dist/ai-streaming-text-IWW1BhvZ.js.map +1 -0
  41. package/dist/{ai-subagent-DcPRqkAA.js → ai-subagent-JA4iIMW3.js} +13 -5
  42. package/dist/ai-subagent-JA4iIMW3.js.map +1 -0
  43. package/dist/{ai-suggestion-MgeCg5Ar.js → ai-suggestion-BdO6MBuH.js} +2 -2
  44. package/dist/{ai-suggestion-MgeCg5Ar.js.map → ai-suggestion-BdO6MBuH.js.map} +1 -1
  45. package/dist/{ai-task-list-Da9zIm00.js → ai-task-list-DYw4R1FA.js} +12 -5
  46. package/dist/ai-task-list-DYw4R1FA.js.map +1 -0
  47. package/dist/{ai-timeline-Cwu045IR.js → ai-timeline-C42tOUT8.js} +1 -1
  48. package/dist/{ai-timeline-Cwu045IR.js.map → ai-timeline-C42tOUT8.js.map} +1 -1
  49. package/dist/{ai-tool-Cn1O4xjP.js → ai-tool-03jOTwUI.js} +23 -10
  50. package/dist/ai-tool-03jOTwUI.js.map +1 -0
  51. package/dist/{ai-usage-bar-DjS12DMp.js → ai-usage-bar-BRf5LC_b.js} +1 -1
  52. package/dist/{ai-usage-bar-DjS12DMp.js.map → ai-usage-bar-BRf5LC_b.js.map} +1 -1
  53. package/dist/{badge-D_eaA6wv.js → badge-BheXjMc8.js} +2 -2
  54. package/dist/{badge-D_eaA6wv.js.map → badge-BheXjMc8.js.map} +1 -1
  55. package/dist/{banner-B_6oBrsu.js → banner-CcsjunJg.js} +7 -2
  56. package/dist/banner-CcsjunJg.js.map +1 -0
  57. package/dist/{breadcrumbs-BlmeYfgq.js → breadcrumbs-CouSyy3H.js} +3 -3
  58. package/dist/{breadcrumbs-BlmeYfgq.js.map → breadcrumbs-CouSyy3H.js.map} +1 -1
  59. package/dist/{button-De0267YU.js → button-CO6-qPax.js} +1 -1
  60. package/dist/{button-De0267YU.js.map → button-CO6-qPax.js.map} +1 -1
  61. package/dist/catalog.js +1 -1
  62. package/dist/{chart-BK3sVPnD.js → chart-Dg0qUeSc.js} +2 -2
  63. package/dist/{chart-BK3sVPnD.js.map → chart-Dg0qUeSc.js.map} +1 -1
  64. package/dist/{checkbox-DYhUmZNw.js → checkbox-D7p4QKsC.js} +2 -2
  65. package/dist/{checkbox-DYhUmZNw.js.map → checkbox-D7p4QKsC.js.map} +1 -1
  66. package/dist/{clipboard-text-ssybngLw.js → clipboard-text-kLaMogs3.js} +3 -3
  67. package/dist/{clipboard-text-ssybngLw.js.map → clipboard-text-kLaMogs3.js.map} +1 -1
  68. package/dist/{code-Cx-QSoOT.js → code-BN8InC0G.js} +2 -2
  69. package/dist/{code-Cx-QSoOT.js.map → code-BN8InC0G.js.map} +1 -1
  70. package/dist/{collapsible-DWsXeXmS.js → collapsible-D_ueZ0jz.js} +1 -1
  71. package/dist/{collapsible-DWsXeXmS.js.map → collapsible-D_ueZ0jz.js.map} +1 -1
  72. package/dist/{combobox-C0iW6a0r.js → combobox-B7TOK0U2.js} +3 -3
  73. package/dist/{combobox-C0iW6a0r.js.map → combobox-B7TOK0U2.js.map} +1 -1
  74. package/dist/{command-palette-DGzioeki.js → command-palette-CuNUyJca.js} +2 -2
  75. package/dist/{command-palette-DGzioeki.js.map → command-palette-CuNUyJca.js.map} +1 -1
  76. package/dist/components/ai-actions.js +1 -1
  77. package/dist/components/ai-agent-card.js +1 -1
  78. package/dist/components/ai-approval.js +1 -1
  79. package/dist/components/ai-code-block.js +1 -1
  80. package/dist/components/ai-conversation.js +2 -2
  81. package/dist/components/ai-info-banner.js +1 -1
  82. package/dist/components/ai-message.js +1 -1
  83. package/dist/components/ai-mission-header.js +1 -1
  84. package/dist/components/ai-part-group.js +1 -1
  85. package/dist/components/ai-prompt-input.js +2 -2
  86. package/dist/components/ai-question.js +1 -1
  87. package/dist/components/ai-reasoning.js +1 -1
  88. package/dist/components/ai-response.js +1 -1
  89. package/dist/components/ai-shimmer.js +1 -1
  90. package/dist/components/ai-status-badge.js +1 -1
  91. package/dist/components/ai-streaming-text.js +2 -2
  92. package/dist/components/ai-subagent.js +1 -1
  93. package/dist/components/ai-suggestion.js +1 -1
  94. package/dist/components/ai-task-list.js +1 -1
  95. package/dist/components/ai-timeline.js +1 -1
  96. package/dist/components/ai-tool.js +1 -1
  97. package/dist/components/ai-usage-bar.js +1 -1
  98. package/dist/components/badge.js +1 -1
  99. package/dist/components/banner.js +1 -1
  100. package/dist/components/breadcrumbs.js +1 -1
  101. package/dist/components/button.js +1 -1
  102. package/dist/components/chart.js +2 -2
  103. package/dist/components/checkbox.js +1 -1
  104. package/dist/components/clipboard-text.js +1 -1
  105. package/dist/components/code.js +1 -1
  106. package/dist/components/collapsible.js +1 -1
  107. package/dist/components/combobox.js +1 -1
  108. package/dist/components/command-palette.js +1 -1
  109. package/dist/components/data-grid.js +1 -1
  110. package/dist/components/date-picker.js +1 -1
  111. package/dist/components/date-range-picker.js +1 -1
  112. package/dist/components/dialog.js +1 -1
  113. package/dist/components/dropdown.js +1 -1
  114. package/dist/components/empty.js +1 -1
  115. package/dist/components/field.js +1 -1
  116. package/dist/components/filters.js +1 -1
  117. package/dist/components/flow.js +1 -1
  118. package/dist/components/grid.js +1 -1
  119. package/dist/components/input.js +2 -2
  120. package/dist/components/label.js +1 -1
  121. package/dist/components/layer-card.js +1 -1
  122. package/dist/components/loader.js +1 -1
  123. package/dist/components/menubar.js +1 -1
  124. package/dist/components/meter.js +1 -1
  125. package/dist/components/pagination.js +1 -1
  126. package/dist/components/popover.js +1 -1
  127. package/dist/components/radio.js +1 -1
  128. package/dist/components/select.js +1 -1
  129. package/dist/components/sensitive-input.js +1 -1
  130. package/dist/components/sidebar.js +1 -1
  131. package/dist/components/signalflare-ai-logo.js +1 -1
  132. package/dist/components/sparkline.js +1 -1
  133. package/dist/components/stat-card.js +1 -1
  134. package/dist/components/surface.js +1 -1
  135. package/dist/components/switch.js +1 -1
  136. package/dist/components/table.js +1 -1
  137. package/dist/components/tabs.js +1 -1
  138. package/dist/components/text-roll.js +1 -1
  139. package/dist/components/text.js +1 -1
  140. package/dist/components/theme-toggle.js +1 -1
  141. package/dist/components/toast.js +1 -1
  142. package/dist/components/tooltip.js +1 -1
  143. package/dist/components/use-agent-harness.js +1 -1
  144. package/dist/{data-grid-CG76N_hK.js → data-grid-DGHmU0w3.js} +8 -8
  145. package/dist/{data-grid-CG76N_hK.js.map → data-grid-DGHmU0w3.js.map} +1 -1
  146. package/dist/{date-picker-Dqg9L4xu.js → date-picker--ox89RBy.js} +1 -1
  147. package/dist/{date-picker-Dqg9L4xu.js.map → date-picker--ox89RBy.js.map} +1 -1
  148. package/dist/{date-range-picker-D75LLINc.js → date-range-picker-DVa7QBqE.js} +1 -1
  149. package/dist/{date-range-picker-D75LLINc.js.map → date-range-picker-DVa7QBqE.js.map} +1 -1
  150. package/dist/{dialog-CyHEQXEY.js → dialog-Bv1oSFOd.js} +2 -2
  151. package/dist/{dialog-CyHEQXEY.js.map → dialog-Bv1oSFOd.js.map} +1 -1
  152. package/dist/{dist-1-gcEL2L.js → dist-B6iWiWwp.js} +25 -25
  153. package/dist/{dist-1-gcEL2L.js.map → dist-B6iWiWwp.js.map} +1 -1
  154. package/dist/{dropdown-qnEYRFXZ.js → dropdown-B_nrGXjV.js} +2 -2
  155. package/dist/{dropdown-qnEYRFXZ.js.map → dropdown-B_nrGXjV.js.map} +1 -1
  156. package/dist/{echart-DURZEyai.js → echart-CdOUaT-r.js} +1 -1
  157. package/dist/{echart-DURZEyai.js.map → echart-CdOUaT-r.js.map} +1 -1
  158. package/dist/{empty-D2TypIId.js → empty-DZnN0zKX.js} +11 -6
  159. package/dist/empty-DZnN0zKX.js.map +1 -0
  160. package/dist/{field-Y_UK1_Cg.js → field-B_yVof52.js} +2 -2
  161. package/dist/{field-Y_UK1_Cg.js.map → field-B_yVof52.js.map} +1 -1
  162. package/dist/{filters-Bw_U6ZTx.js → filters-cpJCY21R.js} +7 -7
  163. package/dist/{filters-Bw_U6ZTx.js.map → filters-cpJCY21R.js.map} +1 -1
  164. package/dist/{flow-BRsYUCJa.js → flow-B4v198ot.js} +1 -1
  165. package/dist/{flow-BRsYUCJa.js.map → flow-B4v198ot.js.map} +1 -1
  166. package/dist/genui.js +1 -1
  167. package/dist/{grid-qUAN9hFx.js → grid-CEd64Lnh.js} +1 -1
  168. package/dist/{grid-qUAN9hFx.js.map → grid-CEd64Lnh.js.map} +1 -1
  169. package/dist/{highlight-to-react-ClEfL81q.js → highlight-to-react-D0Yav4jk.js} +1 -1
  170. package/dist/{highlight-to-react-ClEfL81q.js.map → highlight-to-react-D0Yav4jk.js.map} +1 -1
  171. package/dist/index.js +69 -69
  172. package/dist/{input-DXYUjGgD.js → input-B2bbijRh.js} +2 -2
  173. package/dist/{input-DXYUjGgD.js.map → input-B2bbijRh.js.map} +1 -1
  174. package/dist/{input-DddtBN-g.js → input-ClB_E4Lb.js} +4 -4
  175. package/dist/{input-DddtBN-g.js.map → input-ClB_E4Lb.js.map} +1 -1
  176. package/dist/{label-QtJxtJ4u.js → label-DUv_urO1.js} +2 -2
  177. package/dist/{label-QtJxtJ4u.js.map → label-DUv_urO1.js.map} +1 -1
  178. package/dist/{layer-card-BME0eljh.js → layer-card-BK7eYfwn.js} +1 -1
  179. package/dist/{layer-card-BME0eljh.js.map → layer-card-BK7eYfwn.js.map} +1 -1
  180. package/dist/layout-DJHMMap2.js +6103 -0
  181. package/dist/layout-DJHMMap2.js.map +1 -0
  182. package/dist/measured-text-BI3dTJmH.js +290 -0
  183. package/dist/measured-text-BI3dTJmH.js.map +1 -0
  184. package/dist/{menubar-C8NzAjfd.js → menubar-Cxf3xeAt.js} +2 -2
  185. package/dist/{menubar-C8NzAjfd.js.map → menubar-Cxf3xeAt.js.map} +1 -1
  186. package/dist/{meter-CpmTenEr.js → meter-BFFe9l5b.js} +1 -1
  187. package/dist/{meter-CpmTenEr.js.map → meter-BFFe9l5b.js.map} +1 -1
  188. package/dist/{pagination-BVqdlONY.js → pagination-yS372Tr4.js} +2 -2
  189. package/dist/{pagination-BVqdlONY.js.map → pagination-yS372Tr4.js.map} +1 -1
  190. package/dist/{popover-BRQZ2b6z.js → popover-SRoJaCZr.js} +1 -1
  191. package/dist/{popover-BRQZ2b6z.js.map → popover-SRoJaCZr.js.map} +1 -1
  192. package/dist/{radio-BNSwOt3B.js → radio-BcwhwYNB.js} +1 -1
  193. package/dist/{radio-BNSwOt3B.js.map → radio-BcwhwYNB.js.map} +1 -1
  194. package/dist/{select-1w2aebGQ.js → select-DMhdoHMa.js} +4 -4
  195. package/dist/{select-1w2aebGQ.js.map → select-DMhdoHMa.js.map} +1 -1
  196. package/dist/{sensitive-input-82Cez3vj.js → sensitive-input-CJUpIRal.js} +3 -3
  197. package/dist/{sensitive-input-82Cez3vj.js.map → sensitive-input-CJUpIRal.js.map} +1 -1
  198. package/dist/{sidebar-CAsCmSpM.js → sidebar-D4zrlYpn.js} +2 -2
  199. package/dist/{sidebar-CAsCmSpM.js.map → sidebar-D4zrlYpn.js.map} +1 -1
  200. package/dist/{signalflare-ai-logo-DDhxMJD6.js → signalflare-ai-logo-Bipogceq.js} +1 -1
  201. package/dist/{signalflare-ai-logo-DDhxMJD6.js.map → signalflare-ai-logo-Bipogceq.js.map} +1 -1
  202. package/dist/{skeleton-line-Do3UmGk9.js → skeleton-line-CH1-h6e2.js} +1 -1
  203. package/dist/{skeleton-line-Do3UmGk9.js.map → skeleton-line-CH1-h6e2.js.map} +1 -1
  204. package/dist/{sparkline-DdbeM4Ai.js → sparkline-DHmgj1d0.js} +2 -2
  205. package/dist/{sparkline-DdbeM4Ai.js.map → sparkline-DHmgj1d0.js.map} +1 -1
  206. package/dist/src/blocks/agent-harness/agent-harness.d.ts.map +1 -1
  207. package/dist/src/blocks/agent-harness/agent-harness.tsx +29 -5
  208. package/dist/src/components/ai-conversation/ai-conversation.d.ts +69 -37
  209. package/dist/src/components/ai-conversation/ai-conversation.d.ts.map +1 -1
  210. package/dist/src/components/ai-conversation/index.d.ts +2 -1
  211. package/dist/src/components/ai-conversation/index.d.ts.map +1 -1
  212. package/dist/src/components/ai-conversation/measurement-constants.d.ts +30 -0
  213. package/dist/src/components/ai-conversation/measurement-constants.d.ts.map +1 -0
  214. package/dist/src/components/ai-info-banner/ai-info-banner.d.ts.map +1 -1
  215. package/dist/src/components/ai-message/ai-message.d.ts +3 -0
  216. package/dist/src/components/ai-message/ai-message.d.ts.map +1 -1
  217. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts +58 -4
  218. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
  219. package/dist/src/components/ai-prompt-input/controller.d.ts +10 -2
  220. package/dist/src/components/ai-prompt-input/controller.d.ts.map +1 -1
  221. package/dist/src/components/ai-prompt-input/index.d.ts +2 -2
  222. package/dist/src/components/ai-prompt-input/index.d.ts.map +1 -1
  223. package/dist/src/components/ai-prompt-input/types.d.ts +16 -0
  224. package/dist/src/components/ai-prompt-input/types.d.ts.map +1 -1
  225. package/dist/src/components/ai-response/ai-response.d.ts +12 -1
  226. package/dist/src/components/ai-response/ai-response.d.ts.map +1 -1
  227. package/dist/src/components/ai-streaming-text/ai-streaming-text.d.ts +27 -0
  228. package/dist/src/components/ai-streaming-text/ai-streaming-text.d.ts.map +1 -1
  229. package/dist/src/components/ai-streaming-text/index.d.ts +1 -1
  230. package/dist/src/components/ai-streaming-text/index.d.ts.map +1 -1
  231. package/dist/src/components/ai-subagent/ai-subagent.d.ts.map +1 -1
  232. package/dist/src/components/ai-task-list/ai-task-list.d.ts.map +1 -1
  233. package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -1
  234. package/dist/src/components/banner/banner.d.ts.map +1 -1
  235. package/dist/src/components/empty/empty.d.ts.map +1 -1
  236. package/dist/src/components/stat-card/stat-card.d.ts +5 -0
  237. package/dist/src/components/stat-card/stat-card.d.ts.map +1 -1
  238. package/dist/src/components/text/text.d.ts +35 -1
  239. package/dist/src/components/text/text.d.ts.map +1 -1
  240. package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
  241. package/dist/src/index.d.ts +3 -3
  242. package/dist/src/index.d.ts.map +1 -1
  243. package/dist/src/utils/index.d.ts +2 -0
  244. package/dist/src/utils/index.d.ts.map +1 -1
  245. package/dist/src/utils/measured-text.d.ts +40 -0
  246. package/dist/src/utils/measured-text.d.ts.map +1 -0
  247. package/dist/src/utils/use-measured-text.d.ts +59 -0
  248. package/dist/src/utils/use-measured-text.d.ts.map +1 -0
  249. package/dist/{stat-card-CEZscNh8.js → stat-card-Ew-ofzEm.js} +28 -10
  250. package/dist/stat-card-Ew-ofzEm.js.map +1 -0
  251. package/dist/styles/sf-binding.css +9 -1
  252. package/dist/styles/sf-standalone.css +2 -2
  253. package/dist/styles/shadcn.css +1 -1
  254. package/dist/styles/theme-fedramp.css +12 -3
  255. package/dist/styles/theme-minimal.css +104 -26
  256. package/dist/styles/theme-sf.css +138 -39
  257. package/dist/styles/theme-vesper.css +91 -0
  258. package/dist/{surface-BduI7Ehl.js → surface-DGwRlC0o.js} +1 -1
  259. package/dist/{surface-BduI7Ehl.js.map → surface-DGwRlC0o.js.map} +1 -1
  260. package/dist/{switch-CzZBRBL7.js → switch-BxAMfHdt.js} +2 -2
  261. package/dist/{switch-CzZBRBL7.js.map → switch-BxAMfHdt.js.map} +1 -1
  262. package/dist/{table-Rv4JMy0B.js → table-BBeAtYVZ.js} +2 -2
  263. package/dist/{table-Rv4JMy0B.js.map → table-BBeAtYVZ.js.map} +1 -1
  264. package/dist/{tabs-1cHrYoel.js → tabs-CeHu7Scn.js} +1 -1
  265. package/dist/{tabs-1cHrYoel.js.map → tabs-CeHu7Scn.js.map} +1 -1
  266. package/dist/{text-KJmGkwnf.js → text-Cqryz7rk.js} +27 -5
  267. package/dist/text-Cqryz7rk.js.map +1 -0
  268. package/dist/{text-roll-BZ3I1umc.js → text-roll-Ch52hcQj.js} +1 -1
  269. package/dist/{text-roll-BZ3I1umc.js.map → text-roll-Ch52hcQj.js.map} +1 -1
  270. package/dist/{theme-toggle-Bhu681D7.js → theme-toggle-LDfIKEqx.js} +3 -3
  271. package/dist/{theme-toggle-Bhu681D7.js.map → theme-toggle-LDfIKEqx.js.map} +1 -1
  272. package/dist/{toast-Nw28a5Cx.js → toast-CaFQNYng.js} +2 -2
  273. package/dist/{toast-Nw28a5Cx.js.map → toast-CaFQNYng.js.map} +1 -1
  274. package/dist/{tooltip-Cb7QW-7H.js → tooltip-g9lFsvcT.js} +8 -2
  275. package/dist/tooltip-g9lFsvcT.js.map +1 -0
  276. package/dist/{use-agent-harness-BMyF8pTq.js → use-agent-harness-BTcNJdw4.js} +1 -1
  277. package/dist/{use-agent-harness-BMyF8pTq.js.map → use-agent-harness-BTcNJdw4.js.map} +1 -1
  278. package/dist/utils.js +2 -1
  279. package/package.json +2 -1
  280. package/scripts/component-registry/index.ts +2 -2
  281. package/scripts/css-build.ts +1 -1
  282. package/scripts/theme-generator/config.ts +27 -141
  283. package/scripts/theme-generator/generate-css.ts +0 -1
  284. package/scripts/theme-generator/index.ts +0 -1
  285. package/dist/ai-conversation-CArP7C8K.js +0 -184
  286. package/dist/ai-conversation-CArP7C8K.js.map +0 -1
  287. package/dist/ai-info-banner-uFxHHwBA.js.map +0 -1
  288. package/dist/ai-message-BjnFznXy.js.map +0 -1
  289. package/dist/ai-prompt-input-Dy1LfxPk.js.map +0 -1
  290. package/dist/ai-response-BEUg3xvd.js.map +0 -1
  291. package/dist/ai-streaming-text-CMfoThV0.js.map +0 -1
  292. package/dist/ai-subagent-DcPRqkAA.js.map +0 -1
  293. package/dist/ai-task-list-Da9zIm00.js.map +0 -1
  294. package/dist/ai-tool-Cn1O4xjP.js.map +0 -1
  295. package/dist/banner-B_6oBrsu.js.map +0 -1
  296. package/dist/empty-D2TypIId.js.map +0 -1
  297. package/dist/stat-card-CEZscNh8.js.map +0 -1
  298. package/dist/styles/theme-blue-tint.css +0 -98
  299. package/dist/text-KJmGkwnf.js.map +0 -1
  300. package/dist/tooltip-Cb7QW-7H.js.map +0 -1
@@ -6,7 +6,6 @@
6
6
  * - theme-sf.css (base theme — neutral, WCAG-tuned)
7
7
  * - theme-fedramp.css (fedramp overrides)
8
8
  * - theme-minimal.css (minimal overrides)
9
- * - theme-blue-tint.css (prior sf look — blue-tinted dark surfaces)
10
9
  *
11
10
  * Token naming:
12
11
  * - Key = current token name used in codebase
@@ -32,10 +31,6 @@ export const THEME_CONFIG: ThemeConfig = {
32
31
  light: "oklch(0.145 0 0)",
33
32
  dark: "oklch(0.985 0 0)",
34
33
  },
35
- blueTint: {
36
- light: "oklch(0.145 0 0)",
37
- dark: "oklch(0.985 0 0)",
38
- },
39
34
  },
40
35
  },
41
36
  "sf-inverse": {
@@ -58,10 +53,6 @@ export const THEME_CONFIG: ThemeConfig = {
58
53
  light: "oklch(0.50 0 0)",
59
54
  dark: "oklch(0.55 0 0)",
60
55
  },
61
- blueTint: {
62
- light: "oklch(0.556 0 0)",
63
- dark: "oklch(0.65 0 0)",
64
- },
65
56
  },
66
57
  },
67
58
  "sf-subtle": {
@@ -75,10 +66,6 @@ export const THEME_CONFIG: ThemeConfig = {
75
66
  light: "oklch(0.55 0 0)",
76
67
  dark: "oklch(0.45 0 0)",
77
68
  },
78
- blueTint: {
79
- light: "var(--color-neutral-500, oklch(55.6% 0 0))",
80
- dark: "var(--color-neutral-50, oklch(98.5% 0 0))",
81
- },
82
69
  },
83
70
  },
84
71
  "sf-inactive": {
@@ -92,10 +79,6 @@ export const THEME_CONFIG: ThemeConfig = {
92
79
  light: "oklch(0.65 0 0)",
93
80
  dark: "oklch(0.35 0 0)",
94
81
  },
95
- blueTint: {
96
- light: "var(--color-neutral-400, oklch(70.8% 0 0))",
97
- dark: "var(--color-neutral-600, oklch(70.8% 0 0))",
98
- },
99
82
  },
100
83
  },
101
84
  "sf-brand": {
@@ -120,8 +103,8 @@ export const THEME_CONFIG: ThemeConfig = {
120
103
  newName: "",
121
104
  theme: {
122
105
  sf: {
123
- light: "var(--color-green-500, oklch(72.3% 0.219 149.579))",
124
- dark: "var(--color-green-500, oklch(72.3% 0.219 149.579))",
106
+ light: "#99ffe4",
107
+ dark: "#99ffe4",
125
108
  },
126
109
  },
127
110
  },
@@ -136,10 +119,6 @@ export const THEME_CONFIG: ThemeConfig = {
136
119
  light: "oklch(0.55 0.12 25)",
137
120
  dark: "oklch(0.55 0.10 25)",
138
121
  },
139
- blueTint: {
140
- light: "oklch(0.577 0.245 27.325)",
141
- dark: "oklch(0.55 0.18 25)",
142
- },
143
122
  },
144
123
  },
145
124
  "sf-warning": {
@@ -153,10 +132,6 @@ export const THEME_CONFIG: ThemeConfig = {
153
132
  light: "oklch(0.55 0.08 66)",
154
133
  dark: "oklch(0.65 0.08 66)",
155
134
  },
156
- blueTint: {
157
- light: "var(--color-yellow-800, oklch(47.6% 0.114 61.907))",
158
- dark: "var(--color-yellow-400, oklch(85.2% 0.199 91.936))",
159
- },
160
135
  },
161
136
  },
162
137
  },
@@ -172,7 +147,7 @@ export const THEME_CONFIG: ThemeConfig = {
172
147
  theme: {
173
148
  sf: {
174
149
  light: "oklch(0.95 0 0)",
175
- dark: "oklch(0.10 0 0)",
150
+ dark: "oklch(0.173 0 0)",
176
151
  },
177
152
  fedramp: {
178
153
  light: "#5b697c",
@@ -180,11 +155,7 @@ export const THEME_CONFIG: ThemeConfig = {
180
155
  },
181
156
  minimal: {
182
157
  light: "oklch(0.95 0 0)",
183
- dark: "oklch(0.10 0 0)",
184
- },
185
- blueTint: {
186
- light: "var(--color-neutral-50, oklch(0.985 0 0))",
187
- dark: "var(--color-neutral-950, oklch(0.14 0 0))",
158
+ dark: "oklch(0.173 0 0)",
188
159
  },
189
160
  },
190
161
  },
@@ -193,7 +164,7 @@ export const THEME_CONFIG: ThemeConfig = {
193
164
  theme: {
194
165
  sf: {
195
166
  light: "oklch(0.97 0 0)",
196
- dark: "oklch(0.14 0 0)",
167
+ dark: "oklch(0.1913 0 0)",
197
168
  },
198
169
  fedramp: {
199
170
  light: "#5b697c",
@@ -201,11 +172,7 @@ export const THEME_CONFIG: ThemeConfig = {
201
172
  },
202
173
  minimal: {
203
174
  light: "oklch(0.97 0 0)",
204
- dark: "oklch(0.14 0 0)",
205
- },
206
- blueTint: {
207
- light: "oklch(1 0 0)",
208
- dark: "oklch(0.21 0.005 252)",
175
+ dark: "oklch(0.1913 0 0)",
209
176
  },
210
177
  },
211
178
  },
@@ -214,15 +181,11 @@ export const THEME_CONFIG: ThemeConfig = {
214
181
  theme: {
215
182
  sf: {
216
183
  light: "oklch(1 0 0)",
217
- dark: "oklch(0.22 0 0)",
184
+ dark: "oklch(0.2002 0 0)",
218
185
  },
219
186
  minimal: {
220
187
  light: "oklch(1 0 0)",
221
- dark: "oklch(0.22 0 0)",
222
- },
223
- blueTint: {
224
- light: "oklch(0.99 0 0)",
225
- dark: "oklch(0.24 0.005 252)",
188
+ dark: "oklch(0.2002 0 0)",
226
189
  },
227
190
  },
228
191
  },
@@ -231,15 +194,11 @@ export const THEME_CONFIG: ThemeConfig = {
231
194
  theme: {
232
195
  sf: {
233
196
  light: "oklch(0.92 0 0)",
234
- dark: "oklch(0.10 0 0)",
197
+ dark: "oklch(0.173 0 0)",
235
198
  },
236
199
  minimal: {
237
200
  light: "oklch(0.92 0 0)",
238
- dark: "oklch(0.10 0 0)",
239
- },
240
- blueTint: {
241
- light: "var(--color-neutral-250, oklch(0.9 0 0))",
242
- dark: "var(--color-neutral-750, oklch(0.31 0 0))",
201
+ dark: "oklch(0.173 0 0)",
243
202
  },
244
203
  },
245
204
  },
@@ -248,15 +207,11 @@ export const THEME_CONFIG: ThemeConfig = {
248
207
  theme: {
249
208
  sf: {
250
209
  light: "oklch(0.93 0 0)",
251
- dark: "oklch(0.10 0 0)",
210
+ dark: "oklch(0.173 0 0)",
252
211
  },
253
212
  minimal: {
254
213
  light: "oklch(0.93 0 0)",
255
- dark: "oklch(0.10 0 0)",
256
- },
257
- blueTint: {
258
- light: "var(--color-neutral-50, oklch(98.5% 0 0))",
259
- dark: "var(--color-neutral-950, oklch(0.10 0 0))",
214
+ dark: "oklch(0.173 0 0)",
260
215
  },
261
216
  },
262
217
  },
@@ -271,10 +226,6 @@ export const THEME_CONFIG: ThemeConfig = {
271
226
  light: "oklch(0.35 0 0)",
272
227
  dark: "oklch(0.75 0 0)",
273
228
  },
274
- blueTint: {
275
- light: "oklch(0.205 0 0)",
276
- dark: "oklch(0.55 0.01 40)",
277
- },
278
229
  },
279
230
  },
280
231
  "sf-control": {
@@ -282,15 +233,11 @@ export const THEME_CONFIG: ThemeConfig = {
282
233
  theme: {
283
234
  sf: {
284
235
  light: "oklch(0.95 0 0)",
285
- dark: "oklch(0.17 0 0)",
236
+ dark: "oklch(0.2264 0 0)",
286
237
  },
287
238
  minimal: {
288
239
  light: "oklch(0.95 0 0)",
289
- dark: "oklch(0.17 0 0)",
290
- },
291
- blueTint: {
292
- light: "var(--color-white, #fff)",
293
- dark: "var(--color-neutral-900, oklch(21% 0.006 285.885))",
240
+ dark: "oklch(0.2264 0 0)",
294
241
  },
295
242
  },
296
243
  },
@@ -299,15 +246,11 @@ export const THEME_CONFIG: ThemeConfig = {
299
246
  theme: {
300
247
  sf: {
301
248
  light: "oklch(0.94 0 0)",
302
- dark: "oklch(0.19 0 0)",
249
+ dark: "oklch(0.2562 0 0)",
303
250
  },
304
251
  minimal: {
305
252
  light: "oklch(0.94 0 0)",
306
- dark: "oklch(0.19 0 0)",
307
- },
308
- blueTint: {
309
- light: "var(--color-neutral-150, oklch(0.96 0 0))",
310
- dark: "var(--color-neutral-850, oklch(0.23 0 0))",
253
+ dark: "oklch(0.2562 0 0)",
311
254
  },
312
255
  },
313
256
  },
@@ -318,7 +261,7 @@ export const THEME_CONFIG: ThemeConfig = {
318
261
  /* Interactive boundary (form controls, checkbox/radio idle).
319
262
  More visible than sf-line so controls read as actionable. */
320
263
  light: "oklch(0.80 0 0)",
321
- dark: "oklch(0.38 0 0)",
264
+ dark: "oklch(0.2768 0 0)",
322
265
  },
323
266
  },
324
267
  },
@@ -327,15 +270,11 @@ export const THEME_CONFIG: ThemeConfig = {
327
270
  theme: {
328
271
  sf: {
329
272
  light: "oklch(0.91 0 0)",
330
- dark: "oklch(0.27 0 0)",
273
+ dark: "oklch(0.2562 0 0)",
331
274
  },
332
275
  minimal: {
333
276
  light: "oklch(0.91 0 0)",
334
- dark: "oklch(0.27 0 0)",
335
- },
336
- blueTint: {
337
- light: "var(--color-neutral-200, oklch(92.2% 0 0))",
338
- dark: "var(--color-neutral-800, oklch(26.9% 0 0))",
277
+ dark: "oklch(0.2562 0 0)",
339
278
  },
340
279
  },
341
280
  },
@@ -344,15 +283,11 @@ export const THEME_CONFIG: ThemeConfig = {
344
283
  theme: {
345
284
  sf: {
346
285
  light: "oklch(0.88 0 0)",
347
- dark: "oklch(0.31 0 0)",
286
+ dark: "oklch(0.2768 0 0)",
348
287
  },
349
288
  minimal: {
350
289
  light: "oklch(0.88 0 0)",
351
- dark: "oklch(0.31 0 0)",
352
- },
353
- blueTint: {
354
- light: "var(--color-neutral-200, oklch(92.2% 0 0))",
355
- dark: "var(--color-neutral-700, oklch(37.1% 0 0))",
290
+ dark: "oklch(0.2768 0 0)",
356
291
  },
357
292
  },
358
293
  },
@@ -367,10 +302,6 @@ export const THEME_CONFIG: ThemeConfig = {
367
302
  light: "oklch(0.55 0.06 260)",
368
303
  dark: "oklch(0.55 0.06 260)",
369
304
  },
370
- blueTint: {
371
- light: "oklch(0.5772 0.2324 260)",
372
- dark: "oklch(0.5772 0.2324 260)",
373
- },
374
305
  },
375
306
  },
376
307
  "sf-brand-hover": {
@@ -384,29 +315,21 @@ export const THEME_CONFIG: ThemeConfig = {
384
315
  light: "oklch(0.48 0.05 264)",
385
316
  dark: "oklch(0.48 0.05 264)",
386
317
  },
387
- blueTint: {
388
- light: "var(--color-blue-700, oklch(48.8% 0.243 264.376))",
389
- dark: "var(--color-blue-700, oklch(48.8% 0.243 264.376))",
390
- },
391
318
  },
392
319
  },
393
320
  "sf-line": {
394
321
  newName: "",
395
322
  theme: {
396
323
  sf: {
397
- /* Flat/minimal aesthetic: near-invisible by design. Decorative only
398
- contrast carried by text + sf-ring (focus) + surface elevation. */
324
+ /* Vesper-inspired dark boundary; subtle but visible against the default
325
+ dark surface ramp. */
399
326
  light: "oklch(0.85 0 0 / 0.5)",
400
- dark: "oklch(0.25 0 0 / 0.5)",
327
+ dark: "#282828",
401
328
  },
402
329
  minimal: {
403
330
  light: "oklch(0.85 0 0 / 0.5)",
404
331
  dark: "oklch(0.25 0 0 / 0.5)",
405
332
  },
406
- blueTint: {
407
- light: "oklch(0.922 0 0)",
408
- dark: "oklch(0.3 0.015 250)",
409
- },
410
333
  },
411
334
  },
412
335
  "sf-ring": {
@@ -424,10 +347,6 @@ export const THEME_CONFIG: ThemeConfig = {
424
347
  light: "oklch(0.65 0 0)",
425
348
  dark: "oklch(0.45 0 0)",
426
349
  },
427
- blueTint: {
428
- light: "oklch(0.708 0 0)",
429
- dark: "oklch(0.465 0.015 250)",
430
- },
431
350
  },
432
351
  },
433
352
  "sf-tip-shadow": {
@@ -441,10 +360,6 @@ export const THEME_CONFIG: ThemeConfig = {
441
360
  light: "transparent",
442
361
  dark: "transparent",
443
362
  },
444
- blueTint: {
445
- light: "var(--color-gray-200, oklch(92.8% 0.006 264.531))",
446
- dark: "transparent",
447
- },
448
363
  },
449
364
  },
450
365
  "sf-tip-stroke": {
@@ -452,16 +367,12 @@ export const THEME_CONFIG: ThemeConfig = {
452
367
  theme: {
453
368
  sf: {
454
369
  light: "transparent",
455
- dark: "transparent",
370
+ dark: "#282828",
456
371
  },
457
372
  minimal: {
458
373
  light: "transparent",
459
374
  dark: "transparent",
460
375
  },
461
- blueTint: {
462
- light: "transparent",
463
- dark: "var(--color-neutral-800, oklch(26.9% 0 0))",
464
- },
465
376
  },
466
377
  },
467
378
  "sf-info": {
@@ -475,10 +386,6 @@ export const THEME_CONFIG: ThemeConfig = {
475
386
  light: "oklch(0.55 0.06 260)",
476
387
  dark: "oklch(0.55 0.06 260)",
477
388
  },
478
- blueTint: {
479
- light: "var(--color-blue-500, oklch(62.3% 0.214 259.815))",
480
- dark: "var(--color-blue-700, oklch(48.8% 0.243 264.376))",
481
- },
482
389
  },
483
390
  },
484
391
  "sf-info-tint": {
@@ -492,10 +399,6 @@ export const THEME_CONFIG: ThemeConfig = {
492
399
  light: "oklch(0.94 0.01 260)",
493
400
  dark: "oklch(0.20 0.02 260)",
494
401
  },
495
- blueTint: {
496
- light: "var(--color-blue-300, oklch(80.9% 0.105 251.813))",
497
- dark: "var(--color-blue-900, oklch(37.9% 0.146 265.522))",
498
- },
499
402
  },
500
403
  },
501
404
  "sf-warning": {
@@ -509,10 +412,6 @@ export const THEME_CONFIG: ThemeConfig = {
509
412
  light: "oklch(0.55 0.08 66)",
510
413
  dark: "oklch(0.65 0.08 66)",
511
414
  },
512
- blueTint: {
513
- light: "var(--color-yellow-500, oklch(79.5% 0.184 86.047))",
514
- dark: "var(--color-yellow-700, oklch(55.4% 0.135 66.442))",
515
- },
516
415
  },
517
416
  },
518
417
  "sf-warning-tint": {
@@ -526,10 +425,6 @@ export const THEME_CONFIG: ThemeConfig = {
526
425
  light: "oklch(0.94 0.02 60)",
527
426
  dark: "oklch(0.22 0.03 60)",
528
427
  },
529
- blueTint: {
530
- light: "var(--color-yellow-300, oklch(90.5% 0.182 98.111))",
531
- dark: "var(--color-yellow-900, oklch(42.1% 0.095 57.708))",
532
- },
533
428
  },
534
429
  },
535
430
  "sf-danger": {
@@ -543,10 +438,6 @@ export const THEME_CONFIG: ThemeConfig = {
543
438
  light: "oklch(0.55 0.12 25)",
544
439
  dark: "oklch(0.55 0.10 25)",
545
440
  },
546
- blueTint: {
547
- light: "oklch(0.577 0.245 27.325)",
548
- dark: "oklch(0.55 0.18 25)",
549
- },
550
441
  },
551
442
  },
552
443
  "sf-danger-tint": {
@@ -560,10 +451,6 @@ export const THEME_CONFIG: ThemeConfig = {
560
451
  light: "oklch(0.94 0.02 25)",
561
452
  dark: "oklch(0.20 0.04 25)",
562
453
  },
563
- blueTint: {
564
- light: "var(--color-red-300, oklch(80.8% 0.114 19.571))",
565
- dark: "var(--color-red-900, oklch(39.6% 0.141 25.723))",
566
- },
567
454
  },
568
455
  },
569
456
  "sf-success": {
@@ -572,8 +459,8 @@ export const THEME_CONFIG: ThemeConfig = {
572
459
  "Success signal color (previously hardcoded in the shadcn bridge)",
573
460
  theme: {
574
461
  sf: {
575
- light: "oklch(0.723 0.219 149.579)",
576
- dark: "oklch(0.723 0.219 149.579)",
462
+ light: "#99ffe4",
463
+ dark: "#99ffe4",
577
464
  },
578
465
  },
579
466
  },
@@ -773,7 +660,6 @@ export const AVAILABLE_THEMES = [
773
660
  "sf",
774
661
  "fedramp",
775
662
  "minimal",
776
- "blueTint",
777
663
  ] as const;
778
664
  export type AvailableTheme = (typeof AVAILABLE_THEMES)[number];
779
665
 
@@ -5,7 +5,6 @@
5
5
  * Outputs:
6
6
  * - theme-sf.css: Base theme with all tokens
7
7
  * - theme-fedramp.css: Override layer for fedramp theme
8
- * - theme-blue-tint.css: Override layer for blue-tint theme
9
8
  * - (future themes as needed)
10
9
  */
11
10
 
@@ -52,7 +52,6 @@ Output:
52
52
  Generates theme CSS files in src/styles/:
53
53
  - theme-sf.css Base theme with all tokens
54
54
  - theme-fedramp.css FedRAMP theme overrides
55
- - theme-blue-tint.css Blue-tint theme overrides
56
55
  `);
57
56
  }
58
57
 
@@ -1,184 +0,0 @@
1
- "use client";
2
- import { t as cn } from "./cn-YROP2_ox.js";
3
- import { t as Button } from "./button-De0267YU.js";
4
- import { forwardRef, useCallback, useEffect, useRef, useState } from "react";
5
- import { jsx } from "react/jsx-runtime";
6
- import { ArrowDownIcon } from "@phosphor-icons/react";
7
- import { useVirtualizer } from "@tanstack/react-virtual";
8
- //#region src/components/ai-conversation/ai-conversation.tsx
9
- var SF_AI_CONVERSATION_VARIANTS = {};
10
- var SF_AI_CONVERSATION_DEFAULT_VARIANTS = {};
11
- /**
12
- * Outer scroll container for a conversation. Sticks to the bottom as new
13
- * messages are added. Pair with `AiConversationContent` and optionally
14
- * `AiConversationScrollButton`.
15
- *
16
- * @example
17
- * ```tsx
18
- * <AiConversation ref={scrollRef}>
19
- * <AiConversationContent>
20
- * {messages.map(m => <AiMessage key={m.id} from={m.role}>...</AiMessage>)}
21
- * </AiConversationContent>
22
- * <AiConversationScrollButton scrollRef={scrollRef} />
23
- * </AiConversation>
24
- * ```
25
- */
26
- var AiConversation = forwardRef(({ className, children, ...props }, ref) => {
27
- return /* @__PURE__ */ jsx("div", {
28
- ref,
29
- className: cn("relative flex-1 overflow-y-auto", className),
30
- role: "log",
31
- "aria-live": "polite",
32
- "aria-label": "Conversation",
33
- ...props,
34
- children
35
- });
36
- });
37
- AiConversation.displayName = "AiConversation";
38
- /**
39
- * Inner content wrapper with padding. Place message components inside here.
40
- */
41
- function AiConversationContent({ className, children, ...props }) {
42
- return /* @__PURE__ */ jsx("div", {
43
- className: cn("flex flex-col gap-0 overscroll-y-none p-4", className),
44
- ...props,
45
- children
46
- });
47
- }
48
- /**
49
- * Floating "scroll to bottom" button. Appears when the user has scrolled up
50
- * more than `threshold` pixels from the bottom.
51
- */
52
- function AiConversationScrollButton({ scrollRef, threshold = 100, className, onClick, ...props }) {
53
- const [show, setShow] = useState(false);
54
- useEffect(() => {
55
- const el = scrollRef?.current;
56
- if (!el) return;
57
- const check = () => {
58
- setShow(el.scrollHeight - el.scrollTop - el.clientHeight > threshold);
59
- };
60
- check();
61
- el.addEventListener("scroll", check, { passive: true });
62
- return () => el.removeEventListener("scroll", check);
63
- }, [scrollRef, threshold]);
64
- const handleClick = useCallback((e) => {
65
- scrollRef?.current?.scrollTo({
66
- top: scrollRef.current.scrollHeight,
67
- behavior: "smooth"
68
- });
69
- onClick?.(e);
70
- }, [scrollRef, onClick]);
71
- if (scrollRef && !show) return null;
72
- return /* @__PURE__ */ jsx(Button, {
73
- "aria-label": "Scroll to bottom",
74
- className: cn("absolute bottom-4 left-1/2 -translate-x-1/2 rounded-full shadow-md", className),
75
- onClick: handleClick,
76
- size: "sm",
77
- variant: "secondary",
78
- ...props,
79
- children: /* @__PURE__ */ jsx(ArrowDownIcon, { className: "size-4" })
80
- });
81
- }
82
- /**
83
- * `useConversationVirtualizer` — virtualizes a conversation list with
84
- * dynamic item heights and automatic stick-to-bottom behavior.
85
- *
86
- * Built on `@tanstack/react-virtual`. Items are measured dynamically via
87
- * `ResizeObserver`, so tool calls expanding, subagents collapsing, and
88
- * streaming text growing all work correctly.
89
- *
90
- * **Stick-to-bottom**: When the user is scrolled to (or near) the bottom,
91
- * new items and item resizes automatically keep the viewport pinned to the
92
- * bottom. When the user scrolls up, stick-to-bottom disengages until they
93
- * scroll back down.
94
- *
95
- * @example
96
- * ```tsx
97
- * const { virtualItems, totalSize, measureRef, isAtBottom, scrollToBottom } =
98
- * useConversationVirtualizer({ scrollRef, items });
99
- *
100
- * return (
101
- * <AiConversation ref={scrollRef}>
102
- * <div style={{ height: totalSize, position: "relative" }}>
103
- * {virtualItems.map((vi) => {
104
- * const item = items[vi.index];
105
- * return (
106
- * <div key={item.key} ref={measureRef} data-index={vi.index}
107
- * style={{ position: "absolute", top: vi.start, width: "100%" }}>
108
- * {item.render()}
109
- * </div>
110
- * );
111
- * })}
112
- * </div>
113
- * {!isAtBottom && <button onClick={() => scrollToBottom()}>↓</button>}
114
- * </AiConversation>
115
- * );
116
- * ```
117
- */
118
- function useConversationVirtualizer({ scrollRef, items, estimateSize = 80, overscan = 8, stickThreshold = 40 }) {
119
- const [isAtBottom, setIsAtBottom] = useState(true);
120
- const isAtBottomRef = useRef(true);
121
- const prevCountRef = useRef(items.length);
122
- useEffect(() => {
123
- const el = scrollRef.current;
124
- if (!el) return;
125
- const check = () => {
126
- const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight <= stickThreshold;
127
- isAtBottomRef.current = atBottom;
128
- setIsAtBottom(atBottom);
129
- };
130
- check();
131
- el.addEventListener("scroll", check, { passive: true });
132
- return () => el.removeEventListener("scroll", check);
133
- }, [scrollRef, stickThreshold]);
134
- const prevTotalSizeRef = useRef(0);
135
- const virtualizer = useVirtualizer({
136
- count: items.length,
137
- getScrollElement: () => scrollRef.current,
138
- estimateSize: () => estimateSize,
139
- overscan,
140
- getItemKey: (index) => items[index]?.key ?? index
141
- });
142
- virtualizer.shouldAdjustScrollPositionOnItemSizeChange = () => isAtBottomRef.current;
143
- const virtualItems = virtualizer.getVirtualItems();
144
- const totalSize = virtualizer.getTotalSize();
145
- useEffect(() => {
146
- const count = items.length;
147
- if (count > prevCountRef.current && isAtBottomRef.current) requestAnimationFrame(() => {
148
- virtualizer.scrollToIndex(count - 1, {
149
- align: "end",
150
- behavior: "smooth"
151
- });
152
- });
153
- prevCountRef.current = count;
154
- }, [items.length, virtualizer]);
155
- useEffect(() => {
156
- const prev = prevTotalSizeRef.current;
157
- prevTotalSizeRef.current = totalSize;
158
- if (!isAtBottomRef.current || totalSize <= prev) return;
159
- const el = scrollRef.current;
160
- if (!el) return;
161
- const dist = el.scrollHeight - el.scrollTop - el.clientHeight;
162
- if (dist > 1 && dist < 300) el.scrollTop = el.scrollHeight - el.clientHeight;
163
- }, [totalSize, scrollRef]);
164
- return {
165
- virtualizer,
166
- virtualItems,
167
- totalSize,
168
- isAtBottom,
169
- scrollToBottom: useCallback((behavior = "smooth") => {
170
- if (items.length === 0) return;
171
- virtualizer.scrollToIndex(items.length - 1, {
172
- align: "end",
173
- behavior
174
- });
175
- }, [virtualizer, items.length]),
176
- measureRef: useCallback((node) => {
177
- if (node) virtualizer.measureElement(node);
178
- }, [virtualizer])
179
- };
180
- }
181
- //#endregion
182
- export { SF_AI_CONVERSATION_VARIANTS as a, SF_AI_CONVERSATION_DEFAULT_VARIANTS as i, AiConversationContent as n, useConversationVirtualizer as o, AiConversationScrollButton as r, AiConversation as t };
183
-
184
- //# sourceMappingURL=ai-conversation-CArP7C8K.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-conversation-CArP7C8K.js","names":[],"sources":["../src/components/ai-conversation/ai-conversation.tsx"],"sourcesContent":["\"use client\";\n\nimport { ArrowDownIcon } from \"@phosphor-icons/react\";\nimport { useVirtualizer } from \"@tanstack/react-virtual\";\nimport type { Virtualizer, VirtualItem } from \"@tanstack/react-virtual\";\nimport type { ComponentProps, ReactNode, RefObject } from \"react\";\nimport { forwardRef, useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_CONVERSATION_VARIANTS = {} as const;\nexport const SF_AI_CONVERSATION_DEFAULT_VARIANTS = {} as const;\n\n// ─── AiConversation ──────────────────────────────────────────────────────────\n\nexport type AiConversationProps = ComponentProps<\"div\">;\n\n/**\n * Outer scroll container for a conversation. Sticks to the bottom as new\n * messages are added. Pair with `AiConversationContent` and optionally\n * `AiConversationScrollButton`.\n *\n * @example\n * ```tsx\n * <AiConversation ref={scrollRef}>\n * <AiConversationContent>\n * {messages.map(m => <AiMessage key={m.id} from={m.role}>...</AiMessage>)}\n * </AiConversationContent>\n * <AiConversationScrollButton scrollRef={scrollRef} />\n * </AiConversation>\n * ```\n */\nexport const AiConversation = forwardRef<HTMLDivElement, AiConversationProps>(\n ({ className, children, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\"relative flex-1 overflow-y-auto\", className)}\n role=\"log\"\n aria-live=\"polite\"\n aria-label=\"Conversation\"\n {...props}\n >\n {children}\n </div>\n );\n }\n);\n\nAiConversation.displayName = \"AiConversation\";\n\n// ─── AiConversationContent ───────────────────────────────────────────────────\n\nexport type AiConversationContentProps = ComponentProps<\"div\">;\n\n/**\n * Inner content wrapper with padding. Place message components inside here.\n */\nexport function AiConversationContent({\n className,\n children,\n ...props\n}: AiConversationContentProps) {\n return (\n <div\n className={cn(\"flex flex-col gap-0 overscroll-y-none p-4\", className)}\n {...props}\n >\n {children}\n </div>\n );\n}\n\n// ─── AiConversationScrollButton ──────────────────────────────────────────────\n\nexport type AiConversationScrollButtonProps = ComponentProps<typeof Button> & {\n /**\n * Ref to the scroll container (the `AiConversation` element).\n * When omitted, the button is always visible.\n */\n scrollRef?: RefObject<HTMLElement | null>;\n /** Scroll threshold in pixels from bottom to show the button. @default 100 */\n threshold?: number;\n};\n\n/**\n * Floating \"scroll to bottom\" button. Appears when the user has scrolled up\n * more than `threshold` pixels from the bottom.\n */\nexport function AiConversationScrollButton({\n scrollRef,\n threshold = 100,\n className,\n onClick,\n ...props\n}: AiConversationScrollButtonProps) {\n const [show, setShow] = useState(false);\n\n useEffect(() => {\n const el = scrollRef?.current;\n if (!el) return;\n\n const check = () => {\n const distFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;\n setShow(distFromBottom > threshold);\n };\n\n check();\n el.addEventListener(\"scroll\", check, { passive: true });\n return () => el.removeEventListener(\"scroll\", check);\n }, [scrollRef, threshold]);\n\n const handleClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n scrollRef?.current?.scrollTo({\n top: scrollRef.current.scrollHeight,\n behavior: \"smooth\",\n });\n onClick?.(e);\n },\n [scrollRef, onClick]\n );\n\n if (scrollRef && !show) return null;\n\n return (\n <Button\n aria-label=\"Scroll to bottom\"\n className={cn(\n \"absolute bottom-4 left-1/2 -translate-x-1/2 rounded-full shadow-md\",\n className\n )}\n onClick={handleClick}\n size=\"sm\"\n variant=\"secondary\"\n {...props}\n >\n <ArrowDownIcon className=\"size-4\" />\n </Button>\n );\n}\n\n// ─── Virtualized Conversation ────────────────────────────────────────────────\n\n/** A single item in the virtualized conversation list. */\nexport interface ConversationItem {\n /** Unique key for this item. */\n key: string;\n /**\n * Render the item content. The virtualizer handles measurement and\n * positioning on the wrapper — just return the content.\n */\n render: () => ReactNode;\n}\n\nexport interface UseConversationVirtualizerOptions {\n /** Ref to the scroll container element. */\n scrollRef: RefObject<HTMLElement | null>;\n /** The conversation items to virtualize. */\n items: ConversationItem[];\n /**\n * Estimated height of a single item in pixels.\n * Used before measurement. Doesn't need to be exact.\n * @default 80\n */\n estimateSize?: number;\n /**\n * Number of items to render beyond the visible area.\n * @default 8\n */\n overscan?: number;\n /**\n * Pixel distance from bottom to consider \"at bottom\" for stick-to-bottom.\n * @default 40\n */\n stickThreshold?: number;\n}\n\nexport interface UseConversationVirtualizerReturn {\n /** The TanStack virtualizer instance. */\n virtualizer: Virtualizer<HTMLElement, Element>;\n /** The virtual items to render. */\n virtualItems: VirtualItem[];\n /** Total measured/estimated height of all items. */\n totalSize: number;\n /** Whether the user is currently at the bottom of the conversation. */\n isAtBottom: boolean;\n /** Smoothly scroll to the bottom. */\n scrollToBottom: (behavior?: ScrollBehavior) => void;\n /** Get the measurement ref for a virtual item by index. */\n measureRef: (node: HTMLElement | null) => void;\n}\n\n/**\n * `useConversationVirtualizer` — virtualizes a conversation list with\n * dynamic item heights and automatic stick-to-bottom behavior.\n *\n * Built on `@tanstack/react-virtual`. Items are measured dynamically via\n * `ResizeObserver`, so tool calls expanding, subagents collapsing, and\n * streaming text growing all work correctly.\n *\n * **Stick-to-bottom**: When the user is scrolled to (or near) the bottom,\n * new items and item resizes automatically keep the viewport pinned to the\n * bottom. When the user scrolls up, stick-to-bottom disengages until they\n * scroll back down.\n *\n * @example\n * ```tsx\n * const { virtualItems, totalSize, measureRef, isAtBottom, scrollToBottom } =\n * useConversationVirtualizer({ scrollRef, items });\n *\n * return (\n * <AiConversation ref={scrollRef}>\n * <div style={{ height: totalSize, position: \"relative\" }}>\n * {virtualItems.map((vi) => {\n * const item = items[vi.index];\n * return (\n * <div key={item.key} ref={measureRef} data-index={vi.index}\n * style={{ position: \"absolute\", top: vi.start, width: \"100%\" }}>\n * {item.render()}\n * </div>\n * );\n * })}\n * </div>\n * {!isAtBottom && <button onClick={() => scrollToBottom()}>↓</button>}\n * </AiConversation>\n * );\n * ```\n */\nexport function useConversationVirtualizer({\n scrollRef,\n items,\n estimateSize = 80,\n overscan = 8,\n stickThreshold = 40,\n}: UseConversationVirtualizerOptions): UseConversationVirtualizerReturn {\n const [isAtBottom, setIsAtBottom] = useState(true);\n const isAtBottomRef = useRef(true);\n const prevCountRef = useRef(items.length);\n\n // Track whether user is at the bottom\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) return;\n\n const check = () => {\n const dist = el.scrollHeight - el.scrollTop - el.clientHeight;\n const atBottom = dist <= stickThreshold;\n isAtBottomRef.current = atBottom;\n setIsAtBottom(atBottom);\n };\n\n check();\n el.addEventListener(\"scroll\", check, { passive: true });\n return () => el.removeEventListener(\"scroll\", check);\n }, [scrollRef, stickThreshold]);\n\n // Track the previous totalSize so we can detect growth from item resizes\n const prevTotalSizeRef = useRef(0);\n\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => estimateSize,\n overscan,\n getItemKey: (index) => items[index]?.key ?? index,\n });\n\n // When items resize (streaming text, collapsible expand) and we're at\n // bottom, adjust scroll so the bottom stays pinned.\n virtualizer.shouldAdjustScrollPositionOnItemSizeChange = () =>\n isAtBottomRef.current;\n\n const virtualItems = virtualizer.getVirtualItems();\n const totalSize = virtualizer.getTotalSize();\n\n // When new items are added and we're at bottom, scroll to the end\n useEffect(() => {\n const count = items.length;\n if (count > prevCountRef.current && isAtBottomRef.current) {\n requestAnimationFrame(() => {\n virtualizer.scrollToIndex(count - 1, {\n align: \"end\",\n behavior: \"smooth\",\n });\n });\n }\n prevCountRef.current = count;\n }, [items.length, virtualizer]);\n\n // When totalSize grows (item content expanded, streaming text grew)\n // and we're stuck to bottom, smoothly follow by scrolling down.\n // This complements shouldAdjustScrollPositionOnItemSizeChange which\n // handles the instantaneous adjustment — this handles the smooth follow.\n useEffect(() => {\n const prev = prevTotalSizeRef.current;\n prevTotalSizeRef.current = totalSize;\n\n if (!isAtBottomRef.current || totalSize <= prev) return;\n\n const el = scrollRef.current;\n if (!el) return;\n\n // Only nudge if we're slightly off — the shouldAdjust callback handles\n // most cases, but measurement batching can leave a small gap.\n const dist = el.scrollHeight - el.scrollTop - el.clientHeight;\n if (dist > 1 && dist < 300) {\n el.scrollTop = el.scrollHeight - el.clientHeight;\n }\n }, [totalSize, scrollRef]);\n\n const scrollToBottom = useCallback(\n (behavior: ScrollBehavior = \"smooth\") => {\n if (items.length === 0) return;\n virtualizer.scrollToIndex(items.length - 1, { align: \"end\", behavior });\n },\n [virtualizer, items.length]\n );\n\n const measureRef = useCallback(\n (node: HTMLElement | null) => {\n if (node) virtualizer.measureElement(node);\n },\n [virtualizer]\n );\n\n return {\n virtualizer,\n virtualItems,\n totalSize,\n isAtBottom,\n scrollToBottom,\n measureRef,\n };\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-info-banner-uFxHHwBA.js","names":[],"sources":["../src/components/ai-info-banner/ai-info-banner.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n InfoIcon,\n WarningCircleIcon,\n ArrowsClockwiseIcon,\n} from \"@phosphor-icons/react\";\nimport type { ElementType, HTMLAttributes, ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_INFO_BANNER_VARIANTS = {\n level: {\n info: { classes: \"\", description: \"Informational notice\" },\n error: { classes: \"\", description: \"Error notice\" },\n change: {\n classes: \"\",\n description: \"State change notice (model/mode switch)\",\n },\n },\n} as const;\n\nexport const SF_AI_INFO_BANNER_DEFAULT_VARIANTS = {\n level: \"info\",\n} as const;\n\nexport type SFAiInfoBannerLevel = keyof typeof SF_AI_INFO_BANNER_VARIANTS.level;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type AiInfoBannerProps = HTMLAttributes<HTMLDivElement> & {\n /** Banner level controls icon and color treatment. */\n level?: SFAiInfoBannerLevel;\n /** Custom icon override. */\n icon?: ElementType;\n /** Content to display. */\n children: ReactNode;\n};\n\n// ─── Level config ─────────────────────────────────────────────────────────────\n\nconst LEVEL_CONFIG: Record<\n SFAiInfoBannerLevel,\n { icon: ElementType; iconClassName: string; borderClassName: string }\n> = {\n info: {\n icon: InfoIcon,\n iconClassName: \"text-sf-info\",\n borderClassName: \"border-sf-info/20\",\n },\n error: {\n icon: WarningCircleIcon,\n iconClassName: \"text-sf-danger\",\n borderClassName: \"border-sf-danger/20\",\n },\n change: {\n icon: ArrowsClockwiseIcon,\n iconClassName: \"text-sf-subtle\",\n borderClassName: \"border-sf-line\",\n },\n};\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Inline conversation banner for system notices. Renders as a compact,\n * horizontally centered divider-like notice rather than a chat bubble.\n *\n * Maps to harness events: `error`, `info`, `mode_changed`, `model_changed`.\n *\n * @example\n * ```tsx\n * <AiInfoBanner level=\"error\">\n * Connection lost. Retrying in 3s…\n * </AiInfoBanner>\n *\n * <AiInfoBanner level=\"change\">\n * Switched to claude-opus-4-6\n * </AiInfoBanner>\n *\n * <AiInfoBanner level=\"info\">\n * Follow-up queued — will send after current response\n * </AiInfoBanner>\n * ```\n */\nexport function AiInfoBanner({\n level = \"info\",\n icon,\n children,\n className,\n ...props\n}: AiInfoBannerProps) {\n const config = LEVEL_CONFIG[level];\n const IconComponent = icon ?? config.icon;\n\n return (\n <div\n className={cn(\n \"flex items-center justify-center gap-2 border-y px-4 py-1.5\",\n config.borderClassName,\n className\n )}\n role={level === \"error\" ? \"alert\" : \"status\"}\n {...props}\n >\n <IconComponent\n className={cn(\"size-3.5 shrink-0\", config.iconClassName)}\n />\n <span className=\"text-xs text-sf-subtle\">{children}</span>\n </div>\n );\n}\n\nAiInfoBanner.displayName = \"AiInfoBanner\";\n"],"mappings":";;;;;AAaA,IAAa,6BAA6B,EACxC,OAAO;CACL,MAAM;EAAE,SAAS;EAAI,aAAa;EAAwB;CAC1D,OAAO;EAAE,SAAS;EAAI,aAAa;EAAgB;CACnD,QAAQ;EACN,SAAS;EACT,aAAa;EACd;CACF,EACF;AAED,IAAa,qCAAqC,EAChD,OAAO,QACR;AAiBD,IAAM,eAGF;CACF,MAAM;EACJ,MAAM;EACN,eAAe;EACf,iBAAiB;EAClB;CACD,OAAO;EACL,MAAM;EACN,eAAe;EACf,iBAAiB;EAClB;CACD,QAAQ;EACN,MAAM;EACN,eAAe;EACf,iBAAiB;EAClB;CACF;;;;;;;;;;;;;;;;;;;;;;AAyBD,SAAgB,aAAa,EAC3B,QAAQ,QACR,MACA,UACA,WACA,GAAG,SACiB;CACpB,MAAM,SAAS,aAAa;CAC5B,MAAM,gBAAgB,QAAQ,OAAO;AAErC,QACE,qBAAC,OAAD;EACE,WAAW,GACT,+DACA,OAAO,iBACP,UACD;EACD,MAAM,UAAU,UAAU,UAAU;EACpC,GAAI;YAPN,CASE,oBAAC,eAAD,EACE,WAAW,GAAG,qBAAqB,OAAO,cAAc,EACxD,CAAA,EACF,oBAAC,QAAD;GAAM,WAAU;GAA0B;GAAgB,CAAA,CACtD;;;AAIV,aAAa,cAAc"}