@tetrascience-npm/tetrascience-react-ui 0.7.0-beta.108.1 → 0.7.0-beta.128.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. package/README.md +2 -2
  2. package/dist/components/ai/chain-of-thought.cjs +1 -1
  3. package/dist/components/ai/chain-of-thought.cjs.map +1 -1
  4. package/dist/components/ai/chain-of-thought.js +1 -1
  5. package/dist/components/ai/chain-of-thought.js.map +1 -1
  6. package/dist/components/ai/confirmation.cjs +1 -1
  7. package/dist/components/ai/confirmation.cjs.map +1 -1
  8. package/dist/components/ai/confirmation.js +1 -1
  9. package/dist/components/ai/confirmation.js.map +1 -1
  10. package/dist/components/ai/context.cjs +1 -1
  11. package/dist/components/ai/context.cjs.map +1 -1
  12. package/dist/components/ai/context.js +36 -35
  13. package/dist/components/ai/context.js.map +1 -1
  14. package/dist/components/ai/message.cjs +1 -1
  15. package/dist/components/ai/message.cjs.map +1 -1
  16. package/dist/components/ai/message.js +68 -68
  17. package/dist/components/ai/message.js.map +1 -1
  18. package/dist/components/ai/prompt-input.cjs +1 -1
  19. package/dist/components/ai/prompt-input.cjs.map +1 -1
  20. package/dist/components/ai/prompt-input.js +4 -2
  21. package/dist/components/ai/prompt-input.js.map +1 -1
  22. package/dist/components/ai/queue.cjs +1 -1
  23. package/dist/components/ai/queue.cjs.map +1 -1
  24. package/dist/components/ai/queue.js +9 -9
  25. package/dist/components/ai/queue.js.map +1 -1
  26. package/dist/components/ai/reasoning.cjs +1 -1
  27. package/dist/components/ai/reasoning.cjs.map +1 -1
  28. package/dist/components/ai/reasoning.js +67 -67
  29. package/dist/components/ai/reasoning.js.map +1 -1
  30. package/dist/components/ai/stream-status.cjs +1 -1
  31. package/dist/components/ai/stream-status.cjs.map +1 -1
  32. package/dist/components/ai/stream-status.js +41 -39
  33. package/dist/components/ai/stream-status.js.map +1 -1
  34. package/dist/components/ai/streamdown-code-plugin.cjs +2 -0
  35. package/dist/components/ai/streamdown-code-plugin.cjs.map +1 -0
  36. package/dist/components/ai/streamdown-code-plugin.js +42 -0
  37. package/dist/components/ai/streamdown-code-plugin.js.map +1 -0
  38. package/dist/components/ai/streamdown-plugins.cjs +2 -0
  39. package/dist/components/ai/streamdown-plugins.cjs.map +1 -0
  40. package/dist/components/ai/streamdown-plugins.js +14 -0
  41. package/dist/components/ai/streamdown-plugins.js.map +1 -0
  42. package/dist/components/ai/task.cjs +1 -1
  43. package/dist/components/ai/task.cjs.map +1 -1
  44. package/dist/components/ai/task.js +18 -11
  45. package/dist/components/ai/task.js.map +1 -1
  46. package/dist/components/ai/tool.cjs +1 -1
  47. package/dist/components/ai/tool.cjs.map +1 -1
  48. package/dist/components/ai/tool.js +51 -55
  49. package/dist/components/ai/tool.js.map +1 -1
  50. package/dist/components/ai/use-streamdown-plugins.cjs +2 -0
  51. package/dist/components/ai/use-streamdown-plugins.cjs.map +1 -0
  52. package/dist/components/ai/use-streamdown-plugins.js +25 -0
  53. package/dist/components/ai/use-streamdown-plugins.js.map +1 -0
  54. package/dist/components/charts/AreaPlot/AreaPlot.cjs +2 -0
  55. package/dist/components/charts/AreaPlot/AreaPlot.cjs.map +1 -0
  56. package/dist/components/charts/AreaPlot/AreaPlot.js +270 -0
  57. package/dist/components/charts/AreaPlot/AreaPlot.js.map +1 -0
  58. package/dist/components/charts/BarChart/BarChart.cjs +2 -0
  59. package/dist/components/charts/BarChart/BarChart.cjs.map +1 -0
  60. package/dist/components/charts/BarChart/BarChart.js +219 -0
  61. package/dist/components/charts/BarChart/BarChart.js.map +1 -0
  62. package/dist/components/charts/BoxPlot/BoxPlot.cjs +2 -0
  63. package/dist/components/charts/BoxPlot/BoxPlot.cjs.map +1 -0
  64. package/dist/components/charts/{Boxplot/Boxplot.js → BoxPlot/BoxPlot.js} +78 -79
  65. package/dist/components/charts/BoxPlot/BoxPlot.js.map +1 -0
  66. package/dist/components/charts/ChartTooltip/ChartTooltip.cjs +1 -1
  67. package/dist/components/charts/ChartTooltip/ChartTooltip.cjs.map +1 -1
  68. package/dist/components/charts/ChartTooltip/ChartTooltip.js +22 -22
  69. package/dist/components/charts/ChartTooltip/ChartTooltip.js.map +1 -1
  70. package/dist/components/charts/Chromatogram/Chromatogram.cjs +1 -1
  71. package/dist/components/charts/Chromatogram/Chromatogram.cjs.map +1 -1
  72. package/dist/components/charts/Chromatogram/Chromatogram.js +232 -170
  73. package/dist/components/charts/Chromatogram/Chromatogram.js.map +1 -1
  74. package/dist/components/charts/Chromatogram/annotations.cjs +2 -0
  75. package/dist/components/charts/Chromatogram/annotations.cjs.map +1 -0
  76. package/dist/components/charts/Chromatogram/annotations.js +137 -0
  77. package/dist/components/charts/Chromatogram/annotations.js.map +1 -0
  78. package/dist/components/charts/Chromatogram/boundaryMarkers.cjs.map +1 -0
  79. package/dist/components/charts/Chromatogram/boundaryMarkers.js.map +1 -0
  80. package/dist/components/charts/Chromatogram/constants.cjs.map +1 -0
  81. package/dist/components/charts/Chromatogram/constants.js.map +1 -0
  82. package/dist/components/charts/Chromatogram/dataProcessing.cjs.map +1 -0
  83. package/dist/components/charts/Chromatogram/dataProcessing.js.map +1 -0
  84. package/dist/components/charts/Chromatogram/peakDetection.cjs.map +1 -0
  85. package/dist/components/charts/Chromatogram/peakDetection.js.map +1 -0
  86. package/dist/components/charts/Chromatogram/plotBuilder.cjs +2 -0
  87. package/dist/components/charts/Chromatogram/plotBuilder.cjs.map +1 -0
  88. package/dist/components/charts/Chromatogram/plotBuilder.js +216 -0
  89. package/dist/components/charts/Chromatogram/plotBuilder.js.map +1 -0
  90. package/dist/components/charts/Chromatogram/regionOverlays.cjs.map +1 -0
  91. package/dist/components/charts/Chromatogram/regionOverlays.js.map +1 -0
  92. package/dist/components/charts/Electropherogram/Electropherogram.cjs +2 -0
  93. package/dist/components/charts/Electropherogram/Electropherogram.cjs.map +1 -0
  94. package/dist/components/charts/Electropherogram/Electropherogram.js +180 -0
  95. package/dist/components/charts/Electropherogram/Electropherogram.js.map +1 -0
  96. package/dist/components/charts/Histogram/Histogram.cjs +1 -1
  97. package/dist/components/charts/Histogram/Histogram.cjs.map +1 -1
  98. package/dist/components/charts/Histogram/Histogram.js +107 -108
  99. package/dist/components/charts/Histogram/Histogram.js.map +1 -1
  100. package/dist/components/charts/LinePlot/LinePlot.cjs +2 -0
  101. package/dist/components/charts/LinePlot/LinePlot.cjs.map +1 -0
  102. package/dist/components/charts/LinePlot/LinePlot.js +224 -0
  103. package/dist/components/charts/LinePlot/LinePlot.js.map +1 -0
  104. package/dist/components/charts/PieChart/PieChart.cjs +1 -1
  105. package/dist/components/charts/PieChart/PieChart.cjs.map +1 -1
  106. package/dist/components/charts/PieChart/PieChart.js +62 -61
  107. package/dist/components/charts/PieChart/PieChart.js.map +1 -1
  108. package/dist/components/charts/PlateMap/PlateMap.cjs +1 -1
  109. package/dist/components/charts/PlateMap/PlateMap.cjs.map +1 -1
  110. package/dist/components/charts/PlateMap/PlateMap.js +246 -242
  111. package/dist/components/charts/PlateMap/PlateMap.js.map +1 -1
  112. package/dist/components/charts/ScatterPlot/ScatterPlot.cjs +2 -0
  113. package/dist/components/charts/ScatterPlot/ScatterPlot.cjs.map +1 -0
  114. package/dist/components/charts/ScatterPlot/ScatterPlot.js +252 -0
  115. package/dist/components/charts/ScatterPlot/ScatterPlot.js.map +1 -0
  116. package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.cjs +2 -0
  117. package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.cjs.map +1 -0
  118. package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.js +215 -0
  119. package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.js.map +1 -0
  120. package/dist/components/charts/ScatterPlotInteractive/constants.cjs +2 -0
  121. package/dist/components/charts/ScatterPlotInteractive/constants.cjs.map +1 -0
  122. package/dist/components/charts/ScatterPlotInteractive/constants.js +38 -0
  123. package/dist/components/charts/ScatterPlotInteractive/constants.js.map +1 -0
  124. package/dist/components/charts/ScatterPlotInteractive/utils.cjs +2 -0
  125. package/dist/components/charts/ScatterPlotInteractive/utils.cjs.map +1 -0
  126. package/dist/components/charts/ScatterPlotInteractive/utils.js +261 -0
  127. package/dist/components/charts/ScatterPlotInteractive/utils.js.map +1 -0
  128. package/dist/components/charts/StackedChromatogram/StackedChromatogram.cjs +2 -0
  129. package/dist/components/charts/StackedChromatogram/StackedChromatogram.cjs.map +1 -0
  130. package/dist/components/charts/StackedChromatogram/StackedChromatogram.js +40 -0
  131. package/dist/components/charts/StackedChromatogram/StackedChromatogram.js.map +1 -0
  132. package/dist/components/charts/StackedChromatogram/transforms.cjs.map +1 -0
  133. package/dist/components/charts/StackedChromatogram/transforms.js.map +1 -0
  134. package/dist/components/charts/plotly-loader.cjs +2 -0
  135. package/dist/components/charts/plotly-loader.cjs.map +1 -0
  136. package/dist/components/charts/plotly-loader.js +22 -0
  137. package/dist/components/charts/plotly-loader.js.map +1 -0
  138. package/dist/components/composed/AssistantLayout/AssistantLayout.cjs +2 -0
  139. package/dist/components/composed/AssistantLayout/AssistantLayout.cjs.map +1 -0
  140. package/dist/components/composed/AssistantLayout/AssistantLayout.js +142 -0
  141. package/dist/components/composed/AssistantLayout/AssistantLayout.js.map +1 -0
  142. package/dist/components/composed/AssistantLayout/dockLayout.cjs +2 -0
  143. package/dist/components/composed/AssistantLayout/dockLayout.cjs.map +1 -0
  144. package/dist/components/composed/AssistantLayout/dockLayout.js +10 -0
  145. package/dist/components/composed/AssistantLayout/dockLayout.js.map +1 -0
  146. package/dist/components/composed/Chat/Chat.cjs +1 -1
  147. package/dist/components/composed/Chat/Chat.cjs.map +1 -1
  148. package/dist/components/composed/Chat/Chat.js +23 -23
  149. package/dist/components/composed/Chat/Chat.js.map +1 -1
  150. package/dist/components/composed/ConfirmDialog/ConfirmDialog.cjs +1 -1
  151. package/dist/components/composed/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
  152. package/dist/components/composed/ConfirmDialog/ConfirmDialog.js +33 -29
  153. package/dist/components/composed/ConfirmDialog/ConfirmDialog.js.map +1 -1
  154. package/dist/components/composed/DataAppShell/CollapseButton.cjs +2 -0
  155. package/dist/components/composed/DataAppShell/CollapseButton.cjs.map +1 -0
  156. package/dist/components/composed/DataAppShell/CollapseButton.js +42 -0
  157. package/dist/components/composed/DataAppShell/CollapseButton.js.map +1 -0
  158. package/dist/components/composed/DataAppShell/DataAppShell.cjs +1 -1
  159. package/dist/components/composed/DataAppShell/DataAppShell.cjs.map +1 -1
  160. package/dist/components/composed/DataAppShell/DataAppShell.js +349 -313
  161. package/dist/components/composed/DataAppShell/DataAppShell.js.map +1 -1
  162. package/dist/components/composed/DataAppShell/PrimaryNav.cjs +2 -0
  163. package/dist/components/composed/DataAppShell/PrimaryNav.cjs.map +1 -0
  164. package/dist/components/composed/DataAppShell/PrimaryNav.js +268 -0
  165. package/dist/components/composed/DataAppShell/PrimaryNav.js.map +1 -0
  166. package/dist/components/composed/DataAppShell/RightPanel.cjs +2 -0
  167. package/dist/components/composed/DataAppShell/RightPanel.cjs.map +1 -0
  168. package/dist/components/composed/DataAppShell/RightPanel.js +282 -0
  169. package/dist/components/composed/DataAppShell/RightPanel.js.map +1 -0
  170. package/dist/components/composed/DataAppShell/SecondaryNav.cjs +2 -0
  171. package/dist/components/composed/DataAppShell/SecondaryNav.cjs.map +1 -0
  172. package/dist/components/composed/DataAppShell/SecondaryNav.js +364 -0
  173. package/dist/components/composed/DataAppShell/SecondaryNav.js.map +1 -0
  174. package/dist/components/composed/DataAppShell/ShellContext.cjs +2 -0
  175. package/dist/components/composed/DataAppShell/ShellContext.cjs.map +1 -0
  176. package/dist/components/composed/DataAppShell/ShellContext.js +23 -0
  177. package/dist/components/composed/DataAppShell/ShellContext.js.map +1 -0
  178. package/dist/components/composed/MoleculeStructure/MoleculeStructure.cjs +2 -0
  179. package/dist/components/composed/MoleculeStructure/MoleculeStructure.cjs.map +1 -0
  180. package/dist/components/composed/MoleculeStructure/MoleculeStructure.js +87 -0
  181. package/dist/components/composed/MoleculeStructure/MoleculeStructure.js.map +1 -0
  182. package/dist/components/composed/MoleculeStructure/rdkit-loader.cjs +2 -0
  183. package/dist/components/composed/MoleculeStructure/rdkit-loader.cjs.map +1 -0
  184. package/dist/components/composed/MoleculeStructure/rdkit-loader.js +89 -0
  185. package/dist/components/composed/MoleculeStructure/rdkit-loader.js.map +1 -0
  186. package/dist/components/composed/MoleculeStructure/use-rdkit.cjs +2 -0
  187. package/dist/components/composed/MoleculeStructure/use-rdkit.cjs.map +1 -0
  188. package/dist/components/composed/MoleculeStructure/use-rdkit.js +19 -0
  189. package/dist/components/composed/MoleculeStructure/use-rdkit.js.map +1 -0
  190. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs +1 -1
  191. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs.map +1 -1
  192. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js +17 -17
  193. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js.map +1 -1
  194. package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.cjs +1 -1
  195. package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.cjs.map +1 -1
  196. package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.js +33 -33
  197. package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.js.map +1 -1
  198. package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.cjs +1 -1
  199. package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.cjs.map +1 -1
  200. package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.js +7 -7
  201. package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.js.map +1 -1
  202. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs +1 -1
  203. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs.map +1 -1
  204. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js +1 -1
  205. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js.map +1 -1
  206. package/dist/components/composed/PlateMapEditor/WellLegend.cjs +1 -1
  207. package/dist/components/composed/PlateMapEditor/WellLegend.cjs.map +1 -1
  208. package/dist/components/composed/PlateMapEditor/WellLegend.js +24 -12
  209. package/dist/components/composed/PlateMapEditor/WellLegend.js.map +1 -1
  210. package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs +1 -1
  211. package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs.map +1 -1
  212. package/dist/components/composed/PlateMapEditor/WellManifestTable.js +1 -1
  213. package/dist/components/composed/PlateMapEditor/WellManifestTable.js.map +1 -1
  214. package/dist/components/composed/TdpSearch/components/DefaultFilters.cjs +1 -1
  215. package/dist/components/composed/TdpSearch/components/DefaultFilters.cjs.map +1 -1
  216. package/dist/components/composed/TdpSearch/components/DefaultFilters.js +3 -3
  217. package/dist/components/composed/TdpSearch/components/DefaultFilters.js.map +1 -1
  218. package/dist/components/composed/TopBar/TopBar.cjs +2 -0
  219. package/dist/components/composed/TopBar/TopBar.cjs.map +1 -0
  220. package/dist/components/composed/TopBar/TopBar.js +56 -0
  221. package/dist/components/composed/TopBar/TopBar.js.map +1 -0
  222. package/dist/components/composed/UserMenu/UserMenu.cjs +2 -0
  223. package/dist/components/composed/UserMenu/UserMenu.cjs.map +1 -0
  224. package/dist/components/composed/UserMenu/UserMenu.js +99 -0
  225. package/dist/components/composed/UserMenu/UserMenu.js.map +1 -0
  226. package/dist/components/composed/tdp-link.cjs +1 -1
  227. package/dist/components/composed/tdp-link.cjs.map +1 -1
  228. package/dist/components/composed/tdp-link.js +5 -5
  229. package/dist/components/composed/tdp-link.js.map +1 -1
  230. package/dist/components/ui/alert.cjs +1 -1
  231. package/dist/components/ui/alert.cjs.map +1 -1
  232. package/dist/components/ui/alert.js +12 -12
  233. package/dist/components/ui/alert.js.map +1 -1
  234. package/dist/components/ui/badge.cjs +1 -1
  235. package/dist/components/ui/badge.cjs.map +1 -1
  236. package/dist/components/ui/badge.js +14 -14
  237. package/dist/components/ui/badge.js.map +1 -1
  238. package/dist/components/ui/banner.cjs +1 -1
  239. package/dist/components/ui/banner.cjs.map +1 -1
  240. package/dist/components/ui/banner.js +17 -17
  241. package/dist/components/ui/banner.js.map +1 -1
  242. package/dist/components/ui/button.cjs +1 -1
  243. package/dist/components/ui/button.cjs.map +1 -1
  244. package/dist/components/ui/button.js +16 -16
  245. package/dist/components/ui/button.js.map +1 -1
  246. package/dist/components/ui/calendar.cjs +1 -1
  247. package/dist/components/ui/calendar.cjs.map +1 -1
  248. package/dist/components/ui/calendar.js +3 -3
  249. package/dist/components/ui/calendar.js.map +1 -1
  250. package/dist/components/ui/code-block.cjs +3 -3
  251. package/dist/components/ui/code-block.cjs.map +1 -1
  252. package/dist/components/ui/code-block.js +136 -118
  253. package/dist/components/ui/code-block.js.map +1 -1
  254. package/dist/components/ui/code-editor.cjs +1 -1
  255. package/dist/components/ui/code-editor.cjs.map +1 -1
  256. package/dist/components/ui/code-editor.js +14 -12
  257. package/dist/components/ui/code-editor.js.map +1 -1
  258. package/dist/components/ui/combobox.cjs +1 -1
  259. package/dist/components/ui/combobox.cjs.map +1 -1
  260. package/dist/components/ui/combobox.js +33 -29
  261. package/dist/components/ui/combobox.js.map +1 -1
  262. package/dist/components/ui/command.cjs +1 -1
  263. package/dist/components/ui/command.cjs.map +1 -1
  264. package/dist/components/ui/command.js +81 -77
  265. package/dist/components/ui/command.js.map +1 -1
  266. package/dist/components/ui/context-menu.cjs +1 -1
  267. package/dist/components/ui/context-menu.cjs.map +1 -1
  268. package/dist/components/ui/context-menu.js +13 -13
  269. package/dist/components/ui/context-menu.js.map +1 -1
  270. package/dist/components/ui/data-table/data-table-column-toggle.cjs +1 -1
  271. package/dist/components/ui/data-table/data-table-column-toggle.cjs.map +1 -1
  272. package/dist/components/ui/data-table/data-table-column-toggle.js +70 -62
  273. package/dist/components/ui/data-table/data-table-column-toggle.js.map +1 -1
  274. package/dist/components/ui/data-table/data-table-filter.cjs +1 -1
  275. package/dist/components/ui/data-table/data-table-filter.cjs.map +1 -1
  276. package/dist/components/ui/data-table/data-table-filter.js +24 -23
  277. package/dist/components/ui/data-table/data-table-filter.js.map +1 -1
  278. package/dist/components/ui/data-table/data-table-group.cjs +1 -1
  279. package/dist/components/ui/data-table/data-table-group.cjs.map +1 -1
  280. package/dist/components/ui/data-table/data-table-group.js +17 -16
  281. package/dist/components/ui/data-table/data-table-group.js.map +1 -1
  282. package/dist/components/ui/data-table/data-table-pagination.cjs +1 -1
  283. package/dist/components/ui/data-table/data-table-pagination.cjs.map +1 -1
  284. package/dist/components/ui/data-table/data-table-pagination.js +15 -15
  285. package/dist/components/ui/data-table/data-table-pagination.js.map +1 -1
  286. package/dist/components/ui/data-table/data-table.cjs +1 -1
  287. package/dist/components/ui/data-table/data-table.cjs.map +1 -1
  288. package/dist/components/ui/data-table/data-table.js +191 -190
  289. package/dist/components/ui/data-table/data-table.js.map +1 -1
  290. package/dist/components/ui/dialog.cjs +1 -1
  291. package/dist/components/ui/dialog.cjs.map +1 -1
  292. package/dist/components/ui/dialog.js +1 -1
  293. package/dist/components/ui/dialog.js.map +1 -1
  294. package/dist/components/ui/dropdown-menu.cjs +1 -1
  295. package/dist/components/ui/dropdown-menu.cjs.map +1 -1
  296. package/dist/components/ui/dropdown-menu.js +12 -4
  297. package/dist/components/ui/dropdown-menu.js.map +1 -1
  298. package/dist/components/ui/hover-card.cjs +1 -1
  299. package/dist/components/ui/hover-card.cjs.map +1 -1
  300. package/dist/components/ui/hover-card.js +3 -3
  301. package/dist/components/ui/hover-card.js.map +1 -1
  302. package/dist/components/ui/item.cjs +1 -1
  303. package/dist/components/ui/item.cjs.map +1 -1
  304. package/dist/components/ui/item.js +44 -36
  305. package/dist/components/ui/item.js.map +1 -1
  306. package/dist/components/ui/menubar.cjs +1 -1
  307. package/dist/components/ui/menubar.cjs.map +1 -1
  308. package/dist/components/ui/menubar.js +2 -2
  309. package/dist/components/ui/menubar.js.map +1 -1
  310. package/dist/components/ui/navigation-menu.cjs +1 -1
  311. package/dist/components/ui/navigation-menu.cjs.map +1 -1
  312. package/dist/components/ui/navigation-menu.js +1 -1
  313. package/dist/components/ui/navigation-menu.js.map +1 -1
  314. package/dist/components/ui/popover.cjs +1 -1
  315. package/dist/components/ui/popover.cjs.map +1 -1
  316. package/dist/components/ui/popover.js +1 -1
  317. package/dist/components/ui/popover.js.map +1 -1
  318. package/dist/components/ui/scroll-area.cjs +1 -1
  319. package/dist/components/ui/scroll-area.cjs.map +1 -1
  320. package/dist/components/ui/scroll-area.js +1 -0
  321. package/dist/components/ui/scroll-area.js.map +1 -1
  322. package/dist/components/ui/select.cjs +1 -1
  323. package/dist/components/ui/select.cjs.map +1 -1
  324. package/dist/components/ui/select.js +1 -1
  325. package/dist/components/ui/select.js.map +1 -1
  326. package/dist/components/ui/sheet.cjs +1 -1
  327. package/dist/components/ui/sheet.cjs.map +1 -1
  328. package/dist/components/ui/sheet.js +5 -5
  329. package/dist/components/ui/sheet.js.map +1 -1
  330. package/dist/components/ui/sidebar.cjs +1 -1
  331. package/dist/components/ui/sidebar.cjs.map +1 -1
  332. package/dist/components/ui/sidebar.js +2 -2
  333. package/dist/components/ui/sidebar.js.map +1 -1
  334. package/dist/components/ui/slider.cjs +1 -1
  335. package/dist/components/ui/slider.cjs.map +1 -1
  336. package/dist/components/ui/slider.js +10 -9
  337. package/dist/components/ui/slider.js.map +1 -1
  338. package/dist/components/ui/sonner.cjs +1 -1
  339. package/dist/components/ui/sonner.cjs.map +1 -1
  340. package/dist/components/ui/sonner.js +25 -10
  341. package/dist/components/ui/sonner.js.map +1 -1
  342. package/dist/components/ui/table.cjs +1 -1
  343. package/dist/components/ui/table.cjs.map +1 -1
  344. package/dist/components/ui/table.js +1 -0
  345. package/dist/components/ui/table.js.map +1 -1
  346. package/dist/components/ui/tabs.cjs +1 -1
  347. package/dist/components/ui/tabs.cjs.map +1 -1
  348. package/dist/components/ui/tabs.js +18 -18
  349. package/dist/components/ui/tabs.js.map +1 -1
  350. package/dist/components/ui/tetra-molecule-icon.cjs +2 -0
  351. package/dist/components/ui/tetra-molecule-icon.cjs.map +1 -0
  352. package/dist/components/ui/tetra-molecule-icon.js +49 -0
  353. package/dist/components/ui/tetra-molecule-icon.js.map +1 -0
  354. package/dist/components/ui/toggle-group.cjs +1 -1
  355. package/dist/components/ui/toggle-group.cjs.map +1 -1
  356. package/dist/components/ui/toggle-group.js +35 -31
  357. package/dist/components/ui/toggle-group.js.map +1 -1
  358. package/dist/hooks/use-plotly-theme.cjs +1 -1
  359. package/dist/hooks/use-plotly-theme.cjs.map +1 -1
  360. package/dist/hooks/use-plotly-theme.js +4 -3
  361. package/dist/hooks/use-plotly-theme.js.map +1 -1
  362. package/dist/index.cjs +1 -1
  363. package/dist/index.css +1 -1
  364. package/dist/index.d.ts +1073 -136
  365. package/dist/index.js +698 -647
  366. package/dist/index.js.map +1 -1
  367. package/dist/index.tailwind.css +1 -1
  368. package/dist/lib/shiki.cjs +2 -0
  369. package/dist/lib/shiki.cjs.map +1 -0
  370. package/dist/lib/shiki.js +72 -0
  371. package/dist/lib/shiki.js.map +1 -0
  372. package/package.json +23 -12
  373. package/dist/components/charts/AreaGraph/AreaGraph.cjs +0 -2
  374. package/dist/components/charts/AreaGraph/AreaGraph.cjs.map +0 -1
  375. package/dist/components/charts/AreaGraph/AreaGraph.js +0 -271
  376. package/dist/components/charts/AreaGraph/AreaGraph.js.map +0 -1
  377. package/dist/components/charts/BarGraph/BarGraph.cjs +0 -2
  378. package/dist/components/charts/BarGraph/BarGraph.cjs.map +0 -1
  379. package/dist/components/charts/BarGraph/BarGraph.js +0 -220
  380. package/dist/components/charts/BarGraph/BarGraph.js.map +0 -1
  381. package/dist/components/charts/Boxplot/Boxplot.cjs +0 -2
  382. package/dist/components/charts/Boxplot/Boxplot.cjs.map +0 -1
  383. package/dist/components/charts/Boxplot/Boxplot.js.map +0 -1
  384. package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs +0 -2
  385. package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs.map +0 -1
  386. package/dist/components/charts/ChromatogramChart/ChromatogramChart.js +0 -241
  387. package/dist/components/charts/ChromatogramChart/ChromatogramChart.js.map +0 -1
  388. package/dist/components/charts/ChromatogramChart/annotations.cjs +0 -2
  389. package/dist/components/charts/ChromatogramChart/annotations.cjs.map +0 -1
  390. package/dist/components/charts/ChromatogramChart/annotations.js +0 -136
  391. package/dist/components/charts/ChromatogramChart/annotations.js.map +0 -1
  392. package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs.map +0 -1
  393. package/dist/components/charts/ChromatogramChart/boundaryMarkers.js.map +0 -1
  394. package/dist/components/charts/ChromatogramChart/constants.cjs.map +0 -1
  395. package/dist/components/charts/ChromatogramChart/constants.js.map +0 -1
  396. package/dist/components/charts/ChromatogramChart/dataProcessing.cjs.map +0 -1
  397. package/dist/components/charts/ChromatogramChart/dataProcessing.js.map +0 -1
  398. package/dist/components/charts/ChromatogramChart/peakDetection.cjs.map +0 -1
  399. package/dist/components/charts/ChromatogramChart/peakDetection.js.map +0 -1
  400. package/dist/components/charts/ChromatogramChart/plotBuilder.cjs +0 -2
  401. package/dist/components/charts/ChromatogramChart/plotBuilder.cjs.map +0 -1
  402. package/dist/components/charts/ChromatogramChart/plotBuilder.js +0 -207
  403. package/dist/components/charts/ChromatogramChart/plotBuilder.js.map +0 -1
  404. package/dist/components/charts/ChromatogramChart/regionOverlays.cjs.map +0 -1
  405. package/dist/components/charts/ChromatogramChart/regionOverlays.js.map +0 -1
  406. package/dist/components/charts/DotPlot/DotPlot.cjs +0 -2
  407. package/dist/components/charts/DotPlot/DotPlot.cjs.map +0 -1
  408. package/dist/components/charts/DotPlot/DotPlot.js +0 -208
  409. package/dist/components/charts/DotPlot/DotPlot.js.map +0 -1
  410. package/dist/components/charts/Heatmap/Heatmap.cjs +0 -2
  411. package/dist/components/charts/Heatmap/Heatmap.cjs.map +0 -1
  412. package/dist/components/charts/Heatmap/Heatmap.js +0 -67
  413. package/dist/components/charts/Heatmap/Heatmap.js.map +0 -1
  414. package/dist/components/charts/LineGraph/LineGraph.cjs +0 -2
  415. package/dist/components/charts/LineGraph/LineGraph.cjs.map +0 -1
  416. package/dist/components/charts/LineGraph/LineGraph.js +0 -225
  417. package/dist/components/charts/LineGraph/LineGraph.js.map +0 -1
  418. package/dist/components/charts/ScatterGraph/ScatterGraph.cjs +0 -2
  419. package/dist/components/charts/ScatterGraph/ScatterGraph.cjs.map +0 -1
  420. package/dist/components/charts/ScatterGraph/ScatterGraph.js +0 -234
  421. package/dist/components/charts/ScatterGraph/ScatterGraph.js.map +0 -1
  422. package/dist/components/charts/StackedChromatogramChart/StackedChromatogramChart.cjs +0 -2
  423. package/dist/components/charts/StackedChromatogramChart/StackedChromatogramChart.cjs.map +0 -1
  424. package/dist/components/charts/StackedChromatogramChart/StackedChromatogramChart.js +0 -40
  425. package/dist/components/charts/StackedChromatogramChart/StackedChromatogramChart.js.map +0 -1
  426. package/dist/components/charts/StackedChromatogramChart/transforms.cjs.map +0 -1
  427. package/dist/components/charts/StackedChromatogramChart/transforms.js.map +0 -1
  428. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/boundaryMarkers.cjs +0 -0
  429. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/boundaryMarkers.js +0 -0
  430. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/constants.cjs +0 -0
  431. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/constants.js +0 -0
  432. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/dataProcessing.cjs +0 -0
  433. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/dataProcessing.js +0 -0
  434. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/peakDetection.cjs +0 -0
  435. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/peakDetection.js +0 -0
  436. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/regionOverlays.cjs +0 -0
  437. /package/dist/components/charts/{ChromatogramChart → Chromatogram}/regionOverlays.js +0 -0
  438. /package/dist/components/charts/{StackedChromatogramChart → StackedChromatogram}/transforms.cjs +0 -0
  439. /package/dist/components/charts/{StackedChromatogramChart → StackedChromatogram}/transforms.js +0 -0
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),j=require("@radix-ui/react-use-controllable-state"),M=require("@streamdown/cjk"),P=require("@streamdown/code"),A=require("@streamdown/math"),I=require("@streamdown/mermaid"),b=require("lucide-react"),t=require("react"),S=require("streamdown"),_=require("./shimmer.cjs"),f=require("../ui/collapsible.cjs"),l=require("../../lib/utils.cjs"),T=t.createContext(null),q=()=>{const o=t.useContext(T);if(!o)throw new Error("Reasoning components must be used within Reasoning");return o},z=1e3,L=1e3,v=t.memo(({className:o,isStreaming:e=!1,open:a,defaultOpen:i,onOpenChange:u,duration:d,children:m,...N})=>{const E=i??e,g=i===!1,[r,s]=j.useControllableState({defaultProp:E,onChange:u,prop:a}),[h,x]=j.useControllableState({defaultProp:void 0,prop:d}),C=t.useRef(e),[R,O]=t.useState(!1),c=t.useRef(null);t.useEffect(()=>{e?(C.current=!0,c.current===null&&(c.current=Date.now())):c.current!==null&&(x(Math.ceil((Date.now()-c.current)/L)),c.current=null)},[e,x]),t.useEffect(()=>{e&&!r&&!g&&s(!0)},[e,r,s,g]),t.useEffect(()=>{if(C.current&&!e&&r&&!R){const p=setTimeout(()=>{s(!1),O(!0)},z);return()=>clearTimeout(p)}},[e,r,s,R]);const k=t.useCallback(p=>{s(p)},[s]),D=t.useMemo(()=>({duration:h,isOpen:r,isStreaming:e,setIsOpen:s}),[h,r,e,s]);return n.jsx(T.Provider,{value:D,children:n.jsx(f.Collapsible,{className:l.cn("not-prose mb-4",o),onOpenChange:k,open:r,...N,children:m})})}),U=(o,e)=>o||e===0?n.jsx(_.Shimmer,{duration:1,children:"Thinking..."}):e===void 0?n.jsx("p",{children:"Thought for a few seconds"}):n.jsxs("p",{children:["Thought for ",e," seconds"]}),w=t.memo(({className:o,children:e,getThinkingMessage:a=U,...i})=>{const{isStreaming:u,isOpen:d,duration:m}=q();return n.jsx(f.CollapsibleTrigger,{className:l.cn("group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",o),...i,children:e??n.jsxs(n.Fragment,{children:[n.jsx(b.BrainIcon,{className:"size-4"}),a(u,m),n.jsx(b.ChevronDownIcon,{className:l.cn("size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100",d?"rotate-180 opacity-100":"rotate-0"),"data-slot":"collapsible-chevron"})]})})}),B={cjk:M.cjk,code:P.code,math:A.math,mermaid:I.mermaid},y=t.memo(({className:o,children:e,...a})=>n.jsx(f.CollapsibleContent,{className:l.cn("mt-4 text-sm","data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",o),...a,children:n.jsx(S.Streamdown,{plugins:B,children:e})}));v.displayName="Reasoning";w.displayName="ReasoningTrigger";y.displayName="ReasoningContent";exports.Reasoning=v;exports.ReasoningContent=y;exports.ReasoningTrigger=w;exports.useReasoning=q;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react/jsx-runtime"),b=require("@radix-ui/react-use-controllable-state"),j=require("lucide-react"),t=require("react"),S=require("streamdown"),M=require("./shimmer.cjs"),A=require("./use-streamdown-plugins.cjs"),g=require("../ui/collapsible.cjs"),c=require("../../lib/utils.cjs"),T=t.createContext(null),v=()=>{const o=t.useContext(T);if(!o)throw new Error("Reasoning components must be used within Reasoning");return o},I=1e3,_=1e3,w=t.memo(({className:o,isStreaming:e=!1,open:l,defaultOpen:a,onOpenChange:u,duration:d,children:p,...N})=>{const E=a??e,m=a===!1,[r,s]=b.useControllableState({defaultProp:E,onChange:u,prop:l}),[h,x]=b.useControllableState({defaultProp:void 0,prop:d}),C=t.useRef(e),[R,O]=t.useState(!1),i=t.useRef(null);t.useEffect(()=>{e?(C.current=!0,i.current===null&&(i.current=Date.now())):i.current!==null&&(x(Math.ceil((Date.now()-i.current)/_)),i.current=null)},[e,x]),t.useEffect(()=>{e&&!r&&!m&&s(!0)},[e,r,s,m]),t.useEffect(()=>{if(C.current&&!e&&r&&!R){const f=setTimeout(()=>{s(!1),O(!0)},I);return()=>clearTimeout(f)}},[e,r,s,R]);const D=t.useCallback(f=>{s(f)},[s]),P=t.useMemo(()=>({duration:h,isOpen:r,isStreaming:e,setIsOpen:s}),[h,r,e,s]);return n.jsx(T.Provider,{value:P,children:n.jsx(g.Collapsible,{className:c.cn("not-prose mb-4",o),onOpenChange:D,open:r,...N,children:p})})}),k=(o,e)=>o||e===0?n.jsx(M.Shimmer,{duration:1,children:"Thinking..."}):e===void 0?n.jsx("p",{children:"Thought for a few seconds"}):n.jsxs("p",{children:["Thought for ",e," seconds"]}),y=t.memo(({className:o,children:e,getThinkingMessage:l=k,...a})=>{const{isStreaming:u,isOpen:d,duration:p}=v();return n.jsx(g.CollapsibleTrigger,{className:c.cn("group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",o),...a,children:e??n.jsxs(n.Fragment,{children:[n.jsx(j.BrainIcon,{className:"size-4"}),l(u,p),n.jsx(j.ChevronDownIcon,{className:c.cn("size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100",d?"rotate-180 opacity-100":"rotate-0"),"data-slot":"collapsible-chevron"})]})})}),q=t.memo(({className:o,children:e,...l})=>{const a=A.useStreamdownPlugins();return n.jsx(g.CollapsibleContent,{className:c.cn("mt-4 text-sm","data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",o),...l,children:n.jsx(S.Streamdown,{plugins:a,children:e})})});w.displayName="Reasoning";y.displayName="ReasoningTrigger";q.displayName="ReasoningContent";exports.Reasoning=w;exports.ReasoningContent=q;exports.ReasoningTrigger=y;exports.useReasoning=v;
2
2
  //# sourceMappingURL=reasoning.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"reasoning.cjs","sources":["../../../src/components/ai/reasoning.tsx"],"sourcesContent":["import { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { cjk } from \"@streamdown/cjk\";\nimport { code } from \"@streamdown/code\";\nimport { math } from \"@streamdown/math\";\nimport { mermaid } from \"@streamdown/mermaid\";\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Streamdown } from \"streamdown\";\n\nimport { Shimmer } from \"./shimmer\";\n\nimport type { ComponentProps, ReactNode } from \"react\";\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\n\ninterface ReasoningContextValue {\n isStreaming: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n duration: number | undefined;\n}\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nexport const useReasoning = () => {\n const context = useContext(ReasoningContext);\n if (!context) {\n throw new Error(\"Reasoning components must be used within Reasoning\");\n }\n return context;\n};\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n duration?: number;\n};\n\nconst AUTO_CLOSE_DELAY = 1000;\nconst MS_IN_S = 1000;\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const resolvedDefaultOpen = defaultOpen ?? isStreaming;\n // Track if defaultOpen was explicitly set to false (to prevent auto-open)\n const isExplicitlyClosed = defaultOpen === false;\n\n const [isOpen, setIsOpen] = useControllableState<boolean>({\n defaultProp: resolvedDefaultOpen,\n onChange: onOpenChange,\n prop: open,\n });\n const [duration, setDuration] = useControllableState<number | undefined>({\n defaultProp: undefined,\n prop: durationProp,\n });\n\n const hasEverStreamedRef = useRef(isStreaming);\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const startTimeRef = useRef<number | null>(null);\n\n // Track when streaming starts and compute duration\n useEffect(() => {\n if (isStreaming) {\n hasEverStreamedRef.current = true;\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n } else if (startTimeRef.current !== null) {\n setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S));\n startTimeRef.current = null;\n }\n }, [isStreaming, setDuration]);\n\n // Auto-open when streaming starts (unless explicitly closed)\n useEffect(() => {\n if (isStreaming && !isOpen && !isExplicitlyClosed) {\n setIsOpen(true);\n }\n }, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);\n\n // Auto-close when streaming ends (once only, and only if it ever streamed)\n useEffect(() => {\n if (\n hasEverStreamedRef.current &&\n !isStreaming &&\n isOpen &&\n !hasAutoClosed\n ) {\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, AUTO_CLOSE_DELAY);\n\n return () => clearTimeout(timer);\n }\n }, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setIsOpen(newOpen);\n },\n [setIsOpen]\n );\n\n const contextValue = useMemo(\n () => ({ duration, isOpen, isStreaming, setIsOpen }),\n [duration, isOpen, isStreaming, setIsOpen]\n );\n\n return (\n <ReasoningContext.Provider value={contextValue}>\n <Collapsible\n className={cn(\"not-prose mb-4\", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n );\n }\n);\n\nexport type ReasoningTriggerProps = ComponentProps<\n typeof CollapsibleTrigger\n> & {\n getThinkingMessage?: (isStreaming: boolean, duration?: number) => ReactNode;\n};\n\nconst defaultGetThinkingMessage = (isStreaming: boolean, duration?: number) => {\n if (isStreaming || duration === 0) {\n return <Shimmer duration={1}>Thinking...</Shimmer>;\n }\n if (duration === undefined) {\n return <p>Thought for a few seconds</p>;\n }\n return <p>Thought for {duration} seconds</p>;\n};\n\nexport const ReasoningTrigger = memo(\n ({\n className,\n children,\n getThinkingMessage = defaultGetThinkingMessage,\n ...props\n }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning();\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className=\"size-4\" />\n {getThinkingMessage(isStreaming, duration)}\n <ChevronDownIcon\n className={cn(\n \"size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100\",\n isOpen ? \"rotate-180 opacity-100\" : \"rotate-0\"\n )}\n data-slot=\"collapsible-chevron\"\n />\n </>\n )}\n </CollapsibleTrigger>\n );\n }\n);\n\nexport type ReasoningContentProps = ComponentProps<\n typeof CollapsibleContent\n> & {\n children: string;\n};\n\nconst streamdownPlugins = { cjk, code, math, mermaid };\n\nexport const ReasoningContent = memo(\n ({ className, children, ...props }: ReasoningContentProps) => (\n <CollapsibleContent\n className={cn(\n \"mt-4 text-sm\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n >\n <Streamdown plugins={streamdownPlugins}>{children}</Streamdown>\n </CollapsibleContent>\n )\n);\n\nReasoning.displayName = \"Reasoning\";\nReasoningTrigger.displayName = \"ReasoningTrigger\";\nReasoningContent.displayName = \"ReasoningContent\";\n"],"names":["ReasoningContext","createContext","useReasoning","context","useContext","AUTO_CLOSE_DELAY","MS_IN_S","Reasoning","memo","className","isStreaming","open","defaultOpen","onOpenChange","durationProp","children","props","resolvedDefaultOpen","isExplicitlyClosed","isOpen","setIsOpen","useControllableState","duration","setDuration","hasEverStreamedRef","useRef","hasAutoClosed","setHasAutoClosed","useState","startTimeRef","useEffect","timer","handleOpenChange","useCallback","newOpen","contextValue","useMemo","jsx","Collapsible","cn","defaultGetThinkingMessage","Shimmer","ReasoningTrigger","getThinkingMessage","CollapsibleTrigger","jsxs","Fragment","BrainIcon","ChevronDownIcon","streamdownPlugins","cjk","code","math","mermaid","ReasoningContent","CollapsibleContent","Streamdown"],"mappings":"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"}
1
+ {"version":3,"file":"reasoning.cjs","sources":["../../../src/components/ai/reasoning.tsx"],"sourcesContent":["import { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Streamdown } from \"streamdown\";\n\nimport { Shimmer } from \"./shimmer\";\nimport { useStreamdownPlugins } from \"./use-streamdown-plugins\";\n\nimport type { ComponentProps, ReactNode } from \"react\";\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\n\ninterface ReasoningContextValue {\n isStreaming: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n duration: number | undefined;\n}\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nexport const useReasoning = () => {\n const context = useContext(ReasoningContext);\n if (!context) {\n throw new Error(\"Reasoning components must be used within Reasoning\");\n }\n return context;\n};\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n duration?: number;\n};\n\nconst AUTO_CLOSE_DELAY = 1000;\nconst MS_IN_S = 1000;\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const resolvedDefaultOpen = defaultOpen ?? isStreaming;\n // Track if defaultOpen was explicitly set to false (to prevent auto-open)\n const isExplicitlyClosed = defaultOpen === false;\n\n const [isOpen, setIsOpen] = useControllableState<boolean>({\n defaultProp: resolvedDefaultOpen,\n onChange: onOpenChange,\n prop: open,\n });\n const [duration, setDuration] = useControllableState<number | undefined>({\n defaultProp: undefined,\n prop: durationProp,\n });\n\n const hasEverStreamedRef = useRef(isStreaming);\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const startTimeRef = useRef<number | null>(null);\n\n // Track when streaming starts and compute duration\n useEffect(() => {\n if (isStreaming) {\n hasEverStreamedRef.current = true;\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n } else if (startTimeRef.current !== null) {\n setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S));\n startTimeRef.current = null;\n }\n }, [isStreaming, setDuration]);\n\n // Auto-open when streaming starts (unless explicitly closed)\n useEffect(() => {\n if (isStreaming && !isOpen && !isExplicitlyClosed) {\n setIsOpen(true);\n }\n }, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);\n\n // Auto-close when streaming ends (once only, and only if it ever streamed)\n useEffect(() => {\n if (\n hasEverStreamedRef.current &&\n !isStreaming &&\n isOpen &&\n !hasAutoClosed\n ) {\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, AUTO_CLOSE_DELAY);\n\n return () => clearTimeout(timer);\n }\n }, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setIsOpen(newOpen);\n },\n [setIsOpen]\n );\n\n const contextValue = useMemo(\n () => ({ duration, isOpen, isStreaming, setIsOpen }),\n [duration, isOpen, isStreaming, setIsOpen]\n );\n\n return (\n <ReasoningContext.Provider value={contextValue}>\n <Collapsible\n className={cn(\"not-prose mb-4\", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n );\n }\n);\n\nexport type ReasoningTriggerProps = ComponentProps<\n typeof CollapsibleTrigger\n> & {\n getThinkingMessage?: (isStreaming: boolean, duration?: number) => ReactNode;\n};\n\nconst defaultGetThinkingMessage = (isStreaming: boolean, duration?: number) => {\n if (isStreaming || duration === 0) {\n return <Shimmer duration={1}>Thinking...</Shimmer>;\n }\n if (duration === undefined) {\n return <p>Thought for a few seconds</p>;\n }\n return <p>Thought for {duration} seconds</p>;\n};\n\nexport const ReasoningTrigger = memo(\n ({\n className,\n children,\n getThinkingMessage = defaultGetThinkingMessage,\n ...props\n }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning();\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className=\"size-4\" />\n {getThinkingMessage(isStreaming, duration)}\n <ChevronDownIcon\n className={cn(\n \"size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100\",\n isOpen ? \"rotate-180 opacity-100\" : \"rotate-0\"\n )}\n data-slot=\"collapsible-chevron\"\n />\n </>\n )}\n </CollapsibleTrigger>\n );\n }\n);\n\nexport type ReasoningContentProps = ComponentProps<\n typeof CollapsibleContent\n> & {\n children: string;\n};\n\nexport const ReasoningContent = memo(\n ({ className, children, ...props }: ReasoningContentProps) => {\n // Plugins load lazily (SW-2007): markdown streams in immediately and\n // code/math/mermaid rendering upgrades in place once the chunk arrives.\n const plugins = useStreamdownPlugins();\n\n return (\n <CollapsibleContent\n className={cn(\n \"mt-4 text-sm\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n >\n <Streamdown plugins={plugins}>{children}</Streamdown>\n </CollapsibleContent>\n );\n }\n);\n\nReasoning.displayName = \"Reasoning\";\nReasoningTrigger.displayName = \"ReasoningTrigger\";\nReasoningContent.displayName = \"ReasoningContent\";\n"],"names":["ReasoningContext","createContext","useReasoning","context","useContext","AUTO_CLOSE_DELAY","MS_IN_S","Reasoning","memo","className","isStreaming","open","defaultOpen","onOpenChange","durationProp","children","props","resolvedDefaultOpen","isExplicitlyClosed","isOpen","setIsOpen","useControllableState","duration","setDuration","hasEverStreamedRef","useRef","hasAutoClosed","setHasAutoClosed","useState","startTimeRef","useEffect","timer","handleOpenChange","useCallback","newOpen","contextValue","useMemo","jsx","Collapsible","cn","defaultGetThinkingMessage","Shimmer","ReasoningTrigger","getThinkingMessage","CollapsibleTrigger","jsxs","Fragment","BrainIcon","ChevronDownIcon","ReasoningContent","plugins","useStreamdownPlugins","CollapsibleContent","Streamdown"],"mappings":"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"}
@@ -1,98 +1,95 @@
1
- import { jsx as o, jsxs as w, Fragment as k } from "react/jsx-runtime";
1
+ import { jsx as o, jsxs as w, Fragment as A } from "react/jsx-runtime";
2
2
  import { useControllableState as v } from "@radix-ui/react-use-controllable-state";
3
- import { cjk as A } from "@streamdown/cjk";
4
- import { code as I } from "@streamdown/code";
5
- import { math as M } from "@streamdown/math";
6
- import { mermaid as P } from "@streamdown/mermaid";
7
- import { BrainIcon as _, ChevronDownIcon as j } from "lucide-react";
8
- import { createContext as z, memo as f, useRef as T, useState as L, useEffect as d, useCallback as B, useMemo as F, useContext as G } from "react";
9
- import { Streamdown as H } from "streamdown";
10
- import { Shimmer as U } from "./shimmer.js";
11
- import { Collapsible as V, CollapsibleTrigger as Y, CollapsibleContent as q } from "../ui/collapsible.js";
12
- import { cn as l } from "../../lib/utils.js";
13
- const b = z(null), J = () => {
14
- const t = G(b);
3
+ import { BrainIcon as I, ChevronDownIcon as M } from "lucide-react";
4
+ import { createContext as P, memo as f, useRef as T, useState as _, useEffect as m, useCallback as k, useMemo as j, useContext as z } from "react";
5
+ import { Streamdown as L } from "streamdown";
6
+ import { Shimmer as B } from "./shimmer.js";
7
+ import { useStreamdownPlugins as F } from "./use-streamdown-plugins.js";
8
+ import { Collapsible as G, CollapsibleTrigger as H, CollapsibleContent as S } from "../ui/collapsible.js";
9
+ import { cn as i } from "../../lib/utils.js";
10
+ const b = P(null), U = () => {
11
+ const t = z(b);
15
12
  if (!t)
16
13
  throw new Error("Reasoning components must be used within Reasoning");
17
14
  return t;
18
- }, K = 1e3, Q = 1e3, S = f(
15
+ }, V = 1e3, Y = 1e3, q = f(
19
16
  ({
20
17
  className: t,
21
18
  isStreaming: e = !1,
22
- open: s,
23
- defaultOpen: i,
19
+ open: a,
20
+ defaultOpen: s,
24
21
  onOpenChange: c,
25
22
  duration: u,
26
- children: m,
23
+ children: p,
27
24
  ...N
28
25
  }) => {
29
- const y = i ?? e, h = i === !1, [r, n] = v({
26
+ const y = s ?? e, h = s === !1, [r, n] = v({
30
27
  defaultProp: y,
31
28
  onChange: c,
32
- prop: s
29
+ prop: a
33
30
  }), [g, C] = v({
34
31
  defaultProp: void 0,
35
32
  prop: u
36
- }), x = T(e), [R, O] = L(!1), a = T(null);
37
- d(() => {
38
- e ? (x.current = !0, a.current === null && (a.current = Date.now())) : a.current !== null && (C(Math.ceil((Date.now() - a.current) / Q)), a.current = null);
39
- }, [e, C]), d(() => {
33
+ }), x = T(e), [R, O] = _(!1), l = T(null);
34
+ m(() => {
35
+ e ? (x.current = !0, l.current === null && (l.current = Date.now())) : l.current !== null && (C(Math.ceil((Date.now() - l.current) / Y)), l.current = null);
36
+ }, [e, C]), m(() => {
40
37
  e && !r && !h && n(!0);
41
- }, [e, r, n, h]), d(() => {
38
+ }, [e, r, n, h]), m(() => {
42
39
  if (x.current && !e && r && !R) {
43
- const p = setTimeout(() => {
40
+ const d = setTimeout(() => {
44
41
  n(!1), O(!0);
45
- }, K);
46
- return () => clearTimeout(p);
42
+ }, V);
43
+ return () => clearTimeout(d);
47
44
  }
48
45
  }, [e, r, n, R]);
49
- const D = B(
50
- (p) => {
51
- n(p);
46
+ const D = k(
47
+ (d) => {
48
+ n(d);
52
49
  },
53
50
  [n]
54
- ), E = F(
51
+ ), E = j(
55
52
  () => ({ duration: g, isOpen: r, isStreaming: e, setIsOpen: n }),
56
53
  [g, r, e, n]
57
54
  );
58
55
  return /* @__PURE__ */ o(b.Provider, { value: E, children: /* @__PURE__ */ o(
59
- V,
56
+ G,
60
57
  {
61
- className: l("not-prose mb-4", t),
58
+ className: i("not-prose mb-4", t),
62
59
  onOpenChange: D,
63
60
  open: r,
64
61
  ...N,
65
- children: m
62
+ children: p
66
63
  }
67
64
  ) });
68
65
  }
69
- ), W = (t, e) => t || e === 0 ? /* @__PURE__ */ o(U, { duration: 1, children: "Thinking..." }) : e === void 0 ? /* @__PURE__ */ o("p", { children: "Thought for a few seconds" }) : /* @__PURE__ */ w("p", { children: [
66
+ ), J = (t, e) => t || e === 0 ? /* @__PURE__ */ o(B, { duration: 1, children: "Thinking..." }) : e === void 0 ? /* @__PURE__ */ o("p", { children: "Thought for a few seconds" }) : /* @__PURE__ */ w("p", { children: [
70
67
  "Thought for ",
71
68
  e,
72
69
  " seconds"
73
- ] }), X = f(
70
+ ] }), K = f(
74
71
  ({
75
72
  className: t,
76
73
  children: e,
77
- getThinkingMessage: s = W,
78
- ...i
74
+ getThinkingMessage: a = J,
75
+ ...s
79
76
  }) => {
80
- const { isStreaming: c, isOpen: u, duration: m } = J();
77
+ const { isStreaming: c, isOpen: u, duration: p } = U();
81
78
  return /* @__PURE__ */ o(
82
- Y,
79
+ H,
83
80
  {
84
- className: l(
81
+ className: i(
85
82
  "group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground",
86
83
  t
87
84
  ),
88
- ...i,
89
- children: e ?? /* @__PURE__ */ w(k, { children: [
90
- /* @__PURE__ */ o(_, { className: "size-4" }),
91
- s(c, m),
85
+ ...s,
86
+ children: e ?? /* @__PURE__ */ w(A, { children: [
87
+ /* @__PURE__ */ o(I, { className: "size-4" }),
88
+ a(c, p),
92
89
  /* @__PURE__ */ o(
93
- j,
90
+ M,
94
91
  {
95
- className: l(
92
+ className: i(
96
93
  "size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100",
97
94
  u ? "rotate-180 opacity-100" : "rotate-0"
98
95
  ),
@@ -103,27 +100,30 @@ const b = z(null), J = () => {
103
100
  }
104
101
  );
105
102
  }
106
- ), Z = { cjk: A, code: I, math: M, mermaid: P }, $ = f(
107
- ({ className: t, children: e, ...s }) => /* @__PURE__ */ o(
108
- q,
109
- {
110
- className: l(
111
- "mt-4 text-sm",
112
- "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
113
- t
114
- ),
115
- ...s,
116
- children: /* @__PURE__ */ o(H, { plugins: Z, children: e })
117
- }
118
- )
103
+ ), Q = f(
104
+ ({ className: t, children: e, ...a }) => {
105
+ const s = F();
106
+ return /* @__PURE__ */ o(
107
+ S,
108
+ {
109
+ className: i(
110
+ "mt-4 text-sm",
111
+ "data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
112
+ t
113
+ ),
114
+ ...a,
115
+ children: /* @__PURE__ */ o(L, { plugins: s, children: e })
116
+ }
117
+ );
118
+ }
119
119
  );
120
- S.displayName = "Reasoning";
121
- X.displayName = "ReasoningTrigger";
122
- $.displayName = "ReasoningContent";
120
+ q.displayName = "Reasoning";
121
+ K.displayName = "ReasoningTrigger";
122
+ Q.displayName = "ReasoningContent";
123
123
  export {
124
- S as Reasoning,
125
- $ as ReasoningContent,
126
- X as ReasoningTrigger,
127
- J as useReasoning
124
+ q as Reasoning,
125
+ Q as ReasoningContent,
126
+ K as ReasoningTrigger,
127
+ U as useReasoning
128
128
  };
129
129
  //# sourceMappingURL=reasoning.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reasoning.js","sources":["../../../src/components/ai/reasoning.tsx"],"sourcesContent":["import { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { cjk } from \"@streamdown/cjk\";\nimport { code } from \"@streamdown/code\";\nimport { math } from \"@streamdown/math\";\nimport { mermaid } from \"@streamdown/mermaid\";\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Streamdown } from \"streamdown\";\n\nimport { Shimmer } from \"./shimmer\";\n\nimport type { ComponentProps, ReactNode } from \"react\";\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\n\ninterface ReasoningContextValue {\n isStreaming: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n duration: number | undefined;\n}\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nexport const useReasoning = () => {\n const context = useContext(ReasoningContext);\n if (!context) {\n throw new Error(\"Reasoning components must be used within Reasoning\");\n }\n return context;\n};\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n duration?: number;\n};\n\nconst AUTO_CLOSE_DELAY = 1000;\nconst MS_IN_S = 1000;\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const resolvedDefaultOpen = defaultOpen ?? isStreaming;\n // Track if defaultOpen was explicitly set to false (to prevent auto-open)\n const isExplicitlyClosed = defaultOpen === false;\n\n const [isOpen, setIsOpen] = useControllableState<boolean>({\n defaultProp: resolvedDefaultOpen,\n onChange: onOpenChange,\n prop: open,\n });\n const [duration, setDuration] = useControllableState<number | undefined>({\n defaultProp: undefined,\n prop: durationProp,\n });\n\n const hasEverStreamedRef = useRef(isStreaming);\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const startTimeRef = useRef<number | null>(null);\n\n // Track when streaming starts and compute duration\n useEffect(() => {\n if (isStreaming) {\n hasEverStreamedRef.current = true;\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n } else if (startTimeRef.current !== null) {\n setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S));\n startTimeRef.current = null;\n }\n }, [isStreaming, setDuration]);\n\n // Auto-open when streaming starts (unless explicitly closed)\n useEffect(() => {\n if (isStreaming && !isOpen && !isExplicitlyClosed) {\n setIsOpen(true);\n }\n }, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);\n\n // Auto-close when streaming ends (once only, and only if it ever streamed)\n useEffect(() => {\n if (\n hasEverStreamedRef.current &&\n !isStreaming &&\n isOpen &&\n !hasAutoClosed\n ) {\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, AUTO_CLOSE_DELAY);\n\n return () => clearTimeout(timer);\n }\n }, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setIsOpen(newOpen);\n },\n [setIsOpen]\n );\n\n const contextValue = useMemo(\n () => ({ duration, isOpen, isStreaming, setIsOpen }),\n [duration, isOpen, isStreaming, setIsOpen]\n );\n\n return (\n <ReasoningContext.Provider value={contextValue}>\n <Collapsible\n className={cn(\"not-prose mb-4\", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n );\n }\n);\n\nexport type ReasoningTriggerProps = ComponentProps<\n typeof CollapsibleTrigger\n> & {\n getThinkingMessage?: (isStreaming: boolean, duration?: number) => ReactNode;\n};\n\nconst defaultGetThinkingMessage = (isStreaming: boolean, duration?: number) => {\n if (isStreaming || duration === 0) {\n return <Shimmer duration={1}>Thinking...</Shimmer>;\n }\n if (duration === undefined) {\n return <p>Thought for a few seconds</p>;\n }\n return <p>Thought for {duration} seconds</p>;\n};\n\nexport const ReasoningTrigger = memo(\n ({\n className,\n children,\n getThinkingMessage = defaultGetThinkingMessage,\n ...props\n }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning();\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className=\"size-4\" />\n {getThinkingMessage(isStreaming, duration)}\n <ChevronDownIcon\n className={cn(\n \"size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100\",\n isOpen ? \"rotate-180 opacity-100\" : \"rotate-0\"\n )}\n data-slot=\"collapsible-chevron\"\n />\n </>\n )}\n </CollapsibleTrigger>\n );\n }\n);\n\nexport type ReasoningContentProps = ComponentProps<\n typeof CollapsibleContent\n> & {\n children: string;\n};\n\nconst streamdownPlugins = { cjk, code, math, mermaid };\n\nexport const ReasoningContent = memo(\n ({ className, children, ...props }: ReasoningContentProps) => (\n <CollapsibleContent\n className={cn(\n \"mt-4 text-sm\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n >\n <Streamdown plugins={streamdownPlugins}>{children}</Streamdown>\n </CollapsibleContent>\n )\n);\n\nReasoning.displayName = \"Reasoning\";\nReasoningTrigger.displayName = \"ReasoningTrigger\";\nReasoningContent.displayName = \"ReasoningContent\";\n"],"names":["ReasoningContext","createContext","useReasoning","context","useContext","AUTO_CLOSE_DELAY","MS_IN_S","Reasoning","memo","className","isStreaming","open","defaultOpen","onOpenChange","durationProp","children","props","resolvedDefaultOpen","isExplicitlyClosed","isOpen","setIsOpen","useControllableState","duration","setDuration","hasEverStreamedRef","useRef","hasAutoClosed","setHasAutoClosed","useState","startTimeRef","useEffect","timer","handleOpenChange","useCallback","newOpen","contextValue","useMemo","jsx","Collapsible","cn","defaultGetThinkingMessage","Shimmer","ReasoningTrigger","getThinkingMessage","CollapsibleTrigger","jsxs","Fragment","BrainIcon","ChevronDownIcon","streamdownPlugins","cjk","code","math","mermaid","ReasoningContent","CollapsibleContent","Streamdown"],"mappings":"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"}
1
+ {"version":3,"file":"reasoning.js","sources":["../../../src/components/ai/reasoning.tsx"],"sourcesContent":["import { useControllableState } from \"@radix-ui/react-use-controllable-state\";\nimport { BrainIcon, ChevronDownIcon } from \"lucide-react\";\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Streamdown } from \"streamdown\";\n\nimport { Shimmer } from \"./shimmer\";\nimport { useStreamdownPlugins } from \"./use-streamdown-plugins\";\n\nimport type { ComponentProps, ReactNode } from \"react\";\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\n\ninterface ReasoningContextValue {\n isStreaming: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n duration: number | undefined;\n}\n\nconst ReasoningContext = createContext<ReasoningContextValue | null>(null);\n\nexport const useReasoning = () => {\n const context = useContext(ReasoningContext);\n if (!context) {\n throw new Error(\"Reasoning components must be used within Reasoning\");\n }\n return context;\n};\n\nexport type ReasoningProps = ComponentProps<typeof Collapsible> & {\n isStreaming?: boolean;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n duration?: number;\n};\n\nconst AUTO_CLOSE_DELAY = 1000;\nconst MS_IN_S = 1000;\n\nexport const Reasoning = memo(\n ({\n className,\n isStreaming = false,\n open,\n defaultOpen,\n onOpenChange,\n duration: durationProp,\n children,\n ...props\n }: ReasoningProps) => {\n const resolvedDefaultOpen = defaultOpen ?? isStreaming;\n // Track if defaultOpen was explicitly set to false (to prevent auto-open)\n const isExplicitlyClosed = defaultOpen === false;\n\n const [isOpen, setIsOpen] = useControllableState<boolean>({\n defaultProp: resolvedDefaultOpen,\n onChange: onOpenChange,\n prop: open,\n });\n const [duration, setDuration] = useControllableState<number | undefined>({\n defaultProp: undefined,\n prop: durationProp,\n });\n\n const hasEverStreamedRef = useRef(isStreaming);\n const [hasAutoClosed, setHasAutoClosed] = useState(false);\n const startTimeRef = useRef<number | null>(null);\n\n // Track when streaming starts and compute duration\n useEffect(() => {\n if (isStreaming) {\n hasEverStreamedRef.current = true;\n if (startTimeRef.current === null) {\n startTimeRef.current = Date.now();\n }\n } else if (startTimeRef.current !== null) {\n setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S));\n startTimeRef.current = null;\n }\n }, [isStreaming, setDuration]);\n\n // Auto-open when streaming starts (unless explicitly closed)\n useEffect(() => {\n if (isStreaming && !isOpen && !isExplicitlyClosed) {\n setIsOpen(true);\n }\n }, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);\n\n // Auto-close when streaming ends (once only, and only if it ever streamed)\n useEffect(() => {\n if (\n hasEverStreamedRef.current &&\n !isStreaming &&\n isOpen &&\n !hasAutoClosed\n ) {\n const timer = setTimeout(() => {\n setIsOpen(false);\n setHasAutoClosed(true);\n }, AUTO_CLOSE_DELAY);\n\n return () => clearTimeout(timer);\n }\n }, [isStreaming, isOpen, setIsOpen, hasAutoClosed]);\n\n const handleOpenChange = useCallback(\n (newOpen: boolean) => {\n setIsOpen(newOpen);\n },\n [setIsOpen]\n );\n\n const contextValue = useMemo(\n () => ({ duration, isOpen, isStreaming, setIsOpen }),\n [duration, isOpen, isStreaming, setIsOpen]\n );\n\n return (\n <ReasoningContext.Provider value={contextValue}>\n <Collapsible\n className={cn(\"not-prose mb-4\", className)}\n onOpenChange={handleOpenChange}\n open={isOpen}\n {...props}\n >\n {children}\n </Collapsible>\n </ReasoningContext.Provider>\n );\n }\n);\n\nexport type ReasoningTriggerProps = ComponentProps<\n typeof CollapsibleTrigger\n> & {\n getThinkingMessage?: (isStreaming: boolean, duration?: number) => ReactNode;\n};\n\nconst defaultGetThinkingMessage = (isStreaming: boolean, duration?: number) => {\n if (isStreaming || duration === 0) {\n return <Shimmer duration={1}>Thinking...</Shimmer>;\n }\n if (duration === undefined) {\n return <p>Thought for a few seconds</p>;\n }\n return <p>Thought for {duration} seconds</p>;\n};\n\nexport const ReasoningTrigger = memo(\n ({\n className,\n children,\n getThinkingMessage = defaultGetThinkingMessage,\n ...props\n }: ReasoningTriggerProps) => {\n const { isStreaming, isOpen, duration } = useReasoning();\n\n return (\n <CollapsibleTrigger\n className={cn(\n \"group flex w-full items-center gap-2 text-muted-foreground text-sm transition-colors hover:text-foreground\",\n className\n )}\n {...props}\n >\n {children ?? (\n <>\n <BrainIcon className=\"size-4\" />\n {getThinkingMessage(isStreaming, duration)}\n <ChevronDownIcon\n className={cn(\n \"size-4 opacity-0 transition-all group-focus-visible:opacity-100 group-hover:opacity-100\",\n isOpen ? \"rotate-180 opacity-100\" : \"rotate-0\"\n )}\n data-slot=\"collapsible-chevron\"\n />\n </>\n )}\n </CollapsibleTrigger>\n );\n }\n);\n\nexport type ReasoningContentProps = ComponentProps<\n typeof CollapsibleContent\n> & {\n children: string;\n};\n\nexport const ReasoningContent = memo(\n ({ className, children, ...props }: ReasoningContentProps) => {\n // Plugins load lazily (SW-2007): markdown streams in immediately and\n // code/math/mermaid rendering upgrades in place once the chunk arrives.\n const plugins = useStreamdownPlugins();\n\n return (\n <CollapsibleContent\n className={cn(\n \"mt-4 text-sm\",\n \"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground outline-none data-[state=closed]:animate-out data-[state=open]:animate-in\",\n className\n )}\n {...props}\n >\n <Streamdown plugins={plugins}>{children}</Streamdown>\n </CollapsibleContent>\n );\n }\n);\n\nReasoning.displayName = \"Reasoning\";\nReasoningTrigger.displayName = \"ReasoningTrigger\";\nReasoningContent.displayName = \"ReasoningContent\";\n"],"names":["ReasoningContext","createContext","useReasoning","context","useContext","AUTO_CLOSE_DELAY","MS_IN_S","Reasoning","memo","className","isStreaming","open","defaultOpen","onOpenChange","durationProp","children","props","resolvedDefaultOpen","isExplicitlyClosed","isOpen","setIsOpen","useControllableState","duration","setDuration","hasEverStreamedRef","useRef","hasAutoClosed","setHasAutoClosed","useState","startTimeRef","useEffect","timer","handleOpenChange","useCallback","newOpen","contextValue","useMemo","jsx","Collapsible","cn","defaultGetThinkingMessage","Shimmer","ReasoningTrigger","getThinkingMessage","CollapsibleTrigger","jsxs","Fragment","BrainIcon","ChevronDownIcon","ReasoningContent","plugins","useStreamdownPlugins","CollapsibleContent","Streamdown"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),c=require("lucide-react"),n=require("react"),l=require("../../lib/utils.cjs"),i=1e3,h=60,y=700,v=1e3,g=1e6,j={loader:s.jsx(c.LoaderIcon,{}),"loader-circle":s.jsx(c.LoaderCircleIcon,{}),"loader-pinwheel":s.jsx(c.LoaderPinwheelIcon,{}),"disc-3":s.jsx(c.Disc3Icon,{})},$={streaming:"animate-pulse bg-[#549DFF]",idle:"bg-muted-foreground/40",done:"bg-[#038599]",error:"bg-[#E15759]"};function A(e){const t=Math.floor(e/h),r=e%h;return t>0?`${t}m ${r.toString().padStart(2,"0")}s`:`${r}s`}function D(e){return e>=g?`${(e/g).toFixed(1).replace(/\.0$/,"")}m`:e>=v?`${(e/v).toFixed(1).replace(/\.0$/,"")}k`:String(e)}const P=({startTime:e,isStreaming:t=e!==void 0,state:r,showIndicator:b=!1,tokenCount:u,tokenLabel:d="↓",icon:f,iconVariant:m,className:I})=>{const M=r??(t?"streaming":"idle"),p=f===void 0?m===void 0?void 0:j[m]:f,[R,E]=n.useState(()=>{if(e===void 0)return 0;const o=typeof e=="number"?e:e.getTime();return Math.max(0,Math.floor((Date.now()-o)/i))}),[_,S]=n.useState(!1),x=n.useRef(t);n.useEffect(()=>{const o=x.current;if(x.current=t,o&&!t){S(!0);const a=setTimeout(()=>S(!1),y);return()=>clearTimeout(a)}},[t]),n.useEffect(()=>{if(!t||e===void 0)return;const o=typeof e=="number"?e:e.getTime(),a=()=>E(Math.max(0,Math.floor((Date.now()-o)/i)));a();const w=setInterval(a,i);return()=>clearInterval(w)},[t,e]);const C=e!==void 0,F=u!==void 0;return s.jsxs("div",{"aria-live":"polite",className:l.cn("flex items-center gap-2 text-sm text-muted-foreground",I),children:[p!==void 0&&s.jsx("span",{className:l.cn("shrink-0 [&>svg]:size-3.5",t?"ts-spin-pulse":"opacity-40"),children:p}),C&&s.jsx("span",{className:"tabular-nums",children:A(R)}),F&&s.jsxs(s.Fragment,{children:[s.jsx("span",{"aria-hidden":!0,className:"select-none text-muted-foreground/40",children:"·"}),s.jsxs("span",{className:"tabular-nums",children:[d!=null&&s.jsx("span",{className:"mr-0.5",children:d}),D(u)," tokens"]})]}),b&&s.jsxs("span",{className:"relative flex size-3 shrink-0 items-center justify-center",children:[_&&s.jsx("span",{className:"ts-bubble-confirm absolute size-2 rounded-full bg-[#549DFF]"}),s.jsx("span",{className:l.cn("size-1.5 rounded-full transition-colors duration-500",$[M])})]})]})},N=n.memo(P);N.displayName="StreamStatus";exports.STREAM_STATUS_ICONS=j;exports.StreamStatus=N;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),c=require("lucide-react"),n=require("react"),y=require("../ui/tetra-molecule-icon.cjs"),l=require("../../lib/utils.cjs"),i=1e3,S=60,$=700,h=1e3,j=1e6,g={loader:s.jsx(c.LoaderIcon,{}),"loader-circle":s.jsx(c.LoaderCircleIcon,{}),"loader-pinwheel":s.jsx(c.LoaderPinwheelIcon,{}),"disc-3":s.jsx(c.Disc3Icon,{}),tetra:s.jsx(y.TetraMoleculeIcon,{})},A={streaming:"animate-pulse bg-[#549DFF]",idle:"bg-muted-foreground/40",done:"bg-[#038599]",error:"bg-[#E15759]"};function D(e){const t=Math.floor(e/S),o=e%S;return t>0?`${t}m ${o.toString().padStart(2,"0")}s`:`${o}s`}function P(e){return e>=j?`${(e/j).toFixed(1).replace(/\.0$/,"")}m`:e>=h?`${(e/h).toFixed(1).replace(/\.0$/,"")}k`:String(e)}const T=({startTime:e,isStreaming:t=e!==void 0,state:o,showIndicator:I=!1,tokenCount:u,tokenLabel:d="↓",icon:f,iconVariant:M="tetra",className:N})=>{const b=o??(t?"streaming":"idle"),m=f===void 0?g[M]:f,[R,E]=n.useState(()=>{if(e===void 0)return 0;const r=typeof e=="number"?e:e.getTime();return Math.max(0,Math.floor((Date.now()-r)/i))}),[_,p]=n.useState(!1),x=n.useRef(t);n.useEffect(()=>{const r=x.current;if(x.current=t,r&&!t){p(!0);const a=setTimeout(()=>p(!1),$);return()=>clearTimeout(a)}},[t]),n.useEffect(()=>{if(!t||e===void 0)return;const r=typeof e=="number"?e:e.getTime(),a=()=>E(Math.max(0,Math.floor((Date.now()-r)/i)));a();const w=setInterval(a,i);return()=>clearInterval(w)},[t,e]);const C=e!==void 0,F=u!==void 0;return s.jsxs("div",{"aria-live":"polite",className:l.cn("flex items-center gap-2 text-sm text-muted-foreground",N),children:[m!==void 0&&s.jsx("span",{className:l.cn("shrink-0 [&>svg]:size-3.5",t?"ts-spin-pulse":"opacity-40"),children:m}),C&&s.jsx("span",{className:"tabular-nums",children:D(R)}),F&&s.jsxs(s.Fragment,{children:[s.jsx("span",{"aria-hidden":!0,className:"select-none text-muted-foreground/40",children:"·"}),s.jsxs("span",{className:"tabular-nums",children:[d!=null&&s.jsx("span",{className:"mr-0.5",children:d}),P(u)," tokens"]})]}),I&&s.jsxs("span",{className:"relative flex size-3 shrink-0 items-center justify-center",children:[_&&s.jsx("span",{className:"ts-bubble-confirm absolute size-2 rounded-full bg-[#549DFF]"}),s.jsx("span",{className:l.cn("size-1.5 rounded-full transition-colors duration-500",A[b])})]})]})},v=n.memo(T);v.displayName="StreamStatus";exports.STREAM_STATUS_ICONS=g;exports.StreamStatus=v;
2
2
  //# sourceMappingURL=stream-status.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-status.cjs","sources":["../../../src/components/ai/stream-status.tsx"],"sourcesContent":["import {\n Disc3Icon,\n LoaderCircleIcon,\n LoaderIcon,\n LoaderPinwheelIcon,\n} from \"lucide-react\";\nimport { memo, useEffect, useRef, useState } from \"react\";\n\nimport type { ReactNode } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst MS_PER_S = 1000;\nconst SECS_PER_MIN = 60;\nconst CONFIRM_RIPPLE_MS = 700;\nconst K = 1_000;\nconst M = 1_000_000;\n\n// ---------------------------------------------------------------------------\n// Icon variants\n// ---------------------------------------------------------------------------\n\n/** Built-in Lucide spinner icons that pair well with ts-spin-pulse animation. */\nexport const STREAM_STATUS_ICONS = {\n loader: <LoaderIcon />,\n \"loader-circle\": <LoaderCircleIcon />,\n \"loader-pinwheel\": <LoaderPinwheelIcon />,\n \"disc-3\": <Disc3Icon />,\n} as const;\n\nexport type StreamStatusIconVariant = keyof typeof STREAM_STATUS_ICONS;\n\n// ---------------------------------------------------------------------------\n// State → indicator dot colour\n// ---------------------------------------------------------------------------\n\nexport type StreamStatusState = \"streaming\" | \"idle\" | \"done\" | \"error\";\n\nconst INDICATOR_CLASS: Record<StreamStatusState, string> = {\n streaming: \"animate-pulse bg-[#549DFF]\", // TS Light Blue 300\n idle: \"bg-muted-foreground/40\",\n done: \"bg-[#038599]\", // TS Forest Green 300\n error: \"bg-[#E15759]\", // TS Imperial Red\n};\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface StreamStatusProps {\n /**\n * Timestamp when streaming started (Date or epoch ms).\n * The component manages an internal 1-second ticker when set.\n */\n startTime?: Date | number;\n /** Whether streaming is currently active. Defaults to `true` when `startTime` is set. */\n isStreaming?: boolean;\n /**\n * Explicit state for the right-end indicator dot colour.\n * If omitted, derived from `isStreaming`: `true` → \"streaming\", `false` → \"idle\".\n *\n * | state | colour |\n * |-------------|----------------------------|\n * | streaming | TS Light Blue 300 (pulsing)|\n * | idle | muted gray |\n * | done | TS Forest Green 300 |\n * | error | TS Imperial Red |\n */\n state?: StreamStatusState;\n /**\n * Show the coloured status dot at the right end of the component.\n * Defaults to `false`.\n */\n showIndicator?: boolean;\n /** Token count shown after the separator, e.g. `8700` → \"↓ 8.7k tokens\". */\n tokenCount?: number;\n /** Prefix before the formatted token count. Defaults to `↓`. */\n tokenLabel?: ReactNode;\n /**\n * Custom icon (ReactNode). Takes precedence over `iconVariant`.\n * While streaming, the icon wrapper receives `ts-spin-pulse` — a continuous\n * rotation that occasionally surges to 1.3× scale.\n */\n icon?: ReactNode;\n /**\n * Convenience shorthand to pick a built-in Lucide spinner.\n * Ignored when `icon` is also provided.\n *\n * Options: `\"loader\"` | `\"loader-circle\"` | `\"loader-pinwheel\"` | `\"disc-3\"`\n */\n iconVariant?: StreamStatusIconVariant;\n className?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatElapsed(seconds: number): string {\n const m = Math.floor(seconds / SECS_PER_MIN);\n const s = seconds % SECS_PER_MIN;\n return m > 0 ? `${m}m ${s.toString().padStart(2, \"0\")}s` : `${s}s`;\n}\n\nfunction formatTokens(count: number): string {\n if (count >= M) return `${(count / M).toFixed(1).replace(/\\.0$/, \"\")}m`;\n if (count >= K) return `${(count / K).toFixed(1).replace(/\\.0$/, \"\")}k`;\n return String(count);\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nconst StreamStatusComponent = ({\n startTime,\n isStreaming = startTime !== undefined,\n state: stateProp,\n showIndicator = false,\n tokenCount,\n tokenLabel = \"↓\",\n icon,\n iconVariant,\n className,\n}: StreamStatusProps) => {\n const resolvedState: StreamStatusState =\n stateProp ?? (isStreaming ? \"streaming\" : \"idle\");\n\n const resolvedIcon =\n icon === undefined\n ? iconVariant === undefined\n ? undefined\n : STREAM_STATUS_ICONS[iconVariant]\n : icon;\n\n const [elapsed, setElapsed] = useState(() => {\n if (startTime === undefined) return 0;\n const origin =\n typeof startTime === \"number\" ? startTime : startTime.getTime();\n return Math.max(0, Math.floor((Date.now() - origin) / MS_PER_S));\n });\n\n // Bubble-confirm ripple — fires once when isStreaming transitions true → false\n const [confirming, setConfirming] = useState(false);\n const prevStreamingRef = useRef(isStreaming);\n\n useEffect(() => {\n const was = prevStreamingRef.current;\n prevStreamingRef.current = isStreaming;\n if (was && !isStreaming) {\n setConfirming(true);\n const t = setTimeout(() => setConfirming(false), CONFIRM_RIPPLE_MS);\n return () => clearTimeout(t);\n }\n }, [isStreaming]);\n\n // Elapsed-time ticker — only active while streaming\n useEffect(() => {\n if (!isStreaming || startTime === undefined) return;\n const origin =\n typeof startTime === \"number\" ? startTime : startTime.getTime();\n const tick = () =>\n setElapsed(Math.max(0, Math.floor((Date.now() - origin) / MS_PER_S)));\n tick();\n const id = setInterval(tick, MS_PER_S);\n return () => clearInterval(id);\n }, [isStreaming, startTime]);\n\n const showTime = startTime !== undefined;\n const showTokens = tokenCount !== undefined;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"flex items-center gap-2 text-sm text-muted-foreground\",\n className\n )}\n >\n {/* Spinning icon — spins + pulse-surges while streaming */}\n {resolvedIcon !== undefined && (\n <span\n className={cn(\n \"shrink-0 [&>svg]:size-3.5\",\n isStreaming ? \"ts-spin-pulse\" : \"opacity-40\"\n )}\n >\n {resolvedIcon}\n </span>\n )}\n\n {/* Elapsed time */}\n {showTime && (\n <span className=\"tabular-nums\">{formatElapsed(elapsed)}</span>\n )}\n\n {/* Token count */}\n {showTokens && (\n <>\n <span aria-hidden className=\"select-none text-muted-foreground/40\">\n ·\n </span>\n <span className=\"tabular-nums\">\n {tokenLabel != null && (\n <span className=\"mr-0.5\">{tokenLabel}</span>\n )}\n {formatTokens(tokenCount)} tokens\n </span>\n </>\n )}\n\n {/* Right-end indicator dot — opt-in, colour driven by `state` */}\n {showIndicator && (\n <span className=\"relative flex size-3 shrink-0 items-center justify-center\">\n {confirming && (\n <span className=\"ts-bubble-confirm absolute size-2 rounded-full bg-[#549DFF]\" />\n )}\n <span\n className={cn(\n \"size-1.5 rounded-full transition-colors duration-500\",\n INDICATOR_CLASS[resolvedState]\n )}\n />\n </span>\n )}\n </div>\n );\n};\n\nexport const StreamStatus = memo(StreamStatusComponent);\nStreamStatus.displayName = \"StreamStatus\";\n"],"names":["MS_PER_S","SECS_PER_MIN","CONFIRM_RIPPLE_MS","K","M","STREAM_STATUS_ICONS","LoaderIcon","LoaderCircleIcon","LoaderPinwheelIcon","Disc3Icon","INDICATOR_CLASS","formatElapsed","seconds","m","s","formatTokens","count","StreamStatusComponent","startTime","isStreaming","stateProp","showIndicator","tokenCount","tokenLabel","icon","iconVariant","className","resolvedState","resolvedIcon","elapsed","setElapsed","useState","origin","confirming","setConfirming","prevStreamingRef","useRef","useEffect","was","t","tick","id","showTime","showTokens","jsxs","cn","jsx","Fragment","StreamStatus","memo"],"mappings":"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"}
1
+ {"version":3,"file":"stream-status.cjs","sources":["../../../src/components/ai/stream-status.tsx"],"sourcesContent":["import {\n Disc3Icon,\n LoaderCircleIcon,\n LoaderIcon,\n LoaderPinwheelIcon,\n} from \"lucide-react\";\nimport { memo, useEffect, useRef, useState } from \"react\";\n\nimport type { ReactNode } from \"react\";\n\nimport { TetraMoleculeIcon } from \"@/components/ui/tetra-molecule-icon\";\nimport { cn } from \"@/lib/utils\";\n\nconst MS_PER_S = 1000;\nconst SECS_PER_MIN = 60;\nconst CONFIRM_RIPPLE_MS = 700;\nconst K = 1_000;\nconst M = 1_000_000;\n\n// ---------------------------------------------------------------------------\n// Icon variants\n// ---------------------------------------------------------------------------\n\n/**\n * Built-in spinner icons.\n *\n * The Lucide spinners pair with the flat `ts-spin-pulse` animation; the\n * `tetra` variant is the Tetra-branded \"TetraSpin\" — the official TetraScience\n * molecule logo filled with the brand blue gradient, rotating 360° with the\n * gradient held fixed so its nodes shimmer, echoing the `:tetraspin3d:` gif for\n * a sense of brand identity while an agent is thinking.\n */\nexport const STREAM_STATUS_ICONS = {\n loader: <LoaderIcon />,\n \"loader-circle\": <LoaderCircleIcon />,\n \"loader-pinwheel\": <LoaderPinwheelIcon />,\n \"disc-3\": <Disc3Icon />,\n tetra: <TetraMoleculeIcon />,\n} as const;\n\nexport type StreamStatusIconVariant = keyof typeof STREAM_STATUS_ICONS;\n\n// ---------------------------------------------------------------------------\n// State → indicator dot colour\n// ---------------------------------------------------------------------------\n\nexport type StreamStatusState = \"streaming\" | \"idle\" | \"done\" | \"error\";\n\nconst INDICATOR_CLASS: Record<StreamStatusState, string> = {\n streaming: \"animate-pulse bg-[#549DFF]\", // TS Light Blue 300\n idle: \"bg-muted-foreground/40\",\n done: \"bg-[#038599]\", // TS Forest Green 300\n error: \"bg-[#E15759]\", // TS Imperial Red\n};\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface StreamStatusProps {\n /**\n * Timestamp when streaming started (Date or epoch ms).\n * The component manages an internal 1-second ticker when set.\n */\n startTime?: Date | number;\n /** Whether streaming is currently active. Defaults to `true` when `startTime` is set. */\n isStreaming?: boolean;\n /**\n * Explicit state for the right-end indicator dot colour.\n * If omitted, derived from `isStreaming`: `true` → \"streaming\", `false` → \"idle\".\n *\n * | state | colour |\n * |-------------|----------------------------|\n * | streaming | TS Light Blue 300 (pulsing)|\n * | idle | muted gray |\n * | done | TS Forest Green 300 |\n * | error | TS Imperial Red |\n */\n state?: StreamStatusState;\n /**\n * Show the coloured status dot at the right end of the component.\n * Defaults to `false`.\n */\n showIndicator?: boolean;\n /** Token count shown after the separator, e.g. `8700` → \"↓ 8.7k tokens\". */\n tokenCount?: number;\n /** Prefix before the formatted token count. Defaults to `↓`. */\n tokenLabel?: ReactNode;\n /**\n * Custom icon (ReactNode). Takes precedence over `iconVariant`.\n * While streaming, the icon wrapper receives `ts-spin-pulse` — a continuous\n * rotation that occasionally surges to 1.3× scale.\n */\n icon?: ReactNode;\n /**\n * Convenience shorthand to pick a built-in spinner.\n * Ignored when `icon` is also provided. Defaults to `\"tetra\"`.\n *\n * Options: `\"loader\"` | `\"loader-circle\"` | `\"loader-pinwheel\"` | `\"disc-3\"` | `\"tetra\"`.\n * The default `\"tetra\"` variant renders the official TetraScience molecule\n * logo with a fixed brand-blue gradient. Pass `icon={null}` to render no icon.\n */\n iconVariant?: StreamStatusIconVariant;\n className?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatElapsed(seconds: number): string {\n const m = Math.floor(seconds / SECS_PER_MIN);\n const s = seconds % SECS_PER_MIN;\n return m > 0 ? `${m}m ${s.toString().padStart(2, \"0\")}s` : `${s}s`;\n}\n\nfunction formatTokens(count: number): string {\n if (count >= M) return `${(count / M).toFixed(1).replace(/\\.0$/, \"\")}m`;\n if (count >= K) return `${(count / K).toFixed(1).replace(/\\.0$/, \"\")}k`;\n return String(count);\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nconst StreamStatusComponent = ({\n startTime,\n isStreaming = startTime !== undefined,\n state: stateProp,\n showIndicator = false,\n tokenCount,\n tokenLabel = \"↓\",\n icon,\n iconVariant = \"tetra\",\n className,\n}: StreamStatusProps) => {\n const resolvedState: StreamStatusState =\n stateProp ?? (isStreaming ? \"streaming\" : \"idle\");\n\n // `icon` wins when provided (including `null` for no icon); otherwise fall\n // back to the built-in variant, which defaults to the branded \"tetra\" mark.\n const resolvedIcon =\n icon === undefined ? STREAM_STATUS_ICONS[iconVariant] : icon;\n\n const [elapsed, setElapsed] = useState(() => {\n if (startTime === undefined) return 0;\n const origin =\n typeof startTime === \"number\" ? startTime : startTime.getTime();\n return Math.max(0, Math.floor((Date.now() - origin) / MS_PER_S));\n });\n\n // Bubble-confirm ripple — fires once when isStreaming transitions true → false\n const [confirming, setConfirming] = useState(false);\n const prevStreamingRef = useRef(isStreaming);\n\n useEffect(() => {\n const was = prevStreamingRef.current;\n prevStreamingRef.current = isStreaming;\n if (was && !isStreaming) {\n setConfirming(true);\n const t = setTimeout(() => setConfirming(false), CONFIRM_RIPPLE_MS);\n return () => clearTimeout(t);\n }\n }, [isStreaming]);\n\n // Elapsed-time ticker — only active while streaming\n useEffect(() => {\n if (!isStreaming || startTime === undefined) return;\n const origin =\n typeof startTime === \"number\" ? startTime : startTime.getTime();\n const tick = () =>\n setElapsed(Math.max(0, Math.floor((Date.now() - origin) / MS_PER_S)));\n tick();\n const id = setInterval(tick, MS_PER_S);\n return () => clearInterval(id);\n }, [isStreaming, startTime]);\n\n const showTime = startTime !== undefined;\n const showTokens = tokenCount !== undefined;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"flex items-center gap-2 text-sm text-muted-foreground\",\n className\n )}\n >\n {/* Spinning icon — spins + pulse-surges while streaming */}\n {resolvedIcon !== undefined && (\n <span\n className={cn(\n \"shrink-0 [&>svg]:size-3.5\",\n isStreaming ? \"ts-spin-pulse\" : \"opacity-40\"\n )}\n >\n {resolvedIcon}\n </span>\n )}\n\n {/* Elapsed time */}\n {showTime && (\n <span className=\"tabular-nums\">{formatElapsed(elapsed)}</span>\n )}\n\n {/* Token count */}\n {showTokens && (\n <>\n <span aria-hidden className=\"select-none text-muted-foreground/40\">\n ·\n </span>\n <span className=\"tabular-nums\">\n {tokenLabel != null && (\n <span className=\"mr-0.5\">{tokenLabel}</span>\n )}\n {formatTokens(tokenCount)} tokens\n </span>\n </>\n )}\n\n {/* Right-end indicator dot — opt-in, colour driven by `state` */}\n {showIndicator && (\n <span className=\"relative flex size-3 shrink-0 items-center justify-center\">\n {confirming && (\n <span className=\"ts-bubble-confirm absolute size-2 rounded-full bg-[#549DFF]\" />\n )}\n <span\n className={cn(\n \"size-1.5 rounded-full transition-colors duration-500\",\n INDICATOR_CLASS[resolvedState]\n )}\n />\n </span>\n )}\n </div>\n );\n};\n\nexport const StreamStatus = memo(StreamStatusComponent);\nStreamStatus.displayName = \"StreamStatus\";\n"],"names":["MS_PER_S","SECS_PER_MIN","CONFIRM_RIPPLE_MS","K","M","STREAM_STATUS_ICONS","LoaderIcon","LoaderCircleIcon","LoaderPinwheelIcon","Disc3Icon","TetraMoleculeIcon","INDICATOR_CLASS","formatElapsed","seconds","m","s","formatTokens","count","StreamStatusComponent","startTime","isStreaming","stateProp","showIndicator","tokenCount","tokenLabel","icon","iconVariant","className","resolvedState","resolvedIcon","elapsed","setElapsed","useState","origin","confirming","setConfirming","prevStreamingRef","useRef","useEffect","was","t","tick","id","showTime","showTokens","jsxs","cn","jsx","Fragment","StreamStatus","memo"],"mappings":"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"}
@@ -1,13 +1,15 @@
1
- import { jsxs as a, jsx as n, Fragment as $ } from "react/jsx-runtime";
1
+ import { jsxs as a, jsx as t, Fragment as $ } from "react/jsx-runtime";
2
2
  import { Disc3Icon as D, LoaderPinwheelIcon as k, LoaderCircleIcon as y, LoaderIcon as P } from "lucide-react";
3
- import { memo as z, useState as v, useRef as A, useEffect as S } from "react";
3
+ import { memo as z, useState as h, useRef as A, useEffect as v } from "react";
4
+ import { TetraMoleculeIcon as L } from "../ui/tetra-molecule-icon.js";
4
5
  import { cn as c } from "../../lib/utils.js";
5
- const l = 1e3, g = 60, L = 700, N = 1e3, I = 1e6, j = {
6
- loader: /* @__PURE__ */ n(P, {}),
7
- "loader-circle": /* @__PURE__ */ n(y, {}),
8
- "loader-pinwheel": /* @__PURE__ */ n(k, {}),
9
- "disc-3": /* @__PURE__ */ n(D, {})
10
- }, O = {
6
+ const l = 1e3, S = 60, j = 700, g = 1e3, I = 1e6, O = {
7
+ loader: /* @__PURE__ */ t(P, {}),
8
+ "loader-circle": /* @__PURE__ */ t(y, {}),
9
+ "loader-pinwheel": /* @__PURE__ */ t(k, {}),
10
+ "disc-3": /* @__PURE__ */ t(D, {}),
11
+ tetra: /* @__PURE__ */ t(L, {})
12
+ }, T = {
11
13
  streaming: "animate-pulse bg-[#549DFF]",
12
14
  // TS Light Blue 300
13
15
  idle: "bg-muted-foreground/40",
@@ -17,38 +19,38 @@ const l = 1e3, g = 60, L = 700, N = 1e3, I = 1e6, j = {
17
19
  // TS Imperial Red
18
20
  };
19
21
  function K(e) {
20
- const o = Math.floor(e / g), r = e % g;
22
+ const o = Math.floor(e / S), r = e % S;
21
23
  return o > 0 ? `${o}m ${r.toString().padStart(2, "0")}s` : `${r}s`;
22
24
  }
23
- function T(e) {
24
- return e >= I ? `${(e / I).toFixed(1).replace(/\.0$/, "")}m` : e >= N ? `${(e / N).toFixed(1).replace(/\.0$/, "")}k` : String(e);
25
+ function U(e) {
26
+ return e >= I ? `${(e / I).toFixed(1).replace(/\.0$/, "")}m` : e >= g ? `${(e / g).toFixed(1).replace(/\.0$/, "")}k` : String(e);
25
27
  }
26
- const U = ({
28
+ const q = ({
27
29
  startTime: e,
28
30
  isStreaming: o = e !== void 0,
29
31
  state: r,
30
- showIndicator: b = !1,
32
+ showIndicator: N = !1,
31
33
  tokenCount: i,
32
34
  tokenLabel: d = "↓",
33
35
  icon: u,
34
- iconVariant: m,
36
+ iconVariant: b = "tetra",
35
37
  className: x
36
38
  }) => {
37
- const M = r ?? (o ? "streaming" : "idle"), f = u === void 0 ? m === void 0 ? void 0 : j[m] : u, [E, _] = v(() => {
39
+ const M = r ?? (o ? "streaming" : "idle"), m = u === void 0 ? O[b] : u, [E, _] = h(() => {
38
40
  if (e === void 0) return 0;
39
- const t = typeof e == "number" ? e : e.getTime();
40
- return Math.max(0, Math.floor((Date.now() - t) / l));
41
- }), [F, p] = v(!1), h = A(o);
42
- S(() => {
43
- const t = h.current;
44
- if (h.current = o, t && !o) {
45
- p(!0);
46
- const s = setTimeout(() => p(!1), L);
41
+ const n = typeof e == "number" ? e : e.getTime();
42
+ return Math.max(0, Math.floor((Date.now() - n) / l));
43
+ }), [F, f] = h(!1), p = A(o);
44
+ v(() => {
45
+ const n = p.current;
46
+ if (p.current = o, n && !o) {
47
+ f(!0);
48
+ const s = setTimeout(() => f(!1), j);
47
49
  return () => clearTimeout(s);
48
50
  }
49
- }, [o]), S(() => {
51
+ }, [o]), v(() => {
50
52
  if (!o || e === void 0) return;
51
- const t = typeof e == "number" ? e : e.getTime(), s = () => _(Math.max(0, Math.floor((Date.now() - t) / l)));
53
+ const n = typeof e == "number" ? e : e.getTime(), s = () => _(Math.max(0, Math.floor((Date.now() - n) / l)));
52
54
  s();
53
55
  const C = setInterval(s, l);
54
56
  return () => clearInterval(C);
@@ -63,33 +65,33 @@ const U = ({
63
65
  x
64
66
  ),
65
67
  children: [
66
- f !== void 0 && /* @__PURE__ */ n(
68
+ m !== void 0 && /* @__PURE__ */ t(
67
69
  "span",
68
70
  {
69
71
  className: c(
70
72
  "shrink-0 [&>svg]:size-3.5",
71
73
  o ? "ts-spin-pulse" : "opacity-40"
72
74
  ),
73
- children: f
75
+ children: m
74
76
  }
75
77
  ),
76
- R && /* @__PURE__ */ n("span", { className: "tabular-nums", children: K(E) }),
78
+ R && /* @__PURE__ */ t("span", { className: "tabular-nums", children: K(E) }),
77
79
  w && /* @__PURE__ */ a($, { children: [
78
- /* @__PURE__ */ n("span", { "aria-hidden": !0, className: "select-none text-muted-foreground/40", children: "·" }),
80
+ /* @__PURE__ */ t("span", { "aria-hidden": !0, className: "select-none text-muted-foreground/40", children: "·" }),
79
81
  /* @__PURE__ */ a("span", { className: "tabular-nums", children: [
80
- d != null && /* @__PURE__ */ n("span", { className: "mr-0.5", children: d }),
81
- T(i),
82
+ d != null && /* @__PURE__ */ t("span", { className: "mr-0.5", children: d }),
83
+ U(i),
82
84
  " tokens"
83
85
  ] })
84
86
  ] }),
85
- b && /* @__PURE__ */ a("span", { className: "relative flex size-3 shrink-0 items-center justify-center", children: [
86
- F && /* @__PURE__ */ n("span", { className: "ts-bubble-confirm absolute size-2 rounded-full bg-[#549DFF]" }),
87
- /* @__PURE__ */ n(
87
+ N && /* @__PURE__ */ a("span", { className: "relative flex size-3 shrink-0 items-center justify-center", children: [
88
+ F && /* @__PURE__ */ t("span", { className: "ts-bubble-confirm absolute size-2 rounded-full bg-[#549DFF]" }),
89
+ /* @__PURE__ */ t(
88
90
  "span",
89
91
  {
90
92
  className: c(
91
93
  "size-1.5 rounded-full transition-colors duration-500",
92
- O[M]
94
+ T[M]
93
95
  )
94
96
  }
95
97
  )
@@ -97,10 +99,10 @@ const U = ({
97
99
  ]
98
100
  }
99
101
  );
100
- }, q = z(U);
101
- q.displayName = "StreamStatus";
102
+ }, B = z(q);
103
+ B.displayName = "StreamStatus";
102
104
  export {
103
- j as STREAM_STATUS_ICONS,
104
- q as StreamStatus
105
+ O as STREAM_STATUS_ICONS,
106
+ B as StreamStatus
105
107
  };
106
108
  //# sourceMappingURL=stream-status.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream-status.js","sources":["../../../src/components/ai/stream-status.tsx"],"sourcesContent":["import {\n Disc3Icon,\n LoaderCircleIcon,\n LoaderIcon,\n LoaderPinwheelIcon,\n} from \"lucide-react\";\nimport { memo, useEffect, useRef, useState } from \"react\";\n\nimport type { ReactNode } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst MS_PER_S = 1000;\nconst SECS_PER_MIN = 60;\nconst CONFIRM_RIPPLE_MS = 700;\nconst K = 1_000;\nconst M = 1_000_000;\n\n// ---------------------------------------------------------------------------\n// Icon variants\n// ---------------------------------------------------------------------------\n\n/** Built-in Lucide spinner icons that pair well with ts-spin-pulse animation. */\nexport const STREAM_STATUS_ICONS = {\n loader: <LoaderIcon />,\n \"loader-circle\": <LoaderCircleIcon />,\n \"loader-pinwheel\": <LoaderPinwheelIcon />,\n \"disc-3\": <Disc3Icon />,\n} as const;\n\nexport type StreamStatusIconVariant = keyof typeof STREAM_STATUS_ICONS;\n\n// ---------------------------------------------------------------------------\n// State → indicator dot colour\n// ---------------------------------------------------------------------------\n\nexport type StreamStatusState = \"streaming\" | \"idle\" | \"done\" | \"error\";\n\nconst INDICATOR_CLASS: Record<StreamStatusState, string> = {\n streaming: \"animate-pulse bg-[#549DFF]\", // TS Light Blue 300\n idle: \"bg-muted-foreground/40\",\n done: \"bg-[#038599]\", // TS Forest Green 300\n error: \"bg-[#E15759]\", // TS Imperial Red\n};\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface StreamStatusProps {\n /**\n * Timestamp when streaming started (Date or epoch ms).\n * The component manages an internal 1-second ticker when set.\n */\n startTime?: Date | number;\n /** Whether streaming is currently active. Defaults to `true` when `startTime` is set. */\n isStreaming?: boolean;\n /**\n * Explicit state for the right-end indicator dot colour.\n * If omitted, derived from `isStreaming`: `true` → \"streaming\", `false` → \"idle\".\n *\n * | state | colour |\n * |-------------|----------------------------|\n * | streaming | TS Light Blue 300 (pulsing)|\n * | idle | muted gray |\n * | done | TS Forest Green 300 |\n * | error | TS Imperial Red |\n */\n state?: StreamStatusState;\n /**\n * Show the coloured status dot at the right end of the component.\n * Defaults to `false`.\n */\n showIndicator?: boolean;\n /** Token count shown after the separator, e.g. `8700` → \"↓ 8.7k tokens\". */\n tokenCount?: number;\n /** Prefix before the formatted token count. Defaults to `↓`. */\n tokenLabel?: ReactNode;\n /**\n * Custom icon (ReactNode). Takes precedence over `iconVariant`.\n * While streaming, the icon wrapper receives `ts-spin-pulse` — a continuous\n * rotation that occasionally surges to 1.3× scale.\n */\n icon?: ReactNode;\n /**\n * Convenience shorthand to pick a built-in Lucide spinner.\n * Ignored when `icon` is also provided.\n *\n * Options: `\"loader\"` | `\"loader-circle\"` | `\"loader-pinwheel\"` | `\"disc-3\"`\n */\n iconVariant?: StreamStatusIconVariant;\n className?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatElapsed(seconds: number): string {\n const m = Math.floor(seconds / SECS_PER_MIN);\n const s = seconds % SECS_PER_MIN;\n return m > 0 ? `${m}m ${s.toString().padStart(2, \"0\")}s` : `${s}s`;\n}\n\nfunction formatTokens(count: number): string {\n if (count >= M) return `${(count / M).toFixed(1).replace(/\\.0$/, \"\")}m`;\n if (count >= K) return `${(count / K).toFixed(1).replace(/\\.0$/, \"\")}k`;\n return String(count);\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nconst StreamStatusComponent = ({\n startTime,\n isStreaming = startTime !== undefined,\n state: stateProp,\n showIndicator = false,\n tokenCount,\n tokenLabel = \"↓\",\n icon,\n iconVariant,\n className,\n}: StreamStatusProps) => {\n const resolvedState: StreamStatusState =\n stateProp ?? (isStreaming ? \"streaming\" : \"idle\");\n\n const resolvedIcon =\n icon === undefined\n ? iconVariant === undefined\n ? undefined\n : STREAM_STATUS_ICONS[iconVariant]\n : icon;\n\n const [elapsed, setElapsed] = useState(() => {\n if (startTime === undefined) return 0;\n const origin =\n typeof startTime === \"number\" ? startTime : startTime.getTime();\n return Math.max(0, Math.floor((Date.now() - origin) / MS_PER_S));\n });\n\n // Bubble-confirm ripple — fires once when isStreaming transitions true → false\n const [confirming, setConfirming] = useState(false);\n const prevStreamingRef = useRef(isStreaming);\n\n useEffect(() => {\n const was = prevStreamingRef.current;\n prevStreamingRef.current = isStreaming;\n if (was && !isStreaming) {\n setConfirming(true);\n const t = setTimeout(() => setConfirming(false), CONFIRM_RIPPLE_MS);\n return () => clearTimeout(t);\n }\n }, [isStreaming]);\n\n // Elapsed-time ticker — only active while streaming\n useEffect(() => {\n if (!isStreaming || startTime === undefined) return;\n const origin =\n typeof startTime === \"number\" ? startTime : startTime.getTime();\n const tick = () =>\n setElapsed(Math.max(0, Math.floor((Date.now() - origin) / MS_PER_S)));\n tick();\n const id = setInterval(tick, MS_PER_S);\n return () => clearInterval(id);\n }, [isStreaming, startTime]);\n\n const showTime = startTime !== undefined;\n const showTokens = tokenCount !== undefined;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"flex items-center gap-2 text-sm text-muted-foreground\",\n className\n )}\n >\n {/* Spinning icon — spins + pulse-surges while streaming */}\n {resolvedIcon !== undefined && (\n <span\n className={cn(\n \"shrink-0 [&>svg]:size-3.5\",\n isStreaming ? \"ts-spin-pulse\" : \"opacity-40\"\n )}\n >\n {resolvedIcon}\n </span>\n )}\n\n {/* Elapsed time */}\n {showTime && (\n <span className=\"tabular-nums\">{formatElapsed(elapsed)}</span>\n )}\n\n {/* Token count */}\n {showTokens && (\n <>\n <span aria-hidden className=\"select-none text-muted-foreground/40\">\n ·\n </span>\n <span className=\"tabular-nums\">\n {tokenLabel != null && (\n <span className=\"mr-0.5\">{tokenLabel}</span>\n )}\n {formatTokens(tokenCount)} tokens\n </span>\n </>\n )}\n\n {/* Right-end indicator dot — opt-in, colour driven by `state` */}\n {showIndicator && (\n <span className=\"relative flex size-3 shrink-0 items-center justify-center\">\n {confirming && (\n <span className=\"ts-bubble-confirm absolute size-2 rounded-full bg-[#549DFF]\" />\n )}\n <span\n className={cn(\n \"size-1.5 rounded-full transition-colors duration-500\",\n INDICATOR_CLASS[resolvedState]\n )}\n />\n </span>\n )}\n </div>\n );\n};\n\nexport const StreamStatus = memo(StreamStatusComponent);\nStreamStatus.displayName = \"StreamStatus\";\n"],"names":["MS_PER_S","SECS_PER_MIN","CONFIRM_RIPPLE_MS","K","M","STREAM_STATUS_ICONS","LoaderIcon","LoaderCircleIcon","LoaderPinwheelIcon","Disc3Icon","INDICATOR_CLASS","formatElapsed","seconds","m","s","formatTokens","count","StreamStatusComponent","startTime","isStreaming","stateProp","showIndicator","tokenCount","tokenLabel","icon","iconVariant","className","resolvedState","resolvedIcon","elapsed","setElapsed","useState","origin","confirming","setConfirming","prevStreamingRef","useRef","useEffect","was","t","tick","id","showTime","showTokens","jsxs","cn","jsx","Fragment","StreamStatus","memo"],"mappings":"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"}
1
+ {"version":3,"file":"stream-status.js","sources":["../../../src/components/ai/stream-status.tsx"],"sourcesContent":["import {\n Disc3Icon,\n LoaderCircleIcon,\n LoaderIcon,\n LoaderPinwheelIcon,\n} from \"lucide-react\";\nimport { memo, useEffect, useRef, useState } from \"react\";\n\nimport type { ReactNode } from \"react\";\n\nimport { TetraMoleculeIcon } from \"@/components/ui/tetra-molecule-icon\";\nimport { cn } from \"@/lib/utils\";\n\nconst MS_PER_S = 1000;\nconst SECS_PER_MIN = 60;\nconst CONFIRM_RIPPLE_MS = 700;\nconst K = 1_000;\nconst M = 1_000_000;\n\n// ---------------------------------------------------------------------------\n// Icon variants\n// ---------------------------------------------------------------------------\n\n/**\n * Built-in spinner icons.\n *\n * The Lucide spinners pair with the flat `ts-spin-pulse` animation; the\n * `tetra` variant is the Tetra-branded \"TetraSpin\" — the official TetraScience\n * molecule logo filled with the brand blue gradient, rotating 360° with the\n * gradient held fixed so its nodes shimmer, echoing the `:tetraspin3d:` gif for\n * a sense of brand identity while an agent is thinking.\n */\nexport const STREAM_STATUS_ICONS = {\n loader: <LoaderIcon />,\n \"loader-circle\": <LoaderCircleIcon />,\n \"loader-pinwheel\": <LoaderPinwheelIcon />,\n \"disc-3\": <Disc3Icon />,\n tetra: <TetraMoleculeIcon />,\n} as const;\n\nexport type StreamStatusIconVariant = keyof typeof STREAM_STATUS_ICONS;\n\n// ---------------------------------------------------------------------------\n// State → indicator dot colour\n// ---------------------------------------------------------------------------\n\nexport type StreamStatusState = \"streaming\" | \"idle\" | \"done\" | \"error\";\n\nconst INDICATOR_CLASS: Record<StreamStatusState, string> = {\n streaming: \"animate-pulse bg-[#549DFF]\", // TS Light Blue 300\n idle: \"bg-muted-foreground/40\",\n done: \"bg-[#038599]\", // TS Forest Green 300\n error: \"bg-[#E15759]\", // TS Imperial Red\n};\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\nexport interface StreamStatusProps {\n /**\n * Timestamp when streaming started (Date or epoch ms).\n * The component manages an internal 1-second ticker when set.\n */\n startTime?: Date | number;\n /** Whether streaming is currently active. Defaults to `true` when `startTime` is set. */\n isStreaming?: boolean;\n /**\n * Explicit state for the right-end indicator dot colour.\n * If omitted, derived from `isStreaming`: `true` → \"streaming\", `false` → \"idle\".\n *\n * | state | colour |\n * |-------------|----------------------------|\n * | streaming | TS Light Blue 300 (pulsing)|\n * | idle | muted gray |\n * | done | TS Forest Green 300 |\n * | error | TS Imperial Red |\n */\n state?: StreamStatusState;\n /**\n * Show the coloured status dot at the right end of the component.\n * Defaults to `false`.\n */\n showIndicator?: boolean;\n /** Token count shown after the separator, e.g. `8700` → \"↓ 8.7k tokens\". */\n tokenCount?: number;\n /** Prefix before the formatted token count. Defaults to `↓`. */\n tokenLabel?: ReactNode;\n /**\n * Custom icon (ReactNode). Takes precedence over `iconVariant`.\n * While streaming, the icon wrapper receives `ts-spin-pulse` — a continuous\n * rotation that occasionally surges to 1.3× scale.\n */\n icon?: ReactNode;\n /**\n * Convenience shorthand to pick a built-in spinner.\n * Ignored when `icon` is also provided. Defaults to `\"tetra\"`.\n *\n * Options: `\"loader\"` | `\"loader-circle\"` | `\"loader-pinwheel\"` | `\"disc-3\"` | `\"tetra\"`.\n * The default `\"tetra\"` variant renders the official TetraScience molecule\n * logo with a fixed brand-blue gradient. Pass `icon={null}` to render no icon.\n */\n iconVariant?: StreamStatusIconVariant;\n className?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction formatElapsed(seconds: number): string {\n const m = Math.floor(seconds / SECS_PER_MIN);\n const s = seconds % SECS_PER_MIN;\n return m > 0 ? `${m}m ${s.toString().padStart(2, \"0\")}s` : `${s}s`;\n}\n\nfunction formatTokens(count: number): string {\n if (count >= M) return `${(count / M).toFixed(1).replace(/\\.0$/, \"\")}m`;\n if (count >= K) return `${(count / K).toFixed(1).replace(/\\.0$/, \"\")}k`;\n return String(count);\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nconst StreamStatusComponent = ({\n startTime,\n isStreaming = startTime !== undefined,\n state: stateProp,\n showIndicator = false,\n tokenCount,\n tokenLabel = \"↓\",\n icon,\n iconVariant = \"tetra\",\n className,\n}: StreamStatusProps) => {\n const resolvedState: StreamStatusState =\n stateProp ?? (isStreaming ? \"streaming\" : \"idle\");\n\n // `icon` wins when provided (including `null` for no icon); otherwise fall\n // back to the built-in variant, which defaults to the branded \"tetra\" mark.\n const resolvedIcon =\n icon === undefined ? STREAM_STATUS_ICONS[iconVariant] : icon;\n\n const [elapsed, setElapsed] = useState(() => {\n if (startTime === undefined) return 0;\n const origin =\n typeof startTime === \"number\" ? startTime : startTime.getTime();\n return Math.max(0, Math.floor((Date.now() - origin) / MS_PER_S));\n });\n\n // Bubble-confirm ripple — fires once when isStreaming transitions true → false\n const [confirming, setConfirming] = useState(false);\n const prevStreamingRef = useRef(isStreaming);\n\n useEffect(() => {\n const was = prevStreamingRef.current;\n prevStreamingRef.current = isStreaming;\n if (was && !isStreaming) {\n setConfirming(true);\n const t = setTimeout(() => setConfirming(false), CONFIRM_RIPPLE_MS);\n return () => clearTimeout(t);\n }\n }, [isStreaming]);\n\n // Elapsed-time ticker — only active while streaming\n useEffect(() => {\n if (!isStreaming || startTime === undefined) return;\n const origin =\n typeof startTime === \"number\" ? startTime : startTime.getTime();\n const tick = () =>\n setElapsed(Math.max(0, Math.floor((Date.now() - origin) / MS_PER_S)));\n tick();\n const id = setInterval(tick, MS_PER_S);\n return () => clearInterval(id);\n }, [isStreaming, startTime]);\n\n const showTime = startTime !== undefined;\n const showTokens = tokenCount !== undefined;\n\n return (\n <div\n aria-live=\"polite\"\n className={cn(\n \"flex items-center gap-2 text-sm text-muted-foreground\",\n className\n )}\n >\n {/* Spinning icon — spins + pulse-surges while streaming */}\n {resolvedIcon !== undefined && (\n <span\n className={cn(\n \"shrink-0 [&>svg]:size-3.5\",\n isStreaming ? \"ts-spin-pulse\" : \"opacity-40\"\n )}\n >\n {resolvedIcon}\n </span>\n )}\n\n {/* Elapsed time */}\n {showTime && (\n <span className=\"tabular-nums\">{formatElapsed(elapsed)}</span>\n )}\n\n {/* Token count */}\n {showTokens && (\n <>\n <span aria-hidden className=\"select-none text-muted-foreground/40\">\n ·\n </span>\n <span className=\"tabular-nums\">\n {tokenLabel != null && (\n <span className=\"mr-0.5\">{tokenLabel}</span>\n )}\n {formatTokens(tokenCount)} tokens\n </span>\n </>\n )}\n\n {/* Right-end indicator dot — opt-in, colour driven by `state` */}\n {showIndicator && (\n <span className=\"relative flex size-3 shrink-0 items-center justify-center\">\n {confirming && (\n <span className=\"ts-bubble-confirm absolute size-2 rounded-full bg-[#549DFF]\" />\n )}\n <span\n className={cn(\n \"size-1.5 rounded-full transition-colors duration-500\",\n INDICATOR_CLASS[resolvedState]\n )}\n />\n </span>\n )}\n </div>\n );\n};\n\nexport const StreamStatus = memo(StreamStatusComponent);\nStreamStatus.displayName = \"StreamStatus\";\n"],"names":["MS_PER_S","SECS_PER_MIN","CONFIRM_RIPPLE_MS","K","M","STREAM_STATUS_ICONS","LoaderIcon","LoaderCircleIcon","LoaderPinwheelIcon","Disc3Icon","TetraMoleculeIcon","INDICATOR_CLASS","formatElapsed","seconds","m","s","formatTokens","count","StreamStatusComponent","startTime","isStreaming","stateProp","showIndicator","tokenCount","tokenLabel","icon","iconVariant","className","resolvedState","resolvedIcon","elapsed","setElapsed","useState","origin","confirming","setConfirming","prevStreamingRef","useRef","useEffect","was","t","tick","id","showTime","showTokens","jsxs","cn","jsx","Fragment","StreamStatus","memo"],"mappings":"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"}