@workflow/web-shared 5.0.0-beta.4 → 5.0.0-beta.40

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 (517) hide show
  1. package/README.md +5 -13
  2. package/dist/components/error-boundary.js +1 -1
  3. package/dist/components/event-list-view.d.ts +46 -1
  4. package/dist/components/event-list-view.d.ts.map +1 -1
  5. package/dist/components/event-list-view.js +235 -97
  6. package/dist/components/hook-actions.js +1 -1
  7. package/dist/components/index.d.ts +8 -5
  8. package/dist/components/index.d.ts.map +1 -1
  9. package/dist/components/index.js +6 -4
  10. package/dist/components/sidebar/attribute-panel.d.ts +4 -1
  11. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  12. package/dist/components/sidebar/attribute-panel.js +173 -119
  13. package/dist/components/sidebar/attributes-block.d.ts +40 -0
  14. package/dist/components/sidebar/attributes-block.d.ts.map +1 -0
  15. package/dist/components/sidebar/attributes-block.js +140 -0
  16. package/dist/components/sidebar/conversation-view.js +1 -1
  17. package/dist/components/sidebar/copyable-data-block.d.ts +2 -0
  18. package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
  19. package/dist/components/sidebar/copyable-data-block.js +17 -16
  20. package/dist/components/sidebar/entity-detail-panel.d.ts +11 -11
  21. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
  22. package/dist/components/sidebar/entity-detail-panel.js +37 -71
  23. package/dist/components/sidebar/events-list.d.ts +6 -2
  24. package/dist/components/sidebar/events-list.d.ts.map +1 -1
  25. package/dist/components/sidebar/events-list.js +77 -63
  26. package/dist/components/sidebar/resolve-hook-modal.js +1 -1
  27. package/dist/components/sidebar/sidebar-data-context.d.ts +10 -7
  28. package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -1
  29. package/dist/components/sidebar/sidebar-data-context.js +1 -1
  30. package/dist/components/sidebar/span-detail-merge.d.ts +31 -0
  31. package/dist/components/sidebar/span-detail-merge.d.ts.map +1 -0
  32. package/dist/components/sidebar/span-detail-merge.js +92 -0
  33. package/dist/components/sidebar/use-selected-span-detail.d.ts +16 -0
  34. package/dist/components/sidebar/use-selected-span-detail.d.ts.map +1 -0
  35. package/dist/components/sidebar/use-selected-span-detail.js +93 -0
  36. package/dist/components/stream-viewer-skeleton.d.ts +2 -0
  37. package/dist/components/stream-viewer-skeleton.d.ts.map +1 -0
  38. package/dist/components/stream-viewer-skeleton.js +12 -0
  39. package/dist/components/stream-viewer.d.ts +1 -1
  40. package/dist/components/stream-viewer.d.ts.map +1 -1
  41. package/dist/components/stream-viewer.js +9 -26
  42. package/dist/components/trace-viewer/components/copy-button.d.ts.map +1 -0
  43. package/dist/components/trace-viewer/components/copy-button.js +27 -0
  44. package/dist/components/trace-viewer/components/detail-panel-width.d.ts +34 -0
  45. package/dist/components/trace-viewer/components/detail-panel-width.d.ts.map +1 -0
  46. package/dist/components/trace-viewer/components/detail-panel-width.js +67 -0
  47. package/dist/components/trace-viewer/components/detail-panel.d.ts +14 -0
  48. package/dist/components/trace-viewer/components/detail-panel.d.ts.map +1 -0
  49. package/dist/components/trace-viewer/components/detail-panel.js +122 -0
  50. package/dist/components/trace-viewer/components/draggable-border.d.ts +31 -0
  51. package/dist/components/trace-viewer/components/draggable-border.d.ts.map +1 -0
  52. package/dist/components/trace-viewer/components/draggable-border.js +140 -0
  53. package/dist/components/trace-viewer/components/event-list.d.ts +10 -0
  54. package/dist/components/trace-viewer/components/event-list.d.ts.map +1 -0
  55. package/dist/components/trace-viewer/components/event-list.js +47 -0
  56. package/dist/components/trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
  57. package/dist/components/trace-viewer/components/middle-truncate/copy-selection.js +54 -0
  58. package/dist/components/trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
  59. package/dist/components/trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
  60. package/dist/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/truncate.d.ts +1 -1
  61. package/dist/components/trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
  62. package/dist/components/trace-viewer/components/middle-truncate/truncate.js +101 -0
  63. package/dist/components/trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
  64. package/dist/components/trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
  65. package/dist/components/trace-viewer/components/minimap.d.ts +14 -0
  66. package/dist/components/trace-viewer/components/minimap.d.ts.map +1 -0
  67. package/dist/components/trace-viewer/components/minimap.js +337 -0
  68. package/dist/components/trace-viewer/components/pane-constants.d.ts +14 -0
  69. package/dist/components/trace-viewer/components/pane-constants.d.ts.map +1 -0
  70. package/dist/components/trace-viewer/components/pane-constants.js +16 -0
  71. package/dist/components/trace-viewer/components/span-markers.d.ts +46 -0
  72. package/dist/components/trace-viewer/components/span-markers.d.ts.map +1 -0
  73. package/dist/components/trace-viewer/components/span-markers.js +85 -0
  74. package/dist/components/trace-viewer/components/split-pane.d.ts +10 -0
  75. package/dist/components/trace-viewer/components/split-pane.d.ts.map +1 -0
  76. package/dist/components/trace-viewer/components/split-pane.js +41 -0
  77. package/dist/components/trace-viewer/components/timeline.d.ts +42 -0
  78. package/dist/components/trace-viewer/components/timeline.d.ts.map +1 -0
  79. package/dist/components/trace-viewer/components/timeline.js +321 -0
  80. package/dist/components/trace-viewer/components/timeline.module.css +46 -0
  81. package/dist/components/trace-viewer/components/trace-shortcut-helper.d.ts +5 -0
  82. package/dist/components/trace-viewer/components/trace-shortcut-helper.d.ts.map +1 -0
  83. package/dist/components/trace-viewer/components/trace-shortcut-helper.js +55 -0
  84. package/dist/components/trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  85. package/dist/components/trace-viewer/components/trace-viewer-skeleton.d.ts +2 -0
  86. package/dist/components/trace-viewer/components/trace-viewer-skeleton.d.ts.map +1 -0
  87. package/dist/components/trace-viewer/components/trace-viewer-skeleton.js +26 -0
  88. package/dist/components/trace-viewer/components/use-element-width.d.ts +8 -0
  89. package/dist/components/trace-viewer/components/use-element-width.d.ts.map +1 -0
  90. package/dist/components/trace-viewer/components/use-element-width.js +25 -0
  91. package/dist/components/trace-viewer/components/use-row-window.d.ts +34 -0
  92. package/dist/components/trace-viewer/components/use-row-window.d.ts.map +1 -0
  93. package/dist/components/trace-viewer/components/use-row-window.js +107 -0
  94. package/dist/components/trace-viewer/context.d.ts +14 -182
  95. package/dist/components/trace-viewer/context.d.ts.map +1 -1
  96. package/dist/components/trace-viewer/context.js +44 -351
  97. package/dist/components/trace-viewer/icons.d.ts.map +1 -0
  98. package/dist/components/trace-viewer/icons.js +15 -0
  99. package/dist/components/trace-viewer/search.d.ts +19 -0
  100. package/dist/components/trace-viewer/search.d.ts.map +1 -0
  101. package/dist/components/trace-viewer/search.js +134 -0
  102. package/dist/components/trace-viewer/trace-viewer.d.ts +7 -28
  103. package/dist/components/trace-viewer/trace-viewer.d.ts.map +1 -1
  104. package/dist/components/trace-viewer/trace-viewer.js +306 -356
  105. package/dist/components/trace-viewer/types.d.ts +2 -211
  106. package/dist/components/trace-viewer/types.d.ts.map +1 -1
  107. package/dist/components/trace-viewer/types.js +1 -1
  108. package/dist/components/trace-viewer/util/timing.d.ts +2 -2
  109. package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
  110. package/dist/components/trace-viewer/util/timing.js +3 -3
  111. package/dist/components/trace-viewer/utils.d.ts +111 -0
  112. package/dist/components/trace-viewer/utils.d.ts.map +1 -0
  113. package/dist/components/trace-viewer/utils.js +430 -0
  114. package/dist/components/{trace-viewer-new.d.ts → trace-viewer.d.ts} +7 -3
  115. package/dist/components/trace-viewer.d.ts.map +1 -0
  116. package/dist/components/trace-viewer.js +21 -0
  117. package/dist/components/ui/alert.js +3 -3
  118. package/dist/components/ui/button.d.ts +10 -0
  119. package/dist/components/ui/button.d.ts.map +1 -0
  120. package/dist/components/ui/button.js +46 -0
  121. package/dist/components/ui/card.d.ts.map +1 -1
  122. package/dist/components/ui/card.js +4 -4
  123. package/dist/components/ui/collapsible.d.ts +46 -0
  124. package/dist/components/ui/collapsible.d.ts.map +1 -0
  125. package/dist/components/ui/collapsible.js +66 -0
  126. package/dist/components/ui/context-card.d.ts +47 -0
  127. package/dist/components/ui/context-card.d.ts.map +1 -0
  128. package/dist/components/ui/context-card.js +471 -0
  129. package/dist/components/ui/data-inspector.d.ts +7 -6
  130. package/dist/components/ui/data-inspector.d.ts.map +1 -1
  131. package/dist/components/ui/data-inspector.js +232 -99
  132. package/dist/components/ui/data-inspector.styles.d.ts +29 -0
  133. package/dist/components/ui/data-inspector.styles.d.ts.map +1 -0
  134. package/dist/components/ui/data-inspector.styles.js +95 -0
  135. package/dist/components/ui/decrypt-button.js +1 -1
  136. package/dist/components/ui/error-card.js +3 -3
  137. package/dist/components/ui/error-stack-block.d.ts +17 -10
  138. package/dist/components/ui/error-stack-block.d.ts.map +1 -1
  139. package/dist/components/ui/error-stack-block.js +49 -30
  140. package/dist/components/ui/icon-button.d.ts +19 -0
  141. package/dist/components/ui/icon-button.d.ts.map +1 -0
  142. package/dist/components/ui/icon-button.js +29 -0
  143. package/dist/components/ui/kbd.d.ts +10 -0
  144. package/dist/components/ui/kbd.d.ts.map +1 -0
  145. package/dist/components/ui/kbd.js +25 -0
  146. package/dist/components/ui/load-more-button.js +1 -1
  147. package/dist/components/ui/menu-dropdown.js +1 -1
  148. package/dist/components/ui/skeleton.js +2 -2
  149. package/dist/components/ui/spinner.js +1 -1
  150. package/dist/components/ui/timestamp-tooltip.d.ts +34 -1
  151. package/dist/components/ui/timestamp-tooltip.d.ts.map +1 -1
  152. package/dist/components/ui/timestamp-tooltip.js +80 -132
  153. package/dist/components/ui/tooltip.d.ts +10 -0
  154. package/dist/components/ui/tooltip.d.ts.map +1 -0
  155. package/dist/components/ui/tooltip.js +12 -0
  156. package/dist/components/workflow-traces/event-colors.d.ts +2 -1
  157. package/dist/components/workflow-traces/event-colors.d.ts.map +1 -1
  158. package/dist/components/workflow-traces/event-colors.js +15 -7
  159. package/dist/components/workflow-traces/trace-span-construction.d.ts +6 -3
  160. package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
  161. package/dist/components/workflow-traces/trace-span-construction.js +71 -30
  162. package/dist/components/workflow-traces/trace-time-utils.js +1 -1
  163. package/dist/hooks/use-dark-mode.js +1 -1
  164. package/dist/hooks/use-intersection-observer.d.ts +17 -0
  165. package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
  166. package/dist/hooks/use-intersection-observer.js +29 -0
  167. package/dist/hooks/use-load-more-on-scroll.d.ts +21 -0
  168. package/dist/hooks/use-load-more-on-scroll.d.ts.map +1 -0
  169. package/dist/hooks/use-load-more-on-scroll.js +28 -0
  170. package/dist/hooks/use-reduced-motion.d.ts +10 -0
  171. package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
  172. package/dist/hooks/use-reduced-motion.js +29 -0
  173. package/dist/index.d.ts +4 -3
  174. package/dist/index.d.ts.map +1 -1
  175. package/dist/index.js +4 -3
  176. package/dist/lib/cn.d.ts +10 -0
  177. package/dist/lib/cn.d.ts.map +1 -0
  178. package/dist/lib/cn.js +83 -0
  179. package/dist/lib/event-analysis.d.ts +1 -1
  180. package/dist/lib/event-analysis.d.ts.map +1 -1
  181. package/dist/lib/event-analysis.js +3 -2
  182. package/dist/lib/event-materialization.d.ts +1 -1
  183. package/dist/lib/event-materialization.d.ts.map +1 -1
  184. package/dist/lib/event-materialization.js +29 -21
  185. package/dist/lib/exact-event-search-id.d.ts +25 -0
  186. package/dist/lib/exact-event-search-id.d.ts.map +1 -0
  187. package/dist/lib/exact-event-search-id.js +39 -0
  188. package/dist/lib/hydration.d.ts +17 -2
  189. package/dist/lib/hydration.d.ts.map +1 -1
  190. package/dist/lib/hydration.js +194 -23
  191. package/dist/lib/stream-display.js +1 -1
  192. package/dist/lib/toast.js +1 -1
  193. package/dist/lib/trace-builder.d.ts +17 -5
  194. package/dist/lib/trace-builder.d.ts.map +1 -1
  195. package/dist/lib/trace-builder.js +32 -14
  196. package/dist/lib/trace-types.d.ts +54 -0
  197. package/dist/lib/trace-types.d.ts.map +1 -0
  198. package/dist/lib/trace-types.js +2 -0
  199. package/dist/lib/utils.d.ts +14 -2
  200. package/dist/lib/utils.d.ts.map +1 -1
  201. package/dist/lib/utils.js +46 -6
  202. package/dist/lib/zstd-browser-decoder.d.ts +7 -0
  203. package/dist/lib/zstd-browser-decoder.d.ts.map +1 -0
  204. package/dist/lib/zstd-browser-decoder.js +41 -0
  205. package/dist/styles.css +210 -139
  206. package/package.json +11 -8
  207. package/src/components/event-list-view.tsx +385 -123
  208. package/src/components/index.ts +14 -8
  209. package/src/components/sidebar/attribute-panel.tsx +331 -282
  210. package/src/components/sidebar/attributes-block.tsx +326 -0
  211. package/src/components/sidebar/copyable-data-block.tsx +50 -28
  212. package/src/components/sidebar/entity-detail-panel.tsx +92 -126
  213. package/src/components/sidebar/events-list.tsx +197 -179
  214. package/src/components/sidebar/sidebar-data-context.tsx +11 -11
  215. package/src/components/sidebar/span-detail-merge.ts +134 -0
  216. package/src/components/sidebar/use-selected-span-detail.ts +146 -0
  217. package/src/components/stream-viewer-skeleton.tsx +34 -0
  218. package/src/components/stream-viewer.tsx +34 -106
  219. package/src/components/{new-trace-viewer → trace-viewer}/components/copy-button.tsx +2 -2
  220. package/src/components/trace-viewer/components/detail-panel-width.test.ts +123 -0
  221. package/src/components/trace-viewer/components/detail-panel-width.ts +76 -0
  222. package/src/components/trace-viewer/components/detail-panel.tsx +273 -0
  223. package/src/components/trace-viewer/components/draggable-border.tsx +216 -0
  224. package/src/components/trace-viewer/components/event-list.tsx +144 -0
  225. package/src/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/middle-truncate.tsx +8 -8
  226. package/src/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/truncate.ts +1 -1
  227. package/src/components/trace-viewer/components/minimap.tsx +556 -0
  228. package/src/components/trace-viewer/components/pane-constants.ts +19 -0
  229. package/src/components/trace-viewer/components/span-markers.tsx +173 -0
  230. package/src/components/trace-viewer/components/split-pane.tsx +141 -0
  231. package/src/components/trace-viewer/components/timeline.module.css +46 -0
  232. package/src/components/trace-viewer/components/timeline.tsx +850 -0
  233. package/src/components/trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  234. package/src/components/trace-viewer/components/trace-shortcut-helper.tsx +116 -0
  235. package/src/components/trace-viewer/components/trace-viewer-skeleton.tsx +114 -0
  236. package/src/components/trace-viewer/components/use-element-width.ts +29 -0
  237. package/src/components/trace-viewer/components/use-row-window.ts +140 -0
  238. package/src/components/trace-viewer/context.tsx +63 -656
  239. package/src/components/{new-trace-viewer → trace-viewer}/icons.tsx +2 -2
  240. package/src/components/trace-viewer/search.ts +178 -0
  241. package/src/components/trace-viewer/trace-viewer.tsx +563 -531
  242. package/src/components/trace-viewer/types.ts +2 -234
  243. package/src/components/trace-viewer/util/timing.ts +2 -2
  244. package/src/components/trace-viewer/utils.test.ts +458 -0
  245. package/src/components/{new-trace-viewer → trace-viewer}/utils.ts +271 -50
  246. package/src/components/{trace-viewer-new.tsx → trace-viewer.tsx} +24 -18
  247. package/src/components/ui/alert.tsx +2 -2
  248. package/src/components/ui/button.tsx +68 -0
  249. package/src/components/ui/card.tsx +3 -10
  250. package/src/components/ui/collapsible.tsx +219 -0
  251. package/src/components/ui/context-card.tsx +784 -0
  252. package/src/components/ui/data-inspector.styles.ts +96 -0
  253. package/src/components/ui/data-inspector.tsx +501 -204
  254. package/src/components/ui/error-card.tsx +4 -4
  255. package/src/components/ui/error-stack-block.tsx +84 -55
  256. package/src/components/ui/icon-button.tsx +53 -0
  257. package/src/components/ui/kbd.tsx +43 -0
  258. package/src/components/ui/skeleton.tsx +1 -1
  259. package/src/components/ui/timestamp-tooltip.tsx +132 -194
  260. package/src/components/ui/tooltip.tsx +47 -0
  261. package/src/components/workflow-traces/event-colors.ts +15 -11
  262. package/src/components/workflow-traces/trace-span-construction.test.ts +85 -0
  263. package/src/components/workflow-traces/trace-span-construction.ts +97 -32
  264. package/src/hooks/use-intersection-observer.ts +57 -0
  265. package/src/hooks/use-load-more-on-scroll.ts +49 -0
  266. package/src/hooks/use-reduced-motion.ts +34 -0
  267. package/src/index.ts +10 -4
  268. package/src/lib/cn.ts +93 -0
  269. package/src/lib/event-analysis.ts +6 -4
  270. package/src/lib/event-materialization.ts +35 -21
  271. package/src/lib/exact-event-search-id.ts +67 -0
  272. package/src/lib/hydration.ts +210 -30
  273. package/src/lib/trace-builder.ts +43 -19
  274. package/src/lib/trace-types.ts +56 -0
  275. package/src/lib/utils.test.ts +33 -0
  276. package/src/lib/utils.ts +53 -6
  277. package/src/lib/zstd-browser-decoder.ts +42 -0
  278. package/src/styles.css +210 -139
  279. package/dist/components/error-boundary.js.map +0 -1
  280. package/dist/components/event-list-view.js.map +0 -1
  281. package/dist/components/hook-actions.js.map +0 -1
  282. package/dist/components/index.js.map +0 -1
  283. package/dist/components/new-trace-viewer/components/copy-button.d.ts.map +0 -1
  284. package/dist/components/new-trace-viewer/components/copy-button.js +0 -27
  285. package/dist/components/new-trace-viewer/components/copy-button.js.map +0 -1
  286. package/dist/components/new-trace-viewer/components/event-list.d.ts +0 -8
  287. package/dist/components/new-trace-viewer/components/event-list.d.ts.map +0 -1
  288. package/dist/components/new-trace-viewer/components/event-list.js +0 -38
  289. package/dist/components/new-trace-viewer/components/event-list.js.map +0 -1
  290. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +0 -1
  291. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +0 -54
  292. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js.map +0 -1
  293. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +0 -1
  294. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +0 -81
  295. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js.map +0 -1
  296. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +0 -1
  297. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +0 -101
  298. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js.map +0 -1
  299. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +0 -1
  300. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +0 -114
  301. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js.map +0 -1
  302. package/dist/components/new-trace-viewer/components/split-pane.d.ts +0 -14
  303. package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +0 -1
  304. package/dist/components/new-trace-viewer/components/split-pane.js +0 -99
  305. package/dist/components/new-trace-viewer/components/split-pane.js.map +0 -1
  306. package/dist/components/new-trace-viewer/components/timeline.d.ts +0 -31
  307. package/dist/components/new-trace-viewer/components/timeline.d.ts.map +0 -1
  308. package/dist/components/new-trace-viewer/components/timeline.js +0 -138
  309. package/dist/components/new-trace-viewer/components/timeline.js.map +0 -1
  310. package/dist/components/new-trace-viewer/context.d.ts +0 -15
  311. package/dist/components/new-trace-viewer/context.d.ts.map +0 -1
  312. package/dist/components/new-trace-viewer/context.js +0 -47
  313. package/dist/components/new-trace-viewer/context.js.map +0 -1
  314. package/dist/components/new-trace-viewer/detail-panel.d.ts +0 -10
  315. package/dist/components/new-trace-viewer/detail-panel.d.ts.map +0 -1
  316. package/dist/components/new-trace-viewer/detail-panel.js +0 -12
  317. package/dist/components/new-trace-viewer/detail-panel.js.map +0 -1
  318. package/dist/components/new-trace-viewer/icons.d.ts.map +0 -1
  319. package/dist/components/new-trace-viewer/icons.js +0 -15
  320. package/dist/components/new-trace-viewer/icons.js.map +0 -1
  321. package/dist/components/new-trace-viewer/trace-viewer.d.ts +0 -8
  322. package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +0 -1
  323. package/dist/components/new-trace-viewer/trace-viewer.js +0 -349
  324. package/dist/components/new-trace-viewer/trace-viewer.js.map +0 -1
  325. package/dist/components/new-trace-viewer/types.d.ts +0 -1
  326. package/dist/components/new-trace-viewer/types.d.ts.map +0 -1
  327. package/dist/components/new-trace-viewer/types.js +0 -2
  328. package/dist/components/new-trace-viewer/types.js.map +0 -1
  329. package/dist/components/new-trace-viewer/util/constants.d.ts +0 -1
  330. package/dist/components/new-trace-viewer/util/constants.d.ts.map +0 -1
  331. package/dist/components/new-trace-viewer/util/constants.js +0 -2
  332. package/dist/components/new-trace-viewer/util/constants.js.map +0 -1
  333. package/dist/components/new-trace-viewer/utils.d.ts +0 -42
  334. package/dist/components/new-trace-viewer/utils.d.ts.map +0 -1
  335. package/dist/components/new-trace-viewer/utils.js +0 -305
  336. package/dist/components/new-trace-viewer/utils.js.map +0 -1
  337. package/dist/components/run-trace-view.d.ts +0 -25
  338. package/dist/components/run-trace-view.d.ts.map +0 -1
  339. package/dist/components/run-trace-view.js +0 -11
  340. package/dist/components/run-trace-view.js.map +0 -1
  341. package/dist/components/sidebar/attribute-panel.js.map +0 -1
  342. package/dist/components/sidebar/conversation-view.js.map +0 -1
  343. package/dist/components/sidebar/copyable-data-block.js.map +0 -1
  344. package/dist/components/sidebar/detail-card.d.ts +0 -14
  345. package/dist/components/sidebar/detail-card.d.ts.map +0 -1
  346. package/dist/components/sidebar/detail-card.js +0 -20
  347. package/dist/components/sidebar/detail-card.js.map +0 -1
  348. package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
  349. package/dist/components/sidebar/events-list.js.map +0 -1
  350. package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
  351. package/dist/components/sidebar/sidebar-data-context.js.map +0 -1
  352. package/dist/components/stream-viewer.js.map +0 -1
  353. package/dist/components/trace-viewer/components/map.d.ts +0 -8
  354. package/dist/components/trace-viewer/components/map.d.ts.map +0 -1
  355. package/dist/components/trace-viewer/components/map.js +0 -162
  356. package/dist/components/trace-viewer/components/map.js.map +0 -1
  357. package/dist/components/trace-viewer/components/markers.d.ts +0 -23
  358. package/dist/components/trace-viewer/components/markers.d.ts.map +0 -1
  359. package/dist/components/trace-viewer/components/markers.js +0 -416
  360. package/dist/components/trace-viewer/components/markers.js.map +0 -1
  361. package/dist/components/trace-viewer/components/node.d.ts +0 -35
  362. package/dist/components/trace-viewer/components/node.d.ts.map +0 -1
  363. package/dist/components/trace-viewer/components/node.js +0 -285
  364. package/dist/components/trace-viewer/components/node.js.map +0 -1
  365. package/dist/components/trace-viewer/components/search-input.d.ts +0 -9
  366. package/dist/components/trace-viewer/components/search-input.d.ts.map +0 -1
  367. package/dist/components/trace-viewer/components/search-input.js +0 -9
  368. package/dist/components/trace-viewer/components/search-input.js.map +0 -1
  369. package/dist/components/trace-viewer/components/search.d.ts +0 -3
  370. package/dist/components/trace-viewer/components/search.d.ts.map +0 -1
  371. package/dist/components/trace-viewer/components/search.js +0 -25
  372. package/dist/components/trace-viewer/components/search.js.map +0 -1
  373. package/dist/components/trace-viewer/components/span-content.d.ts +0 -19
  374. package/dist/components/trace-viewer/components/span-content.d.ts.map +0 -1
  375. package/dist/components/trace-viewer/components/span-content.js +0 -137
  376. package/dist/components/trace-viewer/components/span-content.js.map +0 -1
  377. package/dist/components/trace-viewer/components/span-detail-panel.d.ts +0 -10
  378. package/dist/components/trace-viewer/components/span-detail-panel.d.ts.map +0 -1
  379. package/dist/components/trace-viewer/components/span-detail-panel.js +0 -285
  380. package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
  381. package/dist/components/trace-viewer/components/span-segments.d.ts +0 -50
  382. package/dist/components/trace-viewer/components/span-segments.d.ts.map +0 -1
  383. package/dist/components/trace-viewer/components/span-segments.js +0 -445
  384. package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
  385. package/dist/components/trace-viewer/components/span-strategies.d.ts +0 -46
  386. package/dist/components/trace-viewer/components/span-strategies.d.ts.map +0 -1
  387. package/dist/components/trace-viewer/components/span-strategies.js +0 -108
  388. package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
  389. package/dist/components/trace-viewer/components/ui.d.ts +0 -28
  390. package/dist/components/trace-viewer/components/ui.d.ts.map +0 -1
  391. package/dist/components/trace-viewer/components/ui.js +0 -39
  392. package/dist/components/trace-viewer/components/ui.js.map +0 -1
  393. package/dist/components/trace-viewer/components/zoom-button.d.ts +0 -3
  394. package/dist/components/trace-viewer/components/zoom-button.d.ts.map +0 -1
  395. package/dist/components/trace-viewer/components/zoom-button.js +0 -29
  396. package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
  397. package/dist/components/trace-viewer/components/zoom-icons.d.ts +0 -11
  398. package/dist/components/trace-viewer/components/zoom-icons.d.ts.map +0 -1
  399. package/dist/components/trace-viewer/components/zoom-icons.js +0 -11
  400. package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
  401. package/dist/components/trace-viewer/context.js.map +0 -1
  402. package/dist/components/trace-viewer/index.d.ts +0 -5
  403. package/dist/components/trace-viewer/index.d.ts.map +0 -1
  404. package/dist/components/trace-viewer/index.js +0 -4
  405. package/dist/components/trace-viewer/index.js.map +0 -1
  406. package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
  407. package/dist/components/trace-viewer/trace-viewer.module.css +0 -1465
  408. package/dist/components/trace-viewer/types.js.map +0 -1
  409. package/dist/components/trace-viewer/util/constants.d.ts +0 -9
  410. package/dist/components/trace-viewer/util/constants.d.ts.map +0 -1
  411. package/dist/components/trace-viewer/util/constants.js +0 -9
  412. package/dist/components/trace-viewer/util/constants.js.map +0 -1
  413. package/dist/components/trace-viewer/util/scrollbar-width.d.ts +0 -2
  414. package/dist/components/trace-viewer/util/scrollbar-width.d.ts.map +0 -1
  415. package/dist/components/trace-viewer/util/scrollbar-width.js +0 -14
  416. package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
  417. package/dist/components/trace-viewer/util/timing.js.map +0 -1
  418. package/dist/components/trace-viewer/util/tree.d.ts +0 -13
  419. package/dist/components/trace-viewer/util/tree.d.ts.map +0 -1
  420. package/dist/components/trace-viewer/util/tree.js +0 -227
  421. package/dist/components/trace-viewer/util/tree.js.map +0 -1
  422. package/dist/components/trace-viewer/util/use-immediate-style.d.ts +0 -15
  423. package/dist/components/trace-viewer/util/use-immediate-style.d.ts.map +0 -1
  424. package/dist/components/trace-viewer/util/use-immediate-style.js +0 -23
  425. package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
  426. package/dist/components/trace-viewer/util/use-streaming-spans.d.ts +0 -8
  427. package/dist/components/trace-viewer/util/use-streaming-spans.d.ts.map +0 -1
  428. package/dist/components/trace-viewer/util/use-streaming-spans.js +0 -345
  429. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
  430. package/dist/components/trace-viewer/util/use-trackpad-zoom.d.ts +0 -6
  431. package/dist/components/trace-viewer/util/use-trackpad-zoom.d.ts.map +0 -1
  432. package/dist/components/trace-viewer/util/use-trackpad-zoom.js +0 -39
  433. package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
  434. package/dist/components/trace-viewer/worker.d.ts +0 -2
  435. package/dist/components/trace-viewer/worker.d.ts.map +0 -1
  436. package/dist/components/trace-viewer/worker.js +0 -109
  437. package/dist/components/trace-viewer/worker.js.map +0 -1
  438. package/dist/components/trace-viewer-new.d.ts.map +0 -1
  439. package/dist/components/trace-viewer-new.js +0 -23
  440. package/dist/components/trace-viewer-new.js.map +0 -1
  441. package/dist/components/ui/alert.js.map +0 -1
  442. package/dist/components/ui/card.js.map +0 -1
  443. package/dist/components/ui/data-inspector.js.map +0 -1
  444. package/dist/components/ui/decrypt-button.js.map +0 -1
  445. package/dist/components/ui/error-card.js.map +0 -1
  446. package/dist/components/ui/error-stack-block.js.map +0 -1
  447. package/dist/components/ui/inspector-theme.d.ts +0 -95
  448. package/dist/components/ui/inspector-theme.d.ts.map +0 -1
  449. package/dist/components/ui/inspector-theme.js +0 -82
  450. package/dist/components/ui/inspector-theme.js.map +0 -1
  451. package/dist/components/ui/load-more-button.js.map +0 -1
  452. package/dist/components/ui/menu-dropdown.js.map +0 -1
  453. package/dist/components/ui/skeleton.js.map +0 -1
  454. package/dist/components/ui/spinner.js.map +0 -1
  455. package/dist/components/ui/timestamp-tooltip.js.map +0 -1
  456. package/dist/components/workflow-trace-view.d.ts +0 -40
  457. package/dist/components/workflow-trace-view.d.ts.map +0 -1
  458. package/dist/components/workflow-trace-view.js +0 -695
  459. package/dist/components/workflow-trace-view.js.map +0 -1
  460. package/dist/components/workflow-traces/event-colors.js.map +0 -1
  461. package/dist/components/workflow-traces/trace-colors.d.ts +0 -15
  462. package/dist/components/workflow-traces/trace-colors.d.ts.map +0 -1
  463. package/dist/components/workflow-traces/trace-colors.js +0 -87
  464. package/dist/components/workflow-traces/trace-colors.js.map +0 -1
  465. package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
  466. package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
  467. package/dist/hooks/use-dark-mode.js.map +0 -1
  468. package/dist/index.js.map +0 -1
  469. package/dist/lib/event-analysis.js.map +0 -1
  470. package/dist/lib/event-materialization.js.map +0 -1
  471. package/dist/lib/hydration.js.map +0 -1
  472. package/dist/lib/stream-display.js.map +0 -1
  473. package/dist/lib/toast.js.map +0 -1
  474. package/dist/lib/trace-builder.js.map +0 -1
  475. package/dist/lib/utils.js.map +0 -1
  476. package/src/components/new-trace-viewer/components/event-list.tsx +0 -116
  477. package/src/components/new-trace-viewer/components/split-pane.tsx +0 -185
  478. package/src/components/new-trace-viewer/components/timeline.tsx +0 -382
  479. package/src/components/new-trace-viewer/context.tsx +0 -92
  480. package/src/components/new-trace-viewer/detail-panel.tsx +0 -58
  481. package/src/components/new-trace-viewer/trace-viewer.tsx +0 -645
  482. package/src/components/new-trace-viewer/types.ts +0 -0
  483. package/src/components/new-trace-viewer/util/constants.ts +0 -0
  484. package/src/components/run-trace-view.tsx +0 -84
  485. package/src/components/sidebar/detail-card.tsx +0 -65
  486. package/src/components/trace-viewer/components/map.tsx +0 -226
  487. package/src/components/trace-viewer/components/markers.tsx +0 -612
  488. package/src/components/trace-viewer/components/node.tsx +0 -505
  489. package/src/components/trace-viewer/components/search-input.tsx +0 -52
  490. package/src/components/trace-viewer/components/search.tsx +0 -47
  491. package/src/components/trace-viewer/components/span-content.tsx +0 -247
  492. package/src/components/trace-viewer/components/span-detail-panel.tsx +0 -655
  493. package/src/components/trace-viewer/components/span-segments.ts +0 -585
  494. package/src/components/trace-viewer/components/span-strategies.ts +0 -205
  495. package/src/components/trace-viewer/components/ui.tsx +0 -156
  496. package/src/components/trace-viewer/components/zoom-button.tsx +0 -61
  497. package/src/components/trace-viewer/components/zoom-icons.tsx +0 -65
  498. package/src/components/trace-viewer/index.tsx +0 -4
  499. package/src/components/trace-viewer/trace-viewer.module.css +0 -1465
  500. package/src/components/trace-viewer/util/constants.ts +0 -8
  501. package/src/components/trace-viewer/util/scrollbar-width.ts +0 -13
  502. package/src/components/trace-viewer/util/tree.ts +0 -277
  503. package/src/components/trace-viewer/util/use-immediate-style.ts +0 -38
  504. package/src/components/trace-viewer/util/use-streaming-spans.ts +0 -426
  505. package/src/components/trace-viewer/util/use-trackpad-zoom.tsx +0 -51
  506. package/src/components/trace-viewer/worker.ts +0 -131
  507. package/src/components/ui/inspector-theme.ts +0 -110
  508. package/src/components/workflow-trace-view.tsx +0 -1171
  509. package/src/components/workflow-traces/trace-colors.ts +0 -112
  510. /package/dist/components/{new-trace-viewer → trace-viewer}/components/copy-button.d.ts +0 -0
  511. /package/dist/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/copy-selection.d.ts +0 -0
  512. /package/dist/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/middle-truncate.d.ts +0 -0
  513. /package/dist/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/use-middle-truncate.d.ts +0 -0
  514. /package/dist/components/{new-trace-viewer → trace-viewer}/icons.d.ts +0 -0
  515. /package/src/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/copy-selection.ts +0 -0
  516. /package/src/components/{new-trace-viewer → trace-viewer}/components/middle-truncate/use-middle-truncate.ts +0 -0
  517. /package/src/{components/trace-viewer/modules.d.ts → modules.d.ts} +0 -0
@@ -1,1171 +0,0 @@
1
- 'use client';
2
-
3
- import { parseStepName, parseWorkflowName } from '@workflow/utils/parse-name';
4
- import type { Event, Hook, Step, WorkflowRun } from '@workflow/world';
5
- import {
6
- ChevronDown,
7
- ChevronUp,
8
- Clock,
9
- Copy,
10
- Info,
11
- Send,
12
- Type,
13
- X,
14
- XCircle,
15
- } from 'lucide-react';
16
- import type { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
17
- import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
18
- import { createPortal } from 'react-dom';
19
- import { useToast } from '../lib/toast';
20
- import { buildTrace, type TraceWithMeta } from '../lib/trace-builder';
21
- import { ErrorBoundary } from './error-boundary';
22
- import {
23
- EntityDetailPanel,
24
- type SelectedSpanInfo,
25
- type SpanSelectionInfo,
26
- } from './sidebar/entity-detail-panel';
27
- import { ResolveHookModal } from './sidebar/resolve-hook-modal';
28
- import {
29
- TraceViewerContextProvider,
30
- TraceViewerTimeline,
31
- useTraceViewer,
32
- } from './trace-viewer';
33
- import type { Span } from './trace-viewer/types';
34
- import { Skeleton } from './ui/skeleton';
35
- import { Spinner } from './ui/spinner';
36
- import {
37
- getCustomSpanClassName,
38
- getCustomSpanEventClassName,
39
- } from './workflow-traces/trace-colors';
40
-
41
- /**
42
- * While a run is live, continuously grow root.duration and rescale so the
43
- * trace always fits within the viewport. Individual span widths are grown
44
- * by each SpanComponent's own useEffect (see node.tsx).
45
- */
46
- function useLiveTick(isLive: boolean): void {
47
- const { state, dispatch } = useTraceViewer();
48
- const stateRef = useRef(state);
49
- stateRef.current = state;
50
-
51
- useEffect(() => {
52
- if (!isLive) return;
53
-
54
- // Grow root.duration on every frame so span rAFs see the latest time
55
- let rafId = 0;
56
- const tick = (): void => {
57
- const { root } = stateRef.current;
58
- if (root.startTime) {
59
- const nowMs = Date.now();
60
- if (nowMs > root.endTime) {
61
- root.endTime = nowMs;
62
- root.duration = root.endTime - root.startTime;
63
- }
64
- }
65
- rafId = requestAnimationFrame(tick);
66
- };
67
- rafId = requestAnimationFrame(tick);
68
-
69
- // Re-scale smoothly so the trace fits the viewport as it grows.
70
- // We dispatch detectBaseScale only when the computed baseScale has
71
- // changed enough to matter visually (>0.1% shift), avoiding
72
- // unnecessary React re-renders while keeping things smooth.
73
- let scaleRafId = 0;
74
- let lastBaseScale = 0;
75
- const scaleTick = (): void => {
76
- const s = stateRef.current;
77
- if (s.root.duration > 0) {
78
- const newBaseScale = (s.width - s.scrollbarWidth) / s.root.duration;
79
- const delta = Math.abs(newBaseScale - lastBaseScale);
80
- if (delta > lastBaseScale * 0.001 || lastBaseScale === 0) {
81
- lastBaseScale = newBaseScale;
82
- dispatch({ type: 'detectBaseScale' });
83
- }
84
- }
85
- scaleRafId = requestAnimationFrame(scaleTick);
86
- };
87
- scaleRafId = requestAnimationFrame(scaleTick);
88
-
89
- return () => {
90
- cancelAnimationFrame(rafId);
91
- cancelAnimationFrame(scaleRafId);
92
- };
93
- }, [isLive, dispatch]);
94
- }
95
-
96
- const DEFAULT_PANEL_WIDTH = 450;
97
- const MIN_PANEL_WIDTH = 240;
98
-
99
- // ──────────────────────────────────────────────────────────────────────────
100
- // Right-click context menu for spans
101
- // ──────────────────────────────────────────────────────────────────────────
102
-
103
- type ResourceType = 'sleep' | 'step' | 'hook' | 'run' | 'unknown';
104
-
105
- interface ContextMenuState {
106
- x: number;
107
- y: number;
108
- spanId: string;
109
- spanName: string;
110
- resourceType: ResourceType;
111
- /** Whether the span represents an active/pending resource (not yet completed) */
112
- isActive: boolean;
113
- }
114
-
115
- interface ContextMenuItem {
116
- label: string;
117
- icon?: ReactNode;
118
- action: () => void;
119
- destructive?: boolean;
120
- disabled?: boolean;
121
- }
122
-
123
- function SpanContextMenu({
124
- menu,
125
- items,
126
- onClose,
127
- }: {
128
- menu: ContextMenuState;
129
- items: ContextMenuItem[];
130
- onClose: () => void;
131
- }): ReactNode {
132
- const menuRef = useRef<HTMLDivElement>(null);
133
-
134
- // Close on outside click
135
- useEffect(() => {
136
- const handleClick = (e: MouseEvent): void => {
137
- if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
138
- onClose();
139
- }
140
- };
141
- const handleKeyDown = (e: KeyboardEvent): void => {
142
- if (e.key === 'Escape') {
143
- onClose();
144
- }
145
- };
146
- const handleScroll = (): void => {
147
- onClose();
148
- };
149
- // Use a timeout so we don't close immediately from the same event
150
- const timeout = setTimeout(() => {
151
- window.addEventListener('mousedown', handleClick);
152
- window.addEventListener('keydown', handleKeyDown);
153
- window.addEventListener('scroll', handleScroll, true);
154
- }, 0);
155
- return () => {
156
- clearTimeout(timeout);
157
- window.removeEventListener('mousedown', handleClick);
158
- window.removeEventListener('keydown', handleKeyDown);
159
- window.removeEventListener('scroll', handleScroll, true);
160
- };
161
- }, [onClose]);
162
-
163
- // Adjust position if menu would overflow viewport
164
- const [adjustedPos, setAdjustedPos] = useState({ x: menu.x, y: menu.y });
165
- useEffect(() => {
166
- const el = menuRef.current;
167
- if (!el) return;
168
- const rect = el.getBoundingClientRect();
169
- let { x, y } = menu;
170
- if (rect.right > window.innerWidth) {
171
- x = window.innerWidth - rect.width - 8;
172
- }
173
- if (rect.bottom > window.innerHeight) {
174
- y = window.innerHeight - rect.height - 8;
175
- }
176
- if (x !== menu.x || y !== menu.y) {
177
- setAdjustedPos({ x, y });
178
- }
179
- }, [menu]);
180
-
181
- if (items.length === 0) return null;
182
-
183
- return createPortal(
184
- <div
185
- ref={menuRef}
186
- style={{
187
- position: 'fixed',
188
- left: adjustedPos.x,
189
- top: adjustedPos.y,
190
- zIndex: 99999,
191
- boxShadow: 'var(--ds-shadow-menu)',
192
- borderRadius: 12,
193
- background: 'var(--ds-background-100)',
194
- padding: 'var(--geist-space-gap-quarter, 4px)',
195
- fontSize: 14,
196
- minWidth: 180,
197
- overflowX: 'hidden',
198
- overflowY: 'auto',
199
- }}
200
- >
201
- <div
202
- style={{
203
- display: 'block',
204
- color: 'var(--ds-gray-900)',
205
- fontSize: '0.75rem',
206
- padding: 'var(--geist-gap-quarter, 4px) var(--geist-space-2x, 8px)',
207
- fontWeight: 500,
208
- overflow: 'hidden',
209
- textOverflow: 'ellipsis',
210
- whiteSpace: 'nowrap',
211
- maxWidth: 240,
212
- borderBottom: '1px solid var(--ds-gray-alpha-400)',
213
- marginBottom: 4,
214
- }}
215
- >
216
- {menu.spanName}
217
- </div>
218
- {items.map((item) => (
219
- <button
220
- key={item.label}
221
- type="button"
222
- style={{
223
- outline: 'none',
224
- cursor: item.disabled ? 'not-allowed' : 'pointer',
225
- display: 'flex',
226
- alignItems: 'center',
227
- gap: 8,
228
- padding: '0 var(--geist-space-2x, 8px)',
229
- height: 40,
230
- textDecoration: 'none',
231
- borderRadius: 6,
232
- color: item.destructive
233
- ? 'var(--ds-red-900)'
234
- : 'var(--ds-gray-1000)',
235
- width: '100%',
236
- background: 'transparent',
237
- border: 'none',
238
- fontSize: 14,
239
- textAlign: 'left',
240
- opacity: item.disabled ? 0.4 : 1,
241
- transition: 'background 0.15s',
242
- }}
243
- disabled={item.disabled}
244
- onMouseEnter={(e) => {
245
- (e.currentTarget as HTMLButtonElement).style.background =
246
- 'var(--ds-gray-alpha-100)';
247
- }}
248
- onMouseLeave={(e) => {
249
- (e.currentTarget as HTMLButtonElement).style.background =
250
- 'transparent';
251
- }}
252
- onClick={() => {
253
- item.action();
254
- onClose();
255
- }}
256
- >
257
- {item.icon ?? null}
258
- {item.label}
259
- </button>
260
- ))}
261
- </div>,
262
- document.body
263
- );
264
- }
265
-
266
- /** Inner wrapper that has access to the TraceViewer context */
267
- function TraceViewerWithContextMenu({
268
- trace,
269
- run,
270
- isLive,
271
- onWakeUpSleep,
272
- onCancelRun,
273
- onResolveHook,
274
- onLoadMoreSpans,
275
- hasMoreSpans = false,
276
- isLoadingMoreSpans = false,
277
- children,
278
- }: {
279
- trace: { spans: Span[] };
280
- run: WorkflowRun;
281
- isLive: boolean;
282
- onWakeUpSleep?: (
283
- runId: string,
284
- correlationId: string
285
- ) => Promise<{ stoppedCount: number }>;
286
- onCancelRun?: (runId: string) => Promise<void>;
287
- onResolveHook?: (
288
- hookToken: string,
289
- payload: unknown,
290
- hook?: Hook
291
- ) => Promise<void>;
292
- onLoadMoreSpans?: () => void | Promise<void>;
293
- hasMoreSpans?: boolean;
294
- isLoadingMoreSpans?: boolean;
295
- children: ReactNode;
296
- }): ReactNode {
297
- const toast = useToast();
298
- const { state, dispatch } = useTraceViewer();
299
-
300
- // Drive active span widths at 60fps without React re-renders
301
- useLiveTick(isLive);
302
- const [contextMenu, setContextMenu] = useState<ContextMenuState | null>(null);
303
- const [resolveHookTarget, setResolveHookTarget] = useState<{
304
- hookId: string;
305
- token: string;
306
- } | null>(null);
307
- const [resolvingHook, setResolvingHook] = useState(false);
308
- // Track hooks resolved in this session so the context menu item hides immediately
309
- const [resolvedHookIds, setResolvedHookIds] = useState<Set<string>>(
310
- new Set()
311
- );
312
-
313
- // Build a lookup map: spanId -> span
314
- const spanLookup = useMemo(() => {
315
- const map = new Map<string, Span>();
316
- for (const span of trace.spans) {
317
- map.set(span.spanId, span);
318
- }
319
- return map;
320
- }, [trace.spans]);
321
-
322
- const handleResolveHook = useCallback(
323
- async (payload: unknown) => {
324
- if (resolvingHook || !resolveHookTarget || !onResolveHook) return;
325
- if (!resolveHookTarget.token) {
326
- toast.error('Unable to resolve hook', {
327
- description:
328
- 'Missing hook token. Try refreshing the run data and retry.',
329
- });
330
- return;
331
- }
332
- try {
333
- setResolvingHook(true);
334
- await onResolveHook(resolveHookTarget.token, payload);
335
- toast.success('Hook resolved', {
336
- description: 'The payload has been sent and the hook resolved.',
337
- });
338
- // Mark this hook as resolved locally so the menu item hides immediately
339
- setResolvedHookIds((prev) =>
340
- new Set(prev).add(resolveHookTarget.hookId)
341
- );
342
- setResolveHookTarget(null);
343
- } catch (err) {
344
- console.error('Failed to resolve hook:', err);
345
- toast.error('Failed to resolve hook', {
346
- description:
347
- err instanceof Error ? err.message : 'An unknown error occurred',
348
- });
349
- } finally {
350
- setResolvingHook(false);
351
- }
352
- },
353
- [onResolveHook, resolveHookTarget, resolvingHook]
354
- );
355
-
356
- const handleContextMenu = useCallback(
357
- (e: ReactMouseEvent | MouseEvent): void => {
358
- const target = e.target as HTMLElement;
359
- const $button = target.closest<HTMLButtonElement>('[data-span-id]');
360
- if (!$button) return;
361
-
362
- const spanId = $button.dataset.spanId;
363
- if (!spanId) return;
364
-
365
- e.preventDefault();
366
- e.stopPropagation();
367
-
368
- const span = spanLookup.get(spanId);
369
- if (!span) return;
370
-
371
- const resourceType =
372
- (span.attributes.resource as ResourceType) ?? 'unknown';
373
- const spanData = span.attributes.data as
374
- | Record<string, unknown>
375
- | undefined;
376
- const isActive = !spanData?.completedAt && !spanData?.disposedAt;
377
-
378
- setContextMenu({
379
- x: e.clientX,
380
- y: e.clientY,
381
- spanId,
382
- spanName: span.name,
383
- resourceType,
384
- isActive,
385
- });
386
- },
387
- [spanLookup]
388
- );
389
-
390
- const containerRef = useRef<HTMLDivElement>(null);
391
- useEffect(() => {
392
- const $container = containerRef.current;
393
- if (!$container) return;
394
-
395
- const onContextMenu = (event: MouseEvent): void => {
396
- handleContextMenu(event);
397
- };
398
- $container.addEventListener('contextmenu', onContextMenu);
399
-
400
- return () => {
401
- $container.removeEventListener('contextmenu', onContextMenu);
402
- };
403
- }, [handleContextMenu]);
404
-
405
- const loadingMoreRef = useRef(false);
406
- useEffect(() => {
407
- const timeline = state.timelineRef.current;
408
- if (!timeline || !onLoadMoreSpans || !hasMoreSpans) {
409
- return;
410
- }
411
-
412
- const thresholdPx = 200;
413
- const maybeLoadMore = () => {
414
- if (loadingMoreRef.current || isLoadingMoreSpans || !hasMoreSpans) {
415
- return;
416
- }
417
- const remaining =
418
- timeline.scrollHeight - timeline.scrollTop - timeline.clientHeight;
419
- if (remaining > thresholdPx) {
420
- return;
421
- }
422
-
423
- loadingMoreRef.current = true;
424
- Promise.resolve(onLoadMoreSpans()).finally(() => {
425
- loadingMoreRef.current = false;
426
- });
427
- };
428
-
429
- timeline.addEventListener('scroll', maybeLoadMore);
430
- maybeLoadMore();
431
- return () => {
432
- timeline.removeEventListener('scroll', maybeLoadMore);
433
- };
434
- }, [state.timelineRef, onLoadMoreSpans, hasMoreSpans, isLoadingMoreSpans]);
435
-
436
- const closeMenu = useCallback(() => {
437
- setContextMenu(null);
438
- }, []);
439
-
440
- const getMenuItems = useCallback(
441
- (menu: ContextMenuState): ContextMenuItem[] => {
442
- const items: ContextMenuItem[] = [];
443
-
444
- // Sleep-specific: Wake Up (only on active runs)
445
- const isRunActive = !run.completedAt;
446
- if (
447
- menu.resourceType === 'sleep' &&
448
- menu.isActive &&
449
- isRunActive &&
450
- onWakeUpSleep
451
- ) {
452
- items.push({
453
- label: 'Wake Up Sleep',
454
- icon: <Clock className="h-3.5 w-3.5" />,
455
- action: () => {
456
- onWakeUpSleep(run.runId, menu.spanId)
457
- .then((result) => {
458
- if (result.stoppedCount > 0) {
459
- toast.success('Sleep woken up', {
460
- description: `Woke up ${String(result.stoppedCount)} sleep${result.stoppedCount > 1 ? 's' : ''}`,
461
- });
462
- } else {
463
- toast.info('No active sleeps found', {
464
- description: 'The sleep may have already completed.',
465
- });
466
- }
467
- })
468
- .catch((err: unknown) => {
469
- toast.error('Failed to wake up sleep', {
470
- description:
471
- err instanceof Error
472
- ? err.message
473
- : 'An unknown error occurred',
474
- });
475
- });
476
- },
477
- });
478
- }
479
-
480
- // Hook-specific: Resolve Hook (only on active, unresolved hooks)
481
- if (menu.resourceType === 'hook' && isRunActive && onResolveHook) {
482
- const span = spanLookup.get(menu.spanId);
483
- const hookData = span?.attributes?.data as
484
- | { token?: string; disposedAt?: unknown }
485
- | undefined;
486
- // Check data-level disposedAt, span events, AND local resolved state
487
- const isDisposed =
488
- Boolean(hookData?.disposedAt) ||
489
- Boolean(span?.events?.some((e) => e.name === 'hook_disposed')) ||
490
- resolvedHookIds.has(menu.spanId);
491
- if (hookData?.token && !isDisposed) {
492
- items.push({
493
- label: 'Resolve Hook',
494
- icon: <Send className="h-3.5 w-3.5" />,
495
- action: () => {
496
- setResolveHookTarget({
497
- hookId: menu.spanId,
498
- token: hookData.token!,
499
- });
500
- },
501
- });
502
- }
503
- }
504
-
505
- // Run-specific: Cancel (only on active runs)
506
- if (menu.resourceType === 'run' && isRunActive && onCancelRun) {
507
- items.push({
508
- label: 'Cancel Run',
509
- icon: <XCircle className="h-3.5 w-3.5" />,
510
- destructive: true,
511
- action: () => {
512
- onCancelRun(run.runId).catch((err: unknown) => {
513
- toast.error('Failed to cancel run', {
514
- description:
515
- err instanceof Error
516
- ? err.message
517
- : 'An unknown error occurred',
518
- });
519
- });
520
- },
521
- });
522
- }
523
-
524
- // Common actions
525
- items.push({
526
- label: 'View Details',
527
- icon: <Info className="h-3.5 w-3.5" />,
528
- action: () => {
529
- dispatch({ type: 'select', id: menu.spanId });
530
- },
531
- });
532
-
533
- items.push({
534
- label: 'Copy Name',
535
- icon: <Type className="h-3.5 w-3.5" />,
536
- action: () => {
537
- navigator.clipboard
538
- .writeText(menu.spanName)
539
- .then(() => {
540
- toast.success('Name copied to clipboard');
541
- })
542
- .catch(() => {
543
- toast.error('Failed to copy name');
544
- });
545
- },
546
- });
547
-
548
- items.push({
549
- label: 'Copy ID',
550
- icon: <Copy className="h-3.5 w-3.5" />,
551
- action: () => {
552
- navigator.clipboard
553
- .writeText(menu.spanId)
554
- .then(() => {
555
- toast.success('ID copied to clipboard');
556
- })
557
- .catch(() => {
558
- toast.error('Failed to copy ID');
559
- });
560
- },
561
- });
562
-
563
- return items;
564
- },
565
- [
566
- dispatch,
567
- onWakeUpSleep,
568
- onCancelRun,
569
- onResolveHook,
570
- spanLookup,
571
- resolvedHookIds,
572
- run.runId,
573
- run.completedAt,
574
- ]
575
- );
576
-
577
- return (
578
- <div className="relative w-full h-full" ref={containerRef}>
579
- {children}
580
- {contextMenu ? (
581
- <SpanContextMenu
582
- menu={contextMenu}
583
- items={getMenuItems(contextMenu)}
584
- onClose={closeMenu}
585
- />
586
- ) : null}
587
- <ResolveHookModal
588
- isOpen={resolveHookTarget !== null}
589
- onClose={() => setResolveHookTarget(null)}
590
- onSubmit={handleResolveHook}
591
- isSubmitting={resolvingHook}
592
- />
593
- </div>
594
- );
595
- }
596
-
597
- /** Re-export SpanSelectionInfo for consumers */
598
- export type { SpanSelectionInfo };
599
-
600
- // ---------------------------------------------------------------------------
601
- // Bridge: reads selected span from trace viewer context and notifies parent
602
- // ---------------------------------------------------------------------------
603
-
604
- /**
605
- * Bridge component that lives INSIDE the TraceViewerContextProvider and
606
- * reads the selected span info, passing it up to the parent via callback.
607
- * This allows the parent to render the detail panel OUTSIDE the context.
608
- */
609
- function SelectionBridge({
610
- onSelectionChange,
611
- }: {
612
- onSelectionChange: (info: SelectedSpanInfo | null) => void;
613
- }) {
614
- const { state } = useTraceViewer();
615
- const { selected } = state;
616
- const onSelectionChangeRef = useRef(onSelectionChange);
617
- onSelectionChangeRef.current = onSelectionChange;
618
- const prevSpanIdRef = useRef<string | undefined>(undefined);
619
-
620
- useEffect(() => {
621
- const currentSpanId = selected?.span.spanId;
622
- if (currentSpanId === prevSpanIdRef.current) return;
623
- prevSpanIdRef.current = currentSpanId;
624
-
625
- if (selected) {
626
- onSelectionChangeRef.current({
627
- data: selected.span.attributes?.data,
628
- resource: selected.span.attributes?.resource as string | undefined,
629
- spanId: selected.span.spanId,
630
- });
631
- } else {
632
- onSelectionChangeRef.current(null);
633
- }
634
- }, [selected]);
635
-
636
- return null;
637
- }
638
-
639
- /**
640
- * Bridge component to deselect from outside the context.
641
- */
642
- function DeselectBridge({ triggerDeselect }: { triggerDeselect: number }) {
643
- const { dispatch } = useTraceViewer();
644
-
645
- useEffect(() => {
646
- if (triggerDeselect > 0) {
647
- dispatch({ type: 'deselect' });
648
- }
649
- }, [triggerDeselect, dispatch]);
650
-
651
- return null;
652
- }
653
-
654
- /**
655
- * Bridge component to select a span from outside the context.
656
- */
657
- function SelectBridge({
658
- selectRequest,
659
- }: {
660
- selectRequest: { id: string; token: number } | null;
661
- }) {
662
- const { dispatch } = useTraceViewer();
663
-
664
- useEffect(() => {
665
- if (selectRequest?.id) {
666
- dispatch({ type: 'select', id: selectRequest.id });
667
- }
668
- }, [dispatch, selectRequest]);
669
-
670
- return null;
671
- }
672
-
673
- // ---------------------------------------------------------------------------
674
- // Panel chrome (header with name/duration, close button)
675
- // ---------------------------------------------------------------------------
676
-
677
- function PanelResizeHandle({
678
- onResize,
679
- }: {
680
- onResize: (deltaX: number) => void;
681
- }) {
682
- const handlePointerDown = useCallback(
683
- (e: React.PointerEvent) => {
684
- e.preventDefault();
685
- let lastX = e.clientX;
686
- const onPointerMove = (moveEvent: PointerEvent) => {
687
- const deltaX = lastX - moveEvent.clientX;
688
- lastX = moveEvent.clientX;
689
- onResize(deltaX);
690
- };
691
- const onPointerUp = () => {
692
- document.removeEventListener('pointermove', onPointerMove);
693
- document.removeEventListener('pointerup', onPointerUp);
694
- };
695
- document.addEventListener('pointermove', onPointerMove);
696
- document.addEventListener('pointerup', onPointerUp);
697
- },
698
- [onResize]
699
- );
700
-
701
- return (
702
- <div
703
- className="absolute left-0 top-0 bottom-0 w-1 cursor-col-resize hover:bg-blue-400/50 z-10"
704
- onPointerDown={handlePointerDown}
705
- />
706
- );
707
- }
708
-
709
- // ---------------------------------------------------------------------------
710
- // Trace viewer footer — loading / waiting indicator
711
- // ---------------------------------------------------------------------------
712
-
713
- function TraceViewerFooter({
714
- hasMore,
715
- isLive,
716
- isInitialLoading,
717
- }: {
718
- hasMore: boolean;
719
- isLive: boolean;
720
- isInitialLoading: boolean;
721
- }): ReactNode {
722
- const style = { color: 'var(--ds-gray-900)' };
723
- if (hasMore || isInitialLoading) {
724
- return (
725
- <div
726
- className="flex items-center justify-center gap-2 py-3 text-xs"
727
- style={style}
728
- >
729
- <Spinner size={14} />
730
- Loading more events…
731
- </div>
732
- );
733
- }
734
- if (isLive) {
735
- return (
736
- <div
737
- className="flex items-center justify-center py-3 text-xs"
738
- style={style}
739
- >
740
- Waiting for more events…
741
- </div>
742
- );
743
- }
744
- return (
745
- <div
746
- className="flex items-center justify-center py-3 text-xs"
747
- style={style}
748
- >
749
- End of run
750
- </div>
751
- );
752
- }
753
-
754
- // ---------------------------------------------------------------------------
755
- // Main component
756
- // ---------------------------------------------------------------------------
757
-
758
- export const WorkflowTraceViewer = ({
759
- run,
760
- events,
761
- isLoading,
762
- error,
763
- spanDetailData,
764
- spanDetailLoading,
765
- spanDetailError,
766
- onWakeUpSleep,
767
- onResolveHook,
768
- onCancelRun,
769
- onStreamClick,
770
- onRunClick,
771
- onSpanSelect,
772
- onLoadEventData,
773
- onLoadMoreSpans,
774
- hasMoreSpans = false,
775
- isLoadingMoreSpans = false,
776
- encryptionKey,
777
- onDecrypt,
778
- isDecrypting = false,
779
- }: {
780
- run: WorkflowRun;
781
- events: Event[];
782
- isLoading?: boolean;
783
- error?: Error | null;
784
- spanDetailData?: WorkflowRun | Step | Hook | Event | null;
785
- spanDetailLoading?: boolean;
786
- spanDetailError?: Error | null;
787
- onWakeUpSleep?: (
788
- runId: string,
789
- correlationId: string
790
- ) => Promise<{ stoppedCount: number }>;
791
- onResolveHook?: (
792
- hookToken: string,
793
- payload: unknown,
794
- hook?: Hook
795
- ) => Promise<void>;
796
- /** Callback to cancel the current run */
797
- onCancelRun?: (runId: string) => Promise<void>;
798
- /** Callback when a stream reference is clicked in the detail panel */
799
- onStreamClick?: (streamId: string) => void;
800
- /** Callback when a run reference is clicked in the detail panel */
801
- onRunClick?: (runId: string) => void;
802
- /** Callback when a span is selected. */
803
- onSpanSelect?: (info: SpanSelectionInfo) => void;
804
- /** Callback to load event data for a specific event (lazy loading in sidebar) */
805
- onLoadEventData?: (
806
- correlationId: string,
807
- eventId: string
808
- ) => Promise<unknown | null>;
809
- /** Load next trace page when vertical scroll reaches bottom. */
810
- onLoadMoreSpans?: () => void | Promise<void>;
811
- /** Whether trace pagination has more data to load. */
812
- hasMoreSpans?: boolean;
813
- /** Whether trace pagination is currently fetching another page. */
814
- isLoadingMoreSpans?: boolean;
815
- /** Encryption key (available after Decrypt), threaded to event list for re-loading */
816
- encryptionKey?: Uint8Array;
817
- /** Callback to initiate decryption of encrypted run data */
818
- onDecrypt?: () => void;
819
- /** Whether the encryption key is currently being fetched */
820
- isDecrypting?: boolean;
821
- }) => {
822
- const toast = useToast();
823
- const [selectedSpan, setSelectedSpan] = useState<SelectedSpanInfo | null>(
824
- null
825
- );
826
- const [panelWidth, setPanelWidth] = useState(DEFAULT_PANEL_WIDTH);
827
- const [deselectTrigger, setDeselectTrigger] = useState(0);
828
- const [selectRequest, setSelectRequest] = useState<{
829
- id: string;
830
- token: number;
831
- } | null>(null);
832
-
833
- const isLive = Boolean(run && !run.completedAt);
834
-
835
- // Build trace only when actual data changes — no timer-driven rebuilds.
836
- // Active span widths are animated imperatively by useLiveTick at 60fps.
837
- const traceWithMeta: TraceWithMeta | undefined = useMemo(() => {
838
- if (!run?.runId) {
839
- return undefined;
840
- }
841
- return buildTrace(run, events, new Date());
842
- // eslint-disable-next-line react-hooks/exhaustive-deps -- `new Date()` is intentionally not a dep; useLiveTick handles live growth
843
- }, [run, events]);
844
- const trace = traceWithMeta;
845
-
846
- useEffect(() => {
847
- if (error && !isLoading) {
848
- console.error(error);
849
- toast.error('Error loading workflow trace data', {
850
- description: error.message,
851
- });
852
- }
853
- }, [error, isLoading]);
854
-
855
- const handleSpanSelect = useCallback(
856
- (info: SpanSelectionInfo) => {
857
- onSpanSelect?.(info);
858
- },
859
- [onSpanSelect]
860
- );
861
-
862
- const handleSelectionChange = useCallback(
863
- (info: SelectedSpanInfo | null) => {
864
- if (info) {
865
- // Filter raw events by the selected span's correlationId (stepId/hookId)
866
- // This bypasses the trace worker pipeline entirely.
867
- const correlationId = info.spanId;
868
- const rawEvents = correlationId
869
- ? events.filter((e) => e.correlationId === correlationId)
870
- : [];
871
- setSelectedSpan({ ...info, rawEvents });
872
- } else {
873
- setSelectedSpan(null);
874
- }
875
- },
876
- [events]
877
- );
878
-
879
- // Keep selected span raw events live as polling updates arrive.
880
- useEffect(() => {
881
- const correlationId = selectedSpan?.spanId;
882
- if (!correlationId) return;
883
-
884
- const nextRawEvents = events.filter(
885
- (e) => e.correlationId === correlationId
886
- );
887
- setSelectedSpan((prev) => {
888
- if (!prev || prev.spanId !== correlationId) {
889
- return prev;
890
- }
891
-
892
- const prevRawEvents = prev.rawEvents ?? [];
893
- const isSame =
894
- prevRawEvents.length === nextRawEvents.length &&
895
- prevRawEvents.every(
896
- (event, index) => event.eventId === nextRawEvents[index]?.eventId
897
- );
898
- if (isSame) {
899
- return prev;
900
- }
901
-
902
- return {
903
- ...prev,
904
- rawEvents: nextRawEvents,
905
- };
906
- });
907
- }, [events, selectedSpan?.spanId]);
908
-
909
- // Reset selected span when navigating to a different run
910
- useEffect(() => {
911
- setSelectedSpan(null);
912
- setDeselectTrigger((n) => n + 1);
913
- }, [run?.runId]);
914
-
915
- const handleClose = useCallback(() => {
916
- setSelectedSpan(null);
917
- setDeselectTrigger((n) => n + 1);
918
- }, []);
919
-
920
- const handleResize = useCallback((deltaX: number) => {
921
- setPanelWidth((w) => Math.max(MIN_PANEL_WIDTH, w + deltaX));
922
- }, []);
923
- const selectedSpanIndex = useMemo(() => {
924
- if (!selectedSpan?.spanId || !trace) return -1;
925
- return trace.spans.findIndex((span) => span.spanId === selectedSpan.spanId);
926
- }, [selectedSpan?.spanId, trace]);
927
- const canSelectPrevSpan = selectedSpanIndex > 0;
928
- const canSelectNextSpan =
929
- selectedSpanIndex >= 0 &&
930
- trace != null &&
931
- selectedSpanIndex < trace.spans.length - 1;
932
- const handleSelectPrevSpan = useCallback(() => {
933
- if (!trace || selectedSpanIndex <= 0) return;
934
- const targetId = trace.spans[selectedSpanIndex - 1]?.spanId;
935
- if (!targetId) return;
936
- setSelectRequest({ id: targetId, token: Date.now() });
937
- }, [selectedSpanIndex, trace]);
938
- const handleSelectNextSpan = useCallback(() => {
939
- if (!trace || selectedSpanIndex < 0) return;
940
- const targetId = trace.spans[selectedSpanIndex + 1]?.spanId;
941
- if (!targetId) return;
942
- setSelectRequest({ id: targetId, token: Date.now() });
943
- }, [selectedSpanIndex, trace]);
944
-
945
- // Get the selected span name for the panel header
946
- const selectedSpanName = useMemo(() => {
947
- if (!selectedSpan?.data) return undefined;
948
- const data = selectedSpan.data as Record<string, unknown>;
949
- const stepName = data.stepName as string | undefined;
950
- const workflowName = data.workflowName as string | undefined;
951
- return (
952
- (stepName ? parseStepName(stepName)?.shortName : undefined) ??
953
- (workflowName ? parseWorkflowName(workflowName)?.shortName : undefined) ??
954
- stepName ??
955
- workflowName ??
956
- (data.hookId as string) ??
957
- 'Details'
958
- );
959
- }, [selectedSpan?.data]);
960
-
961
- if (!trace) {
962
- return (
963
- <div className="relative w-full h-full">
964
- <div className="border-b border-gray-alpha-400 w-full" />
965
- <Skeleton className="w-full ml-2 mt-1 mb-1 h-[56px]" />
966
- <div className="p-2 relative w-full">
967
- <Skeleton className="w-full mt-6 h-[20px]" />
968
- <Skeleton className="w-[10%] mt-2 ml-6 h-[20px]" />
969
- <Skeleton className="w-[10%] mt-2 ml-12 h-[20px]" />
970
- <Skeleton className="w-[20%] mt-2 ml-16 h-[20px]" />
971
- </div>
972
- </div>
973
- );
974
- }
975
-
976
- return (
977
- <div className="relative w-full h-full flex flex-col">
978
- {/* Timeline (takes remaining space) */}
979
- <div className="flex-1 min-w-0 relative">
980
- <TraceViewerContextProvider
981
- customSpanClassNameFunc={getCustomSpanClassName}
982
- customSpanEventClassNameFunc={getCustomSpanEventClassName}
983
- >
984
- <SelectionBridge onSelectionChange={handleSelectionChange} />
985
- <DeselectBridge triggerDeselect={deselectTrigger} />
986
- <SelectBridge selectRequest={selectRequest} />
987
- <TraceViewerWithContextMenu
988
- trace={trace}
989
- run={run}
990
- isLive={isLive}
991
- onWakeUpSleep={onWakeUpSleep}
992
- onCancelRun={onCancelRun}
993
- onResolveHook={onResolveHook}
994
- onLoadMoreSpans={onLoadMoreSpans}
995
- hasMoreSpans={hasMoreSpans}
996
- isLoadingMoreSpans={isLoadingMoreSpans}
997
- >
998
- <TraceViewerTimeline
999
- eagerRender
1000
- height="100%"
1001
- isLive={isLive}
1002
- trace={trace}
1003
- knownDurationMs={traceWithMeta?.knownDurationMs}
1004
- hasMoreData={hasMoreSpans || Boolean(isLoading)}
1005
- footer={
1006
- <TraceViewerFooter
1007
- hasMore={hasMoreSpans}
1008
- isLive={isLive}
1009
- isInitialLoading={Boolean(isLoading)}
1010
- />
1011
- }
1012
- />
1013
- </TraceViewerWithContextMenu>
1014
- </TraceViewerContextProvider>
1015
- </div>
1016
-
1017
- {/* Detail panel (rendered outside the context, as a sibling) */}
1018
- {selectedSpan && (
1019
- <div
1020
- className="relative border-l flex-shrink-0 flex flex-col"
1021
- style={{
1022
- width: panelWidth,
1023
- borderColor: 'var(--ds-gray-200)',
1024
- backgroundColor: 'var(--ds-background-100)',
1025
- }}
1026
- >
1027
- <PanelResizeHandle onResize={handleResize} />
1028
- {/* Panel header */}
1029
- <div
1030
- className="flex items-center justify-between px-3 py-2 border-y flex-shrink-0"
1031
- style={{ borderColor: 'var(--ds-gray-200)' }}
1032
- >
1033
- <div className="min-w-0 flex-1">
1034
- <div
1035
- className="text-sm font-medium truncate"
1036
- style={{ color: 'var(--ds-gray-1000)' }}
1037
- title={selectedSpanName}
1038
- >
1039
- {selectedSpanName}
1040
- </div>
1041
- </div>
1042
- <div className="flex items-center">
1043
- <button
1044
- type="button"
1045
- aria-label="Previous span"
1046
- onClick={handleSelectPrevSpan}
1047
- disabled={!canSelectPrevSpan}
1048
- style={{
1049
- display: 'flex',
1050
- alignItems: 'center',
1051
- justifyContent: 'center',
1052
- marginLeft: 6,
1053
- width: 24,
1054
- height: 24,
1055
- padding: 0,
1056
- borderRadius: 6,
1057
- border: 'none',
1058
- background: 'transparent',
1059
- color: 'var(--ds-gray-700)',
1060
- cursor: canSelectPrevSpan ? 'pointer' : 'not-allowed',
1061
- opacity: canSelectPrevSpan ? 1 : 0.45,
1062
- flexShrink: 0,
1063
- transition: 'background 0.15s',
1064
- }}
1065
- onMouseEnter={(e) => {
1066
- if (!canSelectPrevSpan) return;
1067
- e.currentTarget.style.background = 'var(--ds-gray-alpha-100)';
1068
- }}
1069
- onMouseLeave={(e) => {
1070
- e.currentTarget.style.background = 'transparent';
1071
- }}
1072
- >
1073
- <ChevronUp size={16} />
1074
- </button>
1075
- <button
1076
- type="button"
1077
- aria-label="Next span"
1078
- onClick={handleSelectNextSpan}
1079
- disabled={!canSelectNextSpan}
1080
- style={{
1081
- display: 'flex',
1082
- alignItems: 'center',
1083
- justifyContent: 'center',
1084
- marginLeft: 2,
1085
- width: 24,
1086
- height: 24,
1087
- padding: 0,
1088
- borderRadius: 6,
1089
- border: 'none',
1090
- background: 'transparent',
1091
- color: 'var(--ds-gray-700)',
1092
- cursor: canSelectNextSpan ? 'pointer' : 'not-allowed',
1093
- opacity: canSelectNextSpan ? 1 : 0.45,
1094
- flexShrink: 0,
1095
- transition: 'background 0.15s',
1096
- }}
1097
- onMouseEnter={(e) => {
1098
- if (!canSelectNextSpan) return;
1099
- e.currentTarget.style.background = 'var(--ds-gray-alpha-100)';
1100
- }}
1101
- onMouseLeave={(e) => {
1102
- e.currentTarget.style.background = 'transparent';
1103
- }}
1104
- >
1105
- <ChevronDown size={16} />
1106
- </button>
1107
- </div>
1108
- <div
1109
- className="flex items-center"
1110
- style={{
1111
- borderLeft: '1px solid var(--ds-gray-300)',
1112
- marginLeft: 6,
1113
- }}
1114
- >
1115
- <button
1116
- type="button"
1117
- aria-label="Close panel"
1118
- onClick={handleClose}
1119
- style={{
1120
- display: 'flex',
1121
- alignItems: 'center',
1122
- justifyContent: 'center',
1123
- marginLeft: 6,
1124
- width: 24,
1125
- height: 24,
1126
- padding: 0,
1127
- borderRadius: 6,
1128
- border: 'none',
1129
- background: 'transparent',
1130
- color: 'var(--ds-gray-700)',
1131
- cursor: 'pointer',
1132
- flexShrink: 0,
1133
- transition: 'background 0.15s',
1134
- }}
1135
- onMouseEnter={(e) => {
1136
- e.currentTarget.style.background = 'var(--ds-gray-alpha-100)';
1137
- }}
1138
- onMouseLeave={(e) => {
1139
- e.currentTarget.style.background = 'transparent';
1140
- }}
1141
- >
1142
- <X size={16} />
1143
- </button>
1144
- </div>
1145
- </div>
1146
- {/* Panel body */}
1147
- <div className="flex-1 overflow-y-auto">
1148
- <ErrorBoundary title="Failed to load entity details">
1149
- <EntityDetailPanel
1150
- run={run}
1151
- onStreamClick={onStreamClick}
1152
- onRunClick={onRunClick}
1153
- spanDetailData={spanDetailData ?? null}
1154
- spanDetailError={spanDetailError}
1155
- spanDetailLoading={spanDetailLoading}
1156
- onSpanSelect={handleSpanSelect}
1157
- onWakeUpSleep={onWakeUpSleep}
1158
- onLoadEventData={onLoadEventData}
1159
- onResolveHook={onResolveHook}
1160
- encryptionKey={encryptionKey}
1161
- onDecrypt={onDecrypt}
1162
- isDecrypting={isDecrypting}
1163
- selectedSpan={selectedSpan}
1164
- />
1165
- </ErrorBoundary>
1166
- </div>
1167
- </div>
1168
- )}
1169
- </div>
1170
- );
1171
- };