@mastra/playground-ui 48.0.0-alpha.13 → 48.0.0-alpha.14

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 (247) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/{Button-Bm94fEF2.cjs → Button-CbPrvFVl.cjs} +3 -2
  3. package/dist/Button-CbPrvFVl.cjs.map +1 -0
  4. package/dist/{Button-Bx2lFdqb.js → Button-jSNYnNNS.js} +3 -2
  5. package/dist/Button-jSNYnNNS.js.map +1 -0
  6. package/dist/{Notice-B9cdEg8R.cjs → Notice-B57eB0Rg.cjs} +2 -2
  7. package/dist/{Notice-B9cdEg8R.cjs.map → Notice-B57eB0Rg.cjs.map} +1 -1
  8. package/dist/{Notice-DIK9IZsq.js → Notice-D3lGV4-M.js} +2 -2
  9. package/dist/{Notice-DIK9IZsq.js.map → Notice-D3lGV4-M.js.map} +1 -1
  10. package/dist/{SessionExpired-C5ADs4NL.cjs → SessionExpired-Bnc0Hf-P.cjs} +2 -2
  11. package/dist/{SessionExpired-C5ADs4NL.cjs.map → SessionExpired-Bnc0Hf-P.cjs.map} +1 -1
  12. package/dist/{SessionExpired-CHF__hq9.js → SessionExpired-JvcosjKD.js} +2 -2
  13. package/dist/{SessionExpired-CHF__hq9.js.map → SessionExpired-JvcosjKD.js.map} +1 -1
  14. package/dist/{combobox-sa_Pxyl4.js → combobox-B0okm2lT.js} +2 -2
  15. package/dist/{combobox-sa_Pxyl4.js.map → combobox-B0okm2lT.js.map} +1 -1
  16. package/dist/{combobox-DXwbHjvQ.cjs → combobox-hjSfb2cd.cjs} +2 -2
  17. package/dist/{combobox-DXwbHjvQ.cjs.map → combobox-hjSfb2cd.cjs.map} +1 -1
  18. package/dist/{command-Duq1xsiS.js → command-DRjtN9Ol.js} +2 -2
  19. package/dist/{command-Duq1xsiS.js.map → command-DRjtN9Ol.js.map} +1 -1
  20. package/dist/{command-qsEykgml.cjs → command-DZ5t8rS3.cjs} +2 -2
  21. package/dist/{command-qsEykgml.cjs.map → command-DZ5t8rS3.cjs.map} +1 -1
  22. package/dist/components/AlertDialog.cjs.js +1 -1
  23. package/dist/components/AlertDialog.es.js +1 -1
  24. package/dist/components/Button.cjs.js +1 -1
  25. package/dist/components/Button.es.js +1 -1
  26. package/dist/components/ClampedText.cjs.js +1 -1
  27. package/dist/components/ClampedText.es.js +1 -1
  28. package/dist/components/CodeBlock.cjs.js +2 -2
  29. package/dist/components/CodeBlock.es.js +2 -2
  30. package/dist/components/CodeEditor.cjs.js +1 -1
  31. package/dist/components/CodeEditor.es.js +1 -1
  32. package/dist/components/Columns.cjs.js +1 -1
  33. package/dist/components/Columns.es.js +1 -1
  34. package/dist/components/Combobox.cjs.js +1 -1
  35. package/dist/components/Combobox.es.js +1 -1
  36. package/dist/components/Command.cjs.js +1 -1
  37. package/dist/components/Command.es.js +1 -1
  38. package/dist/components/CommandPalette.cjs.js +1 -1
  39. package/dist/components/CommandPalette.es.js +1 -1
  40. package/dist/components/CopyButton.cjs.js +1 -1
  41. package/dist/components/CopyButton.es.js +1 -1
  42. package/dist/components/DataCodeSection.cjs.js +1 -1
  43. package/dist/components/DataCodeSection.es.js +1 -1
  44. package/dist/components/DataDetailsPanel.cjs.js +2 -2
  45. package/dist/components/DataDetailsPanel.es.js +2 -2
  46. package/dist/components/DataFilter.cjs.js +2 -2
  47. package/dist/components/DataFilter.es.js +2 -2
  48. package/dist/components/DataList.cjs.js +2 -2
  49. package/dist/components/DataList.es.js +2 -2
  50. package/dist/components/DataPanel.cjs.js +1 -1
  51. package/dist/components/DataPanel.es.js +1 -1
  52. package/dist/components/DateRangeTimeline.cjs.js +1 -1
  53. package/dist/components/DateRangeTimeline.es.js +1 -1
  54. package/dist/components/DateTimePicker.cjs.js +2 -2
  55. package/dist/components/DateTimePicker.es.js +2 -2
  56. package/dist/components/DateTimeRangePicker.cjs.js +1 -1
  57. package/dist/components/DateTimeRangePicker.es.js +1 -1
  58. package/dist/components/Dialog.cjs.js +1 -1
  59. package/dist/components/Dialog.es.js +1 -1
  60. package/dist/components/Drawer.cjs.js +1 -1
  61. package/dist/components/Drawer.es.js +1 -1
  62. package/dist/components/DropdownMenu.cjs.js +1 -1
  63. package/dist/components/DropdownMenu.es.js +1 -1
  64. package/dist/components/EnvironmentVariablesEditor.cjs.js +4 -4
  65. package/dist/components/EnvironmentVariablesEditor.es.js +4 -4
  66. package/dist/components/ErrorBoundary.cjs.js +1 -1
  67. package/dist/components/ErrorBoundary.es.js +1 -1
  68. package/dist/components/FormFieldBlocks.cjs.js +2 -2
  69. package/dist/components/FormFieldBlocks.es.js +2 -2
  70. package/dist/components/HoverCard.cjs.js +1 -1
  71. package/dist/components/HoverCard.es.js +1 -1
  72. package/dist/components/InputGroup.cjs.js +1 -1
  73. package/dist/components/InputGroup.es.js +1 -1
  74. package/dist/components/JSONSchemaForm.cjs.js +2 -2
  75. package/dist/components/JSONSchemaForm.es.js +2 -2
  76. package/dist/components/KeyValueList.cjs.js +1 -1
  77. package/dist/components/KeyValueList.es.js +1 -1
  78. package/dist/components/ListSearch.cjs.js +1 -1
  79. package/dist/components/ListSearch.es.js +1 -1
  80. package/dist/components/MainSidebar.cjs.js +72 -49
  81. package/dist/components/MainSidebar.cjs.js.map +1 -1
  82. package/dist/components/MainSidebar.es.js +72 -49
  83. package/dist/components/MainSidebar.es.js.map +1 -1
  84. package/dist/components/MarkdownRenderer.cjs.js +1 -1
  85. package/dist/components/MarkdownRenderer.es.js +1 -1
  86. package/dist/components/Notice.cjs.js +1 -1
  87. package/dist/components/Notice.es.js +1 -1
  88. package/dist/components/PrevNextNav.cjs.js +1 -1
  89. package/dist/components/PrevNextNav.es.js +1 -1
  90. package/dist/components/PropertyFilter.cjs.js +3 -3
  91. package/dist/components/PropertyFilter.es.js +4 -4
  92. package/dist/components/RuleBuilder.cjs.js +2 -2
  93. package/dist/components/RuleBuilder.es.js +2 -2
  94. package/dist/components/SankeyChart.cjs.js +266 -57
  95. package/dist/components/SankeyChart.cjs.js.map +1 -1
  96. package/dist/components/SankeyChart.es.js +267 -58
  97. package/dist/components/SankeyChart.es.js.map +1 -1
  98. package/dist/components/Select.cjs.js +1 -1
  99. package/dist/components/Select.es.js +1 -1
  100. package/dist/components/SessionExpired.cjs.js +1 -1
  101. package/dist/components/SessionExpired.es.js +1 -1
  102. package/dist/components/SideDialog.cjs.js +3 -3
  103. package/dist/components/SideDialog.es.js +3 -3
  104. package/dist/components/ThreadList.cjs.js +1 -1
  105. package/dist/components/ThreadList.es.js +1 -1
  106. package/dist/components/Truncate.cjs.js +1 -1
  107. package/dist/components/Truncate.es.js +1 -1
  108. package/dist/components/ai/ask-user.cjs.js +1 -1
  109. package/dist/components/ai/ask-user.es.js +1 -1
  110. package/dist/components/ai/plan.cjs.js +2 -2
  111. package/dist/components/ai/plan.es.js +2 -2
  112. package/dist/{copy-button-BKFcsNE1.cjs → copy-button-CbvvXi2V.cjs} +2 -2
  113. package/dist/{copy-button-BKFcsNE1.cjs.map → copy-button-CbvvXi2V.cjs.map} +1 -1
  114. package/dist/{copy-button-H2iaKMng.js → copy-button-D8qhMF81.js} +2 -2
  115. package/dist/{copy-button-H2iaKMng.js.map → copy-button-D8qhMF81.js.map} +1 -1
  116. package/dist/{data-code-section-D2zjah_b.cjs → data-code-section-BlnF-AcH.cjs} +5 -5
  117. package/dist/{data-code-section-D2zjah_b.cjs.map → data-code-section-BlnF-AcH.cjs.map} +1 -1
  118. package/dist/{data-code-section-MHMkC6q9.js → data-code-section-C8h-MUTj.js} +5 -5
  119. package/dist/{data-code-section-MHMkC6q9.js.map → data-code-section-C8h-MUTj.js.map} +1 -1
  120. package/dist/{data-list-Cb-piK4z.cjs → data-list-CeqAz6RR.cjs} +2 -2
  121. package/dist/{data-list-Cb-piK4z.cjs.map → data-list-CeqAz6RR.cjs.map} +1 -1
  122. package/dist/{data-list-CnQRIUyN.js → data-list-Chyj88BP.js} +2 -2
  123. package/dist/{data-list-CnQRIUyN.js.map → data-list-Chyj88BP.js.map} +1 -1
  124. package/dist/{data-panel-BumsjXVz.cjs → data-panel-1SM5j2BQ.cjs} +3 -3
  125. package/dist/{data-panel-BumsjXVz.cjs.map → data-panel-1SM5j2BQ.cjs.map} +1 -1
  126. package/dist/{data-panel-BEvHk4wg.js → data-panel-Bbhd1VVF.js} +3 -3
  127. package/dist/{data-panel-BEvHk4wg.js.map → data-panel-Bbhd1VVF.js.map} +1 -1
  128. package/dist/{date-time-range-picker-yJBIm34J.js → date-time-range-picker-Cz5Xdzm8.js} +4 -4
  129. package/dist/{date-time-range-picker-yJBIm34J.js.map → date-time-range-picker-Cz5Xdzm8.js.map} +1 -1
  130. package/dist/{date-time-range-picker-ue0m5G27.cjs → date-time-range-picker-DkNsQWnt.cjs} +4 -4
  131. package/dist/{date-time-range-picker-ue0m5G27.cjs.map → date-time-range-picker-DkNsQWnt.cjs.map} +1 -1
  132. package/dist/{dialog-bnt6epW2.js → dialog-CnY-gDja.js} +2 -2
  133. package/dist/{dialog-bnt6epW2.js.map → dialog-CnY-gDja.js.map} +1 -1
  134. package/dist/{dialog-ClItuCFY.cjs → dialog-Con_VmlQ.cjs} +2 -2
  135. package/dist/{dialog-ClItuCFY.cjs.map → dialog-Con_VmlQ.cjs.map} +1 -1
  136. package/dist/domains/logs/components/log-details-view.cjs.js +2 -2
  137. package/dist/domains/logs/components/log-details-view.es.js +2 -2
  138. package/dist/domains/logs/components/logs-error-content.cjs.js +1 -1
  139. package/dist/domains/logs/components/logs-error-content.es.js +1 -1
  140. package/dist/domains/logs/components/logs-toolbar.cjs.js +1 -1
  141. package/dist/domains/logs/components/logs-toolbar.es.js +1 -1
  142. package/dist/domains/logs/components/no-logs-info.cjs.js +1 -1
  143. package/dist/domains/logs/components/no-logs-info.es.js +1 -1
  144. package/dist/domains/memory/components/flame-graph.cjs.js +1 -1
  145. package/dist/domains/memory/components/flame-graph.es.js +1 -1
  146. package/dist/domains/memory/components/memory-studio-panel.cjs.js +1 -1
  147. package/dist/domains/memory/components/memory-studio-panel.es.js +1 -1
  148. package/dist/domains/metrics/components/card-action-buttons.cjs.js +1 -1
  149. package/dist/domains/metrics/components/card-action-buttons.es.js +1 -1
  150. package/dist/domains/metrics/components/date-range-selector.cjs.js +1 -1
  151. package/dist/domains/metrics/components/date-range-selector.es.js +1 -1
  152. package/dist/domains/metrics/components/memory-card-view.cjs.js +1 -1
  153. package/dist/domains/metrics/components/memory-card-view.es.js +1 -1
  154. package/dist/domains/metrics/components/model-usage-cost-card-view.cjs.js +1 -1
  155. package/dist/domains/metrics/components/model-usage-cost-card-view.es.js +1 -1
  156. package/dist/domains/metrics/components/scores-card-view.cjs.js +1 -1
  157. package/dist/domains/metrics/components/scores-card-view.es.js +1 -1
  158. package/dist/domains/traces/components/no-traces-info.cjs.js +1 -1
  159. package/dist/domains/traces/components/no-traces-info.es.js +1 -1
  160. package/dist/domains/traces/components/span-data-panel-view.cjs.js +2 -2
  161. package/dist/domains/traces/components/span-data-panel-view.es.js +2 -2
  162. package/dist/domains/traces/components/timeline-name-col.cjs.js +6 -2
  163. package/dist/domains/traces/components/timeline-name-col.cjs.js.map +1 -1
  164. package/dist/domains/traces/components/timeline-name-col.es.js +6 -2
  165. package/dist/domains/traces/components/timeline-name-col.es.js.map +1 -1
  166. package/dist/domains/traces/components/timeline-timing-col.cjs.js +1 -1
  167. package/dist/domains/traces/components/timeline-timing-col.es.js +1 -1
  168. package/dist/domains/traces/components/trace-columns-menu.cjs.js +3 -3
  169. package/dist/domains/traces/components/trace-columns-menu.es.js +3 -3
  170. package/dist/domains/traces/components/trace-data-panel-view.cjs.js +4 -10
  171. package/dist/domains/traces/components/trace-data-panel-view.cjs.js.map +1 -1
  172. package/dist/domains/traces/components/trace-data-panel-view.es.js +5 -11
  173. package/dist/domains/traces/components/trace-data-panel-view.es.js.map +1 -1
  174. package/dist/domains/traces/components/traces-error-content.cjs.js +1 -1
  175. package/dist/domains/traces/components/traces-error-content.es.js +1 -1
  176. package/dist/domains/traces/components/traces-list-mode-toggle.cjs.js +2 -2
  177. package/dist/domains/traces/components/traces-list-mode-toggle.es.js +2 -2
  178. package/dist/domains/traces/components/traces-list-view.cjs.js +2 -2
  179. package/dist/domains/traces/components/traces-list-view.es.js +2 -2
  180. package/dist/domains/traces/components/traces-toolbar.cjs.js +1 -1
  181. package/dist/domains/traces/components/traces-toolbar.es.js +1 -1
  182. package/dist/{drawer-CdsTitFp.cjs → drawer-Bng-J6Ne.cjs} +2 -2
  183. package/dist/{drawer-CdsTitFp.cjs.map → drawer-Bng-J6Ne.cjs.map} +1 -1
  184. package/dist/{drawer-DZ9amYo_.js → drawer-D9Cp7w6N.js} +2 -2
  185. package/dist/{drawer-DZ9amYo_.js.map → drawer-D9Cp7w6N.js.map} +1 -1
  186. package/dist/{dropdown-menu-ppWztidX.cjs → dropdown-menu-BZGlERgf.cjs} +4 -3
  187. package/dist/dropdown-menu-BZGlERgf.cjs.map +1 -0
  188. package/dist/{dropdown-menu-DEFygDZI.js → dropdown-menu-DCMh8P4w.js} +4 -3
  189. package/dist/dropdown-menu-DCMh8P4w.js.map +1 -0
  190. package/dist/ee/signals/components/signals-empty-state.cjs.js +1 -1
  191. package/dist/ee/signals/components/signals-empty-state.es.js +1 -1
  192. package/dist/ee/topics/components/topic-trace-summary-list.cjs.js +3 -3
  193. package/dist/ee/topics/components/topic-trace-summary-list.es.js +3 -3
  194. package/dist/{hover-card-crVofiZO.js → hover-card-Bs845QbV.js} +2 -2
  195. package/dist/{hover-card-crVofiZO.js.map → hover-card-Bs845QbV.js.map} +1 -1
  196. package/dist/{hover-card-Bx258om1.cjs → hover-card-Cd9QK50X.cjs} +2 -2
  197. package/dist/{hover-card-Bx258om1.cjs.map → hover-card-Cd9QK50X.cjs.map} +1 -1
  198. package/dist/{input-group-Dzs-ai0n.js → input-group-BnnvYySr.js} +2 -2
  199. package/dist/{input-group-Dzs-ai0n.js.map → input-group-BnnvYySr.js.map} +1 -1
  200. package/dist/{input-group-CH72YUVL.cjs → input-group-BxAiZUo5.cjs} +2 -2
  201. package/dist/{input-group-CH72YUVL.cjs.map → input-group-BxAiZUo5.cjs.map} +1 -1
  202. package/dist/{markdown-renderer-Bi2fWeoF.js → markdown-renderer-Bpucep5E.js} +36 -18
  203. package/dist/markdown-renderer-Bpucep5E.js.map +1 -0
  204. package/dist/{markdown-renderer-DwfNrhEH.cjs → markdown-renderer-tuX3CjAv.cjs} +36 -18
  205. package/dist/markdown-renderer-tuX3CjAv.cjs.map +1 -0
  206. package/dist/{property-filter-applied-DI4w1ACS.js → property-filter-applied-CdhgsCC8.js} +3 -3
  207. package/dist/{property-filter-applied-DI4w1ACS.js.map → property-filter-applied-CdhgsCC8.js.map} +1 -1
  208. package/dist/{property-filter-applied-BhxbHAN8.cjs → property-filter-applied-DROoy70i.cjs} +3 -3
  209. package/dist/{property-filter-applied-BhxbHAN8.cjs.map → property-filter-applied-DROoy70i.cjs.map} +1 -1
  210. package/dist/resize/panel-drawer.cjs.js +1 -1
  211. package/dist/resize/panel-drawer.es.js +1 -1
  212. package/dist/{search-field-block-DCnFZzRK.js → search-field-block-C15VrrNp.js} +2 -2
  213. package/dist/{search-field-block-DCnFZzRK.js.map → search-field-block-C15VrrNp.js.map} +1 -1
  214. package/dist/{search-field-block-D6TdrHZX.cjs → search-field-block-wjh5uz7E.cjs} +2 -2
  215. package/dist/{search-field-block-D6TdrHZX.cjs.map → search-field-block-wjh5uz7E.cjs.map} +1 -1
  216. package/dist/{select-B6ce20XX.cjs → select-DgOJ6a0U.cjs} +2 -2
  217. package/dist/{select-B6ce20XX.cjs.map → select-DgOJ6a0U.cjs.map} +1 -1
  218. package/dist/{select-Beo8qQ0e.js → select-DzvxwWFF.js} +2 -2
  219. package/dist/{select-Beo8qQ0e.js.map → select-DzvxwWFF.js.map} +1 -1
  220. package/dist/{select-field-block-DXw3tD0y.js → select-field-block-BWwOG2cP.js} +2 -2
  221. package/dist/{select-field-block-DXw3tD0y.js.map → select-field-block-BWwOG2cP.js.map} +1 -1
  222. package/dist/{select-field-block-svlHplxW.cjs → select-field-block-DY9ebut9.cjs} +2 -2
  223. package/dist/{select-field-block-svlHplxW.cjs.map → select-field-block-DY9ebut9.cjs.map} +1 -1
  224. package/dist/src/ds/components/MainSidebar/main-sidebar-nav-item-classes.d.ts +13 -2
  225. package/dist/src/ds/components/MainSidebar/main-sidebar-nav-link.d.ts +2 -2
  226. package/dist/src/ds/components/MarkdownRenderer/markdown-renderer.d.ts +3 -1
  227. package/dist/src/ds/components/SankeyChart/sankey-chart.d.ts +7 -2
  228. package/dist/src/ds/components/SankeyChart/sankey-portal-tooltip.d.ts +8 -0
  229. package/dist/src/ds/components/SankeyChart/use-sankey-geometry-transition.d.ts +11 -0
  230. package/dist/src/ds/components/SankeyChart/use-sankey-hover-tooltip.d.ts +15 -0
  231. package/dist/style.css +31 -4
  232. package/dist/{time-picker-mLzcoQMO.js → time-picker-BOncuX6N.js} +2 -2
  233. package/dist/{time-picker-mLzcoQMO.js.map → time-picker-BOncuX6N.js.map} +1 -1
  234. package/dist/{time-picker-BOQtPoyD.cjs → time-picker-D5KGkYTX.cjs} +2 -2
  235. package/dist/{time-picker-BOQtPoyD.cjs.map → time-picker-D5KGkYTX.cjs.map} +1 -1
  236. package/dist/{traces-data-list-vsvvvEiP.cjs → traces-data-list-BnQncyG0.cjs} +2 -2
  237. package/dist/{traces-data-list-vsvvvEiP.cjs.map → traces-data-list-BnQncyG0.cjs.map} +1 -1
  238. package/dist/{traces-data-list-DtuaCDES.js → traces-data-list-cySY6wpT.js} +2 -2
  239. package/dist/{traces-data-list-DtuaCDES.js.map → traces-data-list-cySY6wpT.js.map} +1 -1
  240. package/package.json +6 -6
  241. package/theme.css +8 -0
  242. package/dist/Button-Bm94fEF2.cjs.map +0 -1
  243. package/dist/Button-Bx2lFdqb.js.map +0 -1
  244. package/dist/dropdown-menu-DEFygDZI.js.map +0 -1
  245. package/dist/dropdown-menu-ppWztidX.cjs.map +0 -1
  246. package/dist/markdown-renderer-Bi2fWeoF.js.map +0 -1
  247. package/dist/markdown-renderer-DwfNrhEH.cjs.map +0 -1
@@ -1,9 +1,9 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { useState, useContext, createContext, useRef, useEffect, useMemo, useId } from 'react';
2
+ import { useState, useContext, createContext, useId, useRef, useEffect, useMemo, useSyncExternalStore } from 'react';
3
3
  import { b as buildSankeyHueMap, n as nodeColor, a as nodeColorVivid } from '../sankeyColor-CQ5nkgtL.js';
4
4
  export { h as hashHue } from '../sankeyColor-CQ5nkgtL.js';
5
- import { createPortal } from 'react-dom';
6
5
  import { ResponsiveContainer, Sankey as Sankey$1 } from 'recharts';
6
+ import { createPortal } from 'react-dom';
7
7
  import { C as Colors } from '../spacings-C87dXiT-.js';
8
8
  import { c as cn } from '../cn-BakJzhuv.js';
9
9
 
@@ -315,6 +315,82 @@ function orderColumns(columns, order) {
315
315
  );
316
316
  }
317
317
 
318
+ const SANKEY_TOOLTIP_MAX_WIDTH_PX = 320;
319
+ const TOOLTIP_TOP_FLIP_THRESHOLD = 120;
320
+ const TOOLTIP_EDGE_INSET = 16;
321
+ const TOOLTIP_RIGHT_INSET = SANKEY_TOOLTIP_MAX_WIDTH_PX + TOOLTIP_EDGE_INSET;
322
+ function useSankeyHoverTooltip(enabled) {
323
+ const id = useId();
324
+ const [isHovered, setIsHovered] = useState(false);
325
+ const [isFocused, setIsFocused] = useState(false);
326
+ const [position, setPosition] = useState();
327
+ function showAt(target) {
328
+ if (!enabled) return;
329
+ const rect = target.getBoundingClientRect();
330
+ const placement = rect.top < TOOLTIP_TOP_FLIP_THRESHOLD ? "below" : "above";
331
+ setPosition({
332
+ left: Math.min(
333
+ Math.max(rect.left, TOOLTIP_EDGE_INSET),
334
+ Math.max(window.innerWidth - TOOLTIP_RIGHT_INSET, TOOLTIP_EDGE_INSET)
335
+ ),
336
+ top: placement === "above" ? rect.top - 8 : rect.bottom + 8,
337
+ placement
338
+ });
339
+ }
340
+ return {
341
+ id,
342
+ position,
343
+ isVisible: Boolean(enabled && position && (isHovered || isFocused)),
344
+ showOnHover(target) {
345
+ setIsHovered(true);
346
+ showAt(target);
347
+ },
348
+ hideOnLeave() {
349
+ setIsHovered(false);
350
+ },
351
+ showOnFocus(target) {
352
+ setIsFocused(true);
353
+ showAt(target);
354
+ },
355
+ hideOnBlur() {
356
+ setIsFocused(false);
357
+ }
358
+ };
359
+ }
360
+
361
+ function SankeyPortalTooltip({
362
+ id,
363
+ title,
364
+ description,
365
+ position,
366
+ visible
367
+ }) {
368
+ if (!visible || !position) return null;
369
+ return createPortal(
370
+ /* @__PURE__ */ jsxs(
371
+ "div",
372
+ {
373
+ "aria-label": `${title}: ${description}`,
374
+ className: "border-border1 bg-surface5 text-neutral6 shadow-elevated pointer-events-none fixed z-50 rounded-md border p-2 text-xs leading-4",
375
+ id,
376
+ role: "tooltip",
377
+ style: {
378
+ left: position.left,
379
+ maxWidth: `min(${SANKEY_TOOLTIP_MAX_WIDTH_PX}px, calc(100vw - 2rem))`,
380
+ top: position.top,
381
+ transform: position.placement === "above" ? "translateY(-100%)" : void 0,
382
+ width: "max-content"
383
+ },
384
+ children: [
385
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: title }),
386
+ /* @__PURE__ */ jsx("div", { className: "text-neutral4 whitespace-pre-wrap", children: description })
387
+ ]
388
+ }
389
+ ),
390
+ document.body
391
+ );
392
+ }
393
+
318
394
  function useSankeyChartMeasurements({
319
395
  graph,
320
396
  height,
@@ -356,6 +432,117 @@ function useSankeyChartMeasurements({
356
432
  return { chartContainerRef, fixedGeometry, labelWidths };
357
433
  }
358
434
 
435
+ const TRANSITION_DURATION_MS = 850;
436
+ function mix(from, to, progress) {
437
+ return from + (to - from) * progress;
438
+ }
439
+ function interpolateNode(from, to, progress) {
440
+ return {
441
+ x: mix(from.x, to.x, progress),
442
+ y: mix(from.y, to.y, progress),
443
+ centerY: mix(from.centerY, to.centerY, progress),
444
+ height: mix(from.height, to.height, progress)
445
+ };
446
+ }
447
+ function interpolateLink(from, to, progress) {
448
+ return {
449
+ sourceX: mix(from.sourceX, to.sourceX, progress),
450
+ targetX: mix(from.targetX, to.targetX, progress),
451
+ sourceY: mix(from.sourceY, to.sourceY, progress),
452
+ targetY: mix(from.targetY, to.targetY, progress),
453
+ sourceWidth: mix(from.sourceWidth, to.sourceWidth, progress),
454
+ targetWidth: mix(from.targetWidth, to.targetWidth, progress)
455
+ };
456
+ }
457
+ function interpolateSankeyGeometry(from, to, progress) {
458
+ const replacedPreviousLinks = [...from.links].filter(([id]) => !to.links.has(id)).map(([, link]) => link);
459
+ const nodes = /* @__PURE__ */ new Map();
460
+ const links = /* @__PURE__ */ new Map();
461
+ for (const [id, target] of to.nodes) {
462
+ nodes.set(id, interpolateNode(from.nodes.get(id) ?? target, target, progress));
463
+ }
464
+ let replacedLinkIndex = 0;
465
+ for (const [id, target] of to.links) {
466
+ const matchingSource = from.links.get(id);
467
+ const syntheticSource = matchingSource ? void 0 : replacedPreviousLinks[replacedLinkIndex++];
468
+ links.set(id, interpolateLink(matchingSource ?? syntheticSource ?? target, target, progress));
469
+ }
470
+ return { nodes, links };
471
+ }
472
+ function prefersReducedMotion() {
473
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
474
+ }
475
+ class SankeyGeometryMotionStore {
476
+ animationFrame = 0;
477
+ key;
478
+ listeners = /* @__PURE__ */ new Set();
479
+ snapshot;
480
+ target;
481
+ transition;
482
+ constructor(key, geometry) {
483
+ this.key = key;
484
+ this.snapshot = geometry;
485
+ this.target = geometry;
486
+ }
487
+ getSnapshot = () => this.snapshot;
488
+ subscribe = (listener) => {
489
+ this.listeners.add(listener);
490
+ return () => this.listeners.delete(listener);
491
+ };
492
+ transitionTo(key, geometry) {
493
+ if (key === this.key && geometry === this.target) return;
494
+ const keyChanged = key !== this.key;
495
+ this.key = key;
496
+ this.target = geometry;
497
+ if (!keyChanged && geometry && this.transition) {
498
+ this.transition = { ...this.transition, to: geometry };
499
+ return;
500
+ }
501
+ cancelAnimationFrame(this.animationFrame);
502
+ this.animationFrame = 0;
503
+ if (!keyChanged || !geometry || !this.snapshot || prefersReducedMotion()) {
504
+ this.transition = void 0;
505
+ this.publish(geometry);
506
+ return;
507
+ }
508
+ this.transition = { from: this.snapshot, to: geometry, startedAt: performance.now() };
509
+ this.animationFrame = requestAnimationFrame(this.animate);
510
+ }
511
+ dispose() {
512
+ cancelAnimationFrame(this.animationFrame);
513
+ this.listeners.clear();
514
+ }
515
+ animate = (now) => {
516
+ const transition = this.transition;
517
+ if (!transition) return;
518
+ const elapsed = Math.min((now - transition.startedAt) / TRANSITION_DURATION_MS, 1);
519
+ const progress = 1 - (1 - elapsed) ** 3;
520
+ this.publish(interpolateSankeyGeometry(transition.from, transition.to, progress));
521
+ if (elapsed < 1) {
522
+ this.animationFrame = requestAnimationFrame(this.animate);
523
+ return;
524
+ }
525
+ this.transition = void 0;
526
+ this.animationFrame = 0;
527
+ };
528
+ publish(geometry) {
529
+ this.snapshot = geometry;
530
+ for (const listener of this.listeners) listener();
531
+ }
532
+ }
533
+ function useSankeyGeometryTransition({
534
+ geometry,
535
+ transitionKey
536
+ }) {
537
+ const [store] = useState(() => new SankeyGeometryMotionStore(transitionKey, geometry));
538
+ const animatedGeometry = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
539
+ useEffect(() => {
540
+ store.transitionTo(transitionKey, geometry);
541
+ }, [geometry, store, transitionKey]);
542
+ useEffect(() => () => store.dispose(), [store]);
543
+ return animatedGeometry;
544
+ }
545
+
359
546
  const NODE_LABEL_FONT_SIZE = 11;
360
547
  const COLUMN_LABEL_FONT_SIZE = 12;
361
548
  const NODE_LABEL_MAX_CHARACTERS = 23;
@@ -365,7 +552,10 @@ function SankeyChart({
365
552
  margin = { top: 64, right: 160, bottom: 12, left: 160 },
366
553
  onCurveClick,
367
554
  onNodeClick,
368
- isNodeClickable
555
+ isNodeClickable,
556
+ getColumnDescription,
557
+ hideColumnLabels = false,
558
+ geometryTransitionKey
369
559
  }) {
370
560
  const { graph, enabledColumns, hueMap, usesFixedGeometry } = useSankeyRenderContext();
371
561
  const { chartContainerRef, fixedGeometry, labelWidths } = useSankeyChartMeasurements({
@@ -374,6 +564,10 @@ function SankeyChart({
374
564
  margin,
375
565
  usesFixedGeometry
376
566
  });
567
+ const animatedGeometry = useSankeyGeometryTransition({
568
+ geometry: fixedGeometry,
569
+ transitionKey: geometryTransitionKey
570
+ });
377
571
  const [hoveredSourceName, setHoveredSourceName] = useState();
378
572
  const [focusedSourceName, setFocusedSourceName] = useState();
379
573
  const activeSourceName = hoveredSourceName ?? focusedSourceName;
@@ -407,8 +601,8 @@ function SankeyChart({
407
601
  margin,
408
602
  node: (props) => {
409
603
  const node = graph.nodes[props.index];
410
- const showColumnLabel = node ? graph.nodes.findIndex((candidate) => candidate.column.id === node.column.id) === props.index : false;
411
- const nodeGeometry = node ? fixedGeometry?.nodes.get(node.id) : void 0;
604
+ const showColumnLabel = !hideColumnLabels && node ? graph.nodes.findIndex((candidate) => candidate.column.id === node.column.id) === props.index : false;
605
+ const nodeGeometry = node ? animatedGeometry?.nodes.get(node.id) : void 0;
412
606
  const selection = node ? getSankeyChartNodeSelection(node) : void 0;
413
607
  const clickable = Boolean(
414
608
  onNodeClick && selection && (isNodeClickable === void 0 || isNodeClickable(selection))
@@ -422,6 +616,7 @@ function SankeyChart({
422
616
  height: nodeGeometry?.height ?? props.height,
423
617
  hueMap,
424
618
  columnLabel: node?.column.label,
619
+ columnDescription: node ? getColumnDescription?.(node.column) : void 0,
425
620
  label: node?.label,
426
621
  nodeValue: node?.displayValue,
427
622
  layoutValue: nodeGeometry ? void 0 : node ? nodeWeights.get(node.id) : void 0,
@@ -441,7 +636,7 @@ function SankeyChart({
441
636
  },
442
637
  link: (props) => {
443
638
  const link = graph.links[props.index];
444
- const linkGeometry = link ? fixedGeometry?.links.get(link.id) : void 0;
639
+ const linkGeometry = link ? animatedGeometry?.links.get(link.id) : void 0;
445
640
  const sourceX = linkGeometry?.sourceX ?? props.sourceX;
446
641
  const targetX = linkGeometry?.targetX ?? props.targetX;
447
642
  const fixedControlX = linkGeometry ? (sourceX + targetX) / 2 : void 0;
@@ -482,6 +677,7 @@ function SankeyNode({
482
677
  payload,
483
678
  hueMap,
484
679
  columnLabel,
680
+ columnDescription,
485
681
  label,
486
682
  nodeValue,
487
683
  layoutValue,
@@ -508,10 +704,7 @@ function SankeyNode({
508
704
  maxCharacters: NODE_LABEL_MAX_CHARACTERS
509
705
  });
510
706
  const visibleColumnLabel = columnLabel ? truncateSankeyLabel(columnLabel, { fontSize: COLUMN_LABEL_FONT_SIZE, maxWidth: nodeLabelWidth }) : void 0;
511
- const tooltipId = useId();
512
- const [isHovered, setIsHovered] = useState(false);
513
- const [isFocused, setIsFocused] = useState(false);
514
- const [tooltipPosition, setTooltipPosition] = useState();
707
+ const tooltip = useSankeyHoverTooltip(description !== void 0);
515
708
  const numericValue = nodeValue ?? (typeof payload.value === "number" ? payload.value : Number(payload.value));
516
709
  const value = Number.isFinite(numericValue) ? String(numericValue) : "";
517
710
  const percentage = columnTotal > 0 && Number.isFinite(numericValue) ? Math.round(numericValue / columnTotal * 100) : 0;
@@ -520,41 +713,27 @@ function SankeyNode({
520
713
  const textAnchor = isFirstColumn ? "start" : isLastColumn ? "end" : "middle";
521
714
  const labelX = isFirstColumn ? x : isLastColumn ? x + width : x + width / 2;
522
715
  const hue = hueMap[name] ?? 0;
523
- const isTooltipVisible = Boolean(description && tooltipPosition && (isHovered || isFocused));
524
- const showTooltipAt = (target) => {
525
- const rect = target.getBoundingClientRect();
526
- const placement = rect.top < 120 ? "below" : "above";
527
- setTooltipPosition({
528
- left: Math.min(Math.max(rect.left, 16), Math.max(window.innerWidth - 336, 16)),
529
- top: placement === "above" ? rect.top - 8 : rect.bottom + 8,
530
- placement
531
- });
532
- };
533
716
  const handleKeyDown = (event) => {
534
717
  if (event.key !== "Enter" && event.key !== " ") return;
535
718
  event.preventDefault();
536
719
  onSelect();
537
720
  };
538
721
  return /* @__PURE__ */ jsxs(Fragment, { children: [
539
- showColumnLabel && visibleColumnLabel ? /* @__PURE__ */ jsxs(
540
- "text",
722
+ showColumnLabel && visibleColumnLabel && columnLabel ? /* @__PURE__ */ jsx(
723
+ SankeyColumnHeader,
541
724
  {
542
725
  x: labelX,
543
- y: 18,
544
726
  textAnchor,
545
727
  fill: nodeColor(hue),
546
- fontSize: COLUMN_LABEL_FONT_SIZE,
547
- fontWeight: 600,
548
- children: [
549
- visibleColumnLabel === columnLabel ? null : /* @__PURE__ */ jsx("title", { children: columnLabel }),
550
- visibleColumnLabel
551
- ]
728
+ label: visibleColumnLabel,
729
+ fullLabel: columnLabel,
730
+ description: columnDescription
552
731
  }
553
732
  ) : null,
554
733
  /* @__PURE__ */ jsxs(
555
734
  "g",
556
735
  {
557
- "aria-describedby": description ? tooltipId : void 0,
736
+ "aria-describedby": description ? tooltip.id : void 0,
558
737
  "aria-label": `${accessibleLabel}: ${value} ${numericValue === 1 ? "trace" : "traces"} (${percentage}%)`,
559
738
  className: "focus-visible:[&>rect]:stroke-neutral6 outline-hidden focus-visible:[&>rect]:stroke-2",
560
739
  onClick: clickable ? onSelect : void 0,
@@ -562,21 +741,19 @@ function SankeyNode({
562
741
  role: clickable ? "button" : void 0,
563
742
  onFocus: (event) => {
564
743
  onFocusChange(name);
565
- setIsFocused(true);
566
- showTooltipAt(event.currentTarget);
744
+ tooltip.showOnFocus(event.currentTarget);
567
745
  },
568
746
  onBlur: () => {
569
747
  onFocusChange(void 0);
570
- setIsFocused(false);
748
+ tooltip.hideOnBlur();
571
749
  },
572
750
  onMouseEnter: (event) => {
573
751
  onHoverChange(name);
574
- setIsHovered(true);
575
- showTooltipAt(event.currentTarget);
752
+ tooltip.showOnHover(event.currentTarget);
576
753
  },
577
754
  onMouseLeave: () => {
578
755
  onHoverChange(void 0);
579
- setIsHovered(false);
756
+ tooltip.hideOnLeave();
580
757
  },
581
758
  style: { cursor: clickable ? "pointer" : void 0 },
582
759
  tabIndex: 0,
@@ -604,28 +781,60 @@ function SankeyNode({
604
781
  ]
605
782
  }
606
783
  ),
607
- description && isTooltipVisible && tooltipPosition ? createPortal(
608
- /* @__PURE__ */ jsxs(
609
- "div",
610
- {
611
- "aria-label": `${visibleDisplayLabel}: ${description}`,
612
- className: "border-border1 bg-surface5 text-neutral6 shadow-elevated pointer-events-none fixed z-50 rounded-md border p-2 text-xs leading-4",
613
- id: tooltipId,
614
- role: "tooltip",
615
- style: {
616
- left: tooltipPosition.left,
617
- maxWidth: "min(20rem, calc(100vw - 2rem))",
618
- top: tooltipPosition.top,
619
- transform: tooltipPosition.placement === "above" ? "translateY(-100%)" : void 0,
620
- width: "max-content"
621
- },
622
- children: [
623
- /* @__PURE__ */ jsx("div", { className: "font-medium", children: visibleDisplayLabel }),
624
- /* @__PURE__ */ jsx("div", { className: "text-neutral4 whitespace-pre-wrap", children: description })
625
- ]
626
- }
627
- ),
628
- document.body
784
+ description ? /* @__PURE__ */ jsx(
785
+ SankeyPortalTooltip,
786
+ {
787
+ id: tooltip.id,
788
+ title: visibleDisplayLabel,
789
+ description,
790
+ position: tooltip.position,
791
+ visible: tooltip.isVisible
792
+ }
793
+ ) : null
794
+ ] });
795
+ }
796
+ function SankeyColumnHeader({
797
+ x,
798
+ textAnchor,
799
+ fill,
800
+ label,
801
+ fullLabel,
802
+ description
803
+ }) {
804
+ const tooltip = useSankeyHoverTooltip(description !== void 0);
805
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
806
+ /* @__PURE__ */ jsxs(
807
+ "text",
808
+ {
809
+ "aria-describedby": description ? tooltip.id : void 0,
810
+ "aria-label": description ? fullLabel : void 0,
811
+ role: description ? "img" : void 0,
812
+ x,
813
+ y: 18,
814
+ textAnchor,
815
+ fill,
816
+ fontSize: COLUMN_LABEL_FONT_SIZE,
817
+ fontWeight: 600,
818
+ tabIndex: description ? 0 : void 0,
819
+ onMouseEnter: description ? (event) => tooltip.showOnHover(event.currentTarget) : void 0,
820
+ onMouseLeave: description ? tooltip.hideOnLeave : void 0,
821
+ onFocus: description ? (event) => tooltip.showOnFocus(event.currentTarget) : void 0,
822
+ onBlur: description ? tooltip.hideOnBlur : void 0,
823
+ children: [
824
+ label === fullLabel || description ? null : /* @__PURE__ */ jsx("title", { children: fullLabel }),
825
+ label
826
+ ]
827
+ }
828
+ ),
829
+ description ? /* @__PURE__ */ jsx(
830
+ SankeyPortalTooltip,
831
+ {
832
+ id: tooltip.id,
833
+ title: fullLabel,
834
+ description,
835
+ position: tooltip.position,
836
+ visible: tooltip.isVisible
837
+ }
629
838
  ) : null
630
839
  ] });
631
840
  }