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

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
@@ -3,16 +3,30 @@
3
3
  import { parseStepName, parseWorkflowName } from '@workflow/utils/parse-name';
4
4
  import type { Event, WorkflowRun } from '@workflow/world';
5
5
  import { Check, ChevronRight, Copy } from 'lucide-react';
6
- import type { MouseEvent as ReactMouseEvent, ReactNode } from 'react';
6
+ import type {
7
+ KeyboardEvent as ReactKeyboardEvent,
8
+ MouseEvent as ReactMouseEvent,
9
+ ReactNode,
10
+ } from 'react';
7
11
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
8
12
  import { Virtuoso, type VirtuosoHandle } from 'react-virtuoso';
13
+ import {
14
+ type ExactIdSearchResult,
15
+ type ExactWorkflowSearchIdKind,
16
+ looksLikeWorkflowIdSearchInput,
17
+ parseExactWorkflowSearchId,
18
+ } from '../lib/exact-event-search-id';
9
19
  import { isEncryptedMarker } from '../lib/hydration';
10
- import { DecryptButton } from './ui/decrypt-button';
20
+ import { useToast } from '../lib/toast';
11
21
  import { formatDuration } from '../lib/utils';
22
+ import { AttrSetEventBlock } from './sidebar/attributes-block';
23
+ import { ContextCardProvider } from './ui/context-card';
12
24
  import { DataInspector, DecryptClickContext } from './ui/data-inspector';
25
+ import { DecryptButton } from './ui/decrypt-button';
13
26
  import {
14
27
  ErrorStackBlock,
15
- isStructuredErrorWithStack,
28
+ isStructuredError,
29
+ type StructuredErrorRecord,
16
30
  } from './ui/error-stack-block';
17
31
  import { LoadMoreButton } from './ui/load-more-button';
18
32
  import { MenuDropdown } from './ui/menu-dropdown';
@@ -55,6 +69,25 @@ function formatEventTime(date: Date): string {
55
69
  );
56
70
  }
57
71
 
72
+ function parseEventDate(value: unknown): Date | null {
73
+ if (value == null) return null;
74
+
75
+ const date = value instanceof Date ? value : new Date(String(value));
76
+ return Number.isNaN(date.getTime()) ? null : date;
77
+ }
78
+
79
+ function getEffectiveEventDate(
80
+ event: Pick<Event, 'createdAt' | 'occurredAt'>
81
+ ): Date {
82
+ return parseEventDate(event.occurredAt) ?? new Date(event.createdAt);
83
+ }
84
+
85
+ function getEffectiveEventTime(
86
+ event: Pick<Event, 'createdAt' | 'occurredAt'>
87
+ ): number {
88
+ return getEffectiveEventDate(event).getTime();
89
+ }
90
+
58
91
  function formatEventType(eventType: Event['eventType']): string {
59
92
  return eventType
60
93
  .split('_')
@@ -84,6 +117,10 @@ function getStatusDotColor(eventType: string): string {
84
117
  if (eventType === 'step_retrying') {
85
118
  return 'var(--ds-amber-700)';
86
119
  }
120
+ // Attribute changes → teal
121
+ if (eventType === 'attr_set') {
122
+ return 'var(--ds-teal-900)';
123
+ }
87
124
  // Completed/succeeded → green
88
125
  if (
89
126
  eventType === 'step_completed' ||
@@ -142,7 +179,7 @@ function buildNameMaps(
142
179
  return { correlationNameMap, workflowName };
143
180
  }
144
181
 
145
- interface DurationInfo {
182
+ export interface DurationInfo {
146
183
  /** Time from created → started (ms) */
147
184
  queued?: number;
148
185
  /** Time from started → completed/failed/cancelled (ms) */
@@ -154,19 +191,30 @@ interface DurationInfo {
154
191
  * created ↔ started (queued) and started ↔ completed/failed/cancelled (ran).
155
192
  * Also computes run-level durations under the key '__run__'.
156
193
  */
157
- function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
194
+ export function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
195
+ // Process events in chronological order so the result doesn't depend on
196
+ // the caller's sort direction. Retried steps emit multiple `step_started`
197
+ // events for the same correlationId; the queued duration must be measured
198
+ // against the first one, not the last.
199
+ const chronological = [...events].sort(
200
+ (a, b) => getEffectiveEventTime(a) - getEffectiveEventTime(b)
201
+ );
202
+
158
203
  const createdTimes = new Map<string, number>();
204
+ const firstStartedTimes = new Map<string, number>();
159
205
  const startedTimes = new Map<string, number>();
160
206
  const durations = new Map<string, DurationInfo>();
161
207
 
162
- for (const event of events) {
163
- const ts = new Date(event.createdAt).getTime();
208
+ for (const event of chronological) {
209
+ const ts = getEffectiveEventTime(event);
164
210
  const key = event.correlationId ?? '__run__';
165
211
  const type: string = event.eventType;
166
212
 
167
213
  // Track created times (first event for each correlation)
168
214
  if (type === 'step_created' || type === 'run_created') {
169
- createdTimes.set(key, ts);
215
+ if (!createdTimes.has(key)) {
216
+ createdTimes.set(key, ts);
217
+ }
170
218
  }
171
219
 
172
220
  // Track started times & compute queued duration
@@ -176,16 +224,21 @@ function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
176
224
  type === 'workflow_started'
177
225
  ) {
178
226
  startedTimes.set(key, ts);
179
- // If no explicit created event was seen, use the started time as created
180
- if (!createdTimes.has(key)) {
181
- createdTimes.set(key, ts);
182
- }
183
- const createdAt = createdTimes.get(key);
184
- const info = durations.get(key) ?? {};
185
- if (createdAt !== undefined) {
186
- info.queued = ts - createdAt;
227
+ // The queued duration is anchored on the first start event only
228
+ // subsequent step_started events come from retries.
229
+ if (!firstStartedTimes.has(key)) {
230
+ firstStartedTimes.set(key, ts);
231
+ // If no explicit created event was seen, use the started time as created
232
+ if (!createdTimes.has(key)) {
233
+ createdTimes.set(key, ts);
234
+ }
235
+ const createdAt = createdTimes.get(key);
236
+ const info = durations.get(key) ?? {};
237
+ if (createdAt !== undefined) {
238
+ info.queued = ts - createdAt;
239
+ }
240
+ durations.set(key, info);
187
241
  }
188
- durations.set(key, info);
189
242
  }
190
243
 
191
244
  // Compute ran duration on terminal events
@@ -230,7 +283,10 @@ function isRunLevel(eventType: string): boolean {
230
283
  eventType === 'run_cancelled' ||
231
284
  eventType === 'workflow_started' ||
232
285
  eventType === 'workflow_completed' ||
233
- eventType === 'workflow_failed'
286
+ eventType === 'workflow_failed' ||
287
+ // attr_set carries a dedup correlationId rather than a child entity ID,
288
+ // so it groups and labels with the run itself.
289
+ eventType === 'attr_set'
234
290
  );
235
291
  }
236
292
 
@@ -492,20 +548,20 @@ function deepParseJson(value: unknown): unknown {
492
548
  }
493
549
 
494
550
  /**
495
- * Extracts a structured error with a stack trace from event data, if present.
551
+ * Extracts a structured error from event data, if present.
496
552
  * Returns the error object to render with ErrorStackBlock, or null if not applicable.
497
553
  */
498
554
  function extractStructuredError(
499
555
  data: unknown,
500
556
  eventType?: string
501
- ): (Record<string, unknown> & { stack: string }) | null {
557
+ ): StructuredErrorRecord | null {
502
558
  if (!eventType || !ERROR_EVENT_TYPES.has(eventType)) return null;
503
559
  if (data == null || typeof data !== 'object') return null;
504
560
  const record = data as Record<string, unknown>;
505
561
  // Check the nested `error` field first (the StructuredError)
506
- if (isStructuredErrorWithStack(record.error)) return record.error;
507
- // Some error formats put the stack at the top level of eventData
508
- if (isStructuredErrorWithStack(record)) return record;
562
+ if (isStructuredError(record.error)) return record.error;
563
+ // Some error formats put the message/stack at the top level of eventData.
564
+ if (isStructuredError(record)) return record;
509
565
  return null;
510
566
  }
511
567
 
@@ -566,6 +622,36 @@ function PayloadBlock({
566
622
  );
567
623
  }
568
624
 
625
+ // Attribute changes — render the changed keys and the writer instead of
626
+ // the raw JSON payload.
627
+ if (eventType === 'attr_set') {
628
+ return <AttrSetEventBlock data={cleaned} />;
629
+ }
630
+
631
+ // Cancellation reason — render the free-text reason as a readable line
632
+ // instead of a raw JSON payload (the only field run_cancelled carries).
633
+ if (eventType === 'run_cancelled') {
634
+ const cancelReason =
635
+ cleaned != null &&
636
+ typeof cleaned === 'object' &&
637
+ typeof (cleaned as Record<string, unknown>).cancelReason === 'string'
638
+ ? ((cleaned as Record<string, unknown>).cancelReason as string)
639
+ : null;
640
+ if (cancelReason) {
641
+ return (
642
+ <div
643
+ className="p-2 text-label-12"
644
+ style={{ color: 'var(--ds-gray-1000)' }}
645
+ >
646
+ <span style={{ color: 'var(--ds-gray-900)' }}>Reason: </span>
647
+ <span className="whitespace-pre-wrap break-words">
648
+ {cancelReason}
649
+ </span>
650
+ </div>
651
+ );
652
+ }
653
+ }
654
+
569
655
  return (
570
656
  <div className="relative group/payload">
571
657
  <div
@@ -577,7 +663,7 @@ function PayloadBlock({
577
663
  <button
578
664
  type="button"
579
665
  onClick={handleCopy}
580
- className="absolute bottom-2 right-2 opacity-0 group-hover/payload:opacity-100 transition-opacity flex items-center gap-1 px-2 py-1 rounded-md text-xs hover:bg-[var(--ds-gray-alpha-200)]"
666
+ className="absolute bottom-2 right-2 opacity-0 group-hover/payload:opacity-100 transition-opacity flex items-center gap-1 px-2 py-1 rounded-md text-button-12 hover:bg-[var(--ds-gray-alpha-200)]"
581
667
  style={{ ...BUTTON_RESET_STYLE, color: 'var(--ds-gray-700)' }}
582
668
  aria-label="Copy payload"
583
669
  >
@@ -609,7 +695,11 @@ const SORT_OPTIONS = [
609
695
  { value: 'asc' as const, label: 'Oldest' },
610
696
  ];
611
697
 
612
- function RowsSkeleton() {
698
+ function RowsSkeleton({
699
+ showSeparateEventOccurrenceTimestamps = false,
700
+ }: {
701
+ showSeparateEventOccurrenceTimestamps?: boolean;
702
+ }) {
613
703
  return (
614
704
  <div className="flex-1 overflow-hidden">
615
705
  {Array.from({ length: 16 }, (_, i) => (
@@ -646,7 +736,12 @@ function RowsSkeleton() {
646
736
  <div className="w-5 flex-shrink-0 flex items-center justify-center">
647
737
  <Skeleton className="w-5 h-5" style={{ borderRadius: 4 }} />
648
738
  </div>
649
- {/* Time */}
739
+ {showSeparateEventOccurrenceTimestamps && (
740
+ <div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
741
+ <Skeleton className="h-3" style={{ width: '70%' }} />
742
+ </div>
743
+ )}
744
+ {/* Created */}
650
745
  <div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
651
746
  <Skeleton className="h-3" style={{ width: '70%' }} />
652
747
  </div>
@@ -705,9 +800,17 @@ interface EventsListProps {
705
800
  isDecrypting?: boolean;
706
801
  /** Run-level hint: the run contains encrypted data (from probe). */
707
802
  hasEncryptedData?: boolean;
803
+ /** Fetch events for an exact correlation or event ID. */
804
+ onExactIdSearch?: (
805
+ id: string,
806
+ kind: ExactWorkflowSearchIdKind,
807
+ signal?: AbortSignal
808
+ ) => Promise<ExactIdSearchResult>;
809
+ /** Show occurredAt separately instead of folding it into the Created timestamp. */
810
+ showSeparateEventOccurrenceTimestamps?: boolean;
708
811
  }
709
812
 
710
- function EventRow({
813
+ export function EventRow({
711
814
  event,
712
815
  index,
713
816
  isFirst,
@@ -727,6 +830,8 @@ function EventRow({
727
830
  onCacheEventData,
728
831
  encryptionKey,
729
832
  onEncryptedDataDetected,
833
+ suppressGroupDimming = false,
834
+ showSeparateEventOccurrenceTimestamps = false,
730
835
  }: {
731
836
  event: Event;
732
837
  index: number;
@@ -747,6 +852,10 @@ function EventRow({
747
852
  onCacheEventData: (eventId: string, data: unknown) => void;
748
853
  encryptionKey?: Uint8Array;
749
854
  onEncryptedDataDetected?: () => void;
855
+ /** Exact-ID search results should not dim unrelated rows. */
856
+ suppressGroupDimming?: boolean;
857
+ /** Show occurredAt separately instead of folding it into the Created timestamp. */
858
+ showSeparateEventOccurrenceTimestamps?: boolean;
750
859
  }) {
751
860
  const [isLoading, setIsLoading] = useState(false);
752
861
  const [loadedEventData, setLoadedEventData] = useState<unknown | null>(
@@ -775,6 +884,10 @@ function EventRow({
775
884
 
776
885
  const statusDotColor = getStatusDotColor(event.eventType);
777
886
  const createdAt = new Date(event.createdAt);
887
+ const occurredAt = parseEventDate(event.occurredAt);
888
+ const displayedCreatedAt = showSeparateEventOccurrenceTimestamps
889
+ ? createdAt
890
+ : getEffectiveEventDate(event);
778
891
  const hasExistingEventData = 'eventData' in event && event.eventData != null;
779
892
  const isRun = isRunLevel(event.eventType);
780
893
  const eventName = isRun
@@ -788,7 +901,7 @@ function EventRow({
788
901
 
789
902
  const hasActive = activeGroupKey !== undefined;
790
903
  const isRelated = rowGroupKey !== undefined && rowGroupKey === activeGroupKey;
791
- const isDimmed = hasActive && !isRelated;
904
+ const isDimmed = hasActive && !isRelated && !suppressGroupDimming;
792
905
  const isPulsing = hasActive && isRelated;
793
906
 
794
907
  // Gutter state derived from selectedGroupRange
@@ -918,7 +1031,7 @@ function EventRow({
918
1031
  onKeyDown={(e) => {
919
1032
  if (e.key === 'Enter' || e.key === ' ') handleRowClick();
920
1033
  }}
921
- className="w-full text-left flex items-center gap-0 text-[13px] hover:bg-[var(--ds-gray-alpha-100)] transition-colors cursor-pointer"
1034
+ className="w-full text-left flex items-center gap-0 text-label-13 hover:bg-[var(--ds-gray-alpha-100)] transition-colors cursor-pointer"
922
1035
  style={{ minHeight: 40 }}
923
1036
  >
924
1037
  <TreeGutter
@@ -955,13 +1068,28 @@ function EventRow({
955
1068
  />
956
1069
  </div>
957
1070
 
958
- {/* Time */}
1071
+ {showSeparateEventOccurrenceTimestamps && (
1072
+ <div
1073
+ className="tabular-nums min-w-0 px-4"
1074
+ style={{ color: 'var(--ds-gray-900)', flex: '2 1 0%' }}
1075
+ >
1076
+ {occurredAt ? (
1077
+ <TimestampTooltip date={occurredAt}>
1078
+ <span>{formatEventTime(occurredAt)}</span>
1079
+ </TimestampTooltip>
1080
+ ) : (
1081
+ '-'
1082
+ )}
1083
+ </div>
1084
+ )}
1085
+
1086
+ {/* Created */}
959
1087
  <div
960
1088
  className="tabular-nums min-w-0 px-4"
961
1089
  style={{ color: 'var(--ds-gray-900)', flex: '2 1 0%' }}
962
1090
  >
963
- <TimestampTooltip date={createdAt}>
964
- <span>{formatEventTime(createdAt)}</span>
1091
+ <TimestampTooltip date={displayedCreatedAt}>
1092
+ <span>{formatEventTime(displayedCreatedAt)}</span>
965
1093
  </TimestampTooltip>
966
1094
  </div>
967
1095
 
@@ -1060,7 +1188,7 @@ function EventRow({
1060
1188
  {(durationInfo?.queued !== undefined ||
1061
1189
  durationInfo?.ran !== undefined) && (
1062
1190
  <div
1063
- className="px-2 pb-1.5 text-xs flex gap-3"
1191
+ className="px-2 pb-1.5 text-label-12 flex gap-3"
1064
1192
  style={{ color: 'var(--ds-gray-900)' }}
1065
1193
  >
1066
1194
  {durationInfo.queued !== undefined &&
@@ -1088,7 +1216,7 @@ function EventRow({
1088
1216
  <PayloadBlock data={displayPayload} eventType={event.eventType} />
1089
1217
  ) : loadError ? (
1090
1218
  <div
1091
- className="rounded-md border p-3 text-xs"
1219
+ className="rounded-md border p-3 text-label-12"
1092
1220
  style={{
1093
1221
  borderColor: 'var(--ds-red-400)',
1094
1222
  backgroundColor: 'var(--ds-red-100)',
@@ -1108,7 +1236,7 @@ function EventRow({
1108
1236
  </div>
1109
1237
  ) : (
1110
1238
  <div
1111
- className="p-2 text-xs"
1239
+ className="p-2 text-label-12"
1112
1240
  style={{ color: 'var(--ds-gray-900)' }}
1113
1241
  >
1114
1242
  No data
@@ -1125,7 +1253,7 @@ function EventRow({
1125
1253
  // Main component
1126
1254
  // ──────────────────────────────────────────────────────────────────────────
1127
1255
 
1128
- export function EventListView({
1256
+ function EventListViewInner({
1129
1257
  events,
1130
1258
  run,
1131
1259
  onLoadEventData,
@@ -1139,7 +1267,10 @@ export function EventListView({
1139
1267
  onDecrypt,
1140
1268
  isDecrypting = false,
1141
1269
  hasEncryptedData: hasEncryptedDataProp = false,
1270
+ onExactIdSearch,
1271
+ showSeparateEventOccurrenceTimestamps = false,
1142
1272
  }: EventsListProps) {
1273
+ const toast = useToast();
1143
1274
  const [internalSortOrder, setInternalSortOrder] = useState<'asc' | 'desc'>(
1144
1275
  'asc'
1145
1276
  );
@@ -1155,25 +1286,40 @@ export function EventListView({
1155
1286
  [onSortOrderChange]
1156
1287
  );
1157
1288
 
1289
+ const [searchQuery, setSearchQuery] = useState('');
1290
+ const [searchResults, setSearchResults] = useState<Event[] | null>(null);
1291
+ const [searchResultsTruncated, setSearchResultsTruncated] = useState(false);
1292
+ const [searchError, setSearchError] = useState<string | null>(null);
1293
+ const [searchLoading, setSearchLoading] = useState(false);
1294
+ const [searchNotFound, setSearchNotFound] = useState(false);
1295
+ const searchRequestRef = useRef(0);
1296
+ const virtuosoRef = useRef<VirtuosoHandle>(null);
1297
+
1298
+ const parsedSearchId = useMemo(
1299
+ () => parseExactWorkflowSearchId(searchQuery),
1300
+ [searchQuery]
1301
+ );
1302
+ const isExactSearchActive = searchResults !== null;
1303
+
1158
1304
  const sortedEvents = useMemo(() => {
1159
- if (!events || events.length === 0) return [];
1305
+ const sourceEvents = isExactSearchActive ? searchResults : (events ?? []);
1306
+ if (sourceEvents.length === 0) return [];
1160
1307
  const dir = effectiveSortOrder === 'desc' ? -1 : 1;
1161
- return [...events].sort(
1162
- (a, b) =>
1163
- dir *
1164
- (new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime())
1308
+ return [...sourceEvents].sort(
1309
+ (a, b) => dir * (getEffectiveEventTime(a) - getEffectiveEventTime(b))
1165
1310
  );
1166
- }, [events, effectiveSortOrder]);
1311
+ }, [events, effectiveSortOrder, isExactSearchActive, searchResults]);
1167
1312
 
1168
1313
  // Detect encrypted fields across all loaded events (inline eventData).
1169
1314
  const hasEncryptedInlineData = useMemo(() => {
1170
- if (!events) return false;
1171
- for (const event of events) {
1315
+ const sourceEvents = isExactSearchActive ? searchResults : events;
1316
+ if (!sourceEvents) return false;
1317
+ for (const event of sourceEvents) {
1172
1318
  const ed = (event as Record<string, unknown>).eventData;
1173
1319
  if (hasEncryptedValues(ed)) return true;
1174
1320
  }
1175
1321
  return false;
1176
- }, [events]);
1322
+ }, [events, isExactSearchActive, searchResults]);
1177
1323
 
1178
1324
  // Tracks whether any expanded row's lazy-loaded data contained encrypted markers.
1179
1325
  // Set to true by EventRow via onEncryptedDataDetected; never reset (sticky).
@@ -1187,8 +1333,12 @@ export function EventListView({
1187
1333
  hasEncryptedDataProp || hasEncryptedInlineData || foundEncryptedInLazyData;
1188
1334
 
1189
1335
  const { correlationNameMap, workflowName } = useMemo(
1190
- () => buildNameMaps(events ?? null, run ?? null),
1191
- [events, run]
1336
+ () =>
1337
+ buildNameMaps(
1338
+ isExactSearchActive ? searchResults : (events ?? null),
1339
+ run ?? null
1340
+ ),
1341
+ [events, isExactSearchActive, run, searchResults]
1192
1342
  );
1193
1343
 
1194
1344
  const durationMap = useMemo(
@@ -1278,68 +1428,139 @@ export function EventListView({
1278
1428
  return first >= 0 ? { first, last } : null;
1279
1429
  }, [activeGroupKey, sortedEvents]);
1280
1430
 
1281
- const [searchQuery, setSearchQuery] = useState('');
1282
- const virtuosoRef = useRef<VirtuosoHandle>(null);
1283
-
1284
- const searchIndex = useMemo(() => {
1285
- const entries: {
1286
- fields: string[];
1287
- groupKey?: string;
1288
- eventId: string;
1289
- index: number;
1290
- }[] = [];
1291
- for (let i = 0; i < sortedEvents.length; i++) {
1292
- const ev = sortedEvents[i];
1293
- const isRun = isRunLevel(ev.eventType);
1294
- const name = isRun
1295
- ? (workflowName ?? '')
1296
- : ev.correlationId
1297
- ? (correlationNameMap.get(ev.correlationId) ?? '')
1298
- : '';
1299
- entries.push({
1300
- fields: [
1301
- ev.eventId,
1302
- ev.correlationId ?? '',
1303
- ev.eventType,
1304
- formatEventType(ev.eventType),
1305
- name,
1306
- ].map((f) => f.toLowerCase()),
1307
- groupKey: ev.correlationId ?? (isRun ? '__run__' : undefined),
1308
- eventId: ev.eventId,
1309
- index: i,
1310
- });
1311
- }
1312
- return entries;
1313
- }, [sortedEvents, correlationNameMap, workflowName]);
1314
-
1315
1431
  useEffect(() => {
1316
- const q = searchQuery.trim().toLowerCase();
1317
- if (!q) {
1432
+ const trimmed = searchQuery.trim();
1433
+ if (!trimmed) {
1434
+ searchRequestRef.current += 1;
1435
+ setSearchResults(null);
1436
+ setSearchResultsTruncated(false);
1437
+ setSearchError(null);
1438
+ setSearchLoading(false);
1439
+ setSearchNotFound(false);
1318
1440
  setSelectedGroupKey(undefined);
1319
1441
  return;
1320
1442
  }
1321
- let bestMatch: (typeof searchIndex)[number] | null = null;
1322
- let bestScore = 0;
1323
- for (const entry of searchIndex) {
1324
- for (const field of entry.fields) {
1325
- if (field && field.includes(q)) {
1326
- const score = q.length / field.length;
1327
- if (score > bestScore) {
1328
- bestScore = score;
1329
- bestMatch = entry;
1443
+
1444
+ const parsed = parseExactWorkflowSearchId(trimmed);
1445
+ if (!parsed || !onExactIdSearch) {
1446
+ setSearchResults(null);
1447
+ setSearchLoading(false);
1448
+ setSearchNotFound(false);
1449
+ return;
1450
+ }
1451
+
1452
+ const requestId = ++searchRequestRef.current;
1453
+ setSearchLoading(true);
1454
+ setSearchNotFound(false);
1455
+ setSearchError(null);
1456
+
1457
+ const abortController = new AbortController();
1458
+
1459
+ const timer = setTimeout(() => {
1460
+ void (async () => {
1461
+ try {
1462
+ const results = await onExactIdSearch(
1463
+ parsed.id,
1464
+ parsed.kind,
1465
+ abortController.signal
1466
+ );
1467
+ if (
1468
+ abortController.signal.aborted ||
1469
+ searchRequestRef.current !== requestId
1470
+ ) {
1471
+ return;
1472
+ }
1473
+
1474
+ if (results.status === 'error') {
1475
+ setSearchResults([]);
1476
+ setSearchResultsTruncated(false);
1477
+ setSearchNotFound(false);
1478
+ setSearchError(results.message);
1479
+ setSelectedGroupKey(undefined);
1480
+ return;
1481
+ }
1482
+
1483
+ if (
1484
+ results.status === 'not_found' ||
1485
+ (results.status === 'ok' && results.events.length === 0)
1486
+ ) {
1487
+ setSearchResults([]);
1488
+ setSearchResultsTruncated(false);
1489
+ setSearchNotFound(true);
1490
+ setSearchError(null);
1491
+ setSelectedGroupKey(undefined);
1492
+ return;
1493
+ }
1494
+
1495
+ setSearchResults(results.events);
1496
+ setSearchResultsTruncated(Boolean(results.truncated));
1497
+ setSearchNotFound(false);
1498
+ setSearchError(null);
1499
+ setSelectedGroupKey(
1500
+ parsed.kind === 'event'
1501
+ ? (() => {
1502
+ const first = results.events[0];
1503
+ if (!first) return undefined;
1504
+ return isRunLevel(first.eventType)
1505
+ ? '__run__'
1506
+ : (first.correlationId ?? undefined);
1507
+ })()
1508
+ : parsed.id
1509
+ );
1510
+ virtuosoRef.current?.scrollToIndex({
1511
+ index: 0,
1512
+ align: 'start',
1513
+ behavior: 'smooth',
1514
+ });
1515
+ } catch {
1516
+ if (
1517
+ abortController.signal.aborted ||
1518
+ searchRequestRef.current !== requestId
1519
+ ) {
1520
+ return;
1521
+ }
1522
+ setSearchResults([]);
1523
+ setSearchResultsTruncated(false);
1524
+ setSearchNotFound(false);
1525
+ setSearchError('Failed to search events. Try again.');
1526
+ setSelectedGroupKey(undefined);
1527
+ } finally {
1528
+ if (
1529
+ searchRequestRef.current === requestId &&
1530
+ !abortController.signal.aborted
1531
+ ) {
1532
+ setSearchLoading(false);
1330
1533
  }
1331
1534
  }
1535
+ })();
1536
+ }, 300);
1537
+
1538
+ return () => {
1539
+ clearTimeout(timer);
1540
+ abortController.abort();
1541
+ };
1542
+ }, [searchQuery, onExactIdSearch]);
1543
+
1544
+ const handleSearchKeyDown = useCallback(
1545
+ (event: ReactKeyboardEvent<HTMLInputElement>) => {
1546
+ if (event.key !== 'Enter') {
1547
+ return;
1332
1548
  }
1333
- }
1334
- if (bestMatch) {
1335
- setSelectedGroupKey(bestMatch.groupKey);
1336
- virtuosoRef.current?.scrollToIndex({
1337
- index: bestMatch.index,
1338
- align: 'center',
1339
- behavior: 'smooth',
1340
- });
1341
- }
1342
- }, [searchQuery, searchIndex]);
1549
+
1550
+ const trimmed = searchQuery.trim();
1551
+ if (
1552
+ !trimmed ||
1553
+ parseExactWorkflowSearchId(trimmed) ||
1554
+ !onExactIdSearch ||
1555
+ !looksLikeWorkflowIdSearchInput(trimmed)
1556
+ ) {
1557
+ return;
1558
+ }
1559
+
1560
+ toast.info('Enter a full step ID, wait ID, hook ID, or event ID');
1561
+ },
1562
+ [searchQuery, onExactIdSearch, toast]
1563
+ );
1343
1564
 
1344
1565
  // Track whether we've ever had events to distinguish initial load from refetch
1345
1566
  const hasHadEventsRef = useRef(false);
@@ -1385,17 +1606,6 @@ export function EventListView({
1385
1606
  );
1386
1607
  }
1387
1608
 
1388
- if (!isLoading && (!events || events.length === 0)) {
1389
- return (
1390
- <div
1391
- className="flex items-center justify-center h-full text-sm"
1392
- style={{ color: 'var(--ds-gray-700)' }}
1393
- >
1394
- No events found
1395
- </div>
1396
- );
1397
- }
1398
-
1399
1609
  return (
1400
1610
  <DecryptClickContext.Provider
1401
1611
  value={onDecrypt ? { onDecrypt, isDecrypting } : undefined}
@@ -1460,9 +1670,16 @@ export function EventListView({
1460
1670
  </div>
1461
1671
  <input
1462
1672
  type="search"
1463
- placeholder="Search by name, event type, or ID…"
1673
+ placeholder="Search by step ID, wait ID, hook ID, or event ID…"
1464
1674
  value={searchQuery}
1465
1675
  onChange={(e) => setSearchQuery(e.target.value)}
1676
+ onKeyDown={handleSearchKeyDown}
1677
+ disabled={!onExactIdSearch}
1678
+ title={
1679
+ onExactIdSearch
1680
+ ? undefined
1681
+ : 'Exact ID search is unavailable in this view.'
1682
+ }
1466
1683
  style={{
1467
1684
  marginLeft: -16,
1468
1685
  paddingInline: 12,
@@ -1473,6 +1690,8 @@ export function EventListView({
1473
1690
  outline: 'none',
1474
1691
  height: 40,
1475
1692
  width: '100%',
1693
+ opacity: onExactIdSearch ? 1 : 0.5,
1694
+ cursor: onExactIdSearch ? 'text' : 'not-allowed',
1476
1695
  }}
1477
1696
  />
1478
1697
  </label>
@@ -1492,7 +1711,7 @@ export function EventListView({
1492
1711
 
1493
1712
  {/* Header */}
1494
1713
  <div
1495
- className="flex items-center gap-0 text-[13px] font-medium h-10 border-b flex-shrink-0"
1714
+ className="flex items-center gap-0 text-label-13 font-medium h-10 border-b flex-shrink-0"
1496
1715
  style={{
1497
1716
  borderColor: 'var(--ds-gray-alpha-200)',
1498
1717
  color: 'var(--ds-gray-900)',
@@ -1501,8 +1720,13 @@ export function EventListView({
1501
1720
  >
1502
1721
  <div className="flex-shrink-0" style={{ width: GUTTER_WIDTH }} />
1503
1722
  <div className="w-5 flex-shrink-0" />
1723
+ {showSeparateEventOccurrenceTimestamps && (
1724
+ <div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
1725
+ Occurred
1726
+ </div>
1727
+ )}
1504
1728
  <div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
1505
- Time
1729
+ Created
1506
1730
  </div>
1507
1731
  <div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
1508
1732
  Event Type
@@ -1519,8 +1743,25 @@ export function EventListView({
1519
1743
  </div>
1520
1744
 
1521
1745
  {/* Virtualized event rows or refetching skeleton */}
1522
- {isRefetching ? (
1523
- <RowsSkeleton />
1746
+ {isRefetching || searchLoading ? (
1747
+ <RowsSkeleton
1748
+ showSeparateEventOccurrenceTimestamps={
1749
+ showSeparateEventOccurrenceTimestamps
1750
+ }
1751
+ />
1752
+ ) : sortedEvents.length === 0 ? (
1753
+ <div
1754
+ className="flex flex-1 items-center justify-center px-6 text-center text-copy-14"
1755
+ style={{ color: 'var(--ds-gray-700)' }}
1756
+ >
1757
+ {searchNotFound && searchQuery.trim()
1758
+ ? `No events found for ${searchQuery.trim()}`
1759
+ : searchError
1760
+ ? searchError
1761
+ : parsedSearchId && searchQuery.trim() && !onExactIdSearch
1762
+ ? 'Exact ID search is unavailable in this view.'
1763
+ : 'No events found'}
1764
+ </div>
1524
1765
  ) : (
1525
1766
  <Virtuoso
1526
1767
  ref={virtuosoRef}
@@ -1528,7 +1769,11 @@ export function EventListView({
1528
1769
  overscan={20}
1529
1770
  defaultItemHeight={40}
1530
1771
  endReached={() => {
1531
- if (!hasMoreEvents || isLoadingMoreEvents) {
1772
+ if (
1773
+ isExactSearchActive ||
1774
+ !hasMoreEvents ||
1775
+ isLoadingMoreEvents
1776
+ ) {
1532
1777
  return;
1533
1778
  }
1534
1779
  void onLoadMoreEvents?.();
@@ -1558,6 +1803,10 @@ export function EventListView({
1558
1803
  onCacheEventData={cacheEventData}
1559
1804
  encryptionKey={encryptionKey}
1560
1805
  onEncryptedDataDetected={handleEncryptedDataDetected}
1806
+ suppressGroupDimming={isExactSearchActive}
1807
+ showSeparateEventOccurrenceTimestamps={
1808
+ showSeparateEventOccurrenceTimestamps
1809
+ }
1561
1810
  />
1562
1811
  );
1563
1812
  }}
@@ -1567,7 +1816,7 @@ export function EventListView({
1567
1816
 
1568
1817
  {/* Fixed footer — count + load more */}
1569
1818
  <div
1570
- className="relative flex-shrink-0 flex items-center h-10 border-t px-4 text-xs"
1819
+ className="relative flex-shrink-0 flex items-center h-10 border-t px-4 text-label-12"
1571
1820
  style={{
1572
1821
  borderColor: 'var(--ds-gray-alpha-200)',
1573
1822
  color: 'var(--ds-gray-900)',
@@ -1575,10 +1824,15 @@ export function EventListView({
1575
1824
  }}
1576
1825
  >
1577
1826
  <span>
1578
- {sortedEvents.length} event
1579
- {sortedEvents.length !== 1 ? 's' : ''} loaded
1827
+ {isExactSearchActive
1828
+ ? searchError
1829
+ ? searchError
1830
+ : searchNotFound
1831
+ ? `No events found for ${searchQuery.trim()}`
1832
+ : `${sortedEvents.length} event${sortedEvents.length !== 1 ? 's' : ''} for ${searchQuery.trim()}${searchResultsTruncated ? ' (results may be truncated)' : ''}`
1833
+ : `${sortedEvents.length} event${sortedEvents.length !== 1 ? 's' : ''} loaded`}
1580
1834
  </span>
1581
- {hasMoreEvents && (
1835
+ {!isExactSearchActive && hasMoreEvents && (
1582
1836
  <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
1583
1837
  <div className="pointer-events-auto">
1584
1838
  <LoadMoreButton
@@ -1593,3 +1847,11 @@ export function EventListView({
1593
1847
  </DecryptClickContext.Provider>
1594
1848
  );
1595
1849
  }
1850
+
1851
+ export function EventListView(props: EventsListProps) {
1852
+ return (
1853
+ <ContextCardProvider>
1854
+ <EventListViewInner {...props} />
1855
+ </ContextCardProvider>
1856
+ );
1857
+ }