@signalflare-ai/ui 1.1.0 → 1.3.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 (362) hide show
  1. package/CHANGELOG.md +102 -5
  2. package/README.md +1 -1
  3. package/ai/component-registry.json +531 -79
  4. package/ai/component-registry.md +4067 -6
  5. package/ai/schemas.ts +6 -1
  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-CBfz5XEf.js} +4 -4
  10. package/dist/{ai-actions-DSVeQn4e.js.map → ai-actions-CBfz5XEf.js.map} +1 -1
  11. package/dist/{ai-agent-card-BXHwhWAU.js → ai-agent-card-CByAUe0q.js} +3 -3
  12. package/dist/ai-agent-card-CByAUe0q.js.map +1 -0
  13. package/dist/{ai-approval-aa0qvjFN.js → ai-approval-Ci8N70a7.js} +4 -3
  14. package/dist/{ai-approval-aa0qvjFN.js.map → ai-approval-Ci8N70a7.js.map} +1 -1
  15. package/dist/{ai-code-block-BgtIxtZZ.js → ai-code-block-P9TJHvaC.js} +37 -39
  16. package/dist/ai-code-block-P9TJHvaC.js.map +1 -0
  17. package/dist/ai-conversation-Qslfdi1t.js +228 -0
  18. package/dist/ai-conversation-Qslfdi1t.js.map +1 -0
  19. package/dist/{ai-info-banner-uFxHHwBA.js → ai-info-banner-B_9vtGK3.js} +8 -4
  20. package/dist/ai-info-banner-B_9vtGK3.js.map +1 -0
  21. package/dist/{ai-message-BjnFznXy.js → ai-message-Ci3gwM7G.js} +29 -10
  22. package/dist/ai-message-Ci3gwM7G.js.map +1 -0
  23. package/dist/{ai-mission-header-08__gULL.js → ai-mission-header-CaBc19-t.js} +2 -2
  24. package/dist/{ai-mission-header-08__gULL.js.map → ai-mission-header-CaBc19-t.js.map} +1 -1
  25. package/dist/{ai-part-group-DBtgTgAn.js → ai-part-group-Dx1Mr92B.js} +5 -4
  26. package/dist/ai-part-group-Dx1Mr92B.js.map +1 -0
  27. package/dist/{ai-prompt-input-CuluUzpf.js → ai-prompt-input-Bm4XoSj2.js} +44 -55
  28. package/dist/ai-prompt-input-Bm4XoSj2.js.map +1 -0
  29. package/dist/{ai-question-CHHoDJMg.js → ai-question-OyJovxGe.js} +4 -3
  30. package/dist/{ai-question-CHHoDJMg.js.map → ai-question-OyJovxGe.js.map} +1 -1
  31. package/dist/{ai-reasoning-CnL6ZSr5.js → ai-reasoning-BLfBXx3F.js} +9 -5
  32. package/dist/ai-reasoning-BLfBXx3F.js.map +1 -0
  33. package/dist/{ai-response-BEUg3xvd.js → ai-response-hbVCZJmo.js} +9 -4
  34. package/dist/ai-response-hbVCZJmo.js.map +1 -0
  35. package/dist/{ai-shimmer-By5_L05p.js → ai-shimmer-BamNMNK3.js} +2 -2
  36. package/dist/{ai-shimmer-By5_L05p.js.map → ai-shimmer-BamNMNK3.js.map} +1 -1
  37. package/dist/{ai-status-badge-BGYGWYF6.js → ai-status-badge-BZLczdkI.js} +2 -2
  38. package/dist/{ai-status-badge-BGYGWYF6.js.map → ai-status-badge-BZLczdkI.js.map} +1 -1
  39. package/dist/{ai-streaming-text-CMfoThV0.js → ai-streaming-text-DgYu64UH.js} +44 -16
  40. package/dist/ai-streaming-text-DgYu64UH.js.map +1 -0
  41. package/dist/{ai-subagent-DcPRqkAA.js → ai-subagent-p97AI1h9.js} +14 -6
  42. package/dist/ai-subagent-p97AI1h9.js.map +1 -0
  43. package/dist/{ai-suggestion-MgeCg5Ar.js → ai-suggestion-Bj6vF7CT.js} +3 -3
  44. package/dist/{ai-suggestion-MgeCg5Ar.js.map → ai-suggestion-Bj6vF7CT.js.map} +1 -1
  45. package/dist/{ai-task-list-Da9zIm00.js → ai-task-list-C_UQYpk9.js} +15 -6
  46. package/dist/ai-task-list-C_UQYpk9.js.map +1 -0
  47. package/dist/{ai-timeline-Cwu045IR.js → ai-timeline-CePL1LOU.js} +3 -3
  48. package/dist/ai-timeline-CePL1LOU.js.map +1 -0
  49. package/dist/{ai-tool-Cn1O4xjP.js → ai-tool-CfRcwmHT.js} +35 -16
  50. package/dist/ai-tool-CfRcwmHT.js.map +1 -0
  51. package/dist/{ai-usage-bar-DjS12DMp.js → ai-usage-bar-45pVRCGA.js} +2 -2
  52. package/dist/{ai-usage-bar-DjS12DMp.js.map → ai-usage-bar-45pVRCGA.js.map} +1 -1
  53. package/dist/{badge-D_eaA6wv.js → badge-Beb-6uut.js} +5 -5
  54. package/dist/{badge-D_eaA6wv.js.map → badge-Beb-6uut.js.map} +1 -1
  55. package/dist/{banner-B_6oBrsu.js → banner-CCEksxPg.js} +8 -3
  56. package/dist/banner-CCEksxPg.js.map +1 -0
  57. package/dist/{breadcrumbs-BlmeYfgq.js → breadcrumbs-HiTmgaZ4.js} +5 -5
  58. package/dist/{breadcrumbs-BlmeYfgq.js.map → breadcrumbs-HiTmgaZ4.js.map} +1 -1
  59. package/dist/{button-De0267YU.js → button-BHOgXJRU.js} +4 -4
  60. package/dist/{button-De0267YU.js.map → button-BHOgXJRU.js.map} +1 -1
  61. package/dist/catalog.js +1 -1
  62. package/dist/catalog.js.map +1 -1
  63. package/dist/{chart-BK3sVPnD.js → chart-B9FfZdKs.js} +7 -7
  64. package/dist/chart-B9FfZdKs.js.map +1 -0
  65. package/dist/{checkbox-DYhUmZNw.js → checkbox-Cy_OCyay.js} +3 -3
  66. package/dist/{checkbox-DYhUmZNw.js.map → checkbox-Cy_OCyay.js.map} +1 -1
  67. package/dist/{clipboard-text-ssybngLw.js → clipboard-text-CKSvNp9L.js} +6 -5
  68. package/dist/clipboard-text-CKSvNp9L.js.map +1 -0
  69. package/dist/{cn-YROP2_ox.js → cn-CmAOpn49.js} +2 -2
  70. package/dist/{cn-YROP2_ox.js.map → cn-CmAOpn49.js.map} +1 -1
  71. package/dist/{code-Cx-QSoOT.js → code-JsQz-0G_.js} +4 -4
  72. package/dist/{code-Cx-QSoOT.js.map → code-JsQz-0G_.js.map} +1 -1
  73. package/dist/{collapsible-DWsXeXmS.js → collapsible-1kOZ-89L.js} +2 -2
  74. package/dist/{collapsible-DWsXeXmS.js.map → collapsible-1kOZ-89L.js.map} +1 -1
  75. package/dist/{combobox-C0iW6a0r.js → combobox-CQwDmqgA.js} +4 -4
  76. package/dist/{combobox-C0iW6a0r.js.map → combobox-CQwDmqgA.js.map} +1 -1
  77. package/dist/command-line/cli.js +3 -3
  78. package/dist/{command-palette-DGzioeki.js → command-palette-Bkuv3e6o.js} +20 -5
  79. package/dist/command-palette-Bkuv3e6o.js.map +1 -0
  80. package/dist/components/ai-actions.js +1 -1
  81. package/dist/components/ai-agent-card.js +1 -1
  82. package/dist/components/ai-approval.js +1 -1
  83. package/dist/components/ai-code-block.js +1 -1
  84. package/dist/components/ai-conversation.js +2 -2
  85. package/dist/components/ai-info-banner.js +1 -1
  86. package/dist/components/ai-message.js +1 -1
  87. package/dist/components/ai-mission-header.js +1 -1
  88. package/dist/components/ai-part-group.js +1 -1
  89. package/dist/components/ai-prompt-input.js +1 -1
  90. package/dist/components/ai-question.js +1 -1
  91. package/dist/components/ai-reasoning.js +1 -1
  92. package/dist/components/ai-response.js +1 -1
  93. package/dist/components/ai-shimmer.js +1 -1
  94. package/dist/components/ai-status-badge.js +1 -1
  95. package/dist/components/ai-streaming-text.js +2 -2
  96. package/dist/components/ai-subagent.js +1 -1
  97. package/dist/components/ai-suggestion.js +1 -1
  98. package/dist/components/ai-task-list.js +1 -1
  99. package/dist/components/ai-timeline.js +1 -1
  100. package/dist/components/ai-tool.js +1 -1
  101. package/dist/components/ai-usage-bar.js +1 -1
  102. package/dist/components/badge.js +1 -1
  103. package/dist/components/banner.js +1 -1
  104. package/dist/components/breadcrumbs.js +1 -1
  105. package/dist/components/button.js +1 -1
  106. package/dist/components/chart.js +2 -2
  107. package/dist/components/checkbox.js +1 -1
  108. package/dist/components/clipboard-text.js +1 -1
  109. package/dist/components/code.js +1 -1
  110. package/dist/components/collapsible.js +1 -1
  111. package/dist/components/combobox.js +1 -1
  112. package/dist/components/command-palette.js +1 -1
  113. package/dist/components/data-grid.js +1 -1
  114. package/dist/components/date-picker.js +1 -1
  115. package/dist/components/date-range-picker.js +1 -1
  116. package/dist/components/dialog.js +1 -1
  117. package/dist/components/dropdown.js +1 -1
  118. package/dist/components/empty.js +1 -1
  119. package/dist/components/field.js +1 -1
  120. package/dist/components/filters.js +1 -1
  121. package/dist/components/flow.js +1 -1
  122. package/dist/components/grid.js +1 -1
  123. package/dist/components/input.js +2 -2
  124. package/dist/components/label.js +1 -1
  125. package/dist/components/layer-card.js +1 -1
  126. package/dist/components/link.js +3 -3
  127. package/dist/components/link.js.map +1 -1
  128. package/dist/components/loader.js +2 -2
  129. package/dist/components/menubar.js +1 -1
  130. package/dist/components/meter.js +1 -1
  131. package/dist/components/pagination.js +1 -1
  132. package/dist/components/popover.js +1 -1
  133. package/dist/components/radio.js +1 -1
  134. package/dist/components/select.js +1 -1
  135. package/dist/components/sensitive-input.js +1 -1
  136. package/dist/components/sidebar.js +1 -1
  137. package/dist/components/signalflare-ai-logo.js +1 -1
  138. package/dist/components/sparkline.js +1 -1
  139. package/dist/components/stat-card.js +1 -1
  140. package/dist/components/surface.js +1 -1
  141. package/dist/components/switch.js +1 -1
  142. package/dist/components/table.js +1 -1
  143. package/dist/components/tabs.js +1 -1
  144. package/dist/components/text-roll.js +1 -1
  145. package/dist/components/text.js +1 -1
  146. package/dist/components/theme-toggle.js +1 -1
  147. package/dist/components/toast.js +1 -1
  148. package/dist/components/tooltip.js +1 -1
  149. package/dist/components/use-agent-harness.js +1 -1
  150. package/dist/{data-grid-CG76N_hK.js → data-grid-DDSFMHud.js} +136 -53
  151. package/dist/data-grid-DDSFMHud.js.map +1 -0
  152. package/dist/{date-picker-Dqg9L4xu.js → date-picker-O34AqG3f.js} +2 -2
  153. package/dist/{date-picker-Dqg9L4xu.js.map → date-picker-O34AqG3f.js.map} +1 -1
  154. package/dist/{date-range-picker-D75LLINc.js → date-range-picker-YKYvum_r.js} +29 -39
  155. package/dist/{date-range-picker-D75LLINc.js.map → date-range-picker-YKYvum_r.js.map} +1 -1
  156. package/dist/{dialog-CyHEQXEY.js → dialog-DYqu4aDO.js} +3 -3
  157. package/dist/{dialog-CyHEQXEY.js.map → dialog-DYqu4aDO.js.map} +1 -1
  158. package/dist/{dist-1-gcEL2L.js → dist-6AtBsaJE.js} +153 -47
  159. package/dist/dist-6AtBsaJE.js.map +1 -0
  160. package/dist/{dropdown-qnEYRFXZ.js → dropdown-XzbnRLYR.js} +15 -5
  161. package/dist/dropdown-XzbnRLYR.js.map +1 -0
  162. package/dist/{echart-DURZEyai.js → echart-DGBIVAv1.js} +23 -57
  163. package/dist/{echart-DURZEyai.js.map → echart-DGBIVAv1.js.map} +1 -1
  164. package/dist/{empty-D2TypIId.js → empty-C1tAkawe.js} +12 -7
  165. package/dist/empty-C1tAkawe.js.map +1 -0
  166. package/dist/{field-Y_UK1_Cg.js → field-DBpFzzBS.js} +3 -3
  167. package/dist/{field-Y_UK1_Cg.js.map → field-DBpFzzBS.js.map} +1 -1
  168. package/dist/{filters-Bw_U6ZTx.js → filters-SmEl93za.js} +10 -10
  169. package/dist/filters-SmEl93za.js.map +1 -0
  170. package/dist/{flow-BRsYUCJa.js → flow-BLzgbq1T.js} +6 -6
  171. package/dist/flow-BLzgbq1T.js.map +1 -0
  172. package/dist/genui.js +2 -2
  173. package/dist/genui.js.map +1 -1
  174. package/dist/{grid-qUAN9hFx.js → grid-CifjQL-5.js} +2 -2
  175. package/dist/{grid-qUAN9hFx.js.map → grid-CifjQL-5.js.map} +1 -1
  176. package/dist/{highlight-to-react-ClEfL81q.js → highlight-to-react-DN9dUCS2.js} +9 -15
  177. package/dist/highlight-to-react-DN9dUCS2.js.map +1 -0
  178. package/dist/index.js +72 -72
  179. package/dist/index.js.map +1 -1
  180. package/dist/{input-DddtBN-g.js → input-COmx2M_R.js} +5 -5
  181. package/dist/{input-DddtBN-g.js.map → input-COmx2M_R.js.map} +1 -1
  182. package/dist/{input-DXYUjGgD.js → input-GkfMQZC_.js} +3 -3
  183. package/dist/{input-DXYUjGgD.js.map → input-GkfMQZC_.js.map} +1 -1
  184. package/dist/{label-QtJxtJ4u.js → label-CiGZ464N.js} +3 -3
  185. package/dist/{label-QtJxtJ4u.js.map → label-CiGZ464N.js.map} +1 -1
  186. package/dist/{layer-card-BME0eljh.js → layer-card-8l8GuLQr.js} +2 -2
  187. package/dist/{layer-card-BME0eljh.js.map → layer-card-8l8GuLQr.js.map} +1 -1
  188. package/dist/layout-CWBE0qwx.js +6207 -0
  189. package/dist/layout-CWBE0qwx.js.map +1 -0
  190. package/dist/{link-provider-BUZKXaNE.js → link-provider-BSn8YJon.js} +2 -2
  191. package/dist/link-provider-BSn8YJon.js.map +1 -0
  192. package/dist/{loader-DAcc-Uag.js → loader-BEMz8pJO.js} +1 -1
  193. package/dist/{loader-DAcc-Uag.js.map → loader-BEMz8pJO.js.map} +1 -1
  194. package/dist/measured-text-CXkdw9Yr.js +305 -0
  195. package/dist/measured-text-CXkdw9Yr.js.map +1 -0
  196. package/dist/{menubar-C8NzAjfd.js → menubar-CoOr4ocj.js} +3 -3
  197. package/dist/{menubar-C8NzAjfd.js.map → menubar-CoOr4ocj.js.map} +1 -1
  198. package/dist/{meter-CpmTenEr.js → meter-Pf_VOl59.js} +2 -2
  199. package/dist/{meter-CpmTenEr.js.map → meter-Pf_VOl59.js.map} +1 -1
  200. package/dist/{pagination-BVqdlONY.js → pagination-DSY279Ta.js} +2 -2
  201. package/dist/{pagination-BVqdlONY.js.map → pagination-DSY279Ta.js.map} +1 -1
  202. package/dist/{popover-BRQZ2b6z.js → popover-BY-e9co1.js} +2 -2
  203. package/dist/{popover-BRQZ2b6z.js.map → popover-BY-e9co1.js.map} +1 -1
  204. package/dist/{radio-BNSwOt3B.js → radio-DZwL13j0.js} +2 -2
  205. package/dist/{radio-BNSwOt3B.js.map → radio-DZwL13j0.js.map} +1 -1
  206. package/dist/{select-1w2aebGQ.js → select-BFifYqHA.js} +6 -6
  207. package/dist/{select-1w2aebGQ.js.map → select-BFifYqHA.js.map} +1 -1
  208. package/dist/{sensitive-input-82Cez3vj.js → sensitive-input-DHLZcM73.js} +4 -4
  209. package/dist/{sensitive-input-82Cez3vj.js.map → sensitive-input-DHLZcM73.js.map} +1 -1
  210. package/dist/{sidebar-CAsCmSpM.js → sidebar-odGsdvG4.js} +6 -7
  211. package/dist/sidebar-odGsdvG4.js.map +1 -0
  212. package/dist/{signalflare-ai-logo-DDhxMJD6.js → signalflare-ai-logo-CNaDT_w8.js} +2 -2
  213. package/dist/{signalflare-ai-logo-DDhxMJD6.js.map → signalflare-ai-logo-CNaDT_w8.js.map} +1 -1
  214. package/dist/{skeleton-line-Do3UmGk9.js → skeleton-line-CxxYVTO2.js} +2 -2
  215. package/dist/{skeleton-line-Do3UmGk9.js.map → skeleton-line-CxxYVTO2.js.map} +1 -1
  216. package/dist/{sparkline-DdbeM4Ai.js → sparkline-BQ-4j2W2.js} +2 -2
  217. package/dist/{sparkline-DdbeM4Ai.js.map → sparkline-BQ-4j2W2.js.map} +1 -1
  218. package/dist/src/blocks/agent-harness/agent-harness.d.ts.map +1 -1
  219. package/dist/src/blocks/agent-harness/agent-harness.tsx +40 -16
  220. package/dist/src/blocks/commander/commander.tsx +15 -15
  221. package/dist/src/blocks/map-block/map-block.d.ts.map +1 -1
  222. package/dist/src/blocks/map-block/map-block.tsx +11 -7
  223. package/dist/src/components/ai-approval/ai-approval.d.ts.map +1 -1
  224. package/dist/src/components/ai-code-block/ai-code-block.d.ts +14 -13
  225. package/dist/src/components/ai-code-block/ai-code-block.d.ts.map +1 -1
  226. package/dist/src/components/ai-conversation/ai-conversation.d.ts +69 -37
  227. package/dist/src/components/ai-conversation/ai-conversation.d.ts.map +1 -1
  228. package/dist/src/components/ai-conversation/index.d.ts +2 -1
  229. package/dist/src/components/ai-conversation/index.d.ts.map +1 -1
  230. package/dist/src/components/ai-conversation/measurement-constants.d.ts +30 -0
  231. package/dist/src/components/ai-conversation/measurement-constants.d.ts.map +1 -0
  232. package/dist/src/components/ai-info-banner/ai-info-banner.d.ts.map +1 -1
  233. package/dist/src/components/ai-message/ai-message.d.ts +3 -0
  234. package/dist/src/components/ai-message/ai-message.d.ts.map +1 -1
  235. package/dist/src/components/ai-part-group/ai-part-group.d.ts.map +1 -1
  236. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts +13 -3
  237. package/dist/src/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -1
  238. package/dist/src/components/ai-prompt-input/controller.d.ts.map +1 -1
  239. package/dist/src/components/ai-prompt-input/index.d.ts +1 -1
  240. package/dist/src/components/ai-prompt-input/index.d.ts.map +1 -1
  241. package/dist/src/components/ai-prompt-input/types.d.ts.map +1 -1
  242. package/dist/src/components/ai-question/ai-question.d.ts.map +1 -1
  243. package/dist/src/components/ai-reasoning/ai-reasoning.d.ts.map +1 -1
  244. package/dist/src/components/ai-response/ai-response.d.ts +12 -1
  245. package/dist/src/components/ai-response/ai-response.d.ts.map +1 -1
  246. package/dist/src/components/ai-streaming-text/ai-streaming-text.d.ts +27 -0
  247. package/dist/src/components/ai-streaming-text/ai-streaming-text.d.ts.map +1 -1
  248. package/dist/src/components/ai-streaming-text/index.d.ts +1 -1
  249. package/dist/src/components/ai-streaming-text/index.d.ts.map +1 -1
  250. package/dist/src/components/ai-subagent/ai-subagent.d.ts.map +1 -1
  251. package/dist/src/components/ai-task-list/ai-task-list.d.ts.map +1 -1
  252. package/dist/src/components/ai-tool/ai-tool.d.ts.map +1 -1
  253. package/dist/src/components/banner/banner.d.ts.map +1 -1
  254. package/dist/src/components/chart/echart.d.ts.map +1 -1
  255. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
  256. package/dist/src/components/data-grid/data-grid.d.ts +2 -1
  257. package/dist/src/components/data-grid/data-grid.d.ts.map +1 -1
  258. package/dist/src/components/data-grid/features.d.ts +20 -0
  259. package/dist/src/components/data-grid/features.d.ts.map +1 -0
  260. package/dist/src/components/data-grid/types.d.ts +38 -7
  261. package/dist/src/components/data-grid/types.d.ts.map +1 -1
  262. package/dist/src/components/empty/empty.d.ts.map +1 -1
  263. package/dist/src/components/filters/filters.d.ts.map +1 -1
  264. package/dist/src/components/flow/use-children.d.ts +1 -1
  265. package/dist/src/components/link/link.d.ts.map +1 -1
  266. package/dist/src/components/sidebar/sidebar.d.ts +1 -1
  267. package/dist/src/components/signalflare-ai-logo/signalflare-ai-logo.d.ts.map +1 -1
  268. package/dist/src/components/stat-card/stat-card.d.ts +5 -0
  269. package/dist/src/components/stat-card/stat-card.d.ts.map +1 -1
  270. package/dist/src/components/text/text.d.ts +36 -1
  271. package/dist/src/components/text/text.d.ts.map +1 -1
  272. package/dist/src/components/text-roll/text-roll.d.ts.map +1 -1
  273. package/dist/src/components/theme-toggle/theme-toggle.d.ts.map +1 -1
  274. package/dist/src/components/toast/toast.d.ts.map +1 -1
  275. package/dist/src/components/tooltip/tooltip.d.ts.map +1 -1
  276. package/dist/src/index.d.ts +2 -2
  277. package/dist/src/index.d.ts.map +1 -1
  278. package/dist/src/utils/highlight-to-react.d.ts.map +1 -1
  279. package/dist/src/utils/index.d.ts +2 -0
  280. package/dist/src/utils/index.d.ts.map +1 -1
  281. package/dist/src/utils/measured-text.d.ts +40 -0
  282. package/dist/src/utils/measured-text.d.ts.map +1 -0
  283. package/dist/src/utils/use-measured-text.d.ts +59 -0
  284. package/dist/src/utils/use-measured-text.d.ts.map +1 -0
  285. package/dist/{stat-card-CEZscNh8.js → stat-card-Bspk4XFr.js} +30 -12
  286. package/dist/stat-card-Bspk4XFr.js.map +1 -0
  287. package/dist/styles/sf-binding.css +1 -1
  288. package/dist/styles/sf-standalone.css +2 -2
  289. package/dist/styles/shadcn.css +1 -1
  290. package/dist/styles/theme-minimal.css +9 -9
  291. package/dist/styles/theme-sf.css +14 -20
  292. package/dist/styles/theme-vesper.css +91 -0
  293. package/dist/{surface-BduI7Ehl.js → surface-CWdSFVUx.js} +3 -3
  294. package/dist/{surface-BduI7Ehl.js.map → surface-CWdSFVUx.js.map} +1 -1
  295. package/dist/{switch-CzZBRBL7.js → switch-TA4cByCJ.js} +5 -5
  296. package/dist/switch-TA4cByCJ.js.map +1 -0
  297. package/dist/{table-Rv4JMy0B.js → table-BM8JBGBs.js} +3 -3
  298. package/dist/{table-Rv4JMy0B.js.map → table-BM8JBGBs.js.map} +1 -1
  299. package/dist/{tabs-1cHrYoel.js → tabs-bnH2vGLv.js} +2 -2
  300. package/dist/{tabs-1cHrYoel.js.map → tabs-bnH2vGLv.js.map} +1 -1
  301. package/dist/{text-KJmGkwnf.js → text-iQ0YUFNg.js} +27 -6
  302. package/dist/text-iQ0YUFNg.js.map +1 -0
  303. package/dist/{text-roll-BZ3I1umc.js → text-roll-C3U2jd2u.js} +5 -2
  304. package/dist/text-roll-C3U2jd2u.js.map +1 -0
  305. package/dist/{theme-toggle-Bhu681D7.js → theme-toggle-BTVxD-fD.js} +10 -9
  306. package/dist/theme-toggle-BTVxD-fD.js.map +1 -0
  307. package/dist/{toast-Nw28a5Cx.js → toast-CgZVaAkw.js} +3 -3
  308. package/dist/{toast-Nw28a5Cx.js.map → toast-CgZVaAkw.js.map} +1 -1
  309. package/dist/{tooltip-Cb7QW-7H.js → tooltip-uobk6Oh-.js} +9 -3
  310. package/dist/tooltip-uobk6Oh-.js.map +1 -0
  311. package/dist/{use-agent-harness-BMyF8pTq.js → use-agent-harness-Dl8w6X5O.js} +3 -3
  312. package/dist/{use-agent-harness-BMyF8pTq.js.map → use-agent-harness-Dl8w6X5O.js.map} +1 -1
  313. package/dist/utils.js +4 -3
  314. package/package.json +27 -24
  315. package/scripts/component-registry/discovery.ts +11 -10
  316. package/scripts/component-registry/example-cleanup.ts +8 -8
  317. package/scripts/component-registry/index.ts +6 -6
  318. package/scripts/component-registry/schema-generator.ts +1 -1
  319. package/scripts/component-registry/sub-components.ts +35 -23
  320. package/scripts/component-registry/utils.ts +11 -11
  321. package/scripts/component-registry/variant-parser.ts +17 -15
  322. package/scripts/convert-demos-to-stories.ts +5 -5
  323. package/scripts/css-build.ts +1 -1
  324. package/scripts/theme-generator/config.ts +28 -146
  325. package/scripts/theme-generator/generate-css.ts +1 -2
  326. package/scripts/theme-generator/index.ts +0 -1
  327. package/scripts/theme-generator/migrate.ts +3 -3
  328. package/dist/ai-agent-card-BXHwhWAU.js.map +0 -1
  329. package/dist/ai-code-block-BgtIxtZZ.js.map +0 -1
  330. package/dist/ai-conversation-CArP7C8K.js +0 -184
  331. package/dist/ai-conversation-CArP7C8K.js.map +0 -1
  332. package/dist/ai-info-banner-uFxHHwBA.js.map +0 -1
  333. package/dist/ai-message-BjnFznXy.js.map +0 -1
  334. package/dist/ai-part-group-DBtgTgAn.js.map +0 -1
  335. package/dist/ai-prompt-input-CuluUzpf.js.map +0 -1
  336. package/dist/ai-reasoning-CnL6ZSr5.js.map +0 -1
  337. package/dist/ai-response-BEUg3xvd.js.map +0 -1
  338. package/dist/ai-streaming-text-CMfoThV0.js.map +0 -1
  339. package/dist/ai-subagent-DcPRqkAA.js.map +0 -1
  340. package/dist/ai-task-list-Da9zIm00.js.map +0 -1
  341. package/dist/ai-timeline-Cwu045IR.js.map +0 -1
  342. package/dist/ai-tool-Cn1O4xjP.js.map +0 -1
  343. package/dist/banner-B_6oBrsu.js.map +0 -1
  344. package/dist/chart-BK3sVPnD.js.map +0 -1
  345. package/dist/clipboard-text-ssybngLw.js.map +0 -1
  346. package/dist/command-palette-DGzioeki.js.map +0 -1
  347. package/dist/data-grid-CG76N_hK.js.map +0 -1
  348. package/dist/dist-1-gcEL2L.js.map +0 -1
  349. package/dist/dropdown-qnEYRFXZ.js.map +0 -1
  350. package/dist/empty-D2TypIId.js.map +0 -1
  351. package/dist/filters-Bw_U6ZTx.js.map +0 -1
  352. package/dist/flow-BRsYUCJa.js.map +0 -1
  353. package/dist/highlight-to-react-ClEfL81q.js.map +0 -1
  354. package/dist/link-provider-BUZKXaNE.js.map +0 -1
  355. package/dist/sidebar-CAsCmSpM.js.map +0 -1
  356. package/dist/stat-card-CEZscNh8.js.map +0 -1
  357. package/dist/styles/theme-blue-tint.css +0 -98
  358. package/dist/switch-CzZBRBL7.js.map +0 -1
  359. package/dist/text-KJmGkwnf.js.map +0 -1
  360. package/dist/text-roll-BZ3I1umc.js.map +0 -1
  361. package/dist/theme-toggle-Bhu681D7.js.map +0 -1
  362. package/dist/tooltip-Cb7QW-7H.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-prompt-input-CuluUzpf.js","names":[],"sources":["../../../node_modules/.bun/@tanstack+store@0.11.0/node_modules/@tanstack/store/dist/alien.js","../../../node_modules/.bun/@tanstack+store@0.11.0/node_modules/@tanstack/store/dist/atom.js","../../../node_modules/.bun/@tanstack+store@0.11.0/node_modules/@tanstack/store/dist/store.js","../../../node_modules/.bun/@tanstack+react-store@0.11.0+21ccd8898788a04d/node_modules/@tanstack/react-store/dist/useSelector.js","../../../node_modules/.bun/@tanstack+react-store@0.11.0+21ccd8898788a04d/node_modules/@tanstack/react-store/dist/useStore.js","../src/components/ai-prompt-input/controller.ts","../src/components/ai-prompt-input/ai-prompt-input.tsx"],"sourcesContent":["//#region src/alien.ts\nlet ReactiveFlags = /* @__PURE__ */ function(ReactiveFlags) {\n\tReactiveFlags[ReactiveFlags[\"None\"] = 0] = \"None\";\n\tReactiveFlags[ReactiveFlags[\"Mutable\"] = 1] = \"Mutable\";\n\tReactiveFlags[ReactiveFlags[\"Watching\"] = 2] = \"Watching\";\n\tReactiveFlags[ReactiveFlags[\"RecursedCheck\"] = 4] = \"RecursedCheck\";\n\tReactiveFlags[ReactiveFlags[\"Recursed\"] = 8] = \"Recursed\";\n\tReactiveFlags[ReactiveFlags[\"Dirty\"] = 16] = \"Dirty\";\n\tReactiveFlags[ReactiveFlags[\"Pending\"] = 32] = \"Pending\";\n\treturn ReactiveFlags;\n}({});\n/* @__NO_SIDE_EFFECTS__ */\nfunction createReactiveSystem({ update, notify, unwatched }) {\n\treturn {\n\t\tlink,\n\t\tunlink,\n\t\tpropagate,\n\t\tcheckDirty,\n\t\tshallowPropagate\n\t};\n\tfunction link(dep, sub, version) {\n\t\tconst prevDep = sub.depsTail;\n\t\tif (prevDep !== void 0 && prevDep.dep === dep) return;\n\t\tconst nextDep = prevDep !== void 0 ? prevDep.nextDep : sub.deps;\n\t\tif (nextDep !== void 0 && nextDep.dep === dep) {\n\t\t\tnextDep.version = version;\n\t\t\tsub.depsTail = nextDep;\n\t\t\treturn;\n\t\t}\n\t\tconst prevSub = dep.subsTail;\n\t\tif (prevSub !== void 0 && prevSub.version === version && prevSub.sub === sub) return;\n\t\tconst newLink = sub.depsTail = dep.subsTail = {\n\t\t\tversion,\n\t\t\tdep,\n\t\t\tsub,\n\t\t\tprevDep,\n\t\t\tnextDep,\n\t\t\tprevSub,\n\t\t\tnextSub: void 0\n\t\t};\n\t\tif (nextDep !== void 0) nextDep.prevDep = newLink;\n\t\tif (prevDep !== void 0) prevDep.nextDep = newLink;\n\t\telse sub.deps = newLink;\n\t\tif (prevSub !== void 0) prevSub.nextSub = newLink;\n\t\telse dep.subs = newLink;\n\t}\n\tfunction unlink(link, sub = link.sub) {\n\t\tconst dep = link.dep;\n\t\tconst prevDep = link.prevDep;\n\t\tconst nextDep = link.nextDep;\n\t\tconst nextSub = link.nextSub;\n\t\tconst prevSub = link.prevSub;\n\t\tif (nextDep !== void 0) nextDep.prevDep = prevDep;\n\t\telse sub.depsTail = prevDep;\n\t\tif (prevDep !== void 0) prevDep.nextDep = nextDep;\n\t\telse sub.deps = nextDep;\n\t\tif (nextSub !== void 0) nextSub.prevSub = prevSub;\n\t\telse dep.subsTail = prevSub;\n\t\tif (prevSub !== void 0) prevSub.nextSub = nextSub;\n\t\telse if ((dep.subs = nextSub) === void 0) unwatched(dep);\n\t\treturn nextDep;\n\t}\n\tfunction propagate(link) {\n\t\tlet next = link.nextSub;\n\t\tlet stack;\n\t\ttop: do {\n\t\t\tconst sub = link.sub;\n\t\t\tlet flags = sub.flags;\n\t\t\tif (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed | ReactiveFlags.Dirty | ReactiveFlags.Pending))) sub.flags = flags | ReactiveFlags.Pending;\n\t\t\telse if (!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed))) flags = ReactiveFlags.None;\n\t\t\telse if (!(flags & ReactiveFlags.RecursedCheck)) sub.flags = flags & ~ReactiveFlags.Recursed | ReactiveFlags.Pending;\n\t\t\telse if (!(flags & (ReactiveFlags.Dirty | ReactiveFlags.Pending)) && isValidLink(link, sub)) {\n\t\t\t\tsub.flags = flags | (ReactiveFlags.Recursed | ReactiveFlags.Pending);\n\t\t\t\tflags &= ReactiveFlags.Mutable;\n\t\t\t} else flags = ReactiveFlags.None;\n\t\t\tif (flags & ReactiveFlags.Watching) notify(sub);\n\t\t\tif (flags & ReactiveFlags.Mutable) {\n\t\t\t\tconst subSubs = sub.subs;\n\t\t\t\tif (subSubs !== void 0) {\n\t\t\t\t\tconst nextSub = (link = subSubs).nextSub;\n\t\t\t\t\tif (nextSub !== void 0) {\n\t\t\t\t\t\tstack = {\n\t\t\t\t\t\t\tvalue: next,\n\t\t\t\t\t\t\tprev: stack\n\t\t\t\t\t\t};\n\t\t\t\t\t\tnext = nextSub;\n\t\t\t\t\t}\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ((link = next) !== void 0) {\n\t\t\t\tnext = link.nextSub;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\twhile (stack !== void 0) {\n\t\t\t\tlink = stack.value;\n\t\t\t\tstack = stack.prev;\n\t\t\t\tif (link !== void 0) {\n\t\t\t\t\tnext = link.nextSub;\n\t\t\t\t\tcontinue top;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t} while (true);\n\t}\n\tfunction checkDirty(link, sub) {\n\t\tlet stack;\n\t\tlet checkDepth = 0;\n\t\tlet dirty = false;\n\t\ttop: do {\n\t\t\tconst dep = link.dep;\n\t\t\tconst flags = dep.flags;\n\t\t\tif (sub.flags & ReactiveFlags.Dirty) dirty = true;\n\t\t\telse if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) === (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) {\n\t\t\t\tif (update(dep)) {\n\t\t\t\t\tconst subs = dep.subs;\n\t\t\t\t\tif (subs.nextSub !== void 0) shallowPropagate(subs);\n\t\t\t\t\tdirty = true;\n\t\t\t\t}\n\t\t\t} else if ((flags & (ReactiveFlags.Mutable | ReactiveFlags.Pending)) === (ReactiveFlags.Mutable | ReactiveFlags.Pending)) {\n\t\t\t\tif (link.nextSub !== void 0 || link.prevSub !== void 0) stack = {\n\t\t\t\t\tvalue: link,\n\t\t\t\t\tprev: stack\n\t\t\t\t};\n\t\t\t\tlink = dep.deps;\n\t\t\t\tsub = dep;\n\t\t\t\t++checkDepth;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (!dirty) {\n\t\t\t\tconst nextDep = link.nextDep;\n\t\t\t\tif (nextDep !== void 0) {\n\t\t\t\t\tlink = nextDep;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile (checkDepth--) {\n\t\t\t\tconst firstSub = sub.subs;\n\t\t\t\tconst hasMultipleSubs = firstSub.nextSub !== void 0;\n\t\t\t\tif (hasMultipleSubs) {\n\t\t\t\t\tlink = stack.value;\n\t\t\t\t\tstack = stack.prev;\n\t\t\t\t} else link = firstSub;\n\t\t\t\tif (dirty) {\n\t\t\t\t\tif (update(sub)) {\n\t\t\t\t\t\tif (hasMultipleSubs) shallowPropagate(firstSub);\n\t\t\t\t\t\tsub = link.sub;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tdirty = false;\n\t\t\t\t} else sub.flags &= ~ReactiveFlags.Pending;\n\t\t\t\tsub = link.sub;\n\t\t\t\tconst nextDep = link.nextDep;\n\t\t\t\tif (nextDep !== void 0) {\n\t\t\t\t\tlink = nextDep;\n\t\t\t\t\tcontinue top;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn dirty;\n\t\t} while (true);\n\t}\n\tfunction shallowPropagate(link) {\n\t\tdo {\n\t\t\tconst sub = link.sub;\n\t\t\tconst flags = sub.flags;\n\t\t\tif ((flags & (ReactiveFlags.Pending | ReactiveFlags.Dirty)) === ReactiveFlags.Pending) {\n\t\t\t\tsub.flags = flags | ReactiveFlags.Dirty;\n\t\t\t\tif ((flags & (ReactiveFlags.Watching | ReactiveFlags.RecursedCheck)) === ReactiveFlags.Watching) notify(sub);\n\t\t\t}\n\t\t} while ((link = link.nextSub) !== void 0);\n\t}\n\tfunction isValidLink(checkLink, sub) {\n\t\tlet link = sub.depsTail;\n\t\twhile (link !== void 0) {\n\t\t\tif (link === checkLink) return true;\n\t\t\tlink = link.prevDep;\n\t\t}\n\t\treturn false;\n\t}\n}\n\n//#endregion\nexport { ReactiveFlags, createReactiveSystem };\n//# sourceMappingURL=alien.js.map","import { ReactiveFlags, createReactiveSystem } from \"./alien.js\";\n\n//#region src/atom.ts\nfunction toObserver(nextHandler, errorHandler, completionHandler) {\n\tconst isObserver = typeof nextHandler === \"object\";\n\tconst self = isObserver ? nextHandler : void 0;\n\treturn {\n\t\tnext: (isObserver ? nextHandler.next : nextHandler)?.bind(self),\n\t\terror: (isObserver ? nextHandler.error : errorHandler)?.bind(self),\n\t\tcomplete: (isObserver ? nextHandler.complete : completionHandler)?.bind(self)\n\t};\n}\nconst queuedEffects = [];\nlet cycle = 0;\nconst { link, unlink, propagate, checkDirty, shallowPropagate } = /* @__PURE__ */ createReactiveSystem({\n\tupdate(atom) {\n\t\treturn atom._update();\n\t},\n\tnotify(effect) {\n\t\tqueuedEffects[queuedEffectsLength++] = effect;\n\t\teffect.flags &= ~ReactiveFlags.Watching;\n\t},\n\tunwatched(atom) {\n\t\tif (atom.depsTail !== void 0) {\n\t\t\tatom.depsTail = void 0;\n\t\t\tatom.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;\n\t\t\tpurgeDeps(atom);\n\t\t}\n\t}\n});\nlet notifyIndex = 0;\nlet queuedEffectsLength = 0;\nlet activeSub;\nlet batchDepth = 0;\nfunction batch(fn) {\n\ttry {\n\t\t++batchDepth;\n\t\tfn();\n\t} finally {\n\t\tif (!--batchDepth) flush();\n\t}\n}\nfunction purgeDeps(sub) {\n\tconst depsTail = sub.depsTail;\n\tlet dep = depsTail !== void 0 ? depsTail.nextDep : sub.deps;\n\twhile (dep !== void 0) dep = unlink(dep, sub);\n}\nfunction flush() {\n\tif (batchDepth > 0) return;\n\twhile (notifyIndex < queuedEffectsLength) {\n\t\tconst effect = queuedEffects[notifyIndex];\n\t\tqueuedEffects[notifyIndex++] = void 0;\n\t\teffect.notify();\n\t}\n\tnotifyIndex = 0;\n\tqueuedEffectsLength = 0;\n}\nfunction createAsyncAtom(getValue, options) {\n\tconst ref = {};\n\tconst atom = createAtom(() => {\n\t\tgetValue().then((data) => {\n\t\t\tconst internalAtom = ref.current;\n\t\t\tif (internalAtom._update({\n\t\t\t\tstatus: \"done\",\n\t\t\t\tdata\n\t\t\t})) {\n\t\t\t\tconst subs = internalAtom.subs;\n\t\t\t\tif (subs !== void 0) {\n\t\t\t\t\tpropagate(subs);\n\t\t\t\t\tshallowPropagate(subs);\n\t\t\t\t\tflush();\n\t\t\t\t}\n\t\t\t}\n\t\t}, (error) => {\n\t\t\tconst internalAtom = ref.current;\n\t\t\tif (internalAtom._update({\n\t\t\t\tstatus: \"error\",\n\t\t\t\terror\n\t\t\t})) {\n\t\t\t\tconst subs = internalAtom.subs;\n\t\t\t\tif (subs !== void 0) {\n\t\t\t\t\tpropagate(subs);\n\t\t\t\t\tshallowPropagate(subs);\n\t\t\t\t\tflush();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\treturn { status: \"pending\" };\n\t}, options);\n\tref.current = atom;\n\treturn atom;\n}\nfunction createAtom(valueOrFn, options) {\n\tconst isComputed = typeof valueOrFn === \"function\";\n\tconst getter = valueOrFn;\n\tconst atom = {\n\t\t_snapshot: isComputed ? void 0 : valueOrFn,\n\t\tsubs: void 0,\n\t\tsubsTail: void 0,\n\t\tdeps: void 0,\n\t\tdepsTail: void 0,\n\t\tflags: isComputed ? ReactiveFlags.None : ReactiveFlags.Mutable,\n\t\tget() {\n\t\t\tif (activeSub !== void 0) link(atom, activeSub, cycle);\n\t\t\treturn atom._snapshot;\n\t\t},\n\t\tsubscribe(observerOrFn) {\n\t\t\tconst obs = toObserver(observerOrFn);\n\t\t\tconst observed = { current: false };\n\t\t\tconst e = effect(() => {\n\t\t\t\tatom.get();\n\t\t\t\tif (!observed.current) observed.current = true;\n\t\t\t\telse obs.next?.(atom._snapshot);\n\t\t\t});\n\t\t\treturn { unsubscribe: () => {\n\t\t\t\te.stop();\n\t\t\t} };\n\t\t},\n\t\t_update(getValue) {\n\t\t\tconst prevSub = activeSub;\n\t\t\tconst compare = options?.compare ?? Object.is;\n\t\t\tif (isComputed) {\n\t\t\t\tactiveSub = atom;\n\t\t\t\t++cycle;\n\t\t\t\tatom.depsTail = void 0;\n\t\t\t} else if (getValue === void 0) return false;\n\t\t\tif (isComputed) atom.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck;\n\t\t\ttry {\n\t\t\t\tconst oldValue = atom._snapshot;\n\t\t\t\tconst newValue = typeof getValue === \"function\" ? getValue(oldValue) : getValue === void 0 && isComputed ? getter(oldValue) : getValue;\n\t\t\t\tif (oldValue === void 0 || !compare(oldValue, newValue)) {\n\t\t\t\t\tatom._snapshot = newValue;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t} finally {\n\t\t\t\tactiveSub = prevSub;\n\t\t\t\tif (isComputed) atom.flags &= ~ReactiveFlags.RecursedCheck;\n\t\t\t\tpurgeDeps(atom);\n\t\t\t}\n\t\t}\n\t};\n\tif (isComputed) {\n\t\tatom.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;\n\t\tatom.get = function() {\n\t\t\tconst flags = atom.flags;\n\t\t\tif (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(atom.deps, atom)) {\n\t\t\t\tif (atom._update()) {\n\t\t\t\t\tconst subs = atom.subs;\n\t\t\t\t\tif (subs !== void 0) shallowPropagate(subs);\n\t\t\t\t}\n\t\t\t} else if (flags & ReactiveFlags.Pending) atom.flags = flags & ~ReactiveFlags.Pending;\n\t\t\tif (activeSub !== void 0) link(atom, activeSub, cycle);\n\t\t\treturn atom._snapshot;\n\t\t};\n\t} else atom.set = function(valueOrFn) {\n\t\tif (atom._update(valueOrFn)) {\n\t\t\tconst subs = atom.subs;\n\t\t\tif (subs !== void 0) {\n\t\t\t\tpropagate(subs);\n\t\t\t\tshallowPropagate(subs);\n\t\t\t\tflush();\n\t\t\t}\n\t\t}\n\t};\n\treturn atom;\n}\nfunction effect(fn) {\n\tconst run = () => {\n\t\tconst prevSub = activeSub;\n\t\tactiveSub = effectObj;\n\t\t++cycle;\n\t\teffectObj.depsTail = void 0;\n\t\teffectObj.flags = ReactiveFlags.Watching | ReactiveFlags.RecursedCheck;\n\t\ttry {\n\t\t\treturn fn();\n\t\t} finally {\n\t\t\tactiveSub = prevSub;\n\t\t\teffectObj.flags &= ~ReactiveFlags.RecursedCheck;\n\t\t\tpurgeDeps(effectObj);\n\t\t}\n\t};\n\tconst effectObj = {\n\t\tdeps: void 0,\n\t\tdepsTail: void 0,\n\t\tsubs: void 0,\n\t\tsubsTail: void 0,\n\t\tflags: ReactiveFlags.Watching | ReactiveFlags.RecursedCheck,\n\t\tnotify() {\n\t\t\tconst flags = this.flags;\n\t\t\tif (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(this.deps, this)) run();\n\t\t\telse this.flags = ReactiveFlags.Watching;\n\t\t},\n\t\tstop() {\n\t\t\tthis.flags = ReactiveFlags.None;\n\t\t\tthis.depsTail = void 0;\n\t\t\tpurgeDeps(this);\n\t\t}\n\t};\n\trun();\n\treturn effectObj;\n}\n\n//#endregion\nexport { batch, createAsyncAtom, createAtom, flush, toObserver };\n//# sourceMappingURL=atom.js.map","import { createAtom, toObserver } from \"./atom.js\";\n\n//#region src/store.ts\nvar Store = class {\n\tconstructor(valueOrFn, actionsFactory) {\n\t\tthis.atom = createAtom(valueOrFn);\n\t\tthis.get = this.get.bind(this);\n\t\tthis.setState = this.setState.bind(this);\n\t\tthis.subscribe = this.subscribe.bind(this);\n\t\tif (actionsFactory) this.actions = actionsFactory(this);\n\t}\n\tsetState(updater) {\n\t\tthis.atom.set(updater);\n\t}\n\tget state() {\n\t\treturn this.atom.get();\n\t}\n\tget() {\n\t\treturn this.state;\n\t}\n\tsubscribe(observerOrFn) {\n\t\treturn this.atom.subscribe(toObserver(observerOrFn));\n\t}\n};\nvar ReadonlyStore = class {\n\tconstructor(valueOrFn) {\n\t\tthis.atom = createAtom(valueOrFn);\n\t}\n\tget state() {\n\t\treturn this.atom.get();\n\t}\n\tget() {\n\t\treturn this.state;\n\t}\n\tsubscribe(observerOrFn) {\n\t\treturn this.atom.subscribe(toObserver(observerOrFn));\n\t}\n};\nfunction createStore(valueOrFn, actions) {\n\tif (typeof valueOrFn === \"function\") return new ReadonlyStore(valueOrFn);\n\tif (actions) return new Store(valueOrFn, actions);\n\treturn new Store(valueOrFn);\n}\n\n//#endregion\nexport { ReadonlyStore, Store, createStore };\n//# sourceMappingURL=store.js.map","import { useCallback } from \"react\";\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/shim/with-selector\";\n\n//#region src/useSelector.ts\nfunction defaultCompare(a, b) {\n\treturn a === b;\n}\n/**\n* Selects a slice of state from an atom or store and subscribes the component\n* to that selection.\n*\n* This is the primary React read hook for TanStack Store. It works with any\n* source that exposes `get()` and `subscribe()`, including atoms, readonly\n* atoms, stores, and readonly stores.\n*\n* Omit the selector to subscribe to the whole value.\n*\n* @example\n* ```tsx\n* const count = useSelector(counterStore, (state) => state.count)\n* ```\n*\n* @example\n* ```tsx\n* const value = useSelector(countAtom)\n* ```\n*/\nfunction useSelector(source, selector = (s) => s, options) {\n\tconst compare = options?.compare ?? defaultCompare;\n\tconst subscribe = useCallback((handleStoreChange) => {\n\t\tconst { unsubscribe } = source.subscribe(handleStoreChange);\n\t\treturn unsubscribe;\n\t}, [source]);\n\tconst getSnapshot = useCallback(() => source.get(), [source]);\n\treturn useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot, selector, compare);\n}\n\n//#endregion\nexport { useSelector };\n//# sourceMappingURL=useSelector.js.map","import { useSelector } from \"./useSelector.js\";\n\n//#region src/useStore.ts\n/**\n* Deprecated alias for {@link useSelector}.\n*\n* @example\n* ```tsx\n* const count = useStore(counterStore, (state) => state.count)\n* ```\n*\n* @deprecated Use `useSelector` instead.\n*/\nconst useStore = (source, selector = (s) => s, compare) => useSelector(source, selector, { compare });\n\n//#endregion\nexport { useStore };\n//# sourceMappingURL=useStore.js.map","/**\n * PromptInputController — the single source of truth for a prompt input tree.\n *\n * Built on @tanstack/store for per-slice subscriptions (sub-components\n * re-render only when the fields they read change). The controller exposes\n * two stores:\n *\n * - `request` : outbound state (text, files, mode, model, …extensions). The\n * user edits these; `submit()` ships them to `onSubmit`.\n * - `display` : inbound state (sendStatus, tasks, pendingQuestion, pendingPlan,\n * usage). The harness writes these in; sub-components read them.\n *\n * Consumers never touch the stores directly. They use:\n *\n * const mode = useRequestField('mode'); // read\n * const setMode = useSetRequestField('mode'); // write\n * const status = useDisplayField('sendStatus'); // read\n *\n * Or, for advanced use, subscribe to the whole store with\n * `useStore(controller.request)`.\n */\n\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport { createContext, useContext, useMemo } from \"react\";\n\nimport type {\n AttachmentFile,\n PromptInputDisplayContext,\n PromptInputRequestContext,\n PromptInputSubmitPayload,\n PromptInputTag,\n} from \"./types\";\n\n// ─── Controller shape ─────────────────────────────────────────────────────────\n\nexport type PromptInputRequestController<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n> = {\n /** Outbound stores (user-edited). */\n request: Store<PromptInputRequestContext<TExt>>;\n /** Inbound stores (harness-pushed). */\n display: Store<PromptInputDisplayContext>;\n\n /** Imperative helpers. */\n setRequestField: <K extends keyof PromptInputRequestContext<TExt>>(\n key: K,\n value: PromptInputRequestContext<TExt>[K]\n ) => void;\n setDisplayField: <K extends keyof PromptInputDisplayContext>(\n key: K,\n value: PromptInputDisplayContext[K]\n ) => void;\n\n /** Attachment helpers (common enough to warrant first-class methods). */\n addAttachments: (files: AttachmentFile[]) => void;\n removeAttachment: (id: string) => void;\n clearAttachments: () => void;\n\n /** Tag helpers for references attached to the prompt. */\n addTags: (tags: PromptInputTag[]) => void;\n insertTag: (tag: PromptInputTag, range?: { start: number; end: number }) => void;\n removeTag: (id: string) => void;\n clearTags: () => void;\n\n /** Reset request state (clears text, files, and tags; keeps mode/model). */\n resetRequest: () => void;\n\n /** Snapshot the current request context (for onSubmit). */\n snapshot: () => PromptInputSubmitPayload<TExt>;\n};\n\n// ─── Factory ──────────────────────────────────────────────────────────────────\n\nconst DEFAULT_REQUEST: PromptInputRequestContext = {\n text: \"\",\n files: [],\n tags: [],\n};\n\nconst DEFAULT_DISPLAY: PromptInputDisplayContext = {\n sendStatus: \"idle\",\n};\n\nexport type CreatePromptInputRequestControllerOptions<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n> = {\n initialRequest?: Partial<PromptInputRequestContext<TExt>>;\n initialDisplay?: Partial<PromptInputDisplayContext>;\n};\n\nexport function createPromptInputRequestController<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(\n options: CreatePromptInputRequestControllerOptions<TExt> = {}\n): PromptInputRequestController<TExt> {\n const request = new Store<PromptInputRequestContext<TExt>>({\n ...(DEFAULT_REQUEST as PromptInputRequestContext<TExt>),\n ...(options.initialRequest as Partial<PromptInputRequestContext<TExt>>),\n });\n\n const display = new Store<PromptInputDisplayContext>({\n ...DEFAULT_DISPLAY,\n ...options.initialDisplay,\n });\n\n return {\n request,\n display,\n setRequestField(key, value) {\n request.setState((prev) => ({ ...prev, [key]: value }));\n },\n setDisplayField(key, value) {\n display.setState((prev) => ({ ...prev, [key]: value }));\n },\n addAttachments(files) {\n request.setState((prev) => ({\n ...prev,\n files: [...prev.files, ...files],\n }));\n },\n removeAttachment(id) {\n request.setState((prev) => {\n const removed = prev.files.find((f) => f.id === id);\n if (removed?.url.startsWith(\"blob:\")) URL.revokeObjectURL(removed.url);\n return { ...prev, files: prev.files.filter((f) => f.id !== id) };\n });\n },\n clearAttachments() {\n request.setState((prev) => {\n for (const f of prev.files) {\n if (f.url.startsWith(\"blob:\")) URL.revokeObjectURL(f.url);\n }\n return { ...prev, files: [] };\n });\n },\n addTags(tags) {\n request.setState((prev) => {\n const existing = prev.tags ?? [];\n const incoming = tags.filter(\n (tag) => !existing.some((item) => item.id === tag.id)\n );\n return { ...prev, tags: [...existing, ...incoming] };\n });\n },\n insertTag(tag, range) {\n request.setState((prev) => {\n const mention = tag.mention ?? `@${tag.label.replace(/\\s+/g, \"-\").toLowerCase()}`;\n const text = prev.text ?? \"\";\n const start = range?.start ?? text.length;\n const end = range?.end ?? text.length;\n const prefix = text.slice(0, start);\n const suffix = text.slice(end);\n const needsPrefixSpace = prefix.length > 0 && !/\\s$/.test(prefix);\n const needsSuffixSpace = suffix.length > 0 && !/^\\s/.test(suffix);\n const nextText = `${prefix}${needsPrefixSpace ? \" \" : \"\"}${mention}${needsSuffixSpace ? \" \" : \"\"}${suffix}`;\n const nextTag = { ...tag, mention };\n const existing = prev.tags ?? [];\n const nextTags = existing.some((item) => item.id === tag.id)\n ? existing.map((item) => (item.id === tag.id ? nextTag : item))\n : [...existing, nextTag];\n return { ...prev, text: nextText, tags: nextTags };\n });\n },\n removeTag(id) {\n request.setState((prev) => ({\n ...prev,\n tags: (prev.tags ?? []).filter((tag) => tag.id !== id),\n }));\n },\n clearTags() {\n request.setState((prev) => ({ ...prev, tags: [] }));\n },\n resetRequest() {\n request.setState((prev) => {\n for (const f of prev.files) {\n if (f.url.startsWith(\"blob:\")) URL.revokeObjectURL(f.url);\n }\n return { ...prev, text: \"\", files: [], tags: [] };\n });\n },\n snapshot() {\n return request.state;\n },\n };\n}\n\n// ─── React context + hooks ────────────────────────────────────────────────────\n\n// Typed as `any` in the context because each provider parameterizes `TExt`\n// differently; callers narrow via the hook generic or typed consumer.\nconst PromptInputRequestControllerContext =\n // biome-ignore lint/suspicious/noExplicitAny: controller TExt is provider-parameterized\n createContext<PromptInputRequestController<any> | null>(null);\n\nexport const PromptInputRequestControllerProvider =\n PromptInputRequestControllerContext.Provider;\n\nexport function usePromptInputRequestController<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(): PromptInputRequestController<TExt> {\n const ctx = useContext(PromptInputRequestControllerContext);\n if (!ctx) {\n throw new Error(\n \"usePromptInputRequestController must be used inside <PromptInput> or <PromptInputRequestProvider>\"\n );\n }\n return ctx as PromptInputRequestController<TExt>;\n}\n\n/** Optional variant — returns null if no controller is in context. */\nexport function useOptionalPromptInputRequestController<\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(): PromptInputRequestController<TExt> | null {\n return useContext(\n PromptInputRequestControllerContext\n ) as PromptInputRequestController<TExt> | null;\n}\n\n// ─── Field hooks ──────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to one field of the request context. Component re-renders only\n * when that field changes.\n */\nexport function useRequestField<\n K extends keyof PromptInputRequestContext<TExt>,\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(key: K): PromptInputRequestContext<TExt>[K] {\n const ctrl = usePromptInputRequestController<TExt>();\n return useStore(ctrl.request, (state) => state[key]);\n}\n\n/** Returns a stable setter for one field of the request context. */\nexport function useSetRequestField<\n K extends keyof PromptInputRequestContext<TExt>,\n TExt extends Record<string, unknown> = Record<string, unknown>,\n>(key: K): (value: PromptInputRequestContext<TExt>[K]) => void {\n const ctrl = usePromptInputRequestController<TExt>();\n return useMemo(\n () => (value: PromptInputRequestContext<TExt>[K]) => {\n ctrl.setRequestField(key, value);\n },\n [ctrl, key]\n );\n}\n\n/**\n * Subscribe to one field of the display context. Component re-renders only\n * when that field changes.\n */\nexport function useDisplayField<K extends keyof PromptInputDisplayContext>(\n key: K\n): PromptInputDisplayContext[K] {\n const ctrl = usePromptInputRequestController();\n return useStore(ctrl.display, (state) => state[key]);\n}\n","\"use client\";\n\nimport { Menu as DropdownMenuPrimitive } from \"@base-ui/react/menu\";\nimport { Select as SelectPrimitive } from \"@base-ui/react/select\";\nimport {\n ArrowUpIcon,\n ArrowsClockwiseIcon,\n CaretDownIcon,\n CheckIcon,\n FileIcon,\n FileTextIcon,\n ImageIcon,\n MicrophoneIcon,\n PaperclipIcon,\n PlusIcon,\n SpinnerGapIcon,\n SquareIcon,\n XIcon,\n} from \"@phosphor-icons/react\";\nimport { useStore } from \"@tanstack/react-store\";\nimport { Store } from \"@tanstack/store\";\nimport type {\n ChangeEvent,\n ChangeEventHandler,\n ClipboardEventHandler,\n ComponentProps,\n CSSProperties,\n FormEvent,\n FormEventHandler,\n HTMLAttributes,\n KeyboardEventHandler,\n PropsWithChildren,\n ReactNode,\n RefObject,\n} from \"react\";\nimport {\n Fragment,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { Button } from \"../button\";\nimport { Tooltip } from \"../tooltip\";\nimport { useOptionalPromptInputRequestController } from \"./controller\";\nimport type {\n ModeOption,\n PromptInputReferenceSearch,\n PromptInputTag as PromptInputTagData,\n} from \"./types\";\n\n// Stable fallback store for selectors used outside a controller — keeps\n// `useStore` hook order consistent whether or not the controller is mounted.\nconst FALLBACK_REQUEST_STORE = new Store<Record<string, unknown>>({});\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_PROMPT_INPUT_VARIANTS = {\n status: {\n idle: { classes: \"\", description: \"Ready to accept input\" },\n submitted: {\n classes: \"\",\n description: \"Waiting for response (shows spinner)\",\n },\n streaming: { classes: \"\", description: \"Streaming response (shows stop)\" },\n error: { classes: \"\", description: \"Error state (shows X)\" },\n },\n} as const;\n\nexport const SF_AI_PROMPT_INPUT_DEFAULT_VARIANTS = {\n status: \"idle\",\n} as const;\n\nexport type SFAiPromptInputStatus =\n keyof typeof SF_AI_PROMPT_INPUT_VARIANTS.status;\n\n// ─── Attachment types ─────────────────────────────────────────────────────────\n\nexport type AttachmentFile = {\n id: string;\n url: string;\n mediaType: string;\n filename: string;\n};\n\nexport type AttachmentsContext = {\n files: AttachmentFile[];\n add: (files: File[] | FileList) => void;\n remove: (id: string) => void;\n clear: () => void;\n openFileDialog: () => void;\n fileInputRef: RefObject<HTMLInputElement | null>;\n};\n\n// ─── Provider Context & Types ─────────────────────────────────────────────────\n\nexport type TextInputContext = {\n value: string;\n setInput: (v: string) => void;\n clear: () => void;\n};\n\nexport type PromptInputController = {\n textInput: TextInputContext;\n attachments: AttachmentsContext;\n /** INTERNAL: Allows PromptInput to register its file input + \"open\" callback */\n __registerFileInput: (\n ref: RefObject<HTMLInputElement | null>,\n open: () => void\n ) => void;\n};\n\nconst PromptInputContext = createContext<PromptInputController | null>(null);\nconst ProviderAttachmentsContext = createContext<AttachmentsContext | null>(\n null\n);\n\nexport const usePromptInputController = () => {\n const ctx = useContext(PromptInputContext);\n if (!ctx) {\n throw new Error(\n \"Wrap your component inside <PromptInputProvider> to use usePromptInputController().\"\n );\n }\n return ctx;\n};\n\nconst useOptionalPromptInputController = () => useContext(PromptInputContext);\n\nexport const useProviderAttachments = () => {\n const ctx = useContext(ProviderAttachmentsContext);\n if (!ctx) {\n throw new Error(\n \"Wrap your component inside <PromptInputProvider> to use useProviderAttachments().\"\n );\n }\n return ctx;\n};\n\nconst useOptionalProviderAttachments = () =>\n useContext(ProviderAttachmentsContext);\n\n// ─── PromptInputProvider ──────────────────────────────────────────────────────\n\nexport type PromptInputProviderProps = PropsWithChildren<{\n initialInput?: string;\n}>;\n\n/**\n * Optional global provider that lifts PromptInput state outside of PromptInput.\n * If you don't use it, PromptInput stays fully self-managed.\n *\n * @example\n * ```tsx\n * <PromptInputProvider>\n * <PromptInput onSubmit={handleSubmit}>...</PromptInput>\n * </PromptInputProvider>\n * ```\n */\nexport function PromptInputProvider({\n initialInput = \"\",\n children,\n}: PromptInputProviderProps) {\n const [textInput, setTextInput] = useState(initialInput);\n const clearInput = useCallback(() => setTextInput(\"\"), []);\n\n const [attachmentItems, setAttachmentItems] = useState<AttachmentFile[]>([]);\n const fileInputRef = useRef<HTMLInputElement | null>(null);\n const openRef = useRef<() => void>(() => {});\n\n const add = useCallback((files: File[] | FileList) => {\n const incoming = Array.from(files);\n if (incoming.length === 0) return;\n setAttachmentItems((prev) =>\n prev.concat(\n incoming.map((file) => ({\n id: `${Date.now()}-${Math.random()}`,\n url: URL.createObjectURL(file),\n mediaType: file.type,\n filename: file.name,\n }))\n )\n );\n }, []);\n\n const remove = useCallback((id: string) => {\n setAttachmentItems((prev) => {\n const found = prev.find((f) => f.id === id);\n if (found?.url) URL.revokeObjectURL(found.url);\n return prev.filter((f) => f.id !== id);\n });\n }, []);\n\n const clear = useCallback(() => {\n setAttachmentItems((prev) => {\n for (const f of prev) if (f.url) URL.revokeObjectURL(f.url);\n return [];\n });\n }, []);\n\n const openFileDialog = useCallback(() => {\n openRef.current?.();\n }, []);\n\n const attachments = useMemo<AttachmentsContext>(\n () => ({\n files: attachmentItems,\n add,\n remove,\n clear,\n openFileDialog,\n fileInputRef,\n }),\n [attachmentItems, add, remove, clear, openFileDialog]\n );\n\n const __registerFileInput = useCallback(\n (ref: RefObject<HTMLInputElement | null>, open: () => void) => {\n fileInputRef.current = ref.current;\n openRef.current = open;\n },\n []\n );\n\n const controller = useMemo<PromptInputController>(\n () => ({\n textInput: {\n value: textInput,\n setInput: setTextInput,\n clear: clearInput,\n },\n attachments,\n __registerFileInput,\n }),\n [textInput, clearInput, attachments, __registerFileInput]\n );\n\n return (\n <PromptInputContext.Provider value={controller}>\n <ProviderAttachmentsContext.Provider value={attachments}>\n {children}\n </ProviderAttachmentsContext.Provider>\n </PromptInputContext.Provider>\n );\n}\n\n// ─── Local Attachments Context ────────────────────────────────────────────────\n\nconst LocalAttachmentsContext = createContext<AttachmentsContext | null>(null);\n\nexport const usePromptInputAttachments = () => {\n const provider = useOptionalProviderAttachments();\n const local = useContext(LocalAttachmentsContext);\n const context = provider ?? local;\n if (!context) {\n throw new Error(\n \"usePromptInputAttachments must be used within a PromptInput or PromptInputProvider\"\n );\n }\n return context;\n};\n\n// ─── Helpers (module-level) ───────────────────────────────────────────────────\n\n/** Convert a blob URL to a base64 data URL for serialization. */\nasync function convertBlobToDataUrl(url: string): Promise<string> {\n const response = await fetch(url);\n const blob = await response.blob();\n // FileReader is callback-only — no Promise-based API exists for this\n // oxlint-disable-next-line avoid-new\n return new Promise<string>((resolve, reject) => {\n const reader = new FileReader();\n reader.addEventListener(\"loadend\", () => resolve(reader.result as string));\n reader.addEventListener(\"error\", () =>\n reject(new Error(\"FileReader error\"))\n );\n reader.readAsDataURL(blob);\n });\n}\n\nfunction makeAttachmentId() {\n return `${Date.now()}-${Math.random()}`;\n}\n\n// ─── PromptInputMessage ───────────────────────────────────────────────────────\n\nexport type PromptInputMessage = {\n text?: string;\n files?: AttachmentFile[];\n tags?: PromptInputTagData[];\n};\n\n// ─── PromptInput ─────────────────────────────────────────────────────────────\n\nexport type PromptInputProps = Omit<\n HTMLAttributes<HTMLFormElement>,\n \"onSubmit\" | \"onError\"\n> & {\n /** Accepted file types — e.g. `\"image/*\"`. Default: any. */\n accept?: string;\n /** Allow selecting multiple files. */\n multiple?: boolean;\n /** When true, accept drops anywhere on document. Default false. */\n globalDrop?: boolean;\n /** Maximum number of attached files. */\n maxFiles?: number;\n /** Maximum file size in bytes. */\n maxFileSize?: number;\n onError?: (err: {\n code: \"max_files\" | \"max_file_size\" | \"accept\";\n message: string;\n }) => void;\n onSubmit: (\n message: PromptInputMessage,\n event: FormEvent<HTMLFormElement>\n ) => void | Promise<void>;\n /**\n * Content rendered in the collapsible back layer (e.g. HITL approvals, task\n * lists). When provided the prompt input is wrapped in a LayerCard shell with\n * a header row containing a chevron toggle.\n * Use `PromptInputBackLayer` to compose structured content for this slot.\n */\n backLayer?: ReactNode;\n /**\n * Title shown in the back layer header row. Defaults to `\"Context\"`.\n */\n backLayerTitle?: string;\n /**\n * Controls whether the back layer is visible. Pair with `onBackLayerOpenChange`\n * for a controlled pattern.\n */\n backLayerOpen?: boolean;\n /** Called when the chevron toggle changes the back layer open state. */\n onBackLayerOpenChange?: (open: boolean) => void;\n /**\n * Automatically opens the back layer when this condition is true.\n * Useful for showing pending approvals/questions without manual toggle.\n */\n autoOpenBackLayerWhen?: boolean;\n};\n\n/**\n * Prompt input form. Can be self-managed or controlled via `PromptInputProvider`.\n *\n * @example\n * ```tsx\n * <PromptInput onSubmit={({ text, files }) => send(text, files)}>\n * <PromptInputAttachments>{(f) => <PromptInputAttachment data={f} />}</PromptInputAttachments>\n * <PromptInputTextarea placeholder=\"Ask anything…\" />\n * <PromptInputToolbar>\n * <PromptInputTools>\n * <PromptInputAttachButton />\n * </PromptInputTools>\n * <PromptInputSubmit />\n * </PromptInputToolbar>\n * </PromptInput>\n * ```\n */\nexport function PromptInput({\n className,\n accept,\n multiple,\n globalDrop,\n maxFiles,\n maxFileSize,\n onError,\n onSubmit,\n children,\n backLayer,\n backLayerTitle = \"Context\",\n backLayerOpen,\n onBackLayerOpenChange,\n autoOpenBackLayerWhen,\n ...props\n}: PromptInputProps) {\n const hasBackLayer = backLayer !== undefined;\n const controller = useOptionalPromptInputController();\n const requestCtrl = useOptionalPromptInputRequestController();\n const usingProvider = !!controller;\n\n const inputRef = useRef<HTMLInputElement | null>(null);\n const anchorRef = useRef<HTMLSpanElement>(null);\n const formRef = useRef<HTMLFormElement | null>(null);\n\n useEffect(() => {\n const root = anchorRef.current?.closest(\"form\");\n if (root instanceof HTMLFormElement) {\n formRef.current = root;\n }\n }, []);\n\n // Auto-open back layer when condition is true\n useEffect(() => {\n if (autoOpenBackLayerWhen) {\n onBackLayerOpenChange?.(true);\n }\n }, [autoOpenBackLayerWhen, onBackLayerOpenChange]);\n\n // Local attachment state (only when no provider)\n const [items, setItems] = useState<AttachmentFile[]>([]);\n const files = usingProvider ? controller.attachments.files : items;\n const tags = useStore(requestCtrl?.request ?? FALLBACK_REQUEST_STORE, (state) =>\n ((state as { tags?: PromptInputTagData[] }).tags ?? [])\n );\n\n const openFileDialogLocal = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const matchesAccept = useCallback(\n (f: File) => {\n if (!accept || accept.trim() === \"\") return true;\n if (accept.includes(\"image/*\")) return f.type.startsWith(\"image/\");\n return true;\n },\n [accept]\n );\n\n const addLocal = useCallback(\n (fileList: File[] | FileList) => {\n const incoming = Array.from(fileList);\n const accepted = incoming.filter((f) => matchesAccept(f));\n if (incoming.length && accepted.length === 0) {\n onError?.({\n code: \"accept\",\n message: \"No files match the accepted types.\",\n });\n return;\n }\n const withinSize = (f: File) =>\n maxFileSize ? f.size <= maxFileSize : true;\n const sized = accepted.filter(withinSize);\n if (accepted.length > 0 && sized.length === 0) {\n onError?.({\n code: \"max_file_size\",\n message: \"All files exceed the maximum size.\",\n });\n return;\n }\n setItems((prev) => {\n const capacity =\n typeof maxFiles === \"number\"\n ? Math.max(0, maxFiles - prev.length)\n : undefined;\n const capped =\n typeof capacity === \"number\" ? sized.slice(0, capacity) : sized;\n if (typeof capacity === \"number\" && sized.length > capacity) {\n onError?.({\n code: \"max_files\",\n message: \"Too many files. Some were not added.\",\n });\n }\n const next: AttachmentFile[] = capped.map((file) => ({\n id: makeAttachmentId(),\n url: URL.createObjectURL(file),\n mediaType: file.type,\n filename: file.name,\n }));\n return prev.concat(next);\n });\n },\n [matchesAccept, maxFiles, maxFileSize, onError]\n );\n\n const add = usingProvider\n ? (f: File[] | FileList) => controller.attachments.add(f)\n : addLocal;\n\n const remove = usingProvider\n ? (id: string) => controller.attachments.remove(id)\n : (id: string) =>\n setItems((prev) => {\n const found = prev.find((f) => f.id === id);\n if (found?.url) URL.revokeObjectURL(found.url);\n return prev.filter((f) => f.id !== id);\n });\n\n const clear = usingProvider\n ? () => controller.attachments.clear()\n : () =>\n setItems((prev) => {\n for (const f of prev) if (f.url) URL.revokeObjectURL(f.url);\n return [];\n });\n\n const openFileDialog = usingProvider\n ? () => controller.attachments.openFileDialog()\n : openFileDialogLocal;\n\n useEffect(() => {\n if (!usingProvider) return;\n controller.__registerFileInput(inputRef, () => inputRef.current?.click());\n }, [usingProvider, controller]);\n\n // File drag-drop on the form\n useEffect(() => {\n const form = formRef.current;\n if (!form) return;\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) {\n add(e.dataTransfer.files);\n }\n };\n form.addEventListener(\"dragover\", onDragOver);\n form.addEventListener(\"drop\", onDrop);\n return () => {\n form.removeEventListener(\"dragover\", onDragOver);\n form.removeEventListener(\"drop\", onDrop);\n };\n }, [add]);\n\n useEffect(() => {\n if (!globalDrop) return;\n const onDragOver = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n };\n const onDrop = (e: DragEvent) => {\n if (e.dataTransfer?.types?.includes(\"Files\")) e.preventDefault();\n if (e.dataTransfer?.files && e.dataTransfer.files.length > 0)\n add(e.dataTransfer.files);\n };\n document.addEventListener(\"dragover\", onDragOver);\n document.addEventListener(\"drop\", onDrop);\n return () => {\n document.removeEventListener(\"dragover\", onDragOver);\n document.removeEventListener(\"drop\", onDrop);\n };\n }, [add, globalDrop]);\n\n // Cleanup blob URLs on unmount (local mode only)\n useEffect(() => {\n return () => {\n if (!usingProvider) {\n for (const f of files) if (f.url) URL.revokeObjectURL(f.url);\n }\n };\n }, [usingProvider, files]);\n\n const handleFileInputChange: ChangeEventHandler<HTMLInputElement> = (\n event\n ) => {\n if (event.currentTarget.files) add(event.currentTarget.files);\n };\n\n const ctx = useMemo<AttachmentsContext>(\n () => ({\n files,\n add,\n remove,\n clear,\n openFileDialog,\n fileInputRef: inputRef,\n }),\n [files, add, remove, clear, openFileDialog]\n );\n\n const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {\n event.preventDefault();\n const form = event.currentTarget;\n const text = requestCtrl\n ? requestCtrl.request.state.text\n : usingProvider\n ? controller.textInput.value\n : (() => {\n const formData = new FormData(form);\n return (formData.get(\"message\") as string) || \"\";\n })();\n\n if (!usingProvider) form.reset();\n\n const doSubmit = async () => {\n const convertedFiles = await Promise.all(\n files.map(async (item) => {\n if (item.url.startsWith(\"blob:\")) {\n return { ...item, url: await convertBlobToDataUrl(item.url) };\n }\n return item;\n })\n );\n\n try {\n await onSubmit({ text, files: convertedFiles, tags }, event);\n if (requestCtrl) {\n requestCtrl.resetRequest();\n } else {\n clear();\n if (usingProvider) controller.textInput.clear();\n }\n } catch {\n // Don't clear on error — user may want to retry\n }\n };\n\n doSubmit().catch(() => {});\n };\n\n const isBackLayerOpen = backLayerOpen ?? false;\n\n const inputShell = hasBackLayer ? (\n // LayerCard-style shell: elevated outer card with header + collapsible back\n // layer + primary layer housing the actual input.\n <div className=\"flex w-full flex-col rounded-xl bg-sf-elevated ring ring-sf-line/50\">\n {/* Header row — always visible, contains title + chevron toggle */}\n <button\n aria-expanded={isBackLayerOpen}\n aria-label={isBackLayerOpen ? \"Collapse context\" : \"Expand context\"}\n className=\"flex w-full items-center justify-between gap-2 px-3 py-2 text-left\"\n onClick={() => onBackLayerOpenChange?.(!isBackLayerOpen)}\n type=\"button\"\n >\n <span className=\"text-sm font-medium text-sf-subtle uppercase tracking-wide select-none\">\n {backLayerTitle}\n </span>\n <CaretDownIcon\n className={cn(\n \"size-3.5 text-sf-subtle transition-transform duration-200\",\n isBackLayerOpen && \"rotate-180\"\n )}\n />\n </button>\n {/* Collapsible back layer content */}\n <PromptInputBackLayerPanel open={isBackLayerOpen}>\n {backLayer}\n </PromptInputBackLayerPanel>\n {/* Primary layer — the input itself, visually raised off the back layer */}\n <div className=\"flex flex-col overflow-visible rounded-xl bg-sf-base ring ring-sf-line/50 focus-within:ring-sf-ring\">\n {children}\n </div>\n </div>\n ) : (\n <div className=\"flex w-full flex-col items-stretch overflow-visible rounded-xl border-0 bg-sf-base shadow-xs ring ring-sf-line focus-within:ring-sf-ring\">\n {children}\n </div>\n );\n\n const inner = (\n <>\n <span aria-hidden=\"true\" className=\"hidden\" ref={anchorRef} />\n <input\n accept={accept}\n aria-label=\"Upload files\"\n className=\"hidden\"\n multiple={multiple}\n onChange={handleFileInputChange}\n ref={inputRef}\n type=\"file\"\n />\n <form\n className={cn(\"w-full\", className)}\n onSubmit={handleSubmit}\n {...props}\n >\n {inputShell}\n </form>\n </>\n );\n\n return usingProvider ? (\n inner\n ) : (\n <LocalAttachmentsContext.Provider value={ctx}>\n {inner}\n </LocalAttachmentsContext.Provider>\n );\n}\n\n// ─── PromptInputBody ──────────────────────────────────────────────────────────\n\nexport type PromptInputBodyProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputBody = ({\n className,\n ...props\n}: PromptInputBodyProps) => (\n <div className={cn(\"contents\", className)} {...props} />\n);\n\n// ─── PromptInputBackLayerPanel (internal) ─────────────────────────────────────\n// Grid-rows animation: collapses to 0fr when closed, expands to 1fr when open.\n\ntype PromptInputBackLayerPanelProps = PropsWithChildren<{\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n}>;\n\nfunction PromptInputBackLayerPanel({\n open,\n children,\n}: PromptInputBackLayerPanelProps) {\n const isOpen = open ?? false;\n\n return (\n <div\n aria-hidden={!isOpen}\n className=\"grid\"\n style={{\n gridTemplateRows: isOpen ? \"1fr\" : \"0fr\",\n opacity: isOpen ? 1 : 0,\n transition: \"grid-template-rows 200ms ease-out, opacity 200ms ease-out\",\n }}\n >\n {/* min-h-0 lets the grid row collapse to 0 */}\n <div className=\"min-h-0 overflow-hidden\">{children}</div>\n </div>\n );\n}\n\n// ─── PromptInputBackLayer (public) ────────────────────────────────────────────\n\nexport type PromptInputBackLayerProps = PropsWithChildren<{\n className?: string;\n}>;\n\n/**\n * Container for back-layer content (HITL approvals, task lists, agent status,\n * etc.). Pass instances of this as the `backLayer` prop on `PromptInput`.\n *\n * @example\n * ```tsx\n * <PromptInput\n * onSubmit={handleSubmit}\n * backLayer={<PromptInputBackLayer>...</PromptInputBackLayer>}\n * backLayerOpen={open}\n * onBackLayerOpenChange={setOpen}\n * >\n * <PromptInputTextarea />\n * <PromptInputToolbar>\n * <PromptInputTools />\n * <PromptInputSubmit />\n * </PromptInputToolbar>\n * </PromptInput>\n * ```\n */\nexport function PromptInputBackLayer({\n children,\n className,\n}: PromptInputBackLayerProps) {\n return (\n <div\n className={cn(\n \"flex flex-col gap-2 px-3 py-2.5 text-sm text-sf-default\",\n className\n )}\n >\n {children}\n </div>\n );\n}\n\n// ─── Textarea helpers (module-level) ──────────────────────────────────────────\n\nconst handleTextareaKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (\n e\n) => {\n if (e.key === \"Enter\") {\n if (e.nativeEvent.isComposing) return;\n if (e.shiftKey) return;\n e.preventDefault();\n e.currentTarget.form?.requestSubmit();\n }\n};\n\n// ─── PromptInputTextarea ──────────────────────────────────────────────────────\n\nexport type PromptInputTextareaProps = ComponentProps<\"textarea\"> & {\n placeholder?: string;\n};\n\n/**\n * Auto-resizing textarea for the prompt. Submits on Enter (Shift+Enter for newline).\n * Pastes files into attachments.\n */\nexport const PromptInputTextarea = ({\n onChange,\n className,\n placeholder = \"What would you like to know?\",\n ...props\n}: PromptInputTextareaProps) => {\n const controller = useOptionalPromptInputController();\n const requestCtrl = useOptionalPromptInputRequestController();\n const requestText = useStore(\n requestCtrl?.request ?? FALLBACK_REQUEST_STORE,\n (state) => (typeof state.text === \"string\" ? state.text : \"\")\n );\n const attachments = usePromptInputAttachments();\n\n const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = (event) => {\n const items = event.clipboardData?.items;\n if (!items) return;\n const pastedFiles: File[] = [];\n for (const item of items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) pastedFiles.push(file);\n }\n }\n if (pastedFiles.length > 0) {\n event.preventDefault();\n attachments.add(pastedFiles);\n }\n };\n\n const controlledProps = requestCtrl\n ? {\n value: requestText,\n onChange: (e: ChangeEvent<HTMLTextAreaElement>) => {\n requestCtrl.setRequestField(\"text\", e.currentTarget.value);\n onChange?.(e);\n },\n }\n : controller\n ? {\n value: controller.textInput.value,\n onChange: (e: ChangeEvent<HTMLTextAreaElement>) => {\n controller.textInput.setInput(e.currentTarget.value);\n onChange?.(e);\n },\n }\n : { onChange };\n\n return (\n <textarea\n className={cn(\n \"field-sizing-content max-h-48 min-h-16 w-full resize-none border-0 bg-transparent px-3 pt-3 pb-1 text-sm text-sf-default outline-none placeholder:text-sf-inactive\",\n className\n )}\n name=\"message\"\n onKeyDown={handleTextareaKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n rows={1}\n {...props}\n {...controlledProps}\n />\n );\n};\n\n// ─── PromptInputEditor ────────────────────────────────────────────────────────\n\ntype PromptInputMentionState = {\n start: number;\n end: number;\n query: string;\n};\n\nconst getTagMention = (tag: PromptInputTagData) =>\n tag.mention ?? `@${tag.label.replace(/\\s+/g, \"-\").toLowerCase()}`;\n\nconst findMentionAtCursor = (\n text: string,\n cursor: number\n): PromptInputMentionState | null => {\n const beforeCursor = text.slice(0, cursor);\n const match = /(^|\\s)@([\\w-]*)$/.exec(beforeCursor);\n if (!match) return null;\n const token = match[0];\n const start = cursor - token.trimStart().length;\n return { start, end: cursor, query: match[2] ?? \"\" };\n};\n\nconst renderInlineReferenceText = (text: string, tags: PromptInputTagData[]) => {\n if (text.length === 0) return null;\n\n const mentions = tags\n .map((tag) => ({ tag, mention: getTagMention(tag) }))\n .filter((item) => item.mention.length > 0)\n .sort((a, b) => b.mention.length - a.mention.length);\n\n const parts: ReactNode[] = [];\n let index = 0;\n\n while (index < text.length) {\n let match: (typeof mentions)[number] | undefined;\n for (const mention of mentions) {\n if (text.startsWith(mention.mention, index)) {\n match = mention;\n break;\n }\n }\n\n if (match) {\n parts.push(\n <span\n className=\"rounded-md bg-sf-tint font-medium text-sf-strong ring-1 ring-sf-line\"\n key={`${match.tag.id}-${index}`}\n >\n {match.mention}\n </span>\n );\n index += match.mention.length;\n continue;\n }\n\n parts.push(text[index]);\n index += 1;\n }\n\n return parts;\n};\n\ntype PromptInputReferencePickerProps = {\n activeIndex: number;\n onSelect: (tag: PromptInputTagData) => void;\n options: PromptInputTagData[];\n style?: CSSProperties;\n};\n\ntype PromptInputPickerPosition = {\n left: number;\n top: number;\n};\n\nconst getTextareaCursorPosition = (\n textarea: HTMLTextAreaElement,\n wrapper: HTMLDivElement | null\n): PromptInputPickerPosition => {\n if (!wrapper) return { left: 12, top: 0 };\n\n const computed = window.getComputedStyle(textarea);\n const mirror = document.createElement(\"div\");\n const marker = document.createElement(\"span\");\n const wrapperRect = wrapper.getBoundingClientRect();\n const properties = [\n \"borderBottomWidth\",\n \"borderLeftWidth\",\n \"borderRightWidth\",\n \"borderTopWidth\",\n \"boxSizing\",\n \"fontFamily\",\n \"fontSize\",\n \"fontStyle\",\n \"fontWeight\",\n \"letterSpacing\",\n \"lineHeight\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"paddingRight\",\n \"paddingTop\",\n \"textTransform\",\n \"width\",\n \"wordSpacing\",\n ] as const;\n\n for (const property of properties) {\n mirror.style[property] = computed[property];\n }\n\n mirror.style.position = \"absolute\";\n mirror.style.visibility = \"hidden\";\n mirror.style.whiteSpace = \"pre-wrap\";\n mirror.style.overflowWrap = \"break-word\";\n mirror.textContent = textarea.value.slice(0, textarea.selectionStart);\n marker.textContent = \"\\u200B\";\n mirror.append(marker);\n document.body.append(mirror);\n\n const markerRect = marker.getBoundingClientRect();\n const top = markerRect.top - mirror.getBoundingClientRect().top + textarea.offsetTop - 6;\n const left = Math.min(\n Math.max(markerRect.left - mirror.getBoundingClientRect().left + textarea.offsetLeft, 12),\n Math.max(wrapperRect.width - 300, 12)\n );\n\n mirror.remove();\n return { left, top };\n};\n\nconst PromptInputReferencePicker = ({\n activeIndex,\n onSelect,\n options,\n style,\n}: PromptInputReferencePickerProps) => (\n <div\n className=\"absolute z-50 w-72 -translate-y-full overflow-hidden rounded-lg bg-sf-elevated p-1 shadow-lg ring ring-sf-line\"\n style={style}\n >\n <div className=\"px-2 py-1.5 text-xs font-medium text-sf-subtle\">References</div>\n <div className=\"max-h-56 overflow-y-auto\">\n {options.map((tag, index) => (\n <button\n aria-selected={index === activeIndex}\n className={cn(\n \"flex w-full items-start gap-2 rounded-md px-2 py-2 text-left text-sm text-sf-default hover:bg-sf-tint aria-selected:bg-sf-tint\",\n index === activeIndex && \"bg-sf-tint\"\n )}\n key={tag.id}\n onMouseDown={(event) => {\n event.preventDefault();\n onSelect(tag);\n }}\n role=\"option\"\n type=\"button\"\n >\n {tag.icon && <span className=\"mt-0.5 shrink-0\">{tag.icon}</span>}\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate font-medium\">{tag.label}</span>\n {tag.description && (\n <span className=\"block truncate text-xs text-sf-subtle\">\n {tag.description}\n </span>\n )}\n </span>\n <span className=\"shrink-0 text-xs text-sf-subtle\">{getTagMention(tag)}</span>\n </button>\n ))}\n </div>\n </div>\n);\n\nexport type PromptInputEditorProps = Omit<\n ComponentProps<\"textarea\">,\n \"children\"\n> & {\n onReferenceSearch?: PromptInputReferenceSearch;\n references?: PromptInputTagData[];\n};\n\nexport const PromptInputEditor = ({\n className,\n placeholder = \"What would you like to know?\",\n onReferenceSearch,\n references,\n onChange,\n onKeyDown,\n style,\n ...props\n}: PromptInputEditorProps) => {\n const controller = useOptionalPromptInputController();\n const requestCtrl = useOptionalPromptInputRequestController();\n const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const [mention, setMention] = useState<PromptInputMentionState | null>(null);\n const [options, setOptions] = useState<PromptInputTagData[]>([]);\n const [activeIndex, setActiveIndex] = useState(0);\n const [pickerPosition, setPickerPosition] = useState<PromptInputPickerPosition>({\n left: 12,\n top: 0,\n });\n\n const requestText = useStore(\n requestCtrl?.request ?? FALLBACK_REQUEST_STORE,\n (state) => (typeof state.text === \"string\" ? state.text : \"\")\n );\n const tags = useStore(\n requestCtrl?.request ?? FALLBACK_REQUEST_STORE,\n (state) => (Array.isArray(state.tags) ? (state.tags as PromptInputTagData[]) : [])\n );\n const attachments = usePromptInputAttachments();\n const value = requestCtrl ? requestText : controller?.textInput.value ?? \"\";\n\n const updateMention = useCallback((textarea: HTMLTextAreaElement) => {\n const nextMention = findMentionAtCursor(textarea.value, textarea.selectionStart);\n if (nextMention) {\n setPickerPosition(getTextareaCursorPosition(textarea, wrapperRef.current));\n }\n setMention((current) => {\n if (!(current || nextMention)) return current;\n if (\n current &&\n nextMention &&\n current.start === nextMention.start &&\n current.end === nextMention.end &&\n current.query === nextMention.query\n ) {\n return current;\n }\n return nextMention;\n });\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n if (!mention) {\n setOptions([]);\n return;\n }\n\n const load = async () => {\n const result = onReferenceSearch\n ? await onReferenceSearch({ trigger: \"@\", query: mention.query })\n : (references ?? []).filter((tag) =>\n tag.label.toLowerCase().includes(mention.query.toLowerCase())\n );\n if (!cancelled) {\n setOptions(result);\n setActiveIndex((index) => (index < result.length ? index : 0));\n }\n };\n\n load().catch(() => {\n if (!cancelled) setOptions([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [mention, onReferenceSearch, references]);\n\n const insertReference = useCallback(\n (tag: PromptInputTagData) => {\n if (!(requestCtrl && mention)) return;\n const mentionText = getTagMention(tag);\n requestCtrl.insertTag({ ...tag, mention: mentionText }, mention);\n setMention(null);\n setOptions([]);\n requestAnimationFrame(() => {\n const textarea = textareaRef.current;\n if (!textarea) return;\n const cursor = mention.start + mentionText.length + 1;\n textarea.focus();\n textarea.setSelectionRange(cursor, cursor);\n });\n },\n [mention, requestCtrl]\n );\n\n const handlePaste: ClipboardEventHandler<HTMLTextAreaElement> = (event) => {\n const items = event.clipboardData?.items;\n if (!items) return;\n const pastedFiles: File[] = [];\n for (const item of items) {\n if (item.kind === \"file\") {\n const file = item.getAsFile();\n if (file) pastedFiles.push(file);\n }\n }\n if (pastedFiles.length > 0) {\n event.preventDefault();\n attachments.add(pastedFiles);\n }\n };\n\n const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (event) => {\n if (mention && options.length > 0) {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n setActiveIndex((index) => (index + 1) % options.length);\n return;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n setActiveIndex((index) => (index - 1 + options.length) % options.length);\n return;\n }\n if (event.key === \"Enter\" || event.key === \"Tab\") {\n event.preventDefault();\n insertReference(options[activeIndex]);\n return;\n }\n if (event.key === \"Escape\") {\n event.preventDefault();\n setMention(null);\n setOptions([]);\n return;\n }\n }\n\n handleTextareaKeyDown(event);\n onKeyDown?.(event);\n };\n\n const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {\n if (requestCtrl) {\n requestCtrl.setRequestField(\"text\", event.currentTarget.value);\n } else if (controller) {\n controller.textInput.setInput(event.currentTarget.value);\n }\n updateMention(event.currentTarget);\n onChange?.(event);\n };\n\n const showPicker = mention && options.length > 0;\n\n return (\n <div className=\"relative\" ref={wrapperRef}>\n <div\n aria-hidden=\"true\"\n className={cn(\n \"pointer-events-none field-sizing-content max-h-48 min-h-16 w-full overflow-hidden whitespace-pre-wrap break-words px-3 pt-3 pb-1 text-sm text-sf-default\",\n value.length === 0 && \"text-transparent\"\n )}\n >\n {renderInlineReferenceText(value, tags)}\n </div>\n <textarea\n className={cn(\n \"absolute inset-0 field-sizing-content max-h-48 min-h-16 w-full resize-none border-0 bg-transparent px-3 pt-3 pb-1 text-sm text-transparent outline-none placeholder:text-sf-inactive\",\n className\n )}\n name=\"message\"\n onChange={handleChange}\n onClick={(event) => updateMention(event.currentTarget)}\n onKeyDown={handleKeyDown}\n onKeyUp={(event) => {\n if ([\"ArrowDown\", \"ArrowUp\", \"Enter\", \"Tab\", \"Escape\"].includes(event.key)) {\n return;\n }\n updateMention(event.currentTarget);\n }}\n onPaste={handlePaste}\n placeholder={placeholder}\n ref={textareaRef}\n rows={1}\n style={{ caretColor: \"var(--text-color-sf-default)\", ...style }}\n value={value}\n {...props}\n />\n {showPicker && (\n <PromptInputReferencePicker\n activeIndex={activeIndex}\n onSelect={insertReference}\n options={options}\n style={{ left: pickerPosition.left, top: pickerPosition.top }}\n />\n )}\n </div>\n );\n};\n\n// ─── PromptInputToolbar ───────────────────────────────────────────────────────\n\nexport type PromptInputToolbarProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputToolbar = ({\n className,\n ...props\n}: PromptInputToolbarProps) => (\n <div\n className={cn(\n \"grid grid-cols-[minmax(0,1fr)_auto] items-end gap-2 px-2.5 pt-1 pb-2\",\n className\n )}\n {...props}\n />\n);\n\n// ─── PromptInputTools ─────────────────────────────────────────────────────────\n\nexport type PromptInputToolsProps = HTMLAttributes<HTMLDivElement>;\n\nexport const PromptInputTools = ({\n className,\n ...props\n}: PromptInputToolsProps) => (\n <div\n className={cn(\"flex min-w-0 flex-wrap items-center gap-1\", className)}\n {...props}\n />\n);\n\n// ─── PromptInputButton ────────────────────────────────────────────────────────\n\nexport type PromptInputButtonProps = ComponentProps<typeof Button> & {\n \"aria-label\": string;\n};\n\nexport const PromptInputButton = ({\n variant = \"ghost\",\n size = \"sm\",\n className,\n ...props\n}: PromptInputButtonProps) => (\n <Button\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n size={size}\n type=\"button\"\n variant={variant}\n {...props}\n />\n);\n\n// ─── PromptInputSubmit ────────────────────────────────────────────────────────\n\nexport type PromptInputSubmitProps = ComponentProps<typeof Button> & {\n status?: SFAiPromptInputStatus;\n};\n\n/**\n * Submit button. Icon changes based on `status`:\n * - `idle` → send arrow\n * - `submitted` → spinner\n * - `streaming` → stop square\n * - `error` → X\n */\nexport const PromptInputSubmit = ({\n className,\n variant = \"primary\",\n size = \"sm\",\n status = \"idle\",\n children,\n ...props\n}: PromptInputSubmitProps) => {\n let Icon: ReactNode;\n if (status === \"submitted\") {\n Icon = <SpinnerGapIcon className=\"size-4 animate-spin\" />;\n } else if (status === \"streaming\") {\n Icon = <SquareIcon className=\"size-4\" />;\n } else if (status === \"error\") {\n Icon = <XIcon className=\"size-4\" />;\n } else {\n Icon = <ArrowUpIcon className=\"size-4\" />;\n }\n\n return (\n <Button\n aria-label=\"Submit\"\n className={cn(\"size-8 shrink-0 justify-center rounded-lg p-0\", className)}\n size={size}\n type=\"submit\"\n variant={variant}\n {...props}\n >\n {children ?? Icon}\n </Button>\n );\n};\n\n// ─── PromptInputActionMenu ────────────────────────────────────────────────────\n\nconst DropdownMenu = DropdownMenuPrimitive;\n\nexport type PromptInputActionMenuProps = ComponentProps<\n typeof DropdownMenu.Root\n>;\n\nexport const PromptInputActionMenu = (props: PromptInputActionMenuProps) => (\n <DropdownMenu.Root {...props} />\n);\n\nexport type PromptInputActionMenuTriggerProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n};\n\nexport const PromptInputActionMenuTrigger = ({\n className,\n children,\n \"aria-label\": ariaLabel = \"More actions\",\n ...props\n}: PromptInputActionMenuTriggerProps) => (\n <DropdownMenu.Trigger\n render={\n <Button\n aria-label={ariaLabel}\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <PlusIcon className=\"size-4\" />}\n </Button>\n }\n />\n);\n\nexport type PromptInputActionMenuContentProps = ComponentProps<\n typeof DropdownMenu.Positioner\n> & { className?: string; children?: ReactNode };\n\nexport const PromptInputActionMenuContent = ({\n className,\n children,\n ...props\n}: PromptInputActionMenuContentProps) => (\n <DropdownMenu.Positioner className=\"z-50\" side=\"top\" align=\"start\" {...props}>\n <DropdownMenu.Popup\n className={cn(\n \"min-w-[160px] rounded-lg bg-sf-elevated p-1 shadow-md\",\n \"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0 transition-opacity duration-100\",\n className\n )}\n >\n {children}\n </DropdownMenu.Popup>\n </DropdownMenu.Positioner>\n);\n\nexport type PromptInputActionMenuItemProps = ComponentProps<\n typeof DropdownMenu.Item\n>;\n\nexport const PromptInputActionMenuItem = ({\n className,\n ...props\n}: PromptInputActionMenuItemProps) => (\n <DropdownMenu.Item\n className={cn(\n \"flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm text-sf-default outline-none\",\n \"data-highlighted:bg-sf-tint\",\n className\n )}\n {...props}\n />\n);\n\n// ─── PromptInputActionAddAttachments ─────────────────────────────────────────\n\nexport type PromptInputActionAddAttachmentsProps =\n PromptInputActionMenuItemProps & {\n label?: string;\n };\n\nexport const PromptInputActionAddAttachments = ({\n label = \"Add photos or files\",\n ...props\n}: PromptInputActionAddAttachmentsProps) => {\n const attachments = usePromptInputAttachments();\n const handleSelect = useCallback(() => {\n attachments.openFileDialog();\n }, [attachments]);\n return (\n <PromptInputActionMenuItem {...props} onSelect={handleSelect}>\n <ImageIcon className=\"size-4\" />\n {label}\n </PromptInputActionMenuItem>\n );\n};\n\n// ─── PromptInputModeSelector ───────────────────────────────────────────────────\n\n/**\n * Pill-style mode selector.\n *\n * Two wiring modes:\n * 1. **Controller-driven (preferred)** — omit `value`/`onChange`; the selector\n * reads/writes `requestContext.mode` via `usePromptInputController()`.\n * 2. **Explicit props** — pass `value` + `onChange` for controlled usage\n * outside a controller (e.g. standalone demos or legacy harnesses).\n *\n * Generic over `TValue` so consumers with a known id union get narrow types.\n *\n * @example Controller-driven\n * ```tsx\n * <PromptInput onSubmit={(ctx) => send(ctx)}>\n * <PromptInputTextarea />\n * <PromptInputToolbar>\n * <PromptInputModeSelector<'build' | 'plan' | 'research'>\n * options={[\n * { value: 'build', label: 'Build' },\n * { value: 'plan', label: 'Plan' },\n * { value: 'research', label: 'Research' },\n * ]}\n * />\n * <PromptInputSubmit />\n * </PromptInputToolbar>\n * </PromptInput>\n * ```\n *\n * @example Explicit\n * ```tsx\n * <PromptInputModeSelector options={opts} value={mode} onChange={setMode} />\n * ```\n */\nexport type PromptInputModeSelectorProps<TValue extends string = string> = {\n /** Available options. Pass an empty array to hide the selector. */\n options: ModeOption<TValue>[];\n /** Controlled value. Omit to bind to `requestContext.mode` via controller. */\n value?: TValue;\n /** Controlled handler. Omit to write `requestContext.mode` via controller. */\n onChange?: (value: TValue) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n className?: string;\n};\n\nexport const PromptInputModeSelector = <TValue extends string = string>({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Select mode\",\n className,\n}: PromptInputModeSelectorProps<TValue>) => {\n const controller = useOptionalPromptInputRequestController();\n\n // Always call the store hook; default to empty store to keep hook order stable.\n const ctxMode = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { mode?: string }).mode\n ) as TValue | undefined;\n\n if (options.length === 0) return null;\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxMode;\n\n const handleSelect = (next: TValue) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"mode\", next);\n }\n };\n\n return (\n <div\n className={cn(\n \"flex items-center gap-0.5 rounded-md bg-sf-tint p-0.5\",\n className\n )}\n role=\"group\"\n aria-label={ariaLabel}\n >\n {options.map((opt) => {\n const isSelected = opt.value === value;\n return (\n <button\n key={opt.value}\n aria-pressed={isSelected}\n disabled={opt.disabled}\n className={cn(\n \"flex cursor-pointer items-center gap-1 rounded-[4px] px-2 py-0.5 text-[11px] font-medium transition-colors\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n isSelected\n ? \"bg-sf-elevated text-sf-default shadow-sm\"\n : \"text-sf-subtle hover:text-sf-default\"\n )}\n onClick={() => handleSelect(opt.value)}\n title={opt.description}\n type=\"button\"\n >\n {opt.icon}\n {opt.label}\n </button>\n );\n })}\n </div>\n );\n};\n\n// ─── PromptInputCompactSelect (shared primitive) ─────────────────────────────\n\nexport type CompactSelectOption = {\n /** Stable value identifier. */\n value: string;\n /** Display label. Falls back to `value` when omitted. */\n label?: string;\n /** Disable selection. */\n disabled?: boolean;\n};\n\nexport type PromptInputCompactSelectProps = {\n /** Available options. Pass an empty array to render nothing. */\n options: CompactSelectOption[];\n /** Controlled value. */\n value?: string;\n /** Fires when the user picks a new option. */\n onChange?: (value: string) => void;\n /** Trigger text when `value` is empty or doesn't match any option. */\n placeholder?: string;\n /** aria-label for the trigger. */\n \"aria-label\"?: string;\n /** Max width of the trigger label (with truncation). Default `160px`. */\n maxWidth?: number | string;\n className?: string;\n};\n\n/**\n * Compact Select primitive sized for the PromptInput toolbar.\n *\n * - 24px-tall trigger with `text-[11px]` label and truncating value\n * - Matching compact popup with the same text scale\n *\n * Build toolbar-specific selectors (mode, model, voice, tone, ...) by\n * wrapping this and wiring `value`/`onChange` to your state source.\n */\nexport const PromptInputCompactSelect = ({\n options,\n value,\n onChange,\n placeholder = \"Select\",\n \"aria-label\": ariaLabel = \"Select\",\n maxWidth = 160,\n className,\n}: PromptInputCompactSelectProps) => {\n if (options.length === 0) return null;\n\n const selected = options.find((o) => o.value === value);\n const triggerMaxWidth =\n typeof maxWidth === \"number\" ? `${maxWidth}px` : maxWidth;\n\n return (\n <SelectPrimitive.Root\n value={value ?? \"\"}\n onValueChange={(v) => {\n if (typeof v === \"string\") onChange?.(v);\n }}\n >\n <SelectPrimitive.Trigger\n aria-label={ariaLabel}\n style={{ maxWidth: triggerMaxWidth }}\n className={cn(\n \"flex h-6 min-w-0 shrink cursor-pointer items-center gap-1 rounded-[4px] px-2 text-[11px] leading-none font-medium text-sf-subtle transition-colors\",\n \"hover:text-sf-default focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sf-ring\",\n className\n )}\n >\n <SelectPrimitive.Value className=\"min-w-0 truncate\">\n {selected ? (selected.label ?? selected.value) : placeholder}\n </SelectPrimitive.Value>\n <SelectPrimitive.Icon className=\"flex shrink-0 items-center\">\n <CaretDownIcon className=\"size-3\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n <SelectPrimitive.Portal>\n <SelectPrimitive.Positioner sideOffset={6}>\n <SelectPrimitive.Popup\n className={cn(\n \"overflow-hidden rounded-lg bg-sf-control p-1 text-[11px] text-sf-default shadow-lg ring ring-sf-line\",\n \"min-w-[calc(var(--anchor-width)+3px)]\"\n )}\n >\n {options.map((opt) => (\n <SelectPrimitive.Item\n key={opt.value}\n value={opt.value}\n disabled={opt.disabled}\n className={cn(\n \"flex cursor-pointer items-center justify-between gap-2 rounded px-2 py-1 text-[11px] leading-tight outline-none\",\n \"data-[highlighted]:bg-sf-tint data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\"\n )}\n >\n <SelectPrimitive.ItemText>\n {opt.label ?? opt.value}\n </SelectPrimitive.ItemText>\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"size-3\" />\n </SelectPrimitive.ItemIndicator>\n </SelectPrimitive.Item>\n ))}\n </SelectPrimitive.Popup>\n </SelectPrimitive.Positioner>\n </SelectPrimitive.Portal>\n </SelectPrimitive.Root>\n );\n};\n\n// ─── PromptInputModelSelect ──────────────────────────────────────────────────\n\nexport type ModelOption = {\n /** Stable model identifier (e.g. `\"anthropic/claude-sonnet-4\"`). */\n value: string;\n /** Display label. Falls back to the last path segment of `value`. */\n label?: string;\n /** Optional group/provider label. */\n group?: string;\n /** Disable selection. */\n disabled?: boolean;\n};\n\nexport type PromptInputModelSelectProps = {\n /** Available model options. Pass an empty array to hide the selector. */\n options: ModelOption[];\n /** Controlled value. Omit to bind to `requestContext.model` via controller. */\n value?: string;\n /** Controlled handler. Omit to write `requestContext.model` via controller. */\n onChange?: (value: string) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n className?: string;\n};\n\nfunction getModelLabel(option: ModelOption): string {\n if (option.label) return option.label;\n return option.value.split(\"/\").pop() ?? option.value;\n}\n\n/**\n * Compact model selector for the PromptInput toolbar.\n *\n * - Controlled: pass `value` + `onChange`.\n * - Controller-bound: omit both and wrap in `PromptInputRequestControllerProvider`\n * — the selector reads/writes `requestContext.model` automatically.\n */\nexport const PromptInputModelSelect = ({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Select model\",\n className,\n}: PromptInputModelSelectProps) => {\n const controller = useOptionalPromptInputRequestController();\n\n const ctxModel = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { model?: string }).model\n );\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxModel;\n\n const handleChange = (next: string) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"model\", next);\n }\n };\n\n const normalized = options.map((o) => ({\n value: o.value,\n label: getModelLabel(o),\n disabled: o.disabled,\n }));\n\n return (\n <PromptInputCompactSelect\n options={normalized}\n value={value}\n onChange={handleChange}\n placeholder=\"Select model\"\n aria-label={ariaLabel}\n className={className}\n />\n );\n};\n\n// ─── PromptInputModeSelect ───────────────────────────────────────────────────\n\nexport type PromptInputModeSelectProps = {\n /** Available modes. */\n options: ModeOption[];\n /** Controlled value. Omit to bind to `requestContext.mode` via controller. */\n value?: string;\n /** Controlled handler. Omit to write `requestContext.mode` via controller. */\n onChange?: (value: string) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n className?: string;\n};\n\n/**\n * Compact mode selector for the PromptInput toolbar — matches\n * `PromptInputModelSelect` visually. For a segmented button-group look\n * (multi-mode headers, empty states), use `PromptInputModeSelector` instead.\n *\n * - Controlled: pass `value` + `onChange`.\n * - Controller-bound: omit both and wrap in `PromptInputRequestControllerProvider`\n * — the selector reads/writes `requestContext.mode` automatically.\n */\nexport const PromptInputModeSelect = ({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Select mode\",\n className,\n}: PromptInputModeSelectProps) => {\n const controller = useOptionalPromptInputRequestController();\n\n const ctxMode = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { mode?: string }).mode\n );\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxMode;\n\n const handleChange = (next: string) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"mode\", next);\n }\n };\n\n const normalized = options.map((o) => ({\n value: o.value,\n label: o.label ?? o.value,\n disabled: o.disabled,\n }));\n\n return (\n <PromptInputCompactSelect\n options={normalized}\n value={value}\n onChange={handleChange}\n placeholder=\"Select mode\"\n aria-label={ariaLabel}\n className={className}\n />\n );\n};\n\n// ─── PromptInputCompactCycle (shared primitive) ──────────────────────────────\n\nexport type PromptInputCompactCycleProps = {\n /** Available options. Cycles through them in order, wrapping at end. */\n options: CompactSelectOption[];\n /** Current value. If unset (or no match), the first option is highlighted. */\n value?: string;\n /** Fires when the user clicks (advances to next non-disabled option). */\n onChange?: (value: string) => void;\n /** aria-label for the button. */\n \"aria-label\"?: string;\n /** Show the small cycle icon next to the label. @default true */\n showIcon?: boolean;\n /** Max width of the label (truncates). @default 160px */\n maxWidth?: number | string;\n className?: string;\n};\n\n/**\n * Single compact button that cycles through `options` on click.\n *\n * - Click / Enter / Space → next option (wraps at end)\n * - Shift+Click / Shift+Enter → previous option\n * - Skips `disabled` options\n *\n * Useful for binary or 2–3 option toggles where a dropdown feels heavy.\n */\nexport const PromptInputCompactCycle = ({\n options,\n value,\n onChange,\n \"aria-label\": ariaLabel = \"Cycle option\",\n showIcon = true,\n maxWidth = 160,\n className,\n}: PromptInputCompactCycleProps) => {\n const enabledOptions = options.filter((o) => !o.disabled);\n if (enabledOptions.length === 0) return null;\n\n const currentIndex = options.findIndex((o) => o.value === value);\n const current =\n currentIndex !== -1 ? options[currentIndex] : enabledOptions[0];\n\n const advance = (direction: 1 | -1) => {\n // Find the next/prev non-disabled option, wrapping around.\n const start = currentIndex !== -1 ? currentIndex : -direction;\n const len = options.length;\n for (let step = 1; step <= len; step++) {\n const i = (start + direction * step + len * len) % len;\n const candidate = options[i];\n if (candidate && !candidate.disabled) {\n onChange?.(candidate.value);\n return;\n }\n }\n };\n\n const triggerMaxWidth =\n typeof maxWidth === \"number\" ? `${maxWidth}px` : maxWidth;\n\n return (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n title={`${current?.label ?? current?.value ?? \"\"} — click to cycle`}\n style={{ maxWidth: triggerMaxWidth }}\n onClick={(e) => advance(e.shiftKey ? -1 : 1)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n advance(e.shiftKey ? -1 : 1);\n }\n }}\n className={cn(\n \"flex h-6 min-w-0 shrink cursor-pointer items-center gap-1 rounded-[4px] px-2 text-[11px] leading-none font-medium text-sf-subtle transition-colors\",\n \"hover:text-sf-default focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sf-ring\",\n className\n )}\n >\n <span className=\"min-w-0 truncate\">\n {current?.label ?? current?.value ?? \"\"}\n </span>\n {showIcon && (\n <ArrowsClockwiseIcon className=\"size-3 shrink-0 opacity-70\" />\n )}\n </button>\n );\n};\n\n// ─── PromptInputModeCycle ────────────────────────────────────────────────────\n\nexport type PromptInputModeCycleProps = {\n /** Available modes to cycle through. */\n options: ModeOption[];\n /** Controlled value. Omit to bind to `requestContext.mode` via controller. */\n value?: string;\n /** Controlled handler. Omit to write `requestContext.mode` via controller. */\n onChange?: (value: string) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n /** Show the small cycle icon next to the label. @default true */\n showIcon?: boolean;\n className?: string;\n};\n\n/**\n * Click-to-cycle mode picker. Single compact button that advances through\n * `options` on each click. Best for 2–3 modes.\n *\n * - Controlled: pass `value` + `onChange`.\n * - Controller-bound: omit both and wrap in `PromptInputRequestControllerProvider`\n * — reads/writes `requestContext.mode` automatically.\n */\nexport const PromptInputModeCycle = ({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Cycle mode\",\n showIcon = true,\n className,\n}: PromptInputModeCycleProps) => {\n const controller = useOptionalPromptInputRequestController();\n\n const ctxMode = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { mode?: string }).mode\n );\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxMode;\n\n const handleChange = (next: string) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"mode\", next);\n }\n };\n\n const normalized = options.map((o) => ({\n value: o.value,\n label: o.label ?? o.value,\n disabled: o.disabled,\n }));\n\n return (\n <PromptInputCompactCycle\n options={normalized}\n value={value}\n onChange={handleChange}\n aria-label={ariaLabel}\n showIcon={showIcon}\n className={className}\n />\n );\n};\n\n// ─── PromptInputModelCycle ───────────────────────────────────────────────────\n\nexport type PromptInputModelCycleProps = {\n /** Available models to cycle through. */\n options: ModelOption[];\n /** Controlled value. Omit to bind to `requestContext.model` via controller. */\n value?: string;\n /** Controlled handler. Omit to write `requestContext.model` via controller. */\n onChange?: (value: string) => void;\n /** Optional aria-label override. */\n \"aria-label\"?: string;\n /** Show the small cycle icon next to the label. @default true */\n showIcon?: boolean;\n className?: string;\n};\n\n/**\n * Click-to-cycle model picker. Single compact button that advances through\n * `options` on each click. Best for 2–3 models.\n *\n * - Controlled: pass `value` + `onChange`.\n * - Controller-bound: omit both and wrap in `PromptInputRequestControllerProvider`\n * — reads/writes `requestContext.model` automatically.\n */\nexport const PromptInputModelCycle = ({\n options,\n value: valueProp,\n onChange: onChangeProp,\n \"aria-label\": ariaLabel = \"Cycle model\",\n showIcon = true,\n className,\n}: PromptInputModelCycleProps) => {\n const controller = useOptionalPromptInputRequestController();\n\n const ctxModel = useStore(\n controller?.request ?? FALLBACK_REQUEST_STORE,\n (s) => (s as { model?: string }).model\n );\n\n const isControlled = valueProp !== undefined || onChangeProp !== undefined;\n const value = isControlled ? valueProp : ctxModel;\n\n const handleChange = (next: string) => {\n if (onChangeProp) {\n onChangeProp(next);\n return;\n }\n if (!isControlled && controller) {\n controller.setRequestField(\"model\", next);\n }\n };\n\n const normalized = options.map((o) => ({\n value: o.value,\n label: getModelLabel(o),\n disabled: o.disabled,\n }));\n\n return (\n <PromptInputCompactCycle\n options={normalized}\n value={value}\n onChange={handleChange}\n aria-label={ariaLabel}\n showIcon={showIcon}\n className={className}\n />\n );\n};\n\n// ─── Attachment display helpers ───────────────────────────────────────────────\n\nconst IMAGE_EXTS = new Set([\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\", \"svg\"]);\n\nfunction getFileIcon(filename: string): ReactNode {\n const ext = filename.split(\".\").pop()?.toLowerCase() ?? \"\";\n if (IMAGE_EXTS.has(ext)) return <ImageIcon className=\"size-3.5\" />;\n if ([\"pdf\", \"doc\", \"docx\", \"txt\", \"md\"].includes(ext))\n return <FileTextIcon className=\"size-3.5\" />;\n return <FileIcon className=\"size-3.5\" />;\n}\n\n// ─── PromptInputAttachment ────────────────────────────────────────────────────\n\nexport type PromptInputAttachmentProps = HTMLAttributes<HTMLDivElement> & {\n data: AttachmentFile;\n};\n\n/**\n * Single attachment chip for images or files. Includes a remove button.\n */\nexport function PromptInputAttachment({\n data,\n className,\n ...props\n}: PromptInputAttachmentProps) {\n const attachments = usePromptInputAttachments();\n const isImage = data.mediaType?.startsWith(\"image/\") && data.url;\n\n const handleRemove = useCallback(() => {\n attachments.remove(data.id);\n }, [attachments, data.id]);\n\n if (isImage) {\n return (\n <div\n className={cn(\n \"group relative size-14 overflow-hidden rounded-md\",\n className\n )}\n {...props}\n >\n <img\n alt={data.filename || \"attachment\"}\n className=\"size-full object-cover\"\n src={data.url}\n />\n <Button\n aria-label=\"Remove attachment\"\n className=\"absolute top-1 right-1 size-5 rounded-full bg-sf-overlay/80 p-0 opacity-0 backdrop-blur-sm transition-opacity group-hover:opacity-100\"\n onClick={handleRemove}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <XIcon className=\"size-3\" />\n </Button>\n </div>\n );\n }\n\n const ext = data.filename.split(\".\").pop()?.toUpperCase() ?? \"FILE\";\n const name = data.filename.replace(/\\.[^/.]+$/, \"\");\n\n return (\n <div\n className={cn(\n \"group relative inline-flex h-8 items-center gap-2 rounded-md bg-sf-tint/50 px-2 text-sm\",\n className\n )}\n {...props}\n >\n <div className=\"flex size-5 shrink-0 items-center justify-center text-sf-subtle\">\n {getFileIcon(data.filename)}\n </div>\n <Tooltip content={data.filename}>\n <span className=\"max-w-[160px] truncate font-medium text-sf-default\">\n {name || \"File\"}\n </span>\n </Tooltip>\n <span className=\"rounded bg-sf-tint px-1 py-0.5 font-semibold text-sf-subtle text-[10px] uppercase\">\n {ext}\n </span>\n <Button\n aria-label=\"Remove attachment\"\n className=\"ml-0.5 size-4 shrink-0 rounded-full p-0 opacity-0 transition-opacity group-hover:opacity-100\"\n onClick={handleRemove}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <XIcon className=\"size-3\" />\n </Button>\n </div>\n );\n}\n\n// ─── PromptInputAttachments ───────────────────────────────────────────────────\n\nexport type PromptInputAttachmentsProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> & {\n children: (attachment: AttachmentFile) => ReactNode;\n};\n\n/**\n * Renders all attachments using a render prop. Hidden when no files.\n * Animates height as files are added/removed.\n */\nexport function PromptInputAttachments({\n className,\n children,\n ...props\n}: PromptInputAttachmentsProps) {\n const attachments = usePromptInputAttachments();\n const [height, setHeight] = useState(0);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (!el) return;\n const ro = new ResizeObserver(() => {\n setHeight(el.getBoundingClientRect().height);\n });\n ro.observe(el);\n setHeight(el.getBoundingClientRect().height);\n return () => ro.disconnect();\n }, []);\n\n // Re-measure when file count changes\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional re-measure on count change\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (el) setHeight(el.getBoundingClientRect().height);\n }, [attachments.files.length]);\n\n if (attachments.files.length === 0) return null;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"overflow-hidden px-2.5 transition-[height] duration-200 ease-out\",\n className\n )}\n style={{ height: attachments.files.length ? height : 0 }}\n {...props}\n >\n <div className=\"flex flex-wrap gap-2 pt-2 pb-1\" ref={contentRef}>\n {attachments.files.map((file) => (\n <Fragment key={file.id}>{children(file)}</Fragment>\n ))}\n </div>\n </div>\n );\n}\n\n// ─── PromptInputTags ──────────────────────────────────────────────────────────\n\nexport type PromptInputTagProps = HTMLAttributes<HTMLDivElement> & {\n data: PromptInputTagData;\n};\n\n/**\n * Single reference chip for prompt tags. Includes a remove button when mounted\n * inside a PromptInputRequestControllerProvider.\n */\nexport function PromptInputTag({\n data,\n className,\n ...props\n}: PromptInputTagProps) {\n const requestCtrl = useOptionalPromptInputRequestController();\n\n const handleRemove = useCallback(() => {\n requestCtrl?.removeTag(data.id);\n }, [requestCtrl, data.id]);\n\n const chip = (\n <div\n className={cn(\n \"group inline-flex h-8 items-center gap-2 rounded-md border border-sf-info/30 bg-sf-info-tint px-2 text-sm text-sf-default\",\n className\n )}\n {...props}\n >\n {data.icon && (\n <div className=\"flex size-4 shrink-0 items-center justify-center\">\n {data.icon}\n </div>\n )}\n <span className=\"max-w-[180px] truncate font-medium\">{data.label}</span>\n {requestCtrl && (\n <Button\n aria-label=\"Remove tag\"\n className=\"ml-0.5 size-4 shrink-0 rounded-full p-0 opacity-0 transition-opacity group-hover:opacity-100\"\n onClick={handleRemove}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n >\n <XIcon className=\"size-3\" />\n </Button>\n )}\n </div>\n );\n\n if (!data.description) return chip;\n return <Tooltip content={data.description}>{chip}</Tooltip>;\n}\n\nexport type PromptInputTagsProps = Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> & {\n children: (tag: PromptInputTagData) => ReactNode;\n};\n\n/**\n * Renders all prompt tags using a render prop. Hidden when no tags.\n * Animates height as tags are added/removed.\n */\nexport function PromptInputTags({\n className,\n children,\n ...props\n}: PromptInputTagsProps) {\n const requestCtrl = useOptionalPromptInputRequestController();\n const tags = useStore(requestCtrl?.request ?? FALLBACK_REQUEST_STORE, (state) =>\n ((state as { tags?: PromptInputTagData[] }).tags ?? [])\n );\n const [height, setHeight] = useState(0);\n const contentRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (!el) return;\n const ro = new ResizeObserver(() => {\n setHeight(el.getBoundingClientRect().height);\n });\n ro.observe(el);\n setHeight(el.getBoundingClientRect().height);\n return () => ro.disconnect();\n }, []);\n\n // Re-measure when tag count changes\n // biome-ignore lint/correctness/useExhaustiveDependencies: intentional re-measure on count change\n useLayoutEffect(() => {\n const el = contentRef.current;\n if (el) setHeight(el.getBoundingClientRect().height);\n }, [tags.length]);\n\n if (tags.length === 0) return null;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"overflow-hidden px-2.5 transition-[height] duration-200 ease-out\",\n className\n )}\n style={{ height: tags.length ? height : 0 }}\n {...props}\n >\n <div className=\"flex flex-wrap gap-2 pt-2 pb-1\" ref={contentRef}>\n {tags.map((tag) => (\n <Fragment key={tag.id}>{children(tag)}</Fragment>\n ))}\n </div>\n </div>\n );\n}\n\nexport type PromptInputAddTagButtonProps = ComponentProps<typeof Button> & {\n onOpenPicker?: () => void;\n};\n\n/**\n * Toolbar trigger for opening a consumer-owned tag picker.\n */\nexport function PromptInputAddTagButton({\n children,\n onClick,\n onOpenPicker,\n ...props\n}: PromptInputAddTagButtonProps) {\n return (\n <Button\n aria-label=\"Add tag\"\n onClick={(event) => {\n onOpenPicker?.();\n onClick?.(event);\n }}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n {children ?? <PlusIcon className=\"size-4\" />}\n </Button>\n );\n}\n\n// ─── Speech recognition types ─────────────────────────────────────────────────\n\ntype SpeechRecognitionInstance = EventTarget & {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n start(): void;\n stop(): void;\n};\n\ntype SpeechRecognitionResultEvent = Event & {\n results: {\n readonly length: number;\n item(index: number): {\n isFinal: boolean;\n [i: number]: { transcript: string };\n };\n [index: number]: { isFinal: boolean; [i: number]: { transcript: string } };\n };\n};\n\ntype SpeechRecognitionConstructor = new () => SpeechRecognitionInstance;\n\ndeclare global {\n interface Window {\n SpeechRecognition?: SpeechRecognitionConstructor;\n webkitSpeechRecognition?: SpeechRecognitionConstructor;\n }\n}\n\n// ─── PromptInputSpeechButton ──────────────────────────────────────────────────\n\nexport type PromptInputSpeechButtonProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n textareaRef?: RefObject<HTMLTextAreaElement | null>;\n onTranscriptionChange?: (text: string) => void;\n};\n\n/**\n * Voice input button. Uses the Web Speech API (Chrome/Edge). Hidden on unsupported browsers.\n * Pulses while listening.\n */\nexport const PromptInputSpeechButton = ({\n className,\n textareaRef,\n onTranscriptionChange,\n \"aria-label\": ariaLabel = \"Voice input\",\n ...props\n}: PromptInputSpeechButtonProps) => {\n const [isListening, setIsListening] = useState(false);\n const [recognition, setRecognition] =\n useState<SpeechRecognitionInstance | null>(null);\n const recognitionRef = useRef<SpeechRecognitionInstance | null>(null);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const SR = window.SpeechRecognition ?? window.webkitSpeechRecognition;\n if (!SR) return;\n\n const sr = new SR() as SpeechRecognitionInstance & {\n continuous: boolean;\n interimResults: boolean;\n lang: string;\n };\n sr.continuous = true;\n sr.interimResults = true;\n sr.lang = \"en-US\";\n\n const handleStart = () => setIsListening(true);\n const handleEnd = () => setIsListening(false);\n const handleResult = (event: Event) => {\n const e = event as SpeechRecognitionResultEvent;\n let final = \"\";\n for (const result of Array.from(\n { length: e.results.length },\n (_, i) => e.results[i]\n )) {\n if (result?.isFinal && result[0]?.transcript) {\n final += result[0].transcript;\n }\n }\n if (final && textareaRef?.current) {\n const ta = textareaRef.current;\n const next = ta.value + (ta.value ? \" \" : \"\") + final;\n ta.value = next;\n ta.dispatchEvent(new Event(\"input\", { bubbles: true }));\n onTranscriptionChange?.(next);\n }\n };\n const handleError = (_event: Event) => setIsListening(false);\n\n sr.addEventListener(\"start\", handleStart);\n sr.addEventListener(\"end\", handleEnd);\n sr.addEventListener(\"result\", handleResult);\n sr.addEventListener(\"error\", handleError);\n\n recognitionRef.current = sr;\n setRecognition(sr);\n\n return () => {\n sr.removeEventListener(\"start\", handleStart);\n sr.removeEventListener(\"end\", handleEnd);\n sr.removeEventListener(\"result\", handleResult);\n sr.removeEventListener(\"error\", handleError);\n recognitionRef.current?.stop();\n };\n }, [textareaRef, onTranscriptionChange]);\n\n const handleToggleListening = useCallback(() => {\n if (!recognition) return;\n const sr = recognition as SpeechRecognitionInstance & {\n start(): void;\n stop(): void;\n };\n if (isListening) sr.stop();\n else sr.start();\n }, [recognition, isListening]);\n\n const button = (\n <Button\n aria-label={ariaLabel}\n className={cn(\n \"text-sf-subtle hover:text-sf-default transition-all\",\n isListening && \"animate-pulse text-sf-brand\",\n className\n )}\n disabled={!recognition}\n onClick={handleToggleListening}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n <MicrophoneIcon className=\"size-4\" />\n </Button>\n );\n\n if (!recognition) return null;\n\n return (\n <Tooltip content={isListening ? \"Stop listening\" : \"Voice input\"}>\n {button}\n </Tooltip>\n );\n};\n\n// ─── PromptInputAttachButton ──────────────────────────────────────────────────\n\nexport type PromptInputAttachButtonProps = Omit<\n PromptInputButtonProps,\n \"aria-label\"\n> & {\n \"aria-label\"?: string;\n};\n\n/**\n * Convenience button that opens the file dialog directly (no dropdown needed).\n */\nexport const PromptInputAttachButton = ({\n \"aria-label\": ariaLabel = \"Attach file\",\n className,\n ...props\n}: PromptInputAttachButtonProps) => {\n const attachments = usePromptInputAttachments();\n const handleClick = useCallback(() => {\n attachments.openFileDialog();\n }, [attachments]);\n return (\n <Tooltip content={ariaLabel}>\n <Button\n aria-label={ariaLabel}\n className={cn(\"text-sf-subtle hover:text-sf-default\", className)}\n onClick={handleClick}\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n {...props}\n >\n <PaperclipIcon className=\"size-4\" />\n </Button>\n </Tooltip>\n );\n};\n\nPromptInput.BackLayer = PromptInputBackLayer;\nPromptInput.Textarea = PromptInputTextarea;\nPromptInput.Editor = PromptInputEditor;\nPromptInput.Toolbar = PromptInputToolbar;\nPromptInput.Tools = PromptInputTools;\nPromptInput.Submit = PromptInputSubmit;\nPromptInput.ModeSelector = PromptInputModeSelector;\nPromptInput.AddTagButton = PromptInputAddTagButton;\nPromptInput.Tags = PromptInputTags;\nPromptInput.Tag = PromptInputTag;\nPromptInput.AttachButton = PromptInputAttachButton;\nPromptInput.Attachments = PromptInputAttachments;\nPromptInput.Attachment = PromptInputAttachment;\n"],"x_google_ignoreList":[0,1,2,3,4],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-reasoning-CnL6ZSr5.js","names":[],"sources":["../src/components/ai-reasoning/ai-reasoning.tsx"],"sourcesContent":["\"use client\";\n\nimport { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\";\nimport {\n BrainIcon,\n CaretDownIcon,\n CaretRightIcon,\n SparkleIcon,\n SpinnerGapIcon,\n CheckIcon,\n} from \"@phosphor-icons/react\";\nimport type { ComponentProps, ElementType } from \"react\";\nimport {\n memo,\n Suspense,\n lazy,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\n\nimport { cn } from \"../../utils/cn\";\nimport { AiStatusBadge } from \"../ai-status-badge\";\n\n// Lazy-load Streamdown for markdown rendering in reasoning content.\n// Mirrors the pattern from ai-response.tsx for SSR safety.\ntype StreamdownModule = {\n default: (props: { children: string; className?: string }) => React.ReactNode;\n};\n\nconst Streamdown = lazy((): Promise<StreamdownModule> => {\n if (typeof window === \"undefined\") {\n return Promise.resolve({\n default: ({ children }: { children: string }) => <span>{children}</span>,\n });\n }\n return import(\"streamdown\").then((sd) => ({\n default: (props: { children: string; className?: string }) => (\n <sd.Streamdown {...props} />\n ),\n }));\n});\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_REASONING_VARIANTS = {\n variant: {\n default: {\n classes: \"\",\n description:\n \"Expandable card with collapsible reasoning text and duration\",\n },\n inline: {\n classes: \"\",\n description: \"Compact single-line display with left accent border\",\n },\n minimal: {\n classes: \"\",\n description: \"Pill-shaped status badge\",\n },\n ephemeral: {\n classes: \"\",\n description:\n \"Single-status row that auto-dismisses after streaming ends. Persists when the user expands it.\",\n },\n },\n} as const;\n\nexport const SF_AI_REASONING_DEFAULT_VARIANTS = {\n variant: \"default\",\n} as const;\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Display variant for reasoning rendering. */\nexport type AiReasoningVariant = keyof typeof SF_AI_REASONING_VARIANTS.variant;\n\n/**\n * Structured reasoning part — mirrors the shape of Vercel AI SDK's\n * `ReasoningUIPart` without requiring the `ai` package as a dependency.\n */\nexport interface AiReasoningPart {\n /** The reasoning text content. */\n text: string;\n}\n\nexport type AiReasoningProps = Omit<ComponentProps<\"div\">, \"part\"> & {\n /** Structured reasoning part data. */\n part: AiReasoningPart;\n /** Display variant. @default \"default\" */\n variant?: AiReasoningVariant;\n /** Whether reasoning is currently streaming. */\n isStreaming?: boolean;\n /** Duration in seconds (passed in or self-tracked when streaming). */\n duration?: number;\n /** Default expanded state. @default false */\n defaultExpanded?: boolean;\n /** Controlled open state. */\n open?: boolean;\n /** Called when open state changes. */\n onOpenChange?: (open: boolean) => void;\n /** Delay in ms before auto-closing after streaming ends. Set to 0 to disable. @default 1000 */\n autoCloseDelay?: number;\n /**\n * Custom icon override. Defaults to `SparkleIcon` (streaming) or `BrainIcon` (done).\n * Use to distinguish observation/reflection blocks from standard reasoning.\n */\n icon?: ElementType;\n /**\n * Custom label override. Defaults to `\"Thinking...\"` (streaming) or `\"Reasoning\"` (done).\n * Use to label observational memory blocks: `\"Observing...\"`, `\"Reflecting...\"`, etc.\n */\n label?: string;\n /**\n * Custom streaming label. When provided, used instead of `label` while `isStreaming` is true.\n * Falls back to `label`, then to the default `\"Thinking...\"`.\n */\n streamingLabel?: string;\n /**\n * For `variant=\"ephemeral\"`: ms to keep the completed row visible before\n * fading out. Set to `0` to disable auto-dismiss. @default 800\n */\n dismissDelay?: number;\n /**\n * For `variant=\"ephemeral\"`: when `true`, the row never auto-dismisses.\n * User-expanded rows are pinned automatically.\n */\n persist?: boolean;\n /** Called once the ephemeral row has finished its dismiss animation. */\n onDismiss?: () => void;\n};\n\nexport type AiReasoningGroupProps = Omit<ComponentProps<\"div\">, \"part\"> & {\n /** Array of reasoning parts. */\n parts: AiReasoningPart[];\n /** Whether the last part is currently streaming. */\n isStreaming?: boolean;\n /** Total duration in seconds. */\n totalDuration?: number;\n /** Default expanded state. @default false */\n defaultExpanded?: boolean;\n};\n\n// ─── Utilities ───────────────────────────────────────────────────────────────\n\n/** Format seconds into a human-friendly duration string. */\nexport function formatDuration(seconds: number): string {\n if (seconds < 60) return `${seconds}s`;\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return secs > 0 ? `${mins}m ${secs}s` : `${mins}m`;\n}\n\n/** Truncate reasoning text with an ellipsis. */\nexport function truncateReasoning(text: string, maxLength = 100): string {\n if (text.length <= maxLength) return text;\n return `${text.slice(0, maxLength).trim()}...`;\n}\n\n/** Extract the first **bold** text from markdown-style reasoning. */\nexport function extractFirstBoldText(text: string): string | null {\n const match = /\\*\\*([^*]+)\\*\\*/.exec(text);\n return match?.[1]?.trim() ?? null;\n}\n\n// ─── AiReasoning ─────────────────────────────────────────────────────────────\n\n/**\n * Collapsible reasoning block. Supports three display variants:\n * - `\"default\"` — expandable card with auto-open on stream start\n * - `\"inline\"` — compact single-line with left accent border\n * - `\"minimal\"` — pill-shaped status badge\n *\n * @example\n * ```tsx\n * <AiReasoning\n * part={{ text: \"First I considered the user's intent...\" }}\n * isStreaming={false}\n * duration={3}\n * />\n * ```\n */\nexport const AiReasoning = memo(\n ({\n part,\n variant = \"default\",\n isStreaming = false,\n duration: durationProp,\n defaultExpanded = false,\n open: openProp,\n onOpenChange,\n autoCloseDelay = 1000,\n icon: iconProp,\n label: labelProp,\n streamingLabel: streamingLabelProp,\n dismissDelay = 800,\n persist = false,\n onDismiss,\n className,\n ...props\n }: AiReasoningProps) => {\n const [internalOpen, setInternalOpen] = useState(defaultExpanded);\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const [userOpened, setUserOpened] = useState(false);\n const [internalDuration, setInternalDuration] = useState(0);\n const startTimeRef = useRef<number | null>(null);\n\n const isControlled = openProp !== undefined;\n const isOpen = isControlled ? openProp : internalOpen;\n\n const rawSetIsOpen = isControlled ? onOpenChange : setInternalOpen;\n const setIsOpen = useCallback(\n (value: boolean) => {\n rawSetIsOpen?.(value);\n },\n [rawSetIsOpen]\n );\n\n const handleUserToggle = useCallback(\n (value: boolean) => {\n if (value) setUserOpened(true);\n setIsOpen(value);\n },\n [setIsOpen]\n );\n\n const displayDuration = durationProp ?? internalDuration;\n const reasoningText = part.text || \"\";\n\n // Resolve custom icon/label (with defaults)\n // When not streaming, try to extract a dynamic title from first **bold** text\n const extractedBoldTitle = !isStreaming\n ? extractFirstBoldText(reasoningText)\n : null;\n const dynamicLabel = extractedBoldTitle\n ? truncateReasoning(extractedBoldTitle, 40)\n : null;\n const displayLabel = isStreaming\n ? (streamingLabelProp ?? labelProp ?? \"Thinking...\")\n : (labelProp ?? dynamicLabel ?? \"Reasoning\");\n const ActiveIcon = iconProp ?? (isStreaming ? SparkleIcon : BrainIcon);\n const StreamIcon = iconProp ?? SparkleIcon;\n const DoneIcon = iconProp ?? BrainIcon;\n\n // Track duration while streaming\n useEffect(() => {\n if (isStreaming) {\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n const interval = setInterval(() => {\n if (startTimeRef.current) {\n setInternalDuration(\n Math.round((Date.now() - startTimeRef.current) / 1000)\n );\n }\n }, 1000);\n return () => clearInterval(interval);\n }\n if (startTimeRef.current !== null) {\n setInternalDuration(\n Math.round((Date.now() - startTimeRef.current) / 1000)\n );\n startTimeRef.current = null;\n }\n }, [isStreaming]);\n\n // Auto-open on stream start, auto-close when done (unless user opened)\n useEffect(() => {\n if (isStreaming && !isOpen) {\n setUserOpened(false);\n setIsOpen(true);\n return;\n }\n if (\n !isStreaming &&\n isOpen &&\n !defaultExpanded &&\n !hasAutoClosed &&\n !userOpened &&\n autoCloseDelay > 0\n ) {\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, autoCloseDelay);\n return () => clearTimeout(timer);\n }\n }, [\n isStreaming,\n isOpen,\n defaultExpanded,\n hasAutoClosed,\n userOpened,\n autoCloseDelay,\n setIsOpen,\n ]);\n\n // ── Ephemeral ────────────────────────────────────────────────────────────\n // Single-status row that auto-dismisses after streaming ends. Pins on\n // user expand or when `persist` is set.\n\n const [ephemeralPhase, setEphemeralPhase] = useState<\n \"live\" | \"fading\" | \"gone\"\n >(\"live\");\n const ephemeralUserExpandedRef = useRef(false);\n\n useEffect(() => {\n if (variant !== \"ephemeral\") return;\n if (ephemeralPhase !== \"live\") return;\n if (isStreaming) return;\n if (persist || ephemeralUserExpandedRef.current) return;\n if (dismissDelay <= 0) return;\n\n const settleTimer = setTimeout(() => {\n setEphemeralPhase(\"fading\");\n }, dismissDelay);\n return () => clearTimeout(settleTimer);\n }, [variant, ephemeralPhase, isStreaming, persist, dismissDelay]);\n\n useEffect(() => {\n if (variant !== \"ephemeral\") return;\n if (ephemeralPhase !== \"fading\") return;\n const fadeTimer = setTimeout(() => {\n setEphemeralPhase(\"gone\");\n onDismiss?.();\n }, 200);\n return () => clearTimeout(fadeTimer);\n }, [variant, ephemeralPhase, onDismiss]);\n\n if (variant === \"ephemeral\") {\n if (ephemeralPhase === \"gone\") return null;\n\n const handleEphemeralToggle = (next: boolean) => {\n if (next) ephemeralUserExpandedRef.current = true;\n setIsOpen(next);\n };\n\n return (\n <BaseCollapsible.Root\n open={isOpen}\n onOpenChange={handleEphemeralToggle}\n >\n <div\n className={cn(\n \"my-0.5 flex w-full max-w-sm flex-col overflow-hidden\",\n \"transition-[opacity,max-height,margin] duration-200 ease-out\",\n ephemeralPhase === \"live\"\n ? \"max-h-40 opacity-100\"\n : \"pointer-events-none my-0 max-h-0 opacity-0\",\n ephemeralPhase === \"live\" && \"animate-in fade-in-0 duration-150\",\n className\n )}\n data-phase={ephemeralPhase}\n {...props}\n >\n <BaseCollapsible.Trigger\n render={\n <button\n type=\"button\"\n className=\"flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint\"\n />\n }\n >\n {isStreaming ? (\n <SpinnerGapIcon className=\"size-3.5 shrink-0 animate-spin text-sf-subtle\" />\n ) : (\n <CheckIcon className=\"size-3.5 shrink-0 text-sf-success\" />\n )}\n <span className=\"min-w-0 truncate text-sm text-sf-subtle\">\n {displayLabel}\n </span>\n {displayDuration > 0 && !isStreaming ? (\n <span className=\"text-xs tabular-nums text-sf-subtle/60\">\n {formatDuration(displayDuration)}\n </span>\n ) : null}\n <CaretDownIcon\n className={cn(\n \"size-3 shrink-0 text-sf-subtle/60 transition-transform duration-200\",\n !isOpen && \"-rotate-90\"\n )}\n />\n </BaseCollapsible.Trigger>\n\n <BaseCollapsible.Panel className=\"overflow-hidden\">\n <div className=\"mt-1 rounded-lg bg-sf-tint/50 px-3 py-2\">\n <Suspense>\n <Streamdown className=\"text-sf-subtle text-sm [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\">\n {reasoningText || \"*No reasoning content*\"}\n </Streamdown>\n </Suspense>\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n }\n\n // ── Minimal ──────────────────────────────────────────────────────────────\n\n if (variant === \"minimal\") {\n return (\n <BaseCollapsible.Root open={isOpen} onOpenChange={handleUserToggle}>\n <div className={cn(\"my-1.5\", className)} {...props}>\n <BaseCollapsible.Trigger\n render={<button type=\"button\" className=\"cursor-pointer\" />}\n >\n <AiStatusBadge\n className=\"py-1\"\n icon={DoneIcon}\n label={displayLabel}\n status={isStreaming ? \"running\" : \"success\"}\n />\n </BaseCollapsible.Trigger>\n <BaseCollapsible.Panel className=\"overflow-hidden\">\n <div className=\"mx-2 mt-1 rounded-lg bg-sf-tint/50 px-3 py-2\">\n <Suspense>\n <Streamdown className=\"text-sf-subtle text-sm [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\">\n {reasoningText}\n </Streamdown>\n </Suspense>\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n }\n\n // ── Inline ───────────────────────────────────────────────────────────────\n\n if (variant === \"inline\") {\n return (\n <div\n className={cn(\n \"my-1.5 flex items-center gap-2 border-l-2 border-sf-line py-1 pl-2\",\n \"animate-in fade-in-0 slide-in-from-bottom-1 duration-200\",\n className\n )}\n {...props}\n >\n <ActiveIcon className=\"size-3.5 shrink-0 text-sf-subtle\" />\n <span className=\"text-sm text-sf-subtle\">{displayLabel}</span>\n {isStreaming ? (\n <SpinnerGapIcon className=\"size-3.5 animate-spin text-sf-subtle\" />\n ) : null}\n {!isStreaming && reasoningText ? (\n <span className=\"max-w-[300px] truncate text-xs text-sf-subtle/60\">\n — {truncateReasoning(reasoningText)}\n </span>\n ) : null}\n </div>\n );\n }\n\n // ── Default (compact expandable row) ─────────────────────────────────────\n\n return (\n <BaseCollapsible.Root open={isOpen} onOpenChange={handleUserToggle}>\n <div\n className={cn(\n \"my-0.5 flex w-full flex-col\",\n \"animate-in fade-in-0 duration-150\",\n className\n )}\n {...props}\n >\n {/* Trigger — content-width, left-justified */}\n <BaseCollapsible.Trigger\n render={\n <button\n type=\"button\"\n className=\"flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint\"\n />\n }\n >\n {isStreaming ? (\n <StreamIcon className=\"size-3.5 shrink-0 animate-pulse text-sf-subtle\" />\n ) : (\n <DoneIcon className=\"size-3.5 shrink-0 text-sf-subtle\" />\n )}\n <span className=\"text-sm text-sf-subtle\">{displayLabel}</span>\n {isStreaming ? (\n <SpinnerGapIcon className=\"size-3 shrink-0 animate-spin text-sf-subtle\" />\n ) : null}\n {displayDuration > 0 && !isStreaming ? (\n <span className=\"text-xs tabular-nums text-sf-subtle/60\">\n {formatDuration(displayDuration)}\n </span>\n ) : null}\n {isOpen ? (\n <CaretDownIcon className=\"size-3 shrink-0 text-sf-subtle/60\" />\n ) : (\n <CaretRightIcon className=\"size-3 shrink-0 text-sf-subtle/60\" />\n )}\n </BaseCollapsible.Trigger>\n\n {/* Detail panel */}\n <BaseCollapsible.Panel className=\"overflow-hidden\">\n <div className=\"mt-1 rounded-lg bg-sf-tint/50 px-3 py-2\">\n <Suspense>\n <Streamdown className=\"text-sf-subtle text-sm [&>*:first-child]:mt-0 [&>*:last-child]:mb-0\">\n {reasoningText || \"*No reasoning content*\"}\n </Streamdown>\n </Suspense>\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n }\n);\n\nAiReasoning.displayName = \"AiReasoning\";\n\n// ─── AiReasoningGroup ────────────────────────────────────────────────────────\n\n/**\n * Renders multiple reasoning steps. Shows a single `<AiReasoning>` directly\n * when only one part is provided. When multiple parts exist, renders a\n * collapsible group with step labels.\n *\n * @example\n * ```tsx\n * <AiReasoningGroup parts={reasoningParts} isStreaming={false} totalDuration={5} />\n * ```\n */\nexport function AiReasoningGroup({\n parts,\n isStreaming = false,\n totalDuration,\n defaultExpanded = false,\n className,\n ...props\n}: AiReasoningGroupProps) {\n const [isExpanded, setIsExpanded] = useState(defaultExpanded);\n\n // Single part — render directly\n if (parts.length === 1 && parts[0]) {\n const singlePart = parts[0];\n // Strip `part` from div props spread to avoid collision with HTML `part` attribute\n const { part: _part, ...restProps } = props as typeof props & {\n part?: unknown;\n };\n return (\n <AiReasoning\n part={singlePart}\n isStreaming={isStreaming}\n duration={totalDuration}\n className={className}\n {...restProps}\n />\n );\n }\n\n return (\n <BaseCollapsible.Root open={isExpanded} onOpenChange={setIsExpanded}>\n <div\n className={cn(\n \"my-0.5 flex w-full flex-col\",\n \"animate-in fade-in-0 duration-150\",\n className\n )}\n {...props}\n >\n <BaseCollapsible.Trigger\n render={\n <button\n type=\"button\"\n className=\"flex w-fit items-center gap-1.5 rounded px-1 py-0.5 text-left transition-colors hover:bg-sf-tint\"\n />\n }\n >\n {isStreaming ? (\n <SparkleIcon className=\"size-3.5 shrink-0 animate-pulse text-sf-subtle\" />\n ) : (\n <BrainIcon className=\"size-3.5 shrink-0 text-sf-subtle\" />\n )}\n <span className=\"text-sm text-sf-subtle\">\n {isStreaming ? \"Thinking...\" : `${parts.length} reasoning steps`}\n </span>\n {isStreaming ? (\n <SpinnerGapIcon className=\"size-3 shrink-0 animate-spin text-sf-subtle\" />\n ) : null}\n {totalDuration && totalDuration > 0 && !isStreaming ? (\n <span className=\"text-xs tabular-nums text-sf-subtle/60\">\n {formatDuration(totalDuration)}\n </span>\n ) : null}\n {isExpanded ? (\n <CaretDownIcon className=\"size-3 shrink-0 text-sf-subtle/60\" />\n ) : (\n <CaretRightIcon className=\"size-3 shrink-0 text-sf-subtle/60\" />\n )}\n </BaseCollapsible.Trigger>\n\n <BaseCollapsible.Panel className=\"overflow-hidden\">\n <div className=\"mt-1 space-y-2 rounded-lg bg-sf-tint/50 px-3 py-2\">\n {parts.map((partItem, index) => (\n <div key={index} className=\"text-sm text-sf-subtle\">\n {parts.length > 1 ? (\n <p className=\"mb-0.5 text-[10px] uppercase tracking-wider text-sf-subtle/50\">\n Step {index + 1}\n </p>\n ) : null}\n <Suspense>\n <Streamdown className=\"[&>*:first-child]:mt-0 [&>*:last-child]:mb-0\">\n {partItem.text || \"*No content*\"}\n </Streamdown>\n </Suspense>\n </div>\n ))}\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-response-BEUg3xvd.js","names":[],"sources":["../src/components/ai-response/ai-response.tsx"],"sourcesContent":["\"use client\";\n\nimport { code } from \"@streamdown/code\";\nimport { memo } from \"react\";\nimport { Streamdown, type StreamdownProps } from \"streamdown\";\n\nimport { cn } from \"../../utils/cn\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_RESPONSE_VARIANTS = {} as const;\nexport const SF_AI_RESPONSE_DEFAULT_VARIANTS = {} as const;\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nconst plugins = { code };\n\nexport type AiResponseProps = StreamdownProps & {\n /** Additional CSS classes. */\n className?: string;\n};\n\n/**\n * Renders AI-generated markdown using Streamdown.\n * Supports streaming animation, syntax-highlighted code, tables, and more.\n *\n * Pass `isAnimating={true}` while streaming and `false` once complete to get\n * character-by-character reveal animation.\n *\n * @example\n * ```tsx\n * // Static\n * <AiResponse>{\"# Hello\\n\\nThis is **bold** and _italic_.\"}</AiResponse>\n *\n * // Streaming\n * <AiResponse isAnimating={isStreaming}>{streamedText}</AiResponse>\n * ```\n */\nexport const AiResponse = memo(\n ({ className, children, ...props }: AiResponseProps) => {\n return (\n <Streamdown\n className={cn(\n \"w-full text-sf-default text-sm\",\n \"[&>*:first-child]:mt-0 [&>*:last-child]:mb-0\",\n // Bridge shadcn tokens used by @streamdown/code to sf tokens so\n // code blocks render with visible borders/backgrounds/text.\n \"[--border:var(--color-sf-line)] [--sidebar:var(--color-sf-elevated)]\",\n \"[--background:var(--color-sf-recessed)] [--foreground:var(--text-color-sf-default)]\",\n \"[--muted-foreground:var(--text-color-sf-subtle)]\",\n className\n )}\n plugins={plugins}\n {...props}\n >\n {children}\n </Streamdown>\n );\n },\n (prev, next) =>\n prev.children === next.children && prev.isAnimating === next.isAnimating\n);\n\nAiResponse.displayName = \"AiResponse\";\n"],"mappings":";;;;;;;AAUA,IAAa,0BAA0B,EAAE;AACzC,IAAa,kCAAkC,EAAE;AAIjD,IAAM,UAAU,EAAE,MAAM;;;;;;;;;;;;;;;;;AAuBxB,IAAa,aAAa,MACvB,EAAE,WAAW,UAAU,GAAG,YAA6B;AACtD,QACE,oBAAC,YAAD;EACE,WAAW,GACT,kCACA,gDAGA,wEACA,uFACA,oDACA,UACD;EACQ;EACT,GAAI;EAEH;EACU,CAAA;IAGhB,MAAM,SACL,KAAK,aAAa,KAAK,YAAY,KAAK,gBAAgB,KAAK,YAChE;AAED,WAAW,cAAc"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-streaming-text-CMfoThV0.js","names":[],"sources":["../src/components/ai-streaming-text/ai-streaming-text.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_STREAMING_TEXT_VARIANTS = {} as const;\nexport const SF_AI_STREAMING_TEXT_DEFAULT_VARIANTS = {} as const;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface UseAiStreamingTextOptions {\n /** Whether content is actively streaming. @default false */\n isStreaming?: boolean;\n /** Characters to release per animation frame tick. @default 10 */\n charsPerTick?: number;\n /** Milliseconds between releases (~16ms = 60fps). @default 16 */\n tickInterval?: number;\n /** Immediately flush all text when streaming stops. @default true */\n flushOnStop?: boolean;\n}\n\n// ─── Hook ────────────────────────────────────────────────────────────────────\n\n/**\n * Buffers incoming text and releases it character-by-character for a smooth\n * typing effect. Pass the full (possibly incomplete) text and whether streaming\n * is active — get back the display-ready substring.\n *\n * @example\n * ```tsx\n * function StreamingMessage({ text, isStreaming }) {\n * const displayText = useAiStreamingText(text, { isStreaming });\n * return <AiResponse>{displayText}</AiResponse>;\n * }\n * ```\n */\nexport function useAiStreamingText(\n text: string,\n options: UseAiStreamingTextOptions = {}\n): string {\n const {\n isStreaming = false,\n charsPerTick = 10,\n tickInterval = 16,\n flushOnStop = true,\n } = options;\n\n const [displayText, setDisplayText] = useState(text);\n const targetRef = useRef(text);\n const posRef = useRef(text.length);\n const rafRef = useRef<number | null>(null);\n const lastTickRef = useRef(0);\n\n useEffect(() => {\n targetRef.current = text;\n }, [text]);\n\n useEffect(() => {\n if (!isStreaming) {\n if (flushOnStop) {\n setDisplayText(text);\n posRef.current = text.length;\n }\n return;\n }\n\n const animate = (timestamp: number) => {\n const target = targetRef.current;\n const pos = posRef.current;\n\n if (pos >= target.length) {\n rafRef.current = requestAnimationFrame(animate);\n return;\n }\n\n if (timestamp - lastTickRef.current < tickInterval) {\n rafRef.current = requestAnimationFrame(animate);\n return;\n }\n lastTickRef.current = timestamp;\n\n const newPos = Math.min(pos + charsPerTick, target.length);\n posRef.current = newPos;\n setDisplayText(target.slice(0, newPos));\n rafRef.current = requestAnimationFrame(animate);\n };\n\n rafRef.current = requestAnimationFrame(animate);\n return () => {\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n };\n }, [isStreaming, charsPerTick, tickInterval, flushOnStop, text]);\n\n useEffect(() => {\n if (!isStreaming && flushOnStop && displayText !== text) {\n setDisplayText(text);\n posRef.current = text.length;\n }\n }, [isStreaming, flushOnStop, text, displayText]);\n\n return displayText;\n}\n"],"mappings":";;;AAMA,IAAa,gCAAgC,EAAE;AAC/C,IAAa,wCAAwC,EAAE;;;;;;;;;;;;;;AA8BvD,SAAgB,mBACd,MACA,UAAqC,EAAE,EAC/B;CACR,MAAM,EACJ,cAAc,OACd,eAAe,IACf,eAAe,IACf,cAAc,SACZ;CAEJ,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,YAAY,OAAO,KAAK;CAC9B,MAAM,SAAS,OAAO,KAAK,OAAO;CAClC,MAAM,SAAS,OAAsB,KAAK;CAC1C,MAAM,cAAc,OAAO,EAAE;AAE7B,iBAAgB;AACd,YAAU,UAAU;IACnB,CAAC,KAAK,CAAC;AAEV,iBAAgB;AACd,MAAI,CAAC,aAAa;AAChB,OAAI,aAAa;AACf,mBAAe,KAAK;AACpB,WAAO,UAAU,KAAK;;AAExB;;EAGF,MAAM,WAAW,cAAsB;GACrC,MAAM,SAAS,UAAU;GACzB,MAAM,MAAM,OAAO;AAEnB,OAAI,OAAO,OAAO,QAAQ;AACxB,WAAO,UAAU,sBAAsB,QAAQ;AAC/C;;AAGF,OAAI,YAAY,YAAY,UAAU,cAAc;AAClD,WAAO,UAAU,sBAAsB,QAAQ;AAC/C;;AAEF,eAAY,UAAU;GAEtB,MAAM,SAAS,KAAK,IAAI,MAAM,cAAc,OAAO,OAAO;AAC1D,UAAO,UAAU;AACjB,kBAAe,OAAO,MAAM,GAAG,OAAO,CAAC;AACvC,UAAO,UAAU,sBAAsB,QAAQ;;AAGjD,SAAO,UAAU,sBAAsB,QAAQ;AAC/C,eAAa;AACX,OAAI,OAAO,QAAS,sBAAqB,OAAO,QAAQ;;IAEzD;EAAC;EAAa;EAAc;EAAc;EAAa;EAAK,CAAC;AAEhE,iBAAgB;AACd,MAAI,CAAC,eAAe,eAAe,gBAAgB,MAAM;AACvD,kBAAe,KAAK;AACpB,UAAO,UAAU,KAAK;;IAEvB;EAAC;EAAa;EAAa;EAAM;EAAY,CAAC;AAEjD,QAAO"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-subagent-DcPRqkAA.js","names":[],"sources":["../src/components/ai-subagent/ai-subagent.tsx"],"sourcesContent":["\"use client\";\n\nimport { Collapsible as BaseCollapsible } from \"@base-ui/react/collapsible\";\nimport {\n RobotIcon,\n CaretDownIcon,\n SpinnerGapIcon,\n CheckCircleIcon,\n XCircleIcon,\n} from \"@phosphor-icons/react\";\nimport type { ElementType, HTMLAttributes, ReactNode } from \"react\";\nimport { useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_SUBAGENT_VARIANTS = {\n status: {\n running: { classes: \"\", description: \"Subagent is actively processing\" },\n completed: { classes: \"\", description: \"Subagent finished successfully\" },\n error: { classes: \"\", description: \"Subagent encountered an error\" },\n },\n} as const;\n\nexport const SF_AI_SUBAGENT_DEFAULT_VARIANTS = {\n status: \"running\",\n} as const;\n\nexport type SFAiSubagentStatus = keyof typeof SF_AI_SUBAGENT_VARIANTS.status;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type AiSubagentProps = HTMLAttributes<HTMLDivElement> & {\n /** Subagent type ID (e.g. `\"explore\"`, `\"execute\"`). */\n agentType?: string;\n /** Human-readable name for this subagent. */\n name?: string;\n /** Current status. */\n status?: SFAiSubagentStatus;\n /** Current model ID being used (e.g. `\"claude-haiku-3.5\"`). */\n modelId?: string;\n /** Duration in milliseconds. */\n duration?: number;\n /** Custom icon. Defaults to `RobotIcon`. */\n icon?: ElementType;\n /** Whether the subagent content is expanded by default. */\n defaultExpanded?: boolean;\n /** Controlled open state. */\n open?: boolean;\n /** Called when open state changes. */\n onOpenChange?: (open: boolean) => void;\n /**\n * Content rendered inside the collapsible body — typically streaming text,\n * tool calls, and other nested agent output.\n */\n children?: ReactNode;\n};\n\n// ─── Status config ────────────────────────────────────────────────────────────\n\nconst STATUS_CONFIG: Record<\n SFAiSubagentStatus,\n {\n icon: ElementType;\n className: string;\n label: string;\n }\n> = {\n running: {\n icon: SpinnerGapIcon,\n className: \"text-sf-brand animate-spin\",\n label: \"Running\",\n },\n completed: {\n icon: CheckCircleIcon,\n className: \"text-sf-success\",\n label: \"Completed\",\n },\n error: {\n icon: XCircleIcon,\n className: \"text-sf-danger\",\n label: \"Error\",\n },\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n const s = Math.floor(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n const remaining = s % 60;\n return remaining > 0 ? `${m}m ${remaining}s` : `${m}m`;\n}\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\n/**\n * Collapsible wrapper for nested subagent activity. Shows the subagent name,\n * status, model, and duration in a header, with all subagent output (text,\n * tool calls, etc.) in a collapsible body.\n *\n * Maps to harness events: `subagent_start`, `subagent_text_delta`,\n * `subagent_tool_start`, `subagent_tool_end`, `subagent_end`,\n * `subagent_model_changed`.\n *\n * @example\n * ```tsx\n * <AiSubagent\n * name=\"Explore\"\n * agentType=\"explore\"\n * status=\"running\"\n * modelId=\"claude-haiku-3.5\"\n * defaultExpanded\n * >\n * <AiResponse isAnimating>{streamingText}</AiResponse>\n * <AiToolCallGroup tools={toolCalls} />\n * </AiSubagent>\n * ```\n */\nexport function AiSubagent({\n agentType,\n name,\n status = \"running\",\n modelId,\n duration,\n icon,\n defaultExpanded = true,\n open: controlledOpen,\n onOpenChange,\n children,\n className,\n ...props\n}: AiSubagentProps) {\n const [internalOpen, setInternalOpen] = useState(defaultExpanded);\n const isControlled = controlledOpen !== undefined;\n const isOpen = isControlled ? controlledOpen : internalOpen;\n\n const handleOpenChange = (nextOpen: boolean) => {\n if (!isControlled) setInternalOpen(nextOpen);\n onOpenChange?.(nextOpen);\n };\n\n const IconComponent = icon ?? RobotIcon;\n const statusConfig = STATUS_CONFIG[status];\n const StatusIcon = statusConfig.icon;\n const displayName = name ?? agentType ?? \"Subagent\";\n\n return (\n <BaseCollapsible.Root\n defaultOpen={defaultExpanded}\n onOpenChange={handleOpenChange}\n open={isOpen}\n >\n <div\n className={cn(\"flex flex-col overflow-hidden rounded-lg\", className)}\n {...props}\n >\n {/* Header / trigger */}\n <BaseCollapsible.Trigger className=\"flex w-fit items-center gap-2 rounded-md px-2 py-1.5 text-left transition-colors hover:bg-sf-tint\">\n {/* Agent icon */}\n <div className=\"flex size-5 shrink-0 items-center justify-center rounded bg-sf-tint text-sf-subtle\">\n <IconComponent className=\"size-3.5\" />\n </div>\n\n {/* Name + model */}\n <div className=\"flex min-w-0 grow items-center gap-2\">\n <span className=\"text-sm font-medium text-sf-default\">\n {displayName}\n </span>\n {modelId && (\n <span className=\"truncate rounded bg-sf-tint px-1.5 py-0.5 font-mono text-[10px] text-sf-subtle\">\n {modelId}\n </span>\n )}\n </div>\n\n {/* Status + duration + caret */}\n <div className=\"flex shrink-0 items-center gap-2\">\n {duration !== undefined && (\n <span className=\"text-xs tabular-nums text-sf-subtle\">\n {formatDuration(duration)}\n </span>\n )}\n <StatusIcon className={cn(\"size-3.5\", statusConfig.className)} />\n <CaretDownIcon\n className={cn(\n \"size-3 text-sf-subtle transition-transform duration-200\",\n isOpen && \"rotate-180\"\n )}\n />\n </div>\n </BaseCollapsible.Trigger>\n\n {/* Collapsible content */}\n <BaseCollapsible.Panel className=\"overflow-hidden [&[data-ending-style]]:h-0 [&[data-starting-style]]:h-0\">\n <div className=\"flex flex-col gap-2 bg-sf-tint/50 px-3 py-2.5\">\n {children}\n </div>\n </BaseCollapsible.Panel>\n </div>\n </BaseCollapsible.Root>\n );\n}\n\nAiSubagent.displayName = \"AiSubagent\";\n"],"mappings":";;;;;;;AAiBA,IAAa,0BAA0B,EACrC,QAAQ;CACN,SAAS;EAAE,SAAS;EAAI,aAAa;EAAmC;CACxE,WAAW;EAAE,SAAS;EAAI,aAAa;EAAkC;CACzE,OAAO;EAAE,SAAS;EAAI,aAAa;EAAiC;CACrE,EACF;AAED,IAAa,kCAAkC,EAC7C,QAAQ,WACT;AAkCD,IAAM,gBAOF;CACF,SAAS;EACP,MAAM;EACN,WAAW;EACX,OAAO;EACR;CACD,WAAW;EACT,MAAM;EACN,WAAW;EACX,OAAO;EACR;CACD,OAAO;EACL,MAAM;EACN,WAAW;EACX,OAAO;EACR;CACF;AAID,SAAS,eAAe,IAAoB;AAC1C,KAAI,KAAK,IAAM,QAAO,GAAG,GAAG;CAC5B,MAAM,IAAI,KAAK,MAAM,KAAK,IAAK;AAC/B,KAAI,IAAI,GAAI,QAAO,GAAG,EAAE;CACxB,MAAM,IAAI,KAAK,MAAM,IAAI,GAAG;CAC5B,MAAM,YAAY,IAAI;AACtB,QAAO,YAAY,IAAI,GAAG,EAAE,IAAI,UAAU,KAAK,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;AA4BtD,SAAgB,WAAW,EACzB,WACA,MACA,SAAS,WACT,SACA,UACA,MACA,kBAAkB,MAClB,MAAM,gBACN,cACA,UACA,WACA,GAAG,SACe;CAClB,MAAM,CAAC,cAAc,mBAAmB,SAAS,gBAAgB;CACjE,MAAM,eAAe,mBAAmB,KAAA;CACxC,MAAM,SAAS,eAAe,iBAAiB;CAE/C,MAAM,oBAAoB,aAAsB;AAC9C,MAAI,CAAC,aAAc,iBAAgB,SAAS;AAC5C,iBAAe,SAAS;;CAG1B,MAAM,gBAAgB,QAAQ;CAC9B,MAAM,eAAe,cAAc;CACnC,MAAM,aAAa,aAAa;CAChC,MAAM,cAAc,QAAQ,aAAa;AAEzC,QACE,oBAAC,YAAgB,MAAjB;EACE,aAAa;EACb,cAAc;EACd,MAAM;YAEN,qBAAC,OAAD;GACE,WAAW,GAAG,4CAA4C,UAAU;GACpE,GAAI;aAFN,CAKE,qBAAC,YAAgB,SAAjB;IAAyB,WAAU;cAAnC;KAEE,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,eAAD,EAAe,WAAU,YAAa,CAAA;MAClC,CAAA;KAGN,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,QAAD;OAAM,WAAU;iBACb;OACI,CAAA,EACN,WACC,oBAAC,QAAD;OAAM,WAAU;iBACb;OACI,CAAA,CAEL;;KAGN,qBAAC,OAAD;MAAK,WAAU;gBAAf;OACG,aAAa,KAAA,KACZ,oBAAC,QAAD;QAAM,WAAU;kBACb,eAAe,SAAS;QACpB,CAAA;OAET,oBAAC,YAAD,EAAY,WAAW,GAAG,YAAY,aAAa,UAAU,EAAI,CAAA;OACjE,oBAAC,eAAD,EACE,WAAW,GACT,2DACA,UAAU,aACX,EACD,CAAA;OACE;;KACkB;OAG1B,oBAAC,YAAgB,OAAjB;IAAuB,WAAU;cAC/B,oBAAC,OAAD;KAAK,WAAU;KACZ;KACG,CAAA;IACgB,CAAA,CACpB;;EACe,CAAA;;AAI3B,WAAW,cAAc"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-task-list-Da9zIm00.js","names":[],"sources":["../src/components/ai-task-list/ai-task-list.tsx"],"sourcesContent":["\"use client\";\n\nimport type { ElementType, HTMLAttributes, ReactNode } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_TASK_LIST_VARIANTS = {} as const;\nexport const SF_AI_TASK_LIST_DEFAULT_VARIANTS = {} as const;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type AiTaskStatus =\n | \"pending\"\n | \"in_progress\"\n | \"completed\"\n | \"cancelled\";\n\nexport type AiTaskPriority = \"high\" | \"medium\" | \"low\";\n\nexport type AiTaskItem = {\n /** Unique task identifier. */\n id: string;\n /** Task description. */\n content: string;\n /** Current status. */\n status: AiTaskStatus;\n /** Priority level. */\n priority?: AiTaskPriority;\n};\n\nexport type AiTaskListProps = Omit<HTMLAttributes<HTMLDivElement>, \"title\"> & {\n /** List of tasks. */\n tasks: AiTaskItem[];\n /** Optional title above the task list. */\n title?: string;\n /** Custom icon for the title area. */\n icon?: ElementType;\n /** Show a progress summary (e.g. \"3 / 7 done\"). Default: `true`. */\n showProgress?: boolean;\n /** Content rendered below the task list. */\n children?: ReactNode;\n};\n\nexport type AiTaskListItemProps = HTMLAttributes<HTMLDivElement> & {\n task: AiTaskItem;\n};\n\n// ─── Status config ────────────────────────────────────────────────────────────\n\nconst STATUS_CONFIG: Record<\n AiTaskStatus,\n { dotClassName: string; textClassName: string }\n> = {\n pending: {\n dotClassName: \"bg-sf-subtle/30\",\n textClassName: \"text-sf-subtle\",\n },\n in_progress: {\n dotClassName: \"bg-sf-brand\",\n textClassName: \"text-sf-default\",\n },\n completed: {\n dotClassName: \"bg-sf-success\",\n textClassName: \"text-sf-subtle/60 line-through\",\n },\n cancelled: {\n dotClassName: \"bg-sf-subtle/30\",\n textClassName: \"text-sf-subtle/40 line-through\",\n },\n};\n\nconst PRIORITY_DOT: Record<AiTaskPriority, string> = {\n high: \"bg-sf-danger\",\n medium: \"bg-sf-warning\",\n low: \"bg-sf-subtle\",\n};\n\n// ─── AiTaskListItem ──────────────────────────────────────────────────────────\n\n/**\n * Single task item with status icon, content, and optional priority dot.\n */\nexport function AiTaskListItem({\n task,\n className,\n ...props\n}: AiTaskListItemProps) {\n const config = STATUS_CONFIG[task.status];\n\n return (\n <div className={cn(\"flex items-start gap-2 py-1\", className)} {...props}>\n <span\n aria-hidden\n className={cn(\n \"mt-[0.4375rem] size-1.5 shrink-0 rounded-full\",\n config.dotClassName\n )}\n />\n <span className={cn(\"min-w-0 grow text-sm\", config.textClassName)}>\n {task.content}\n </span>\n {task.priority && (\n <span\n className={cn(\n \"mt-2 size-1 shrink-0 rounded-full\",\n PRIORITY_DOT[task.priority]\n )}\n title={`${task.priority} priority`}\n />\n )}\n </div>\n );\n}\n\nAiTaskListItem.displayName = \"AiTaskListItem\";\n\n// ─── AiTaskList ──────────────────────────────────────────────────────────────\n\n/**\n * Task progress list. Renders structured tasks from the harness `task_write`\n * tool. Typically rendered inside the `PromptInputBackLayer` or inline in\n * conversation.\n *\n * Maps to harness event: `task_updated`.\n *\n * @example\n * ```tsx\n * <AiTaskList\n * title=\"Current tasks\"\n * tasks={[\n * { id: \"1\", content: \"Read config file\", status: \"completed\", priority: \"high\" },\n * { id: \"2\", content: \"Run migrations\", status: \"in_progress\", priority: \"high\" },\n * { id: \"3\", content: \"Seed database\", status: \"pending\", priority: \"medium\" },\n * ]}\n * />\n * ```\n */\nexport function AiTaskList({\n tasks,\n title,\n icon,\n showProgress = true,\n children,\n className,\n ...props\n}: AiTaskListProps) {\n const completed = tasks.filter((t) => t.status === \"completed\").length;\n const total = tasks.filter((t) => t.status !== \"cancelled\").length;\n\n return (\n <div className={cn(\"flex flex-col gap-1\", className)} {...props}>\n {/* Header */}\n {(title || showProgress) && (\n <div className=\"flex items-center justify-between gap-2 pb-0.5\">\n <div className=\"flex items-center gap-1.5\">\n {icon &&\n (() => {\n const Icon = icon;\n return <Icon className=\"size-3.5 text-sf-subtle\" />;\n })()}\n {title && <span className=\"text-sm text-sf-subtle\">{title}</span>}\n </div>\n {showProgress && total > 0 && (\n <span className=\"text-xs tabular-nums text-sf-subtle/60\">\n {completed}/{total}\n </span>\n )}\n </div>\n )}\n\n {/* Tasks */}\n <div className=\"flex flex-col\">\n {tasks.map((task) => (\n <AiTaskListItem key={task.id} task={task} />\n ))}\n </div>\n\n {/* Progress bar */}\n {showProgress && total > 0 && (\n <div className=\"mt-1 h-0.5 overflow-hidden rounded-full bg-sf-tint\">\n <div\n className=\"h-full rounded-full bg-sf-brand/60 transition-[width] duration-300 ease-out\"\n style={{ width: `${(completed / total) * 100}%` }}\n />\n </div>\n )}\n\n {children}\n </div>\n );\n}\n\nAiTaskList.displayName = \"AiTaskList\";\n"],"mappings":";;;;AAQA,IAAa,2BAA2B,EAAE;AAC1C,IAAa,mCAAmC,EAAE;AA0ClD,IAAM,gBAGF;CACF,SAAS;EACP,cAAc;EACd,eAAe;EAChB;CACD,aAAa;EACX,cAAc;EACd,eAAe;EAChB;CACD,WAAW;EACT,cAAc;EACd,eAAe;EAChB;CACD,WAAW;EACT,cAAc;EACd,eAAe;EAChB;CACF;AAED,IAAM,eAA+C;CACnD,MAAM;CACN,QAAQ;CACR,KAAK;CACN;;;;AAOD,SAAgB,eAAe,EAC7B,MACA,WACA,GAAG,SACmB;CACtB,MAAM,SAAS,cAAc,KAAK;AAElC,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,+BAA+B,UAAU;EAAE,GAAI;YAAlE;GACE,oBAAC,QAAD;IACE,eAAA;IACA,WAAW,GACT,iDACA,OAAO,aACR;IACD,CAAA;GACF,oBAAC,QAAD;IAAM,WAAW,GAAG,wBAAwB,OAAO,cAAc;cAC9D,KAAK;IACD,CAAA;GACN,KAAK,YACJ,oBAAC,QAAD;IACE,WAAW,GACT,qCACA,aAAa,KAAK,UACnB;IACD,OAAO,GAAG,KAAK,SAAS;IACxB,CAAA;GAEA;;;AAIV,eAAe,cAAc;;;;;;;;;;;;;;;;;;;;AAuB7B,SAAgB,WAAW,EACzB,OACA,OACA,MACA,eAAe,MACf,UACA,WACA,GAAG,SACe;CAClB,MAAM,YAAY,MAAM,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC;CAChE,MAAM,QAAQ,MAAM,QAAQ,MAAM,EAAE,WAAW,YAAY,CAAC;AAE5D,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,uBAAuB,UAAU;EAAE,GAAI;YAA1D;IAEI,SAAS,iBACT,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,qBAAC,OAAD;KAAK,WAAU;eAAf,CACG,QAGU,oBADM,MACN,EAAM,WAAU,2BAA4B,CAAA,EAEtD,SAAS,oBAAC,QAAD;MAAM,WAAU;gBAA0B;MAAa,CAAA,CAC7D;QACL,gBAAgB,QAAQ,KACvB,qBAAC,QAAD;KAAM,WAAU;eAAhB;MACG;MAAU;MAAE;MACR;OAEL;;GAIR,oBAAC,OAAD;IAAK,WAAU;cACZ,MAAM,KAAK,SACV,oBAAC,gBAAD,EAAoC,MAAQ,EAAvB,KAAK,GAAkB,CAC5C;IACE,CAAA;GAGL,gBAAgB,QAAQ,KACvB,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,OAAD;KACE,WAAU;KACV,OAAO,EAAE,OAAO,GAAI,YAAY,QAAS,IAAI,IAAI;KACjD,CAAA;IACE,CAAA;GAGP;GACG;;;AAIV,WAAW,cAAc"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ai-timeline-Cwu045IR.js","names":[],"sources":["../src/components/ai-timeline/ai-timeline.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n BrainIcon,\n CaretDownIcon,\n CheckCircleIcon,\n CircleDashedIcon,\n CodeIcon,\n LightningIcon,\n MagnifyingGlassIcon,\n RobotIcon,\n ShieldWarningIcon,\n SpinnerGapIcon,\n WrenchIcon,\n XCircleIcon,\n} from \"@phosphor-icons/react\";\nimport type { ComponentProps, ElementType, ReactNode } from \"react\";\nimport { forwardRef, useCallback, useMemo, useRef, useState } from \"react\";\n\nimport { cn } from \"../../utils/cn\";\n\n// ─── Variants ────────────────────────────────────────────────────────────────\n\nexport const SF_AI_TIMELINE_VARIANTS = {\n density: {\n comfortable: { classes: \"\", description: \"Taller lanes with more padding\" },\n compact: { classes: \"\", description: \"Tight lanes for dense views\" },\n },\n} as const;\n\nexport const SF_AI_TIMELINE_DEFAULT_VARIANTS = {\n density: \"comfortable\",\n} as const;\n\nexport type SFAiTimelineDensity = keyof typeof SF_AI_TIMELINE_VARIANTS.density;\n\n// ─── Block types ─────────────────────────────────────────────────────────────\n\n/** Visual type of a timeline block — controls color and icon. */\nexport type AiTimelineBlockType =\n | \"running\" // brand blue — agent actively generating\n | \"tool_call\" // amber — executing a tool\n | \"waiting\" // gray — idle/blocked\n | \"approval\" // purple — waiting for human approval\n | \"completed\" // green — successfully finished\n | \"error\"; // red — failed\n\n/** A colored segment on a lane representing a period of activity. */\nexport interface AiTimelineBlock {\n /** Unique ID for this block. */\n id: string;\n /** Visual type (controls color). */\n type: AiTimelineBlockType;\n /** Wall-clock ms when this activity started. */\n startMs: number;\n /**\n * Wall-clock ms when this activity ended.\n * Undefined means still active — the block extends to \"now\".\n */\n endMs?: number;\n /** Short label shown inside the block when space allows. */\n label?: string;\n /** Longer description shown in the expanded detail panel. */\n description?: string;\n /** Extra detail content shown when the block is expanded. */\n detail?: ReactNode;\n}\n\n// ─── Lane props ───────────────────────────────────────────────────────────────\n\nexport type AiTimelineLaneProps = Omit<ComponentProps<\"div\">, \"children\"> & {\n /** Lane label (agent name). */\n label: string;\n /** Agent type string for icon selection. */\n agentType?: string;\n /** Model ID shown as a subtle badge. */\n modelId?: string;\n /** Current lane status — controls the label icon. */\n status?: \"idle\" | \"running\" | \"completed\" | \"error\";\n /** Ordered activity blocks for this lane. */\n blocks: AiTimelineBlock[];\n /** Timeline origin (ms) — same as AiTimeline timeOrigin. */\n timeOrigin: number;\n /** Current \"now\" timestamp (ms) for live blocks. */\n nowMs: number;\n /** Pixels per millisecond (zoom level). */\n pxPerMs: number;\n /** Whether the lane is expanded to show block details. */\n defaultExpanded?: boolean;\n /** Callback when a block is clicked. */\n onBlockClick?: (block: AiTimelineBlock) => void;\n /** Custom icon override. */\n icon?: ElementType;\n /** Lane height variant. */\n density?: SFAiTimelineDensity;\n};\n\n// ─── Timeline props ───────────────────────────────────────────────────────────\n\nexport type AiTimelineProps = Omit<ComponentProps<\"div\">, \"children\"> & {\n /**\n * Wall-clock ms for the timeline origin (t=0).\n * Defaults to the startMs of the first block across all lanes.\n */\n timeOrigin?: number;\n /**\n * Pixels per second of elapsed time.\n * Controls horizontal zoom level.\n * @default 30\n */\n pixelsPerSecond?: number;\n /**\n * Whether to show a pulsing \"now\" marker at the live edge.\n * @default true\n */\n showNowMarker?: boolean;\n /**\n * Current timestamp in ms. Used to render the \"now\" marker and open-ended\n * block widths. Pass a stable `useState` value to prevent hydration shifts.\n * When omitted, `Date.now()` is called at render time (fine for live views\n * driven by a ticking parent, not suitable for SSR).\n */\n nowMs?: number;\n /** Lane density variant. @default \"comfortable\" */\n density?: SFAiTimelineDensity;\n /** Children should be `AiTimelineLane` components. */\n children?: ReactNode;\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nconst AGENT_ICONS: Record<string, ElementType> = {\n explore: MagnifyingGlassIcon,\n search: MagnifyingGlassIcon,\n execute: CodeIcon,\n code: CodeIcon,\n plan: BrainIcon,\n think: BrainIcon,\n tool: WrenchIcon,\n build: WrenchIcon,\n main: LightningIcon,\n};\n\nfunction getAgentIcon(\n agentType?: string,\n customIcon?: ElementType\n): ElementType {\n if (customIcon) return customIcon;\n if (agentType) {\n const lower = agentType.toLowerCase();\n for (const [key, icon] of Object.entries(AGENT_ICONS)) {\n if (lower.includes(key)) return icon;\n }\n }\n return RobotIcon;\n}\n\nfunction getModelShort(modelId?: string) {\n if (!modelId) return \"\";\n return (\n modelId\n .split(\"/\")\n .pop()\n ?.replace(/^claude-/, \"\")\n .replace(/-\\d+$/, \"\") ?? \"\"\n );\n}\n\nfunction formatMs(ms: number) {\n const s = Math.round(ms / 100) / 10;\n if (s < 60) return `${s}s`;\n return `${Math.floor(s / 60)}m ${Math.round(s % 60)}s`;\n}\n\n// Block colors — all semantic SignalFlare tokens, no raw Tailwind colors\nconst BLOCK_COLORS: Record<AiTimelineBlockType, string> = {\n running: \"bg-sf-brand text-sf-inverse\",\n tool_call: \"bg-sf-warning text-sf-inverse\",\n waiting: \"bg-sf-fill text-sf-subtle\",\n approval: \"bg-sf-info text-sf-inverse\",\n completed: \"bg-sf-brand/60 text-sf-inverse\",\n error: \"bg-sf-danger text-sf-inverse\",\n};\n\n// Hover is a uniform subtle brightness lift — no per-type color shifting\nconst BLOCK_HOVER = \"hover:brightness-110 hover:shadow-sm\";\n\nfunction BlockIcon({ type }: { type: AiTimelineBlockType }) {\n switch (type) {\n case \"running\":\n return <SpinnerGapIcon size={8} className=\"animate-spin\" />;\n case \"tool_call\":\n return <WrenchIcon size={8} />;\n case \"approval\":\n return <ShieldWarningIcon size={8} />;\n case \"completed\":\n return <CheckCircleIcon size={8} />;\n case \"error\":\n return <XCircleIcon size={8} />;\n default:\n return <CircleDashedIcon size={8} />;\n }\n}\n\n// ─── AiTimelineBlock (rendered) ───────────────────────────────────────────────\n\nfunction TimelineBlockSegment({\n block,\n timeOrigin,\n nowMs,\n pxPerMs,\n laneHeight,\n onBlockClick,\n rowIndex = 0,\n rowCount = 1,\n}: {\n block: AiTimelineBlock;\n timeOrigin: number;\n nowMs: number;\n pxPerMs: number;\n laneHeight: number;\n onBlockClick?: (block: AiTimelineBlock) => void;\n rowIndex?: number;\n rowCount?: number;\n}) {\n const left = Math.max(0, (block.startMs - timeOrigin) * pxPerMs);\n const end = block.endMs ?? nowMs;\n const width = Math.max(4, (end - block.startMs) * pxPerMs);\n const durationMs = end - block.startMs;\n\n const MIN_LABEL_PX = 40;\n // Short blocks get sharp corners to avoid weird rounded look when overlaid\n const isShort = width < 20;\n const roundedClass = isShort\n ? \"rounded-none\"\n : width < 40\n ? \"rounded-sm\"\n : \"rounded-md\";\n\n // Calculate vertical position for overlapping blocks\n // Blocks that overlap in time stack vertically, centered within the lane\n const blockHeight = laneHeight - 8;\n const innerPadding = 2;\n const availableHeight = blockHeight - innerPadding * 2;\n const rowHeight = availableHeight / rowCount;\n const topOffset = innerPadding + rowIndex * rowHeight;\n\n return (\n <button\n type=\"button\"\n aria-label={block.label ?? block.type}\n title={block.description ?? block.label}\n onClick={onBlockClick ? () => onBlockClick(block) : undefined}\n className={cn(\n \"group absolute transition-[width] duration-150\",\n roundedClass,\n BLOCK_COLORS[block.type],\n onBlockClick ? BLOCK_HOVER : \"cursor-default\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sf-ring\",\n \"flex items-center gap-1 overflow-hidden px-1.5\"\n )}\n style={{\n left,\n width,\n height: rowHeight - 1,\n top: topOffset,\n }}\n >\n <BlockIcon type={block.type} />\n {width >= MIN_LABEL_PX && block.label && (\n <span className=\"truncate text-[9px] font-medium leading-none\">\n {block.label}\n </span>\n )}\n {width >= MIN_LABEL_PX && (\n <span className=\"ml-auto shrink-0 text-[8px] opacity-70\">\n {formatMs(durationMs)}\n </span>\n )}\n </button>\n );\n}\n\n/**\n * Calculate row assignments for blocks to avoid overlap.\n * Returns arrays of blocks grouped by row, where no blocks in a row overlap in time.\n */\nfunction computeBlockRows(blocks: AiTimelineBlock[]): AiTimelineBlock[][] {\n if (blocks.length === 0) return [];\n\n // Sort blocks by start time\n const sorted = [...blocks].sort((a, b) => a.startMs - b.startMs);\n const rows: AiTimelineBlock[][] = [];\n\n for (const block of sorted) {\n // Find the first row where this block doesn't overlap with any existing block\n let placed = false;\n for (const row of rows) {\n const overlaps = row.some(\n (existing) =>\n block.startMs < (existing.endMs ?? Infinity) &&\n (block.endMs ?? Infinity) > existing.startMs\n );\n if (!overlaps) {\n row.push(block);\n placed = true;\n break;\n }\n }\n if (!placed) {\n // Start a new row\n rows.push([block]);\n }\n }\n\n return rows;\n}\n\n// ─── AiTimelineLane ───────────────────────────────────────────────────────────\n\nconst LANE_HEIGHT_COMFORTABLE = 40;\nconst LANE_HEIGHT_COMPACT = 28;\nconst LABEL_WIDTH = 128;\n\n/**\n * `AiTimelineLane` — a single horizontal swim lane within an `AiTimeline`.\n *\n * Shows one agent's activity as colored blocks on a time axis. Blocks\n * represent periods of activity: running, tool calls, waiting, etc.\n *\n * Consumed by `AiTimeline` — pass lanes as children.\n */\nexport const AiTimelineLane = forwardRef<HTMLDivElement, AiTimelineLaneProps>(\n (\n {\n label,\n agentType,\n modelId,\n status = \"idle\",\n blocks,\n timeOrigin,\n nowMs,\n pxPerMs,\n defaultExpanded = false,\n onBlockClick,\n icon,\n density = \"comfortable\",\n className,\n ...props\n },\n ref\n ) => {\n const [expanded, setExpanded] = useState(defaultExpanded);\n const Icon = getAgentIcon(agentType, icon);\n const modelShort = getModelShort(modelId);\n\n // Compute block rows to handle overlapping blocks\n const blockRows = useMemo(() => computeBlockRows(blocks), [blocks]);\n const rowCount = blockRows.length;\n\n // Lane height scales with number of rows for overlapping blocks\n const baseLaneH =\n density === \"compact\" ? LANE_HEIGHT_COMPACT : LANE_HEIGHT_COMFORTABLE;\n const laneH = rowCount > 1 ? baseLaneH * rowCount : baseLaneH;\n\n // Total timeline width needed for this lane\n const maxEnd = useMemo(() => {\n if (!blocks.length) return timeOrigin;\n return Math.max(...blocks.map((b) => b.endMs ?? nowMs));\n }, [blocks, timeOrigin, nowMs]);\n\n const totalWidth = Math.max(0, (maxEnd - timeOrigin) * pxPerMs);\n\n return (\n <div\n ref={ref}\n className={cn(\"border-b border-sf-line last:border-b-0\", className)}\n {...props}\n >\n {/* Lane row */}\n <div className=\"flex\" style={{ height: laneH }}>\n {/* Label sidebar */}\n <div\n className=\"flex shrink-0 items-center gap-2 border-r border-sf-line bg-sf-base px-3\"\n style={{ width: LABEL_WIDTH }}\n >\n {/* Expand toggle (only when there are expandable blocks) */}\n {blocks.some((b) => b.detail) && (\n <button\n type=\"button\"\n aria-label={expanded ? \"Collapse lane\" : \"Expand lane\"}\n onClick={() => setExpanded((v) => !v)}\n className=\"shrink-0 text-sf-subtle hover:text-sf-default focus-visible:outline-none\"\n >\n <CaretDownIcon\n size={10}\n className={cn(\n \"transition-transform\",\n expanded && \"rotate-180\"\n )}\n />\n </button>\n )}\n\n {/* Agent icon */}\n <div\n className={cn(\n \"flex shrink-0 items-center justify-center rounded\",\n density === \"compact\" ? \"size-5\" : \"size-6\",\n status === \"running\"\n ? \"text-sf-brand\"\n : status === \"completed\"\n ? \"text-sf-success\"\n : status === \"error\"\n ? \"text-sf-danger\"\n : \"text-sf-subtle\"\n )}\n >\n {status === \"running\" ? (\n <SpinnerGapIcon\n size={density === \"compact\" ? 12 : 14}\n className=\"animate-spin\"\n />\n ) : (\n <Icon size={density === \"compact\" ? 12 : 14} />\n )}\n </div>\n\n {/* Name + model */}\n <div className=\"min-w-0 flex-1\">\n <div\n className={cn(\n \"truncate font-medium text-sf-default\",\n density === \"compact\" ? \"text-[10px]\" : \"text-xs\"\n )}\n >\n {label}\n </div>\n {modelShort && density === \"comfortable\" && (\n <div className=\"truncate font-mono text-[9px] text-sf-inactive\">\n {modelShort}\n </div>\n )}\n </div>\n </div>\n\n {/* Blocks area */}\n <div\n className=\"relative flex-1 overflow-hidden\"\n style={{ minWidth: totalWidth }}\n >\n {blockRows.map((row, rowIndex) =>\n row.map((block) => (\n <TimelineBlockSegment\n key={block.id}\n block={block}\n timeOrigin={timeOrigin}\n nowMs={nowMs}\n pxPerMs={pxPerMs}\n laneHeight={laneH}\n onBlockClick={onBlockClick}\n rowIndex={rowIndex}\n rowCount={rowCount}\n />\n ))\n )}\n </div>\n </div>\n\n {/* Expanded detail rows */}\n {expanded &&\n blocks\n .filter((b) => b.detail)\n .map((block) => (\n <div\n key={`detail-${block.id}`}\n className=\"ml-[128px] border-t border-sf-line/50 bg-sf-recessed px-3 py-2\"\n >\n <div className=\"mb-1 flex items-center gap-1.5\">\n <span\n className={cn(\n \"size-1.5 rounded-full\",\n BLOCK_COLORS[block.type].split(\" \")[0]\n )}\n />\n <span className=\"text-[10px] font-medium text-sf-strong\">\n {block.label ?? block.type}\n </span>\n {block.endMs && (\n <span className=\"text-[10px] text-sf-subtle\">\n {formatMs(block.endMs - block.startMs)}\n </span>\n )}\n </div>\n <div className=\"text-xs text-sf-subtle\">{block.detail}</div>\n </div>\n ))}\n </div>\n );\n }\n);\n\nAiTimelineLane.displayName = \"AiTimelineLane\";\n\n// ─── AiTimeline ───────────────────────────────────────────────────────────────\n\nconst TIME_AXIS_HEIGHT = 24;\n\n/** Format elapsed time for tick labels — shows seconds with 1 decimal when under 1 minute */\nfunction formatElapsed(ms: number): string {\n if (ms < 60_000) {\n const s = Math.round(ms / 100) / 10;\n return `${s.toFixed(s % 1 === 0 ? 0 : 1)}s`;\n }\n const m = Math.floor(ms / 60_000);\n const s = Math.round((ms % 60_000) / 1000);\n return s > 0 ? `${m}m ${s}s` : `${m}m`;\n}\n\n/** Generate time axis tick marks spaced appropriately for the zoom level. */\nfunction generateTicks(\n originMs: number,\n nowMs: number,\n pxPerMs: number,\n totalWidth: number\n): Array<{ label: string; sublabel?: string; x: number }> {\n const durationMs = nowMs - originMs;\n const tickIntervalMs = (() => {\n const pxPerSec = pxPerMs * 1000;\n if (pxPerSec >= 100) return 1000; // 1s ticks\n if (pxPerSec >= 30) return 5000; // 5s ticks\n if (pxPerSec >= 10) return 10_000; // 10s ticks\n if (pxPerSec >= 5) return 30_000; // 30s ticks\n return 60_000; // 1min ticks\n })();\n\n const ticks: Array<{ label: string; sublabel?: string; x: number }> = [];\n const firstTick = Math.ceil(originMs / tickIntervalMs) * tickIntervalMs;\n\n for (let t = firstTick; t <= originMs + durationMs; t += tickIntervalMs) {\n const elapsed = t - originMs;\n const x = elapsed * pxPerMs;\n if (x > totalWidth) break;\n const label = formatElapsed(elapsed);\n ticks.push({ label, x });\n }\n return ticks;\n}\n\n/**\n * `AiTimeline` — horizontal swim-lane timeline for commander-level orchestration.\n *\n * Displays multiple `AiTimelineLane` children on a shared time axis. Supports\n * live updating (a \"now\" marker follows the live edge), panning, and zoom via\n * `pixelsPerSecond`.\n *\n * @example\n * ```tsx\n * <AiTimeline\n * timeOrigin={state.missionStartedAt}\n * pixelsPerSecond={30}\n * showNowMarker\n * >\n * <AiTimelineLane\n * label=\"Main\"\n * blocks={mainLaneBlocks}\n * timeOrigin={timeOrigin}\n * nowMs={Date.now()}\n * pxPerMs={pxPerMs}\n * />\n * <AiTimelineLane label=\"Explore\" blocks={exploreBlocks} ... />\n * </AiTimeline>\n * ```\n */\nexport const AiTimeline = forwardRef<HTMLDivElement, AiTimelineProps>(\n (\n {\n timeOrigin,\n pixelsPerSecond = 30,\n showNowMarker = true,\n nowMs: nowMsProp,\n density: _density = SF_AI_TIMELINE_DEFAULT_VARIANTS.density,\n className,\n children,\n ...props\n },\n ref\n ) => {\n // Use the provided stable nowMs, or fall back to Date.now().\n // For SSR-safe demos, always pass a stable useState value as nowMs.\n const nowMs = nowMsProp ?? Date.now();\n const origin = timeOrigin ?? nowMs;\n const pxPerMs = pixelsPerSecond / 1000;\n const totalDurationMs = nowMs - origin;\n const totalWidth = Math.max(400, totalDurationMs * pxPerMs + 120);\n const nowX = totalDurationMs * pxPerMs;\n\n const ticks = useMemo(\n () => generateTicks(origin, nowMs, pxPerMs, totalWidth),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [origin, Math.floor(nowMs / 2000), pxPerMs, totalWidth]\n );\n\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Scroll to keep the now-marker in view\n const scrollToNow = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n const targetScroll = LABEL_WIDTH + nowX - el.clientWidth * 0.85;\n el.scrollLeft = Math.max(0, targetScroll);\n }, [nowX]);\n\n return (\n <div\n ref={ref}\n className={cn(\n \"relative overflow-hidden rounded-lg border border-sf-line bg-sf-base\",\n className\n )}\n {...props}\n >\n {/* Scrollable horizontal container */}\n <div ref={scrollRef} className=\"overflow-x-auto\">\n <div style={{ minWidth: LABEL_WIDTH + totalWidth }}>\n {/* Time axis */}\n <div\n className=\"flex border-b border-sf-line\"\n style={{ height: TIME_AXIS_HEIGHT }}\n >\n {/* Label column spacer */}\n <div\n className=\"shrink-0 border-r border-sf-line bg-sf-elevated px-3\"\n style={{ width: LABEL_WIDTH }}\n >\n <span className=\"text-[10px] font-medium uppercase tracking-wider text-sf-subtle\">\n Time\n </span>\n </div>\n {/* Axis ticks */}\n <div\n className=\"relative flex-1 bg-sf-recessed\"\n style={{ minWidth: totalWidth }}\n >\n {ticks.map((tick) => (\n <div\n key={tick.x}\n className=\"absolute top-0 flex flex-col items-center\"\n style={{ left: tick.x }}\n >\n <div className=\"h-2 w-px bg-sf-line\" />\n <span className=\"mt-0.5 font-mono text-[9px] text-sf-inactive\">\n +{tick.label}\n </span>\n </div>\n ))}\n\n {/* Now marker line */}\n {showNowMarker && (\n <div\n className=\"absolute top-0 flex flex-col items-center\"\n style={{ left: nowX }}\n >\n <div className=\"h-2 w-px bg-sf-brand\" />\n <span className=\"mt-0.5 font-mono text-[9px] font-medium text-sf-brand\">\n now\n </span>\n </div>\n )}\n </div>\n </div>\n\n {/* Lanes — pass timeOrigin/nowMs/pxPerMs via context-like clone or expect them as props */}\n <div className=\"relative\">\n {/* Vertical grid lines at tick positions */}\n <div className=\"pointer-events-none absolute inset-0 ml-[128px]\">\n {ticks.map((tick) => (\n <div\n key={`grid-${tick.x}`}\n className=\"absolute top-0 h-full w-px bg-sf-line/50\"\n style={{ left: tick.x }}\n />\n ))}\n {/* Now marker vertical line */}\n {showNowMarker && (\n <div\n className=\"absolute top-0 h-full w-px bg-sf-brand/30\"\n style={{ left: nowX }}\n />\n )}\n </div>\n\n {children}\n </div>\n </div>\n </div>\n\n {/* Scroll-to-now button */}\n {showNowMarker && (\n <button\n type=\"button\"\n aria-label=\"Scroll to now\"\n onClick={scrollToNow}\n className={cn(\n \"absolute right-2 top-1 rounded px-1.5 py-0.5 text-[9px] font-medium\",\n \"bg-sf-brand/10 text-sf-brand hover:bg-sf-brand/20 transition-colors\",\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sf-ring\"\n )}\n >\n → now\n </button>\n )}\n </div>\n );\n }\n);\n\nAiTimeline.displayName = \"AiTimeline\";\n"],"mappings":";;;;;;AAuBA,IAAa,0BAA0B,EACrC,SAAS;CACP,aAAa;EAAE,SAAS;EAAI,aAAa;EAAkC;CAC3E,SAAS;EAAE,SAAS;EAAI,aAAa;EAA+B;CACrE,EACF;AAED,IAAa,kCAAkC,EAC7C,SAAS,eACV;AAmGD,IAAM,cAA2C;CAC/C,SAAS;CACT,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;CACN,OAAO;CACP,MAAM;CACN,OAAO;CACP,MAAM;CACP;AAED,SAAS,aACP,WACA,YACa;AACb,KAAI,WAAY,QAAO;AACvB,KAAI,WAAW;EACb,MAAM,QAAQ,UAAU,aAAa;AACrC,OAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,YAAY,CACnD,KAAI,MAAM,SAAS,IAAI,CAAE,QAAO;;AAGpC,QAAO;;AAGT,SAAS,cAAc,SAAkB;AACvC,KAAI,CAAC,QAAS,QAAO;AACrB,QACE,QACG,MAAM,IAAI,CACV,KAAK,EACJ,QAAQ,YAAY,GAAG,CACxB,QAAQ,SAAS,GAAG,IAAI;;AAI/B,SAAS,SAAS,IAAY;CAC5B,MAAM,IAAI,KAAK,MAAM,KAAK,IAAI,GAAG;AACjC,KAAI,IAAI,GAAI,QAAO,GAAG,EAAE;AACxB,QAAO,GAAG,KAAK,MAAM,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,GAAG,CAAC;;AAItD,IAAM,eAAoD;CACxD,SAAS;CACT,WAAW;CACX,SAAS;CACT,UAAU;CACV,WAAW;CACX,OAAO;CACR;AAGD,IAAM,cAAc;AAEpB,SAAS,UAAU,EAAE,QAAuC;AAC1D,SAAQ,MAAR;EACE,KAAK,UACH,QAAO,oBAAC,gBAAD;GAAgB,MAAM;GAAG,WAAU;GAAiB,CAAA;EAC7D,KAAK,YACH,QAAO,oBAAC,YAAD,EAAY,MAAM,GAAK,CAAA;EAChC,KAAK,WACH,QAAO,oBAAC,mBAAD,EAAmB,MAAM,GAAK,CAAA;EACvC,KAAK,YACH,QAAO,oBAAC,iBAAD,EAAiB,MAAM,GAAK,CAAA;EACrC,KAAK,QACH,QAAO,oBAAC,aAAD,EAAa,MAAM,GAAK,CAAA;EACjC,QACE,QAAO,oBAAC,kBAAD,EAAkB,MAAM,GAAK,CAAA;;;AAM1C,SAAS,qBAAqB,EAC5B,OACA,YACA,OACA,SACA,YACA,cACA,WAAW,GACX,WAAW,KAUV;CACD,MAAM,OAAO,KAAK,IAAI,IAAI,MAAM,UAAU,cAAc,QAAQ;CAChE,MAAM,MAAM,MAAM,SAAS;CAC3B,MAAM,QAAQ,KAAK,IAAI,IAAI,MAAM,MAAM,WAAW,QAAQ;CAC1D,MAAM,aAAa,MAAM,MAAM;CAE/B,MAAM,eAAe;CAGrB,MAAM,eADU,QAAQ,KAEpB,iBACA,QAAQ,KACN,eACA;CAIN,MAAM,cAAc,aAAa;CACjC,MAAM,eAAe;CAErB,MAAM,aADkB,cAAc,eAAe,KACjB;CACpC,MAAM,YAAY,eAAe,WAAW;AAE5C,QACE,qBAAC,UAAD;EACE,MAAK;EACL,cAAY,MAAM,SAAS,MAAM;EACjC,OAAO,MAAM,eAAe,MAAM;EAClC,SAAS,qBAAqB,aAAa,MAAM,GAAG,KAAA;EACpD,WAAW,GACT,kDACA,cACA,aAAa,MAAM,OACnB,eAAe,cAAc,kBAC7B,8EACA,iDACD;EACD,OAAO;GACL;GACA;GACA,QAAQ,YAAY;GACpB,KAAK;GACN;YAlBH;GAoBE,oBAAC,WAAD,EAAW,MAAM,MAAM,MAAQ,CAAA;GAC9B,SAAS,gBAAgB,MAAM,SAC9B,oBAAC,QAAD;IAAM,WAAU;cACb,MAAM;IACF,CAAA;GAER,SAAS,gBACR,oBAAC,QAAD;IAAM,WAAU;cACb,SAAS,WAAW;IAChB,CAAA;GAEF;;;;;;;AAQb,SAAS,iBAAiB,QAAgD;AACxE,KAAI,OAAO,WAAW,EAAG,QAAO,EAAE;CAGlC,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,EAAE,UAAU,EAAE,QAAQ;CAChE,MAAM,OAA4B,EAAE;AAEpC,MAAK,MAAM,SAAS,QAAQ;EAE1B,IAAI,SAAS;AACb,OAAK,MAAM,OAAO,KAMhB,KAAI,CALa,IAAI,MAClB,aACC,MAAM,WAAW,SAAS,SAAS,cAClC,MAAM,SAAS,YAAY,SAAS,QACxC,EACc;AACb,OAAI,KAAK,MAAM;AACf,YAAS;AACT;;AAGJ,MAAI,CAAC,OAEH,MAAK,KAAK,CAAC,MAAM,CAAC;;AAItB,QAAO;;AAKT,IAAM,0BAA0B;AAChC,IAAM,sBAAsB;AAC5B,IAAM,cAAc;;;;;;;;;AAUpB,IAAa,iBAAiB,YAE1B,EACE,OACA,WACA,SACA,SAAS,QACT,QACA,YACA,OACA,SACA,kBAAkB,OAClB,cACA,MACA,UAAU,eACV,WACA,GAAG,SAEL,QACG;CACH,MAAM,CAAC,UAAU,eAAe,SAAS,gBAAgB;CACzD,MAAM,OAAO,aAAa,WAAW,KAAK;CAC1C,MAAM,aAAa,cAAc,QAAQ;CAGzC,MAAM,YAAY,cAAc,iBAAiB,OAAO,EAAE,CAAC,OAAO,CAAC;CACnE,MAAM,WAAW,UAAU;CAG3B,MAAM,YACJ,YAAY,YAAY,sBAAsB;CAChD,MAAM,QAAQ,WAAW,IAAI,YAAY,WAAW;CAGpD,MAAM,SAAS,cAAc;AAC3B,MAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,SAAO,KAAK,IAAI,GAAG,OAAO,KAAK,MAAM,EAAE,SAAS,MAAM,CAAC;IACtD;EAAC;EAAQ;EAAY;EAAM,CAAC;CAE/B,MAAM,aAAa,KAAK,IAAI,IAAI,SAAS,cAAc,QAAQ;AAE/D,QACE,qBAAC,OAAD;EACO;EACL,WAAW,GAAG,2CAA2C,UAAU;EACnE,GAAI;YAHN,CAME,qBAAC,OAAD;GAAK,WAAU;GAAO,OAAO,EAAE,QAAQ,OAAO;aAA9C,CAEE,qBAAC,OAAD;IACE,WAAU;IACV,OAAO,EAAE,OAAO,aAAa;cAF/B;KAKG,OAAO,MAAM,MAAM,EAAE,OAAO,IAC3B,oBAAC,UAAD;MACE,MAAK;MACL,cAAY,WAAW,kBAAkB;MACzC,eAAe,aAAa,MAAM,CAAC,EAAE;MACrC,WAAU;gBAEV,oBAAC,eAAD;OACE,MAAM;OACN,WAAW,GACT,wBACA,YAAY,aACb;OACD,CAAA;MACK,CAAA;KAIX,oBAAC,OAAD;MACE,WAAW,GACT,qDACA,YAAY,YAAY,WAAW,UACnC,WAAW,YACP,kBACA,WAAW,cACT,oBACA,WAAW,UACT,mBACA,iBACT;gBAEA,WAAW,YACV,oBAAC,gBAAD;OACE,MAAM,YAAY,YAAY,KAAK;OACnC,WAAU;OACV,CAAA,GAEF,oBAAC,MAAD,EAAM,MAAM,YAAY,YAAY,KAAK,IAAM,CAAA;MAE7C,CAAA;KAGN,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,oBAAC,OAAD;OACE,WAAW,GACT,wCACA,YAAY,YAAY,gBAAgB,UACzC;iBAEA;OACG,CAAA,EACL,cAAc,YAAY,iBACzB,oBAAC,OAAD;OAAK,WAAU;iBACZ;OACG,CAAA,CAEJ;;KACF;OAGN,oBAAC,OAAD;IACE,WAAU;IACV,OAAO,EAAE,UAAU,YAAY;cAE9B,UAAU,KAAK,KAAK,aACnB,IAAI,KAAK,UACP,oBAAC,sBAAD;KAES;KACK;KACL;KACE;KACT,YAAY;KACE;KACJ;KACA;KACV,EATK,MAAM,GASX,CACF,CACH;IACG,CAAA,CACF;MAGL,YACC,OACG,QAAQ,MAAM,EAAE,OAAO,CACvB,KAAK,UACJ,qBAAC,OAAD;GAEE,WAAU;aAFZ,CAIE,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAAC,QAAD,EACE,WAAW,GACT,yBACA,aAAa,MAAM,MAAM,MAAM,IAAI,CAAC,GACrC,EACD,CAAA;KACF,oBAAC,QAAD;MAAM,WAAU;gBACb,MAAM,SAAS,MAAM;MACjB,CAAA;KACN,MAAM,SACL,oBAAC,QAAD;MAAM,WAAU;gBACb,SAAS,MAAM,QAAQ,MAAM,QAAQ;MACjC,CAAA;KAEL;OACN,oBAAC,OAAD;IAAK,WAAU;cAA0B,MAAM;IAAa,CAAA,CACxD;KApBC,UAAU,MAAM,KAoBjB,CACN,CACF;;EAGX;AAED,eAAe,cAAc;AAI7B,IAAM,mBAAmB;;AAGzB,SAAS,cAAc,IAAoB;AACzC,KAAI,KAAK,KAAQ;EACf,MAAM,IAAI,KAAK,MAAM,KAAK,IAAI,GAAG;AACjC,SAAO,GAAG,EAAE,QAAQ,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;;CAE3C,MAAM,IAAI,KAAK,MAAM,KAAK,IAAO;CACjC,MAAM,IAAI,KAAK,MAAO,KAAK,MAAU,IAAK;AAC1C,QAAO,IAAI,IAAI,GAAG,EAAE,IAAI,EAAE,KAAK,GAAG,EAAE;;;AAItC,SAAS,cACP,UACA,OACA,SACA,YACwD;CACxD,MAAM,aAAa,QAAQ;CAC3B,MAAM,wBAAwB;EAC5B,MAAM,WAAW,UAAU;AAC3B,MAAI,YAAY,IAAK,QAAO;AAC5B,MAAI,YAAY,GAAI,QAAO;AAC3B,MAAI,YAAY,GAAI,QAAO;AAC3B,MAAI,YAAY,EAAG,QAAO;AAC1B,SAAO;KACL;CAEJ,MAAM,QAAgE,EAAE;CACxE,MAAM,YAAY,KAAK,KAAK,WAAW,eAAe,GAAG;AAEzD,MAAK,IAAI,IAAI,WAAW,KAAK,WAAW,YAAY,KAAK,gBAAgB;EACvE,MAAM,UAAU,IAAI;EACpB,MAAM,IAAI,UAAU;AACpB,MAAI,IAAI,WAAY;EACpB,MAAM,QAAQ,cAAc,QAAQ;AACpC,QAAM,KAAK;GAAE;GAAO;GAAG,CAAC;;AAE1B,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BT,IAAa,aAAa,YAEtB,EACE,YACA,kBAAkB,IAClB,gBAAgB,MAChB,OAAO,WACP,SAAS,WAAW,gCAAgC,SACpD,WACA,UACA,GAAG,SAEL,QACG;CAGH,MAAM,QAAQ,aAAa,KAAK,KAAK;CACrC,MAAM,SAAS,cAAc;CAC7B,MAAM,UAAU,kBAAkB;CAClC,MAAM,kBAAkB,QAAQ;CAChC,MAAM,aAAa,KAAK,IAAI,KAAK,kBAAkB,UAAU,IAAI;CACjE,MAAM,OAAO,kBAAkB;CAE/B,MAAM,QAAQ,cACN,cAAc,QAAQ,OAAO,SAAS,WAAW,EAEvD;EAAC;EAAQ,KAAK,MAAM,QAAQ,IAAK;EAAE;EAAS;EAAW,CACxD;CAED,MAAM,YAAY,OAAuB,KAAK;CAG9C,MAAM,cAAc,kBAAkB;EACpC,MAAM,KAAK,UAAU;AACrB,MAAI,CAAC,GAAI;EACT,MAAM,eAAe,cAAc,OAAO,GAAG,cAAc;AAC3D,KAAG,aAAa,KAAK,IAAI,GAAG,aAAa;IACxC,CAAC,KAAK,CAAC;AAEV,QACE,qBAAC,OAAD;EACO;EACL,WAAW,GACT,wEACA,UACD;EACD,GAAI;YANN,CASE,oBAAC,OAAD;GAAK,KAAK;GAAW,WAAU;aAC7B,qBAAC,OAAD;IAAK,OAAO,EAAE,UAAU,cAAc,YAAY;cAAlD,CAEE,qBAAC,OAAD;KACE,WAAU;KACV,OAAO,EAAE,QAAQ,kBAAkB;eAFrC,CAKE,oBAAC,OAAD;MACE,WAAU;MACV,OAAO,EAAE,OAAO,aAAa;gBAE7B,oBAAC,QAAD;OAAM,WAAU;iBAAkE;OAE3E,CAAA;MACH,CAAA,EAEN,qBAAC,OAAD;MACE,WAAU;MACV,OAAO,EAAE,UAAU,YAAY;gBAFjC,CAIG,MAAM,KAAK,SACV,qBAAC,OAAD;OAEE,WAAU;OACV,OAAO,EAAE,MAAM,KAAK,GAAG;iBAHzB,CAKE,oBAAC,OAAD,EAAK,WAAU,uBAAwB,CAAA,EACvC,qBAAC,QAAD;QAAM,WAAU;kBAAhB,CAA+D,KAC3D,KAAK,MACF;UACH;SARC,KAAK,EAQN,CACN,EAGD,iBACC,qBAAC,OAAD;OACE,WAAU;OACV,OAAO,EAAE,MAAM,MAAM;iBAFvB,CAIE,oBAAC,OAAD,EAAK,WAAU,wBAAyB,CAAA,EACxC,oBAAC,QAAD;QAAM,WAAU;kBAAwD;QAEjE,CAAA,CACH;SAEJ;QACF;QAGN,qBAAC,OAAD;KAAK,WAAU;eAAf,CAEE,qBAAC,OAAD;MAAK,WAAU;gBAAf,CACG,MAAM,KAAK,SACV,oBAAC,OAAD;OAEE,WAAU;OACV,OAAO,EAAE,MAAM,KAAK,GAAG;OACvB,EAHK,QAAQ,KAAK,IAGlB,CACF,EAED,iBACC,oBAAC,OAAD;OACE,WAAU;OACV,OAAO,EAAE,MAAM,MAAM;OACrB,CAAA,CAEA;SAEL,SACG;OACF;;GACF,CAAA,EAGL,iBACC,oBAAC,UAAD;GACE,MAAK;GACL,cAAW;GACX,SAAS;GACT,WAAW,GACT,uEACA,uEACA,6EACD;aACF;GAEQ,CAAA,CAEP;;EAGX;AAED,WAAW,cAAc"}