@workflow/web-shared 5.0.0-beta.3 → 5.0.0-beta.30

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 (402) hide show
  1. package/README.md +2 -10
  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 +228 -90
  6. package/dist/components/hook-actions.js +1 -1
  7. package/dist/components/index.d.ts +6 -2
  8. package/dist/components/index.d.ts.map +1 -1
  9. package/dist/components/index.js +5 -2
  10. package/dist/components/new-trace-viewer/components/copy-button.js +3 -3
  11. package/dist/components/new-trace-viewer/components/detail-panel-width.d.ts +34 -0
  12. package/dist/components/new-trace-viewer/components/detail-panel-width.d.ts.map +1 -0
  13. package/dist/components/new-trace-viewer/components/detail-panel-width.js +67 -0
  14. package/dist/components/new-trace-viewer/components/detail-panel.d.ts +14 -0
  15. package/dist/components/new-trace-viewer/components/detail-panel.d.ts.map +1 -0
  16. package/dist/components/new-trace-viewer/components/detail-panel.js +122 -0
  17. package/dist/components/new-trace-viewer/components/draggable-border.d.ts +31 -0
  18. package/dist/components/new-trace-viewer/components/draggable-border.d.ts.map +1 -0
  19. package/dist/components/new-trace-viewer/components/draggable-border.js +140 -0
  20. package/dist/components/new-trace-viewer/components/event-list.d.ts +4 -2
  21. package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -1
  22. package/dist/components/new-trace-viewer/components/event-list.js +22 -13
  23. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
  24. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
  25. package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
  26. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
  27. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
  28. package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
  29. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
  30. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
  31. package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
  32. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
  33. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
  34. package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
  35. package/dist/components/new-trace-viewer/components/minimap.d.ts +14 -0
  36. package/dist/components/new-trace-viewer/components/minimap.d.ts.map +1 -0
  37. package/dist/components/new-trace-viewer/components/minimap.js +337 -0
  38. package/dist/components/new-trace-viewer/components/pane-constants.d.ts +14 -0
  39. package/dist/components/new-trace-viewer/components/pane-constants.d.ts.map +1 -0
  40. package/dist/components/new-trace-viewer/components/pane-constants.js +16 -0
  41. package/dist/components/new-trace-viewer/components/span-markers.d.ts +46 -0
  42. package/dist/components/new-trace-viewer/components/span-markers.d.ts.map +1 -0
  43. package/dist/components/new-trace-viewer/components/span-markers.js +85 -0
  44. package/dist/components/new-trace-viewer/components/split-pane.d.ts +3 -7
  45. package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -1
  46. package/dist/components/new-trace-viewer/components/split-pane.js +25 -84
  47. package/dist/components/new-trace-viewer/components/timeline.d.ts +19 -15
  48. package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -1
  49. package/dist/components/new-trace-viewer/components/timeline.js +229 -111
  50. package/dist/components/new-trace-viewer/components/timeline.module.css +46 -0
  51. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.d.ts +5 -0
  52. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.d.ts.map +1 -0
  53. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.js +55 -0
  54. package/dist/components/new-trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  55. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts +2 -0
  56. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.d.ts.map +1 -0
  57. package/dist/components/new-trace-viewer/components/trace-viewer-skeleton.js +26 -0
  58. package/dist/components/new-trace-viewer/components/use-element-width.d.ts +8 -0
  59. package/dist/components/new-trace-viewer/components/use-element-width.d.ts.map +1 -0
  60. package/dist/components/new-trace-viewer/components/use-element-width.js +25 -0
  61. package/dist/components/new-trace-viewer/components/use-row-window.d.ts +34 -0
  62. package/dist/components/new-trace-viewer/components/use-row-window.d.ts.map +1 -0
  63. package/dist/components/new-trace-viewer/components/use-row-window.js +107 -0
  64. package/dist/components/new-trace-viewer/context.d.ts +3 -1
  65. package/dist/components/new-trace-viewer/context.d.ts.map +1 -1
  66. package/dist/components/new-trace-viewer/context.js +9 -10
  67. package/dist/components/new-trace-viewer/icons.js +3 -3
  68. package/dist/components/new-trace-viewer/search.d.ts +19 -0
  69. package/dist/components/new-trace-viewer/search.d.ts.map +1 -0
  70. package/dist/components/new-trace-viewer/search.js +134 -0
  71. package/dist/components/new-trace-viewer/trace-viewer.d.ts +6 -3
  72. package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -1
  73. package/dist/components/new-trace-viewer/trace-viewer.js +167 -162
  74. package/dist/components/new-trace-viewer/types.d.ts +2 -0
  75. package/dist/components/new-trace-viewer/types.d.ts.map +1 -1
  76. package/dist/components/new-trace-viewer/types.js +2 -2
  77. package/dist/components/new-trace-viewer/utils.d.ts +48 -13
  78. package/dist/components/new-trace-viewer/utils.d.ts.map +1 -1
  79. package/dist/components/new-trace-viewer/utils.js +135 -107
  80. package/dist/components/run-trace-view.d.ts +5 -7
  81. package/dist/components/run-trace-view.d.ts.map +1 -1
  82. package/dist/components/run-trace-view.js +3 -3
  83. package/dist/components/sidebar/attribute-panel.d.ts +4 -1
  84. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
  85. package/dist/components/sidebar/attribute-panel.js +133 -113
  86. package/dist/components/sidebar/attributes-block.d.ts +40 -0
  87. package/dist/components/sidebar/attributes-block.d.ts.map +1 -0
  88. package/dist/components/sidebar/attributes-block.js +140 -0
  89. package/dist/components/sidebar/conversation-view.js +1 -1
  90. package/dist/components/sidebar/copyable-data-block.d.ts +2 -0
  91. package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
  92. package/dist/components/sidebar/copyable-data-block.js +17 -16
  93. package/dist/components/sidebar/entity-detail-panel.d.ts +11 -11
  94. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
  95. package/dist/components/sidebar/entity-detail-panel.js +35 -69
  96. package/dist/components/sidebar/events-list.d.ts +6 -2
  97. package/dist/components/sidebar/events-list.d.ts.map +1 -1
  98. package/dist/components/sidebar/events-list.js +76 -62
  99. package/dist/components/sidebar/resolve-hook-modal.js +1 -1
  100. package/dist/components/sidebar/sidebar-data-context.d.ts +10 -7
  101. package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -1
  102. package/dist/components/sidebar/sidebar-data-context.js +1 -1
  103. package/dist/components/sidebar/span-detail-merge.d.ts +31 -0
  104. package/dist/components/sidebar/span-detail-merge.d.ts.map +1 -0
  105. package/dist/components/sidebar/span-detail-merge.js +92 -0
  106. package/dist/components/sidebar/use-selected-span-detail.d.ts +16 -0
  107. package/dist/components/sidebar/use-selected-span-detail.d.ts.map +1 -0
  108. package/dist/components/sidebar/use-selected-span-detail.js +93 -0
  109. package/dist/components/stream-viewer.js +1 -1
  110. package/dist/components/trace-viewer/components/map.d.ts +2 -2
  111. package/dist/components/trace-viewer/components/map.d.ts.map +1 -1
  112. package/dist/components/trace-viewer/components/map.js +1 -1
  113. package/dist/components/trace-viewer/components/markers.js +1 -1
  114. package/dist/components/trace-viewer/components/node.d.ts +7 -7
  115. package/dist/components/trace-viewer/components/node.d.ts.map +1 -1
  116. package/dist/components/trace-viewer/components/node.js +2 -1
  117. package/dist/components/trace-viewer/components/search-input.js +1 -1
  118. package/dist/components/trace-viewer/components/search.js +1 -1
  119. package/dist/components/trace-viewer/components/span-content.js +1 -1
  120. package/dist/components/trace-viewer/components/span-detail-panel.js +1 -1
  121. package/dist/components/trace-viewer/components/span-segments.js +1 -1
  122. package/dist/components/trace-viewer/components/span-strategies.js +1 -1
  123. package/dist/components/trace-viewer/components/ui.js +1 -1
  124. package/dist/components/trace-viewer/components/zoom-button.js +1 -1
  125. package/dist/components/trace-viewer/components/zoom-icons.js +1 -1
  126. package/dist/components/trace-viewer/context.js +1 -1
  127. package/dist/components/trace-viewer/index.js +1 -1
  128. package/dist/components/trace-viewer/trace-viewer.js +1 -1
  129. package/dist/components/trace-viewer/trace-viewer.module.css +4 -4
  130. package/dist/components/trace-viewer/types.js +1 -1
  131. package/dist/components/trace-viewer/util/constants.js +1 -1
  132. package/dist/components/trace-viewer/util/scrollbar-width.js +1 -1
  133. package/dist/components/trace-viewer/util/timing.d.ts +3 -3
  134. package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
  135. package/dist/components/trace-viewer/util/timing.js +8 -11
  136. package/dist/components/trace-viewer/util/tree.js +1 -1
  137. package/dist/components/trace-viewer/util/use-immediate-style.js +1 -1
  138. package/dist/components/trace-viewer/util/use-streaming-spans.js +1 -1
  139. package/dist/components/trace-viewer/util/use-trackpad-zoom.js +1 -1
  140. package/dist/components/trace-viewer/worker.js +1 -1
  141. package/dist/components/trace-viewer-new.d.ts +5 -1
  142. package/dist/components/trace-viewer-new.d.ts.map +1 -1
  143. package/dist/components/trace-viewer-new.js +8 -10
  144. package/dist/components/ui/alert.js +2 -2
  145. package/dist/components/ui/button.d.ts +10 -0
  146. package/dist/components/ui/button.d.ts.map +1 -0
  147. package/dist/components/ui/button.js +46 -0
  148. package/dist/components/ui/card.js +2 -2
  149. package/dist/components/ui/collapsible.d.ts +46 -0
  150. package/dist/components/ui/collapsible.d.ts.map +1 -0
  151. package/dist/components/ui/collapsible.js +66 -0
  152. package/dist/components/ui/context-card.d.ts +47 -0
  153. package/dist/components/ui/context-card.d.ts.map +1 -0
  154. package/dist/components/ui/context-card.js +471 -0
  155. package/dist/components/ui/data-inspector.d.ts +7 -6
  156. package/dist/components/ui/data-inspector.d.ts.map +1 -1
  157. package/dist/components/ui/data-inspector.js +232 -99
  158. package/dist/components/ui/data-inspector.styles.d.ts +29 -0
  159. package/dist/components/ui/data-inspector.styles.d.ts.map +1 -0
  160. package/dist/components/ui/data-inspector.styles.js +95 -0
  161. package/dist/components/ui/decrypt-button.js +1 -1
  162. package/dist/components/ui/error-card.js +2 -2
  163. package/dist/components/ui/error-stack-block.d.ts +17 -10
  164. package/dist/components/ui/error-stack-block.d.ts.map +1 -1
  165. package/dist/components/ui/error-stack-block.js +49 -30
  166. package/dist/components/ui/icon-button.d.ts +19 -0
  167. package/dist/components/ui/icon-button.d.ts.map +1 -0
  168. package/dist/components/ui/icon-button.js +29 -0
  169. package/dist/components/ui/kbd.d.ts +10 -0
  170. package/dist/components/ui/kbd.d.ts.map +1 -0
  171. package/dist/components/ui/kbd.js +25 -0
  172. package/dist/components/ui/load-more-button.js +1 -1
  173. package/dist/components/ui/menu-dropdown.js +1 -1
  174. package/dist/components/ui/skeleton.js +2 -2
  175. package/dist/components/ui/spinner.js +1 -1
  176. package/dist/components/ui/timestamp-tooltip.d.ts +34 -1
  177. package/dist/components/ui/timestamp-tooltip.d.ts.map +1 -1
  178. package/dist/components/ui/timestamp-tooltip.js +80 -132
  179. package/dist/components/ui/tooltip.d.ts +10 -0
  180. package/dist/components/ui/tooltip.d.ts.map +1 -0
  181. package/dist/components/ui/tooltip.js +12 -0
  182. package/dist/components/workflow-trace-view.d.ts +7 -8
  183. package/dist/components/workflow-trace-view.d.ts.map +1 -1
  184. package/dist/components/workflow-trace-view.js +11 -16
  185. package/dist/components/workflow-traces/event-colors.d.ts +2 -1
  186. package/dist/components/workflow-traces/event-colors.d.ts.map +1 -1
  187. package/dist/components/workflow-traces/event-colors.js +15 -7
  188. package/dist/components/workflow-traces/trace-colors.d.ts.map +1 -1
  189. package/dist/components/workflow-traces/trace-colors.js +3 -4
  190. package/dist/components/workflow-traces/trace-span-construction.d.ts +7 -4
  191. package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
  192. package/dist/components/workflow-traces/trace-span-construction.js +87 -33
  193. package/dist/components/workflow-traces/trace-time-utils.js +1 -1
  194. package/dist/hooks/use-dark-mode.js +1 -1
  195. package/dist/hooks/use-intersection-observer.d.ts +17 -0
  196. package/dist/hooks/use-intersection-observer.d.ts.map +1 -0
  197. package/dist/hooks/use-intersection-observer.js +29 -0
  198. package/dist/hooks/use-load-more-on-scroll.d.ts +21 -0
  199. package/dist/hooks/use-load-more-on-scroll.d.ts.map +1 -0
  200. package/dist/hooks/use-load-more-on-scroll.js +28 -0
  201. package/dist/hooks/use-reduced-motion.d.ts +10 -0
  202. package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
  203. package/dist/hooks/use-reduced-motion.js +29 -0
  204. package/dist/index.d.ts +3 -2
  205. package/dist/index.d.ts.map +1 -1
  206. package/dist/index.js +4 -3
  207. package/dist/lib/cn.d.ts +10 -0
  208. package/dist/lib/cn.d.ts.map +1 -0
  209. package/dist/lib/cn.js +83 -0
  210. package/dist/lib/event-analysis.d.ts +1 -1
  211. package/dist/lib/event-analysis.d.ts.map +1 -1
  212. package/dist/lib/event-analysis.js +3 -2
  213. package/dist/lib/event-materialization.d.ts +1 -1
  214. package/dist/lib/event-materialization.d.ts.map +1 -1
  215. package/dist/lib/event-materialization.js +29 -21
  216. package/dist/lib/exact-event-search-id.d.ts +25 -0
  217. package/dist/lib/exact-event-search-id.d.ts.map +1 -0
  218. package/dist/lib/exact-event-search-id.js +39 -0
  219. package/dist/lib/hydration.d.ts +17 -2
  220. package/dist/lib/hydration.d.ts.map +1 -1
  221. package/dist/lib/hydration.js +185 -22
  222. package/dist/lib/stream-display.js +1 -1
  223. package/dist/lib/toast.js +1 -1
  224. package/dist/lib/trace-builder.d.ts +16 -4
  225. package/dist/lib/trace-builder.d.ts.map +1 -1
  226. package/dist/lib/trace-builder.js +34 -15
  227. package/dist/lib/utils.d.ts +23 -9
  228. package/dist/lib/utils.d.ts.map +1 -1
  229. package/dist/lib/utils.js +73 -33
  230. package/dist/lib/zstd-browser-decoder.d.ts +7 -0
  231. package/dist/lib/zstd-browser-decoder.d.ts.map +1 -0
  232. package/dist/lib/zstd-browser-decoder.js +41 -0
  233. package/dist/styles.css +14 -0
  234. package/package.json +10 -7
  235. package/src/components/event-list-view.tsx +375 -116
  236. package/src/components/index.ts +12 -5
  237. package/src/components/new-trace-viewer/components/copy-button.tsx +2 -2
  238. package/src/components/new-trace-viewer/components/detail-panel-width.test.ts +123 -0
  239. package/src/components/new-trace-viewer/components/detail-panel-width.ts +76 -0
  240. package/src/components/new-trace-viewer/components/detail-panel.tsx +273 -0
  241. package/src/components/new-trace-viewer/components/draggable-border.tsx +216 -0
  242. package/src/components/new-trace-viewer/components/event-list.tsx +57 -32
  243. package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
  244. package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
  245. package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
  246. package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
  247. package/src/components/new-trace-viewer/components/minimap.tsx +559 -0
  248. package/src/components/new-trace-viewer/components/pane-constants.ts +19 -0
  249. package/src/components/new-trace-viewer/components/span-markers.tsx +173 -0
  250. package/src/components/new-trace-viewer/components/split-pane.tsx +80 -135
  251. package/src/components/new-trace-viewer/components/timeline.module.css +46 -0
  252. package/src/components/new-trace-viewer/components/timeline.tsx +603 -239
  253. package/src/components/new-trace-viewer/components/trace-shortcut-helper.module.css +20 -0
  254. package/src/components/new-trace-viewer/components/trace-shortcut-helper.tsx +116 -0
  255. package/src/components/new-trace-viewer/components/trace-viewer-skeleton.tsx +114 -0
  256. package/src/components/new-trace-viewer/components/use-element-width.ts +29 -0
  257. package/src/components/new-trace-viewer/components/use-row-window.ts +140 -0
  258. package/src/components/new-trace-viewer/context.tsx +13 -14
  259. package/src/components/new-trace-viewer/icons.tsx +2 -2
  260. package/src/components/new-trace-viewer/search.ts +178 -0
  261. package/src/components/new-trace-viewer/trace-viewer.tsx +336 -293
  262. package/src/components/new-trace-viewer/types.ts +2 -0
  263. package/src/components/new-trace-viewer/utils.test.ts +247 -0
  264. package/src/components/new-trace-viewer/utils.ts +203 -134
  265. package/src/components/run-trace-view.tsx +10 -14
  266. package/src/components/sidebar/attribute-panel.tsx +276 -275
  267. package/src/components/sidebar/attributes-block.tsx +326 -0
  268. package/src/components/sidebar/copyable-data-block.tsx +50 -28
  269. package/src/components/sidebar/entity-detail-panel.tsx +89 -123
  270. package/src/components/sidebar/events-list.tsx +196 -178
  271. package/src/components/sidebar/sidebar-data-context.tsx +11 -11
  272. package/src/components/sidebar/span-detail-merge.ts +134 -0
  273. package/src/components/sidebar/use-selected-span-detail.ts +146 -0
  274. package/src/components/trace-viewer/components/node.tsx +3 -2
  275. package/src/components/trace-viewer/trace-viewer.module.css +4 -4
  276. package/src/components/trace-viewer/util/timing.ts +7 -11
  277. package/src/components/trace-viewer-new.tsx +21 -15
  278. package/src/components/ui/alert.tsx +1 -1
  279. package/src/components/ui/button.tsx +68 -0
  280. package/src/components/ui/card.tsx +1 -1
  281. package/src/components/ui/collapsible.tsx +219 -0
  282. package/src/components/ui/context-card.tsx +784 -0
  283. package/src/components/ui/data-inspector.styles.ts +96 -0
  284. package/src/components/ui/data-inspector.tsx +501 -204
  285. package/src/components/ui/error-card.tsx +1 -1
  286. package/src/components/ui/error-stack-block.tsx +84 -55
  287. package/src/components/ui/icon-button.tsx +53 -0
  288. package/src/components/ui/kbd.tsx +43 -0
  289. package/src/components/ui/skeleton.tsx +1 -1
  290. package/src/components/ui/timestamp-tooltip.tsx +132 -194
  291. package/src/components/ui/tooltip.tsx +47 -0
  292. package/src/components/workflow-trace-view.tsx +31 -36
  293. package/src/components/workflow-traces/event-colors.ts +15 -11
  294. package/src/components/workflow-traces/trace-colors.ts +6 -6
  295. package/src/components/workflow-traces/trace-span-construction.test.ts +85 -0
  296. package/src/components/workflow-traces/trace-span-construction.ts +118 -35
  297. package/src/hooks/use-intersection-observer.ts +57 -0
  298. package/src/hooks/use-load-more-on-scroll.ts +49 -0
  299. package/src/hooks/use-reduced-motion.ts +34 -0
  300. package/src/index.ts +9 -0
  301. package/src/lib/cn.ts +93 -0
  302. package/src/lib/event-analysis.ts +6 -4
  303. package/src/lib/event-materialization.ts +35 -21
  304. package/src/lib/exact-event-search-id.ts +67 -0
  305. package/src/lib/hydration.ts +203 -29
  306. package/src/lib/trace-builder.ts +44 -19
  307. package/src/lib/utils.test.ts +33 -0
  308. package/src/lib/utils.ts +82 -35
  309. package/src/lib/zstd-browser-decoder.ts +42 -0
  310. package/src/styles.css +14 -0
  311. package/dist/components/error-boundary.js.map +0 -1
  312. package/dist/components/event-list-view.js.map +0 -1
  313. package/dist/components/hook-actions.js.map +0 -1
  314. package/dist/components/index.js.map +0 -1
  315. package/dist/components/new-trace-viewer/components/copy-button.js.map +0 -1
  316. package/dist/components/new-trace-viewer/components/event-list.js.map +0 -1
  317. package/dist/components/new-trace-viewer/components/split-pane.js.map +0 -1
  318. package/dist/components/new-trace-viewer/components/timeline.js.map +0 -1
  319. package/dist/components/new-trace-viewer/context.js.map +0 -1
  320. package/dist/components/new-trace-viewer/detail-panel.d.ts +0 -10
  321. package/dist/components/new-trace-viewer/detail-panel.d.ts.map +0 -1
  322. package/dist/components/new-trace-viewer/detail-panel.js +0 -11
  323. package/dist/components/new-trace-viewer/detail-panel.js.map +0 -1
  324. package/dist/components/new-trace-viewer/icons.js.map +0 -1
  325. package/dist/components/new-trace-viewer/trace-viewer.js.map +0 -1
  326. package/dist/components/new-trace-viewer/types.js.map +0 -1
  327. package/dist/components/new-trace-viewer/util/constants.d.ts +0 -1
  328. package/dist/components/new-trace-viewer/util/constants.d.ts.map +0 -1
  329. package/dist/components/new-trace-viewer/util/constants.js +0 -2
  330. package/dist/components/new-trace-viewer/util/constants.js.map +0 -1
  331. package/dist/components/new-trace-viewer/utils.js.map +0 -1
  332. package/dist/components/run-trace-view.js.map +0 -1
  333. package/dist/components/sidebar/attribute-panel.js.map +0 -1
  334. package/dist/components/sidebar/conversation-view.js.map +0 -1
  335. package/dist/components/sidebar/copyable-data-block.js.map +0 -1
  336. package/dist/components/sidebar/detail-card.d.ts +0 -14
  337. package/dist/components/sidebar/detail-card.d.ts.map +0 -1
  338. package/dist/components/sidebar/detail-card.js +0 -20
  339. package/dist/components/sidebar/detail-card.js.map +0 -1
  340. package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
  341. package/dist/components/sidebar/events-list.js.map +0 -1
  342. package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
  343. package/dist/components/sidebar/sidebar-data-context.js.map +0 -1
  344. package/dist/components/stream-viewer.js.map +0 -1
  345. package/dist/components/trace-viewer/components/map.js.map +0 -1
  346. package/dist/components/trace-viewer/components/markers.js.map +0 -1
  347. package/dist/components/trace-viewer/components/node.js.map +0 -1
  348. package/dist/components/trace-viewer/components/search-input.js.map +0 -1
  349. package/dist/components/trace-viewer/components/search.js.map +0 -1
  350. package/dist/components/trace-viewer/components/span-content.js.map +0 -1
  351. package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
  352. package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
  353. package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
  354. package/dist/components/trace-viewer/components/ui.js.map +0 -1
  355. package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
  356. package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
  357. package/dist/components/trace-viewer/context.js.map +0 -1
  358. package/dist/components/trace-viewer/index.js.map +0 -1
  359. package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
  360. package/dist/components/trace-viewer/types.js.map +0 -1
  361. package/dist/components/trace-viewer/util/constants.js.map +0 -1
  362. package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
  363. package/dist/components/trace-viewer/util/timing.js.map +0 -1
  364. package/dist/components/trace-viewer/util/tree.js.map +0 -1
  365. package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
  366. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
  367. package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
  368. package/dist/components/trace-viewer/worker.js.map +0 -1
  369. package/dist/components/trace-viewer-new.js.map +0 -1
  370. package/dist/components/ui/alert.js.map +0 -1
  371. package/dist/components/ui/card.js.map +0 -1
  372. package/dist/components/ui/data-inspector.js.map +0 -1
  373. package/dist/components/ui/decrypt-button.js.map +0 -1
  374. package/dist/components/ui/error-card.js.map +0 -1
  375. package/dist/components/ui/error-stack-block.js.map +0 -1
  376. package/dist/components/ui/inspector-theme.d.ts +0 -95
  377. package/dist/components/ui/inspector-theme.d.ts.map +0 -1
  378. package/dist/components/ui/inspector-theme.js +0 -82
  379. package/dist/components/ui/inspector-theme.js.map +0 -1
  380. package/dist/components/ui/load-more-button.js.map +0 -1
  381. package/dist/components/ui/menu-dropdown.js.map +0 -1
  382. package/dist/components/ui/skeleton.js.map +0 -1
  383. package/dist/components/ui/spinner.js.map +0 -1
  384. package/dist/components/ui/timestamp-tooltip.js.map +0 -1
  385. package/dist/components/workflow-trace-view.js.map +0 -1
  386. package/dist/components/workflow-traces/event-colors.js.map +0 -1
  387. package/dist/components/workflow-traces/trace-colors.js.map +0 -1
  388. package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
  389. package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
  390. package/dist/hooks/use-dark-mode.js.map +0 -1
  391. package/dist/index.js.map +0 -1
  392. package/dist/lib/event-analysis.js.map +0 -1
  393. package/dist/lib/event-materialization.js.map +0 -1
  394. package/dist/lib/hydration.js.map +0 -1
  395. package/dist/lib/stream-display.js.map +0 -1
  396. package/dist/lib/toast.js.map +0 -1
  397. package/dist/lib/trace-builder.js.map +0 -1
  398. package/dist/lib/utils.js.map +0 -1
  399. package/src/components/new-trace-viewer/detail-panel.tsx +0 -57
  400. package/src/components/new-trace-viewer/util/constants.ts +0 -0
  401. package/src/components/sidebar/detail-card.tsx +0 -65
  402. package/src/components/ui/inspector-theme.ts +0 -110
@@ -1,15 +1,20 @@
1
1
  'use client';
2
2
 
3
3
  import type { ReactNode } from 'react';
4
- import { useEffect, useRef, useState } from 'react';
5
- import { createPortal } from 'react-dom';
4
+ import { useEffect, useState } from 'react';
5
+ import {
6
+ ContextCardProvider,
7
+ ContextCardTrigger,
8
+ type ContextCardTriggerProps,
9
+ useHasContextCardProvider,
10
+ } from './context-card';
6
11
 
7
12
  // ---------------------------------------------------------------------------
8
13
  // Time formatting helpers
9
14
  // ---------------------------------------------------------------------------
10
15
 
11
16
  interface TimeUnit {
12
- unit: string;
17
+ unit: Intl.RelativeTimeFormatUnit;
13
18
  ms: number;
14
19
  }
15
20
 
@@ -38,25 +43,69 @@ function formatTimeDifference(diff: number): string {
38
43
  return result.join(', ');
39
44
  }
40
45
 
41
- function useTimeAgo(date: number): string {
46
+ /**
47
+ * Detailed relative time string that auto-updates every second
48
+ * (e.g. "2 hours, 15 minutes, 30 seconds ago"). Used inside the hover card.
49
+ */
50
+ export function useTimeAgo(date: number): string {
42
51
  const [timeAgo, setTimeAgo] = useState<string>('');
43
52
 
44
53
  useEffect(() => {
45
- const update = (): void => {
54
+ const updateTimeAgo = (): void => {
46
55
  const diff = Date.now() - date;
47
- const formatted = formatTimeDifference(diff);
48
- setTimeAgo(formatted ? `${formatted} ago` : 'Just now');
56
+ const formattedDiff = formatTimeDifference(diff);
57
+ setTimeAgo(formattedDiff ? `${formattedDiff} ago` : 'Just now');
49
58
  };
50
- update();
51
- const timer = setInterval(update, 1000);
59
+
60
+ updateTimeAgo();
61
+ const timer = setInterval(updateTimeAgo, 1000);
52
62
  return () => clearInterval(timer);
53
63
  }, [date]);
54
64
 
55
65
  return timeAgo;
56
66
  }
57
67
 
68
+ /**
69
+ * Short relative time string that auto-updates every minute
70
+ * (e.g. "3 days ago", "5 hours ago"). Returns an empty string if `date` is
71
+ * nullish.
72
+ */
73
+ export function useShortTimeAgo(date: number | null | undefined): string {
74
+ const [shortTimeAgo, setShortTimeAgo] = useState<string>('');
75
+
76
+ useEffect(() => {
77
+ if (!date) {
78
+ setShortTimeAgo('');
79
+ return;
80
+ }
81
+
82
+ const updateShortTimeAgo = (): void => {
83
+ const diff = Date.now() - date;
84
+ const days = Math.floor(diff / (1000 * 60 * 60 * 24));
85
+ const hours = Math.floor(diff / (1000 * 60 * 60));
86
+ const minutes = Math.floor(diff / (1000 * 60));
87
+
88
+ if (days > 0) {
89
+ setShortTimeAgo(`${days} day${days > 1 ? 's' : ''} ago`);
90
+ } else if (hours > 0) {
91
+ setShortTimeAgo(`${hours} hour${hours > 1 ? 's' : ''} ago`);
92
+ } else if (minutes > 0) {
93
+ setShortTimeAgo(`${minutes} minute${minutes > 1 ? 's' : ''} ago`);
94
+ } else {
95
+ setShortTimeAgo('Just now');
96
+ }
97
+ };
98
+
99
+ updateShortTimeAgo();
100
+ const timer = setInterval(updateShortTimeAgo, 60000);
101
+ return () => clearInterval(timer);
102
+ }, [date]);
103
+
104
+ return shortTimeAgo;
105
+ }
106
+
58
107
  // ---------------------------------------------------------------------------
59
- // Timezone row
108
+ // Hover card content
60
109
  // ---------------------------------------------------------------------------
61
110
 
62
111
  function ZoneDateTimeRow({
@@ -91,86 +140,34 @@ function ZoneDateTimeRow({
91
140
  });
92
141
 
93
142
  return (
94
- <div
95
- style={{
96
- display: 'flex',
97
- alignItems: 'center',
98
- justifyContent: 'space-between',
99
- gap: 12,
100
- }}
101
- >
102
- <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
103
- <div
104
- style={{
105
- display: 'inline-flex',
106
- alignItems: 'center',
107
- justifyContent: 'center',
108
- height: 16,
109
- padding: '0 6px',
110
- backgroundColor: 'var(--ds-gray-200)',
111
- borderRadius: 3,
112
- fontSize: 11,
113
- fontFamily: 'var(--font-mono, monospace)',
114
- fontWeight: 500,
115
- color: 'var(--ds-gray-900)',
116
- whiteSpace: 'nowrap',
117
- }}
118
- >
119
- {formattedZone}
143
+ <div className="flex items-center justify-between gap-3">
144
+ <div className="flex items-center gap-1.5">
145
+ <div className="flex items-center justify-center h-4 px-1.5 bg-gray-200 rounded-xs">
146
+ <span className="text-[12px] font-mono text-gray-900">
147
+ {formattedZone}
148
+ </span>
120
149
  </div>
121
- <span
122
- style={{
123
- fontSize: 13,
124
- color: 'var(--ds-gray-1000)',
125
- whiteSpace: 'nowrap',
126
- }}
127
- >
128
- {formattedDate}
129
- </span>
150
+ <span className="text-[13px] text-gray-1000">{formattedDate}</span>
130
151
  </div>
131
- <span
132
- style={{
133
- fontSize: 11,
134
- fontFamily: 'var(--font-mono, monospace)',
135
- fontVariantNumeric: 'tabular-nums',
136
- color: 'var(--ds-gray-900)',
137
- whiteSpace: 'nowrap',
138
- }}
139
- >
152
+ <span className="tabular-nums text-[12px] font-mono text-gray-900">
140
153
  {formattedTime}
141
154
  </span>
142
155
  </div>
143
156
  );
144
157
  }
145
158
 
146
- // ---------------------------------------------------------------------------
147
- // Tooltip card content
148
- // ---------------------------------------------------------------------------
149
-
150
- function TimestampTooltipContent({ date }: { date: number }): ReactNode {
159
+ function RelativeTimeContextCardContent({ date }: { date: number }): ReactNode {
151
160
  const localTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
152
161
  const timeAgo = useTimeAgo(date);
153
162
 
154
163
  return (
155
- <div
156
- style={{
157
- display: 'flex',
158
- flexDirection: 'column',
159
- gap: 12,
160
- minWidth: 300,
161
- padding: '12px 14px',
162
- }}
163
- >
164
- <span
165
- style={{
166
- fontSize: 13,
167
- fontVariantNumeric: 'tabular-nums',
168
- color: 'var(--ds-gray-900)',
169
- }}
170
- >
171
- {timeAgo}
172
- </span>
173
- <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
164
+ <div className="flex flex-col gap-3 min-w-[300px]">
165
+ <div className="flex flex-col gap-3">
166
+ <span className="tabular-nums text-[13px] text-gray-900">
167
+ {timeAgo}
168
+ </span>
169
+ </div>
170
+ <div className="flex flex-col gap-2">
174
171
  <ZoneDateTimeRow date={date} zone="UTC" />
175
172
  <ZoneDateTimeRow date={date} zone={localTimezone} />
176
173
  </div>
@@ -178,102 +175,75 @@ function TimestampTooltipContent({ date }: { date: number }): ReactNode {
178
175
  );
179
176
  }
180
177
 
178
+ function DefaultTimeText({
179
+ date,
180
+ }: {
181
+ date: number | null | undefined;
182
+ }): ReactNode {
183
+ const shortTimeAgo = useShortTimeAgo(date);
184
+ return <span className="text-label-14 text-gray-900">{shortTimeAgo}</span>;
185
+ }
186
+
181
187
  // ---------------------------------------------------------------------------
182
- // Hover tooltip wrapper
188
+ // RelativeTimeCard
183
189
  // ---------------------------------------------------------------------------
184
190
 
185
- const TOOLTIP_WIDTH = 330;
186
- const VIEWPORT_PAD = 8;
187
-
188
- function TooltipPortal({
189
- triggerRect,
190
- onMouseEnter,
191
- onMouseLeave,
191
+ type RelativeTimeCardProps = Omit<
192
+ ContextCardTriggerProps,
193
+ 'content' | 'children'
194
+ > & {
195
+ /** Timestamp in milliseconds to display as a relative time. */
196
+ date?: number | null;
197
+ /** Custom content to render instead of the default relative time text. */
198
+ children?: ReactNode;
199
+ };
200
+
201
+ /**
202
+ * Relative time label that reveals a context card with detailed UTC and local
203
+ * timestamps on hover. Renders a default short relative time label (e.g.
204
+ * "3 days ago") when `children` is omitted; renders just the children without
205
+ * the hover card when `date` is nullish.
206
+ */
207
+ export function RelativeTimeCard({
192
208
  date,
193
- }: {
194
- triggerRect: DOMRect;
195
- onMouseEnter: () => void;
196
- onMouseLeave: () => void;
197
- date: number;
198
- }): ReactNode {
199
- const tooltipRef = useRef<HTMLDivElement>(null);
200
- const [style, setStyle] = useState<React.CSSProperties>({
201
- position: 'fixed',
202
- zIndex: 9999,
203
- visibility: 'hidden',
204
- });
209
+ children: _children,
210
+ ...props
211
+ }: RelativeTimeCardProps): ReactNode {
212
+ const children =
213
+ _children === undefined ? <DefaultTimeText date={date} /> : _children;
205
214
 
206
- useEffect(() => {
207
- const placement = triggerRect.top > 240 ? 'above' : 'below';
208
- const centerX = triggerRect.left + triggerRect.width / 2;
209
-
210
- const el = tooltipRef.current;
211
- const w = el ? el.offsetWidth : TOOLTIP_WIDTH;
212
- const h = el ? el.offsetHeight : 100;
213
-
214
- let left = centerX - w / 2;
215
- left = Math.max(
216
- VIEWPORT_PAD,
217
- Math.min(left, window.innerWidth - w - VIEWPORT_PAD)
218
- );
219
-
220
- let top: number;
221
- if (placement === 'above') {
222
- top = triggerRect.top - h - 6;
223
- if (top < VIEWPORT_PAD) {
224
- top = triggerRect.bottom + 6;
225
- }
226
- } else {
227
- top = triggerRect.bottom + 6;
228
- if (top + h > window.innerHeight - VIEWPORT_PAD) {
229
- top = triggerRect.top - h - 6;
230
- }
231
- }
215
+ if (!date) return children;
232
216
 
233
- setStyle({
234
- position: 'fixed',
235
- left,
236
- top,
237
- zIndex: 9999,
238
- borderRadius: 10,
239
- border: '1px solid var(--ds-gray-alpha-200)',
240
- backgroundColor: 'var(--ds-background-100)',
241
- boxShadow: '0 4px 12px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.06)',
242
- visibility: 'visible',
243
- });
244
- }, [triggerRect]);
245
-
246
- return createPortal(
247
- // biome-ignore lint/a11y/noStaticElementInteractions: tooltip hover zone
248
- <div
249
- ref={tooltipRef}
250
- onMouseEnter={onMouseEnter}
251
- onMouseLeave={onMouseLeave}
252
- style={style}
217
+ return (
218
+ <ContextCardTrigger
219
+ content={<RelativeTimeContextCardContent date={date} />}
220
+ {...props}
253
221
  >
254
- <TimestampTooltipContent date={date} />
255
- </div>,
256
- document.body
222
+ {children}
223
+ </ContextCardTrigger>
257
224
  );
258
225
  }
259
226
 
227
+ // ---------------------------------------------------------------------------
228
+ // TimestampTooltip — convenience wrapper used across the observability UI
229
+ // ---------------------------------------------------------------------------
230
+
231
+ /**
232
+ * Wraps an already-formatted timestamp display with a relative-time hover
233
+ * card. Self-mounts a {@link ContextCardProvider} when one isn't already
234
+ * present so it works anywhere, but shares a provider (enabling the animated
235
+ * card morph between adjacent timestamps) when rendered inside one.
236
+ */
260
237
  export function TimestampTooltip({
261
238
  date,
262
239
  children,
240
+ side = 'top',
263
241
  }: {
264
242
  date: number | Date | string | null | undefined;
265
243
  children: ReactNode;
244
+ side?: ContextCardTriggerProps['side'];
266
245
  }): ReactNode {
267
- const [open, setOpen] = useState(false);
268
- const [triggerRect, setTriggerRect] = useState<DOMRect | null>(null);
269
- const triggerRef = useRef<HTMLSpanElement>(null);
270
- const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
271
-
272
- useEffect(() => {
273
- return () => {
274
- if (closeTimer.current) clearTimeout(closeTimer.current);
275
- };
276
- }, []);
246
+ const hasProvider = useHasContextCardProvider();
277
247
 
278
248
  const ts =
279
249
  date == null
@@ -284,43 +254,11 @@ export function TimestampTooltip({
284
254
 
285
255
  if (ts == null || Number.isNaN(ts)) return <>{children}</>;
286
256
 
287
- const cancelClose = () => {
288
- if (closeTimer.current) {
289
- clearTimeout(closeTimer.current);
290
- closeTimer.current = null;
291
- }
292
- };
293
-
294
- const scheduleClose = () => {
295
- cancelClose();
296
- closeTimer.current = setTimeout(() => setOpen(false), 120);
297
- };
298
-
299
- const handleOpen = () => {
300
- cancelClose();
301
- if (triggerRef.current) {
302
- setTriggerRect(triggerRef.current.getBoundingClientRect());
303
- }
304
- setOpen(true);
305
- };
306
-
307
- return (
308
- // biome-ignore lint/a11y/noStaticElementInteractions: tooltip trigger
309
- <span
310
- ref={triggerRef}
311
- onMouseEnter={handleOpen}
312
- onMouseLeave={scheduleClose}
313
- style={{ display: 'inline-flex' }}
314
- >
257
+ const card = (
258
+ <RelativeTimeCard date={ts} side={side} asChild>
315
259
  {children}
316
- {open && triggerRect && (
317
- <TooltipPortal
318
- triggerRect={triggerRect}
319
- onMouseEnter={cancelClose}
320
- onMouseLeave={scheduleClose}
321
- date={ts}
322
- />
323
- )}
324
- </span>
260
+ </RelativeTimeCard>
325
261
  );
262
+
263
+ return hasProvider ? card : <ContextCardProvider>{card}</ContextCardProvider>;
326
264
  }
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+
3
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
4
+ import * as React from 'react';
5
+ import { cn } from '../../lib/cn';
6
+
7
+ const TooltipProvider = TooltipPrimitive.Provider;
8
+
9
+ const Tooltip = TooltipPrimitive.Root;
10
+
11
+ const TooltipTrigger = TooltipPrimitive.Trigger;
12
+
13
+ const TooltipContent = React.forwardRef<
14
+ React.ElementRef<typeof TooltipPrimitive.Content>,
15
+ React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & {
16
+ showArrow?: boolean;
17
+ }
18
+ >(
19
+ (
20
+ { className, sideOffset = 8, showArrow = true, children, ...props },
21
+ ref
22
+ ) => (
23
+ <TooltipPrimitive.Portal>
24
+ <TooltipPrimitive.Content
25
+ ref={ref}
26
+ sideOffset={sideOffset}
27
+ className={cn(
28
+ 'z-[99999] flex items-center gap-1 rounded-[10px] bg-gray-1000 px-2 py-1.5 !text-label-13 text-background-100 shadow-md select-none',
29
+ className
30
+ )}
31
+ {...props}
32
+ >
33
+ {children}
34
+ {showArrow ? (
35
+ <TooltipPrimitive.Arrow
36
+ width={11}
37
+ height={5}
38
+ className="fill-gray-1000"
39
+ />
40
+ ) : null}
41
+ </TooltipPrimitive.Content>
42
+ </TooltipPrimitive.Portal>
43
+ )
44
+ );
45
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
46
+
47
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { parseStepName, parseWorkflowName } from '@workflow/utils/parse-name';
4
- import type { Event, Hook, Step, WorkflowRun } from '@workflow/world';
4
+ import type { Event, Hook, WorkflowRun } from '@workflow/world';
5
5
  import {
6
6
  ChevronDown,
7
7
  ChevronUp,
@@ -17,7 +17,11 @@ import type { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
17
17
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
18
18
  import { createPortal } from 'react-dom';
19
19
  import { useToast } from '../lib/toast';
20
- import { buildTrace, type TraceWithMeta } from '../lib/trace-builder';
20
+ import {
21
+ buildTrace,
22
+ filterSpanRawEvents,
23
+ type TraceWithMeta,
24
+ } from '../lib/trace-builder';
21
25
  import { ErrorBoundary } from './error-boundary';
22
26
  import {
23
27
  EntityDetailPanel,
@@ -25,6 +29,7 @@ import {
25
29
  type SpanSelectionInfo,
26
30
  } from './sidebar/entity-detail-panel';
27
31
  import { ResolveHookModal } from './sidebar/resolve-hook-modal';
32
+ import type { FetchSpanDetail } from './sidebar/use-selected-span-detail';
28
33
  import {
29
34
  TraceViewerContextProvider,
30
35
  TraceViewerTimeline,
@@ -760,15 +765,12 @@ export const WorkflowTraceViewer = ({
760
765
  events,
761
766
  isLoading,
762
767
  error,
763
- spanDetailData,
764
- spanDetailLoading,
765
- spanDetailError,
768
+ fetchSpanDetail,
766
769
  onWakeUpSleep,
767
770
  onResolveHook,
768
771
  onCancelRun,
769
772
  onStreamClick,
770
773
  onRunClick,
771
- onSpanSelect,
772
774
  onLoadEventData,
773
775
  onLoadMoreSpans,
774
776
  hasMoreSpans = false,
@@ -776,14 +778,13 @@ export const WorkflowTraceViewer = ({
776
778
  encryptionKey,
777
779
  onDecrypt,
778
780
  isDecrypting = false,
781
+ showSeparateEventOccurrenceTimestamps = false,
779
782
  }: {
780
783
  run: WorkflowRun;
781
784
  events: Event[];
782
785
  isLoading?: boolean;
783
786
  error?: Error | null;
784
- spanDetailData?: WorkflowRun | Step | Hook | Event | null;
785
- spanDetailLoading?: boolean;
786
- spanDetailError?: Error | null;
787
+ fetchSpanDetail: FetchSpanDetail;
787
788
  onWakeUpSleep?: (
788
789
  runId: string,
789
790
  correlationId: string
@@ -799,13 +800,8 @@ export const WorkflowTraceViewer = ({
799
800
  onStreamClick?: (streamId: string) => void;
800
801
  /** Callback when a run reference is clicked in the detail panel */
801
802
  onRunClick?: (runId: string) => void;
802
- /** Callback when a span is selected. */
803
- onSpanSelect?: (info: SpanSelectionInfo) => void;
804
803
  /** 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>;
804
+ onLoadEventData?: (event: Event) => Promise<unknown | null>;
809
805
  /** Load next trace page when vertical scroll reaches bottom. */
810
806
  onLoadMoreSpans?: () => void | Promise<void>;
811
807
  /** Whether trace pagination has more data to load. */
@@ -818,6 +814,8 @@ export const WorkflowTraceViewer = ({
818
814
  onDecrypt?: () => void;
819
815
  /** Whether the encryption key is currently being fetched */
820
816
  isDecrypting?: boolean;
817
+ /** Show occurredAt separately instead of folding it into the Created timestamp. */
818
+ showSeparateEventOccurrenceTimestamps?: boolean;
821
819
  }) => {
822
820
  const toast = useToast();
823
821
  const [selectedSpan, setSelectedSpan] = useState<SelectedSpanInfo | null>(
@@ -852,22 +850,17 @@ export const WorkflowTraceViewer = ({
852
850
  }
853
851
  }, [error, isLoading]);
854
852
 
855
- const handleSpanSelect = useCallback(
856
- (info: SpanSelectionInfo) => {
857
- onSpanSelect?.(info);
858
- },
859
- [onSpanSelect]
860
- );
861
-
862
853
  const handleSelectionChange = useCallback(
863
854
  (info: SelectedSpanInfo | null) => {
864
855
  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
- : [];
856
+ // Filter raw events for the selected span: child spans match on
857
+ // correlationId (stepId/hookId), the run root span gets run-level
858
+ // events. This bypasses the trace worker pipeline entirely.
859
+ const rawEvents = filterSpanRawEvents(
860
+ events,
861
+ info.resource,
862
+ info.spanId
863
+ );
871
864
  setSelectedSpan({ ...info, rawEvents });
872
865
  } else {
873
866
  setSelectedSpan(null);
@@ -881,8 +874,10 @@ export const WorkflowTraceViewer = ({
881
874
  const correlationId = selectedSpan?.spanId;
882
875
  if (!correlationId) return;
883
876
 
884
- const nextRawEvents = events.filter(
885
- (e) => e.correlationId === correlationId
877
+ const nextRawEvents = filterSpanRawEvents(
878
+ events,
879
+ selectedSpan?.resource,
880
+ correlationId
886
881
  );
887
882
  setSelectedSpan((prev) => {
888
883
  if (!prev || prev.spanId !== correlationId) {
@@ -904,7 +899,7 @@ export const WorkflowTraceViewer = ({
904
899
  rawEvents: nextRawEvents,
905
900
  };
906
901
  });
907
- }, [events, selectedSpan?.spanId]);
902
+ }, [events, selectedSpan?.spanId, selectedSpan?.resource]);
908
903
 
909
904
  // Reset selected span when navigating to a different run
910
905
  useEffect(() => {
@@ -974,7 +969,7 @@ export const WorkflowTraceViewer = ({
974
969
  }
975
970
 
976
971
  return (
977
- <div className="relative w-full h-full flex flex-col">
972
+ <div className="relative w-full h-full flex flex-row">
978
973
  {/* Timeline (takes remaining space) */}
979
974
  <div className="flex-1 min-w-0 relative">
980
975
  <TraceViewerContextProvider
@@ -1150,10 +1145,7 @@ export const WorkflowTraceViewer = ({
1150
1145
  run={run}
1151
1146
  onStreamClick={onStreamClick}
1152
1147
  onRunClick={onRunClick}
1153
- spanDetailData={spanDetailData ?? null}
1154
- spanDetailError={spanDetailError}
1155
- spanDetailLoading={spanDetailLoading}
1156
- onSpanSelect={handleSpanSelect}
1148
+ fetchSpanDetail={fetchSpanDetail}
1157
1149
  onWakeUpSleep={onWakeUpSleep}
1158
1150
  onLoadEventData={onLoadEventData}
1159
1151
  onResolveHook={onResolveHook}
@@ -1161,6 +1153,9 @@ export const WorkflowTraceViewer = ({
1161
1153
  onDecrypt={onDecrypt}
1162
1154
  isDecrypting={isDecrypting}
1163
1155
  selectedSpan={selectedSpan}
1156
+ showSeparateEventOccurrenceTimestamps={
1157
+ showSeparateEventOccurrenceTimestamps
1158
+ }
1164
1159
  />
1165
1160
  </ErrorBoundary>
1166
1161
  </div>
@@ -2,7 +2,7 @@
2
2
  * Color utilities for workflow event markers
3
3
  */
4
4
 
5
- import type { Event } from '@workflow/world';
5
+ import { type Event, isHookLifecycleEventType } from '@workflow/world';
6
6
 
7
7
  export interface EventColorPalette {
8
8
  /** Color of the diamond/marker itself */
@@ -22,6 +22,7 @@ export interface EventColorPalette {
22
22
  * - Red for failures (step_failed, run_failed)
23
23
  * - Orange/yellow for retries (step_retrying)
24
24
  * - Purple for webhook-related events
25
+ * - Teal for attribute changes (attr_set)
25
26
  * - Blue otherwise (default)
26
27
  */
27
28
  export function getEventColor(
@@ -50,11 +51,7 @@ export function getEventColor(
50
51
  }
51
52
 
52
53
  // Webhook-related - Purple
53
- if (
54
- eventType === 'hook_created' ||
55
- eventType === 'hook_received' ||
56
- eventType === 'hook_disposed'
57
- ) {
54
+ if (isHookLifecycleEventType(eventType)) {
58
55
  return {
59
56
  color: 'var(--ds-purple-600)',
60
57
  background: 'var(--ds-purple-100)',
@@ -64,6 +61,17 @@ export function getEventColor(
64
61
  };
65
62
  }
66
63
 
64
+ // Attribute changes - Teal
65
+ if (eventType === 'attr_set') {
66
+ return {
67
+ color: 'var(--ds-teal-900)',
68
+ background: 'var(--ds-teal-200)',
69
+ border: 'var(--ds-teal-500)',
70
+ text: 'var(--ds-teal-900)',
71
+ secondary: 'var(--ds-gray-900)',
72
+ };
73
+ }
74
+
67
75
  // Default - Blue
68
76
  return {
69
77
  color: 'var(--ds-blue-600)',
@@ -81,11 +89,7 @@ export function getEventColor(
81
89
  */
82
90
  export function shouldShowVerticalLine(eventType: Event['eventType']): boolean {
83
91
  // Show vertical lines for hook-related events
84
- if (
85
- eventType === 'hook_created' ||
86
- eventType === 'hook_received' ||
87
- eventType === 'hook_disposed'
88
- ) {
92
+ if (isHookLifecycleEventType(eventType)) {
89
93
  return true;
90
94
  }
91
95