@workflow/web-shared 4.1.0-beta.47 → 4.1.0-beta.49

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 (301) hide show
  1. package/README.md +26 -52
  2. package/dist/components/error-boundary.d.ts.map +1 -0
  3. package/dist/{error-boundary.js → components/error-boundary.js} +1 -1
  4. package/dist/components/error-boundary.js.map +1 -0
  5. package/dist/{event-list-view.d.ts → components/event-list-view.d.ts} +2 -3
  6. package/dist/components/event-list-view.d.ts.map +1 -0
  7. package/dist/{event-list-view.js → components/event-list-view.js} +9 -17
  8. package/dist/components/event-list-view.js.map +1 -0
  9. package/dist/{hook-actions.d.ts → components/hook-actions.d.ts} +2 -3
  10. package/dist/components/hook-actions.d.ts.map +1 -0
  11. package/dist/{hook-actions.js → components/hook-actions.js} +3 -4
  12. package/dist/components/hook-actions.js.map +1 -0
  13. package/dist/components/index.d.ts +10 -0
  14. package/dist/components/index.d.ts.map +1 -0
  15. package/dist/components/index.js +8 -0
  16. package/dist/components/index.js.map +1 -0
  17. package/dist/components/run-trace-view.d.ts +22 -0
  18. package/dist/components/run-trace-view.d.ts.map +1 -0
  19. package/dist/components/run-trace-view.js +11 -0
  20. package/dist/components/run-trace-view.js.map +1 -0
  21. package/dist/components/sidebar/attribute-panel.d.ts.map +1 -0
  22. package/dist/{sidebar → components/sidebar}/attribute-panel.js +3 -3
  23. package/dist/components/sidebar/attribute-panel.js.map +1 -0
  24. package/dist/components/sidebar/conversation-view.d.ts.map +1 -0
  25. package/dist/components/sidebar/conversation-view.js.map +1 -0
  26. package/dist/components/sidebar/detail-card.d.ts.map +1 -0
  27. package/dist/components/sidebar/detail-card.js.map +1 -0
  28. package/dist/components/sidebar/entity-detail-panel.d.ts +32 -0
  29. package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -0
  30. package/dist/{sidebar → components/sidebar}/entity-detail-panel.js +61 -49
  31. package/dist/components/sidebar/entity-detail-panel.js.map +1 -0
  32. package/dist/components/sidebar/events-list.d.ts +8 -0
  33. package/dist/components/sidebar/events-list.d.ts.map +1 -0
  34. package/dist/components/sidebar/events-list.js +16 -0
  35. package/dist/components/sidebar/events-list.js.map +1 -0
  36. package/dist/components/sidebar/resolve-hook-modal.d.ts.map +1 -0
  37. package/dist/components/sidebar/resolve-hook-modal.js.map +1 -0
  38. package/dist/components/stream-viewer.d.ts +18 -0
  39. package/dist/components/stream-viewer.d.ts.map +1 -0
  40. package/dist/{stream-viewer.js → components/stream-viewer.js} +1 -59
  41. package/dist/components/stream-viewer.js.map +1 -0
  42. package/dist/components/trace-viewer/components/map.d.ts.map +1 -0
  43. package/dist/components/trace-viewer/components/map.js.map +1 -0
  44. package/dist/components/trace-viewer/components/markers.d.ts.map +1 -0
  45. package/dist/components/trace-viewer/components/markers.js.map +1 -0
  46. package/dist/components/trace-viewer/components/node.d.ts.map +1 -0
  47. package/dist/components/trace-viewer/components/node.js.map +1 -0
  48. package/dist/components/trace-viewer/components/search-input.d.ts.map +1 -0
  49. package/dist/components/trace-viewer/components/search-input.js.map +1 -0
  50. package/dist/components/trace-viewer/components/search.d.ts.map +1 -0
  51. package/dist/components/trace-viewer/components/search.js.map +1 -0
  52. package/dist/components/trace-viewer/components/span-detail-panel.d.ts.map +1 -0
  53. package/dist/components/trace-viewer/components/span-detail-panel.js.map +1 -0
  54. package/dist/components/trace-viewer/components/ui.d.ts.map +1 -0
  55. package/dist/components/trace-viewer/components/ui.js.map +1 -0
  56. package/dist/components/trace-viewer/components/zoom-button.d.ts.map +1 -0
  57. package/dist/components/trace-viewer/components/zoom-button.js.map +1 -0
  58. package/dist/components/trace-viewer/components/zoom-icons.d.ts.map +1 -0
  59. package/dist/components/trace-viewer/components/zoom-icons.js.map +1 -0
  60. package/dist/components/trace-viewer/context.d.ts.map +1 -0
  61. package/dist/components/trace-viewer/context.js.map +1 -0
  62. package/dist/components/trace-viewer/index.d.ts.map +1 -0
  63. package/dist/components/trace-viewer/index.js.map +1 -0
  64. package/dist/components/trace-viewer/trace-viewer.d.ts.map +1 -0
  65. package/dist/components/trace-viewer/trace-viewer.js.map +1 -0
  66. package/dist/components/trace-viewer/types.d.ts.map +1 -0
  67. package/dist/components/trace-viewer/types.js.map +1 -0
  68. package/dist/components/trace-viewer/util/constants.d.ts.map +1 -0
  69. package/dist/components/trace-viewer/util/constants.js.map +1 -0
  70. package/dist/components/trace-viewer/util/scrollbar-width.d.ts.map +1 -0
  71. package/dist/components/trace-viewer/util/scrollbar-width.js.map +1 -0
  72. package/dist/{trace-viewer → components/trace-viewer}/util/timing.d.ts +1 -1
  73. package/dist/components/trace-viewer/util/timing.d.ts.map +1 -0
  74. package/dist/{trace-viewer → components/trace-viewer}/util/timing.js +1 -1
  75. package/dist/components/trace-viewer/util/timing.js.map +1 -0
  76. package/dist/components/trace-viewer/util/tree.d.ts.map +1 -0
  77. package/dist/components/trace-viewer/util/tree.js.map +1 -0
  78. package/dist/components/trace-viewer/util/use-immediate-style.d.ts.map +1 -0
  79. package/dist/components/trace-viewer/util/use-immediate-style.js.map +1 -0
  80. package/dist/components/trace-viewer/util/use-streaming-spans.d.ts.map +1 -0
  81. package/dist/components/trace-viewer/util/use-streaming-spans.js.map +1 -0
  82. package/dist/components/trace-viewer/util/use-trackpad-zoom.d.ts.map +1 -0
  83. package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +1 -0
  84. package/dist/components/trace-viewer/worker.d.ts.map +1 -0
  85. package/dist/components/trace-viewer/worker.js.map +1 -0
  86. package/dist/components/workflow-trace-view.d.ts +24 -0
  87. package/dist/components/workflow-trace-view.d.ts.map +1 -0
  88. package/dist/components/workflow-trace-view.js +152 -0
  89. package/dist/components/workflow-trace-view.js.map +1 -0
  90. package/dist/components/workflow-traces/event-colors.d.ts.map +1 -0
  91. package/dist/components/workflow-traces/event-colors.js.map +1 -0
  92. package/dist/components/workflow-traces/trace-colors.d.ts.map +1 -0
  93. package/dist/components/workflow-traces/trace-colors.js.map +1 -0
  94. package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -0
  95. package/dist/components/workflow-traces/trace-span-construction.js.map +1 -0
  96. package/dist/components/workflow-traces/trace-time-utils.d.ts.map +1 -0
  97. package/dist/components/workflow-traces/trace-time-utils.js.map +1 -0
  98. package/dist/index.d.ts +3 -13
  99. package/dist/index.d.ts.map +1 -1
  100. package/dist/index.js +2 -9
  101. package/dist/index.js.map +1 -1
  102. package/package.json +15 -11
  103. package/src/components/error-boundary.tsx +79 -0
  104. package/src/components/event-list-view.tsx +429 -0
  105. package/src/components/hook-actions.tsx +167 -0
  106. package/src/components/index.d.ts +1 -0
  107. package/src/components/index.ts +23 -0
  108. package/src/components/run-trace-view.tsx +75 -0
  109. package/src/components/sidebar/attribute-panel.tsx +938 -0
  110. package/src/components/sidebar/conversation-view.tsx +235 -0
  111. package/src/components/sidebar/detail-card.tsx +43 -0
  112. package/src/components/sidebar/entity-detail-panel.tsx +338 -0
  113. package/src/components/sidebar/events-list.tsx +119 -0
  114. package/src/components/sidebar/resolve-hook-modal.tsx +219 -0
  115. package/src/components/stream-viewer.tsx +143 -0
  116. package/src/components/trace-viewer/components/map.tsx +226 -0
  117. package/src/components/trace-viewer/components/markers.tsx +564 -0
  118. package/src/components/trace-viewer/components/node.tsx +259 -0
  119. package/src/components/trace-viewer/components/search-input.tsx +52 -0
  120. package/src/components/trace-viewer/components/search.tsx +47 -0
  121. package/src/components/trace-viewer/components/span-detail-panel.tsx +650 -0
  122. package/src/components/trace-viewer/components/ui.tsx +156 -0
  123. package/src/components/trace-viewer/components/zoom-button.tsx +61 -0
  124. package/src/components/trace-viewer/components/zoom-icons.tsx +65 -0
  125. package/src/components/trace-viewer/context.tsx +633 -0
  126. package/src/components/trace-viewer/index.tsx +4 -0
  127. package/src/components/trace-viewer/modules.d.ts +16 -0
  128. package/src/components/trace-viewer/trace-viewer.module.css +1292 -0
  129. package/src/components/trace-viewer/trace-viewer.tsx +448 -0
  130. package/src/components/trace-viewer/types.ts +234 -0
  131. package/src/components/trace-viewer/util/constants.ts +8 -0
  132. package/src/components/trace-viewer/util/scrollbar-width.ts +13 -0
  133. package/src/components/trace-viewer/util/timing.ts +33 -0
  134. package/src/components/trace-viewer/util/tree.ts +277 -0
  135. package/src/components/trace-viewer/util/use-immediate-style.ts +38 -0
  136. package/src/components/trace-viewer/util/use-streaming-spans.ts +415 -0
  137. package/src/components/trace-viewer/util/use-trackpad-zoom.tsx +51 -0
  138. package/src/components/trace-viewer/worker.ts +128 -0
  139. package/src/components/ui/alert.tsx +59 -0
  140. package/src/components/ui/card.tsx +88 -0
  141. package/src/components/ui/error-card.tsx +65 -0
  142. package/src/components/ui/skeleton.tsx +15 -0
  143. package/src/components/workflow-trace-view.tsx +306 -0
  144. package/src/components/workflow-traces/event-colors.ts +94 -0
  145. package/src/components/workflow-traces/trace-colors.ts +112 -0
  146. package/src/components/workflow-traces/trace-span-construction.ts +299 -0
  147. package/src/components/workflow-traces/trace-time-utils.ts +50 -0
  148. package/src/hooks/use-dark-mode.ts +34 -0
  149. package/src/index.d.ts +1 -0
  150. package/src/index.ts +29 -0
  151. package/src/lib/event-analysis.ts +231 -0
  152. package/src/lib/utils.ts +166 -0
  153. package/dist/api/workflow-api-client.d.ts +0 -543
  154. package/dist/api/workflow-api-client.d.ts.map +0 -1
  155. package/dist/api/workflow-api-client.js +0 -953
  156. package/dist/api/workflow-api-client.js.map +0 -1
  157. package/dist/api/workflow-server-actions.d.ts +0 -230
  158. package/dist/api/workflow-server-actions.d.ts.map +0 -1
  159. package/dist/api/workflow-server-actions.js +0 -861
  160. package/dist/api/workflow-server-actions.js.map +0 -1
  161. package/dist/error-boundary.d.ts.map +0 -1
  162. package/dist/error-boundary.js.map +0 -1
  163. package/dist/event-list-view.d.ts.map +0 -1
  164. package/dist/event-list-view.js.map +0 -1
  165. package/dist/hook-actions.d.ts.map +0 -1
  166. package/dist/hook-actions.js.map +0 -1
  167. package/dist/run-trace-view.d.ts +0 -8
  168. package/dist/run-trace-view.d.ts.map +0 -1
  169. package/dist/run-trace-view.js +0 -15
  170. package/dist/run-trace-view.js.map +0 -1
  171. package/dist/sidebar/attribute-panel.d.ts.map +0 -1
  172. package/dist/sidebar/attribute-panel.js.map +0 -1
  173. package/dist/sidebar/conversation-view.d.ts.map +0 -1
  174. package/dist/sidebar/conversation-view.js.map +0 -1
  175. package/dist/sidebar/detail-card.d.ts.map +0 -1
  176. package/dist/sidebar/detail-card.js.map +0 -1
  177. package/dist/sidebar/entity-detail-panel.d.ts +0 -12
  178. package/dist/sidebar/entity-detail-panel.d.ts.map +0 -1
  179. package/dist/sidebar/entity-detail-panel.js.map +0 -1
  180. package/dist/sidebar/events-list.d.ts +0 -9
  181. package/dist/sidebar/events-list.d.ts.map +0 -1
  182. package/dist/sidebar/events-list.js +0 -36
  183. package/dist/sidebar/events-list.js.map +0 -1
  184. package/dist/sidebar/resolve-hook-modal.d.ts.map +0 -1
  185. package/dist/sidebar/resolve-hook-modal.js.map +0 -1
  186. package/dist/stream-viewer.d.ts +0 -13
  187. package/dist/stream-viewer.d.ts.map +0 -1
  188. package/dist/stream-viewer.js.map +0 -1
  189. package/dist/trace-viewer/components/map.d.ts.map +0 -1
  190. package/dist/trace-viewer/components/map.js.map +0 -1
  191. package/dist/trace-viewer/components/markers.d.ts.map +0 -1
  192. package/dist/trace-viewer/components/markers.js.map +0 -1
  193. package/dist/trace-viewer/components/node.d.ts.map +0 -1
  194. package/dist/trace-viewer/components/node.js.map +0 -1
  195. package/dist/trace-viewer/components/search-input.d.ts.map +0 -1
  196. package/dist/trace-viewer/components/search-input.js.map +0 -1
  197. package/dist/trace-viewer/components/search.d.ts.map +0 -1
  198. package/dist/trace-viewer/components/search.js.map +0 -1
  199. package/dist/trace-viewer/components/span-detail-panel.d.ts.map +0 -1
  200. package/dist/trace-viewer/components/span-detail-panel.js.map +0 -1
  201. package/dist/trace-viewer/components/ui.d.ts.map +0 -1
  202. package/dist/trace-viewer/components/ui.js.map +0 -1
  203. package/dist/trace-viewer/components/zoom-button.d.ts.map +0 -1
  204. package/dist/trace-viewer/components/zoom-button.js.map +0 -1
  205. package/dist/trace-viewer/components/zoom-icons.d.ts.map +0 -1
  206. package/dist/trace-viewer/components/zoom-icons.js.map +0 -1
  207. package/dist/trace-viewer/context.d.ts.map +0 -1
  208. package/dist/trace-viewer/context.js.map +0 -1
  209. package/dist/trace-viewer/index.d.ts.map +0 -1
  210. package/dist/trace-viewer/index.js.map +0 -1
  211. package/dist/trace-viewer/trace-viewer.d.ts.map +0 -1
  212. package/dist/trace-viewer/trace-viewer.js.map +0 -1
  213. package/dist/trace-viewer/types.d.ts.map +0 -1
  214. package/dist/trace-viewer/types.js.map +0 -1
  215. package/dist/trace-viewer/util/constants.d.ts.map +0 -1
  216. package/dist/trace-viewer/util/constants.js.map +0 -1
  217. package/dist/trace-viewer/util/scrollbar-width.d.ts.map +0 -1
  218. package/dist/trace-viewer/util/scrollbar-width.js.map +0 -1
  219. package/dist/trace-viewer/util/timing.d.ts.map +0 -1
  220. package/dist/trace-viewer/util/timing.js.map +0 -1
  221. package/dist/trace-viewer/util/tree.d.ts.map +0 -1
  222. package/dist/trace-viewer/util/tree.js.map +0 -1
  223. package/dist/trace-viewer/util/use-immediate-style.d.ts.map +0 -1
  224. package/dist/trace-viewer/util/use-immediate-style.js.map +0 -1
  225. package/dist/trace-viewer/util/use-streaming-spans.d.ts.map +0 -1
  226. package/dist/trace-viewer/util/use-streaming-spans.js.map +0 -1
  227. package/dist/trace-viewer/util/use-trackpad-zoom.d.ts.map +0 -1
  228. package/dist/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
  229. package/dist/trace-viewer/worker.d.ts.map +0 -1
  230. package/dist/trace-viewer/worker.js.map +0 -1
  231. package/dist/workflow-trace-view.d.ts +0 -14
  232. package/dist/workflow-trace-view.d.ts.map +0 -1
  233. package/dist/workflow-trace-view.js +0 -135
  234. package/dist/workflow-trace-view.js.map +0 -1
  235. package/dist/workflow-traces/event-colors.d.ts.map +0 -1
  236. package/dist/workflow-traces/event-colors.js.map +0 -1
  237. package/dist/workflow-traces/trace-colors.d.ts.map +0 -1
  238. package/dist/workflow-traces/trace-colors.js.map +0 -1
  239. package/dist/workflow-traces/trace-span-construction.d.ts.map +0 -1
  240. package/dist/workflow-traces/trace-span-construction.js.map +0 -1
  241. package/dist/workflow-traces/trace-time-utils.d.ts.map +0 -1
  242. package/dist/workflow-traces/trace-time-utils.js.map +0 -1
  243. package/server/README.md +0 -1
  244. package/server/package.json +0 -4
  245. /package/dist/{error-boundary.d.ts → components/error-boundary.d.ts} +0 -0
  246. /package/dist/{sidebar → components/sidebar}/attribute-panel.d.ts +0 -0
  247. /package/dist/{sidebar → components/sidebar}/conversation-view.d.ts +0 -0
  248. /package/dist/{sidebar → components/sidebar}/conversation-view.js +0 -0
  249. /package/dist/{sidebar → components/sidebar}/detail-card.d.ts +0 -0
  250. /package/dist/{sidebar → components/sidebar}/detail-card.js +0 -0
  251. /package/dist/{sidebar → components/sidebar}/resolve-hook-modal.d.ts +0 -0
  252. /package/dist/{sidebar → components/sidebar}/resolve-hook-modal.js +0 -0
  253. /package/dist/{trace-viewer → components/trace-viewer}/components/map.d.ts +0 -0
  254. /package/dist/{trace-viewer → components/trace-viewer}/components/map.js +0 -0
  255. /package/dist/{trace-viewer → components/trace-viewer}/components/markers.d.ts +0 -0
  256. /package/dist/{trace-viewer → components/trace-viewer}/components/markers.js +0 -0
  257. /package/dist/{trace-viewer → components/trace-viewer}/components/node.d.ts +0 -0
  258. /package/dist/{trace-viewer → components/trace-viewer}/components/node.js +0 -0
  259. /package/dist/{trace-viewer → components/trace-viewer}/components/search-input.d.ts +0 -0
  260. /package/dist/{trace-viewer → components/trace-viewer}/components/search-input.js +0 -0
  261. /package/dist/{trace-viewer → components/trace-viewer}/components/search.d.ts +0 -0
  262. /package/dist/{trace-viewer → components/trace-viewer}/components/search.js +0 -0
  263. /package/dist/{trace-viewer → components/trace-viewer}/components/span-detail-panel.d.ts +0 -0
  264. /package/dist/{trace-viewer → components/trace-viewer}/components/span-detail-panel.js +0 -0
  265. /package/dist/{trace-viewer → components/trace-viewer}/components/ui.d.ts +0 -0
  266. /package/dist/{trace-viewer → components/trace-viewer}/components/ui.js +0 -0
  267. /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-button.d.ts +0 -0
  268. /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-button.js +0 -0
  269. /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-icons.d.ts +0 -0
  270. /package/dist/{trace-viewer → components/trace-viewer}/components/zoom-icons.js +0 -0
  271. /package/dist/{trace-viewer → components/trace-viewer}/context.d.ts +0 -0
  272. /package/dist/{trace-viewer → components/trace-viewer}/context.js +0 -0
  273. /package/dist/{trace-viewer → components/trace-viewer}/index.d.ts +0 -0
  274. /package/dist/{trace-viewer → components/trace-viewer}/index.js +0 -0
  275. /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.d.ts +0 -0
  276. /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.js +0 -0
  277. /package/dist/{trace-viewer → components/trace-viewer}/trace-viewer.module.css +0 -0
  278. /package/dist/{trace-viewer → components/trace-viewer}/types.d.ts +0 -0
  279. /package/dist/{trace-viewer → components/trace-viewer}/types.js +0 -0
  280. /package/dist/{trace-viewer → components/trace-viewer}/util/constants.d.ts +0 -0
  281. /package/dist/{trace-viewer → components/trace-viewer}/util/constants.js +0 -0
  282. /package/dist/{trace-viewer → components/trace-viewer}/util/scrollbar-width.d.ts +0 -0
  283. /package/dist/{trace-viewer → components/trace-viewer}/util/scrollbar-width.js +0 -0
  284. /package/dist/{trace-viewer → components/trace-viewer}/util/tree.d.ts +0 -0
  285. /package/dist/{trace-viewer → components/trace-viewer}/util/tree.js +0 -0
  286. /package/dist/{trace-viewer → components/trace-viewer}/util/use-immediate-style.d.ts +0 -0
  287. /package/dist/{trace-viewer → components/trace-viewer}/util/use-immediate-style.js +0 -0
  288. /package/dist/{trace-viewer → components/trace-viewer}/util/use-streaming-spans.d.ts +0 -0
  289. /package/dist/{trace-viewer → components/trace-viewer}/util/use-streaming-spans.js +0 -0
  290. /package/dist/{trace-viewer → components/trace-viewer}/util/use-trackpad-zoom.d.ts +0 -0
  291. /package/dist/{trace-viewer → components/trace-viewer}/util/use-trackpad-zoom.js +0 -0
  292. /package/dist/{trace-viewer → components/trace-viewer}/worker.d.ts +0 -0
  293. /package/dist/{trace-viewer → components/trace-viewer}/worker.js +0 -0
  294. /package/dist/{workflow-traces → components/workflow-traces}/event-colors.d.ts +0 -0
  295. /package/dist/{workflow-traces → components/workflow-traces}/event-colors.js +0 -0
  296. /package/dist/{workflow-traces → components/workflow-traces}/trace-colors.d.ts +0 -0
  297. /package/dist/{workflow-traces → components/workflow-traces}/trace-colors.js +0 -0
  298. /package/dist/{workflow-traces → components/workflow-traces}/trace-span-construction.d.ts +0 -0
  299. /package/dist/{workflow-traces → components/workflow-traces}/trace-span-construction.js +0 -0
  300. /package/dist/{workflow-traces → components/workflow-traces}/trace-time-utils.d.ts +0 -0
  301. /package/dist/{workflow-traces → components/workflow-traces}/trace-time-utils.js +0 -0
@@ -0,0 +1,564 @@
1
+ 'use client';
2
+
3
+ import { clsx } from 'clsx';
4
+ import type {
5
+ CSSProperties,
6
+ Dispatch,
7
+ MutableRefObject,
8
+ ReactNode,
9
+ } from 'react';
10
+ import { useEffect, useMemo, useRef } from 'react';
11
+ import { type TraceViewerAction, useTraceViewer } from '../context';
12
+ import styles from '../trace-viewer.module.css';
13
+ import type {
14
+ MemoCache,
15
+ RootNode,
16
+ ScrollSnapshot,
17
+ VisibleSpan,
18
+ VisibleSpanEvent,
19
+ } from '../types';
20
+ import {
21
+ MARKER_HEIGHT,
22
+ ROW_HEIGHT,
23
+ ROW_PADDING,
24
+ TIMELINE_PADDING,
25
+ } from '../util/constants';
26
+ import { formatDurationForTimeline, formatTimeSelection } from '../util/timing';
27
+ import { useImmediateStyle } from '../util/use-immediate-style';
28
+ import { useTrackpadZoom } from '../util/use-trackpad-zoom';
29
+
30
+ const DIVISORS = [1, 2, 4, 5, 8, 10];
31
+
32
+ export function Markers({ scale }: { scale: number }): ReactNode {
33
+ const {
34
+ state: { root },
35
+ } = useTraceViewer();
36
+
37
+ const fullDuration = root.duration;
38
+ const logFull = Math.floor(Math.log10(fullDuration));
39
+ const logHalf = Math.floor(Math.log10(fullDuration * 0.5));
40
+ let markerDuration = Math.max(
41
+ 2,
42
+ 10 ** logFull * (logHalf === logFull ? 1 : 0.5)
43
+ );
44
+ let markerWidth = markerDuration * scale;
45
+ let divisor = 1;
46
+ for (const d of DIVISORS) {
47
+ if (markerDuration / d < 24) break;
48
+ divisor = d;
49
+ }
50
+ markerDuration /= divisor;
51
+ markerWidth /= divisor;
52
+ const markerCount = Math.ceil(fullDuration / markerDuration);
53
+
54
+ // How often labels should appear for markers, e.g. 3 === one label for every third marker
55
+ const labelSpacing = Math.ceil(100 / markerWidth) || 1;
56
+
57
+ return (
58
+ <div className={styles.markersContainer}>
59
+ <div
60
+ aria-hidden
61
+ className={styles.markers}
62
+ style={
63
+ {
64
+ width: Math.floor(root.duration * scale + 15),
65
+ visibility: scale !== -1 ? 'visible' : 'hidden',
66
+ '--marker-width': `${markerWidth}px`,
67
+ } as CSSProperties
68
+ }
69
+ >
70
+ {new Array(markerCount).fill(null).map((_, i) => {
71
+ const hasLabel = i % labelSpacing === 0;
72
+ return (
73
+ <span
74
+ className={clsx(styles.marker, !hasLabel && styles.notch)}
75
+ key={String(i)}
76
+ >
77
+ {hasLabel ? (
78
+ <span className={styles.markerLabel}>
79
+ {formatDurationForTimeline(markerDuration * i)}
80
+ </span>
81
+ ) : null}
82
+ </span>
83
+ );
84
+ })}
85
+ </div>
86
+ </div>
87
+ );
88
+ }
89
+
90
+ export function EventMarkers({
91
+ events,
92
+ root,
93
+ scale,
94
+ }: {
95
+ events: VisibleSpanEvent[];
96
+ root: RootNode;
97
+ scale: number;
98
+ }): ReactNode {
99
+ // Filter out events that should not show vertical lines (workflow-specific feature)
100
+ const eventsWithVerticalLines = useMemo(
101
+ () => events.filter((x) => x.event.showVerticalLine !== false),
102
+ [events]
103
+ );
104
+
105
+ return (
106
+ <div className={styles.eventMarkersContainer}>
107
+ <div
108
+ aria-hidden
109
+ className={styles.eventMarkers}
110
+ style={
111
+ {
112
+ width: Math.floor(root.duration * scale),
113
+ } as CSSProperties
114
+ }
115
+ >
116
+ {eventsWithVerticalLines.map((x) => {
117
+ return (
118
+ <span
119
+ className={clsx(styles.eventMarker)}
120
+ key={x.key}
121
+ style={{
122
+ left: Math.floor((x.timestamp - root.startTime) * scale),
123
+ ...(x.event.color && { borderLeftColor: x.event.color }),
124
+ }}
125
+ />
126
+ );
127
+ })}
128
+ </div>
129
+ </div>
130
+ );
131
+ }
132
+
133
+ const HOVER_OVERSCAN = 2;
134
+
135
+ interface TrackpadZoom {
136
+ anchorX: number;
137
+ anchorT: number;
138
+ }
139
+
140
+ export function CursorMarker({
141
+ memoCacheRef,
142
+ timelineRef,
143
+ root,
144
+ spans,
145
+ events,
146
+ scale,
147
+ dispatch,
148
+ scrollSnapshotRef,
149
+ }: {
150
+ memoCacheRef: MutableRefObject<MemoCache>;
151
+ timelineRef: MutableRefObject<HTMLDivElement | null>;
152
+ root: RootNode;
153
+ spans: VisibleSpan[];
154
+ events: VisibleSpanEvent[];
155
+ scale: number;
156
+ dispatch: Dispatch<TraceViewerAction>;
157
+ scrollSnapshotRef: MutableRefObject<ScrollSnapshot | undefined>;
158
+ }): ReactNode {
159
+ const hasEnteredRef = useRef(false);
160
+ const spansRef = useRef(spans);
161
+ spansRef.current = spans;
162
+ const eventsRef = useRef(events);
163
+ eventsRef.current = events;
164
+ const labelRef = useRef<HTMLDivElement>(null);
165
+ const { style: labelStyle, setStyle: setLabelStyle } =
166
+ useImmediateStyle(labelRef);
167
+ const labelTextRef = useRef<HTMLDivElement>(null);
168
+
169
+ const ref = useRef<HTMLDivElement>(null);
170
+ const { style, setStyle } = useImmediateStyle(ref);
171
+ const rectRef = useRef<DOMRect>(undefined);
172
+
173
+ const selectionRef = useRef<HTMLDivElement>(null);
174
+ const { style: selectionStyle, setStyle: setSelectionStyle } =
175
+ useImmediateStyle(selectionRef);
176
+
177
+ const xRef = useRef(0);
178
+ useEffect(() => {
179
+ const $timeline = timelineRef.current;
180
+ if (!$timeline) return;
181
+
182
+ let x = xRef.current;
183
+ let xStart = 0;
184
+ let isDragging = false;
185
+ let isExternalDrag = false;
186
+ let hasMoved = false;
187
+ let isRightClick = false;
188
+ let scrollX = 0;
189
+ let scrollY = 0;
190
+ const hoverStartT = Date.now() + 500;
191
+ const updateRect = (): void => {
192
+ if (rectRef.current) return;
193
+ rectRef.current = $timeline.getBoundingClientRect();
194
+ };
195
+
196
+ const getRowFromY = (y: number): number => {
197
+ if (!rectRef.current) return 0;
198
+ return (
199
+ (y - MARKER_HEIGHT - TIMELINE_PADDING) / (ROW_HEIGHT + ROW_PADDING)
200
+ );
201
+ };
202
+
203
+ const removeHover = (): void => {
204
+ const cache = memoCacheRef.current;
205
+ // Remove hover styling from any elements that have it
206
+ for (const span of spansRef.current) {
207
+ if (!span.isHovered) continue;
208
+ span.isHovered = false;
209
+ cache.set(span.span.spanId, {});
210
+ }
211
+ dispatch({
212
+ type: 'forceRender',
213
+ });
214
+ };
215
+
216
+ let nextFrame = 0;
217
+ const onFrame = (): void => {
218
+ if (!hasEnteredRef.current) return;
219
+ if (!rectRef.current) updateRect();
220
+ const rect = rectRef.current;
221
+ if (!rect) return;
222
+
223
+ const { scrollLeft, scrollTop } = $timeline;
224
+
225
+ const left = Math.max(
226
+ 0,
227
+ Math.min(
228
+ x + scrollLeft - rect.left - TIMELINE_PADDING,
229
+ root.duration * scale
230
+ )
231
+ );
232
+ const leftStyle = `${left - scrollLeft + TIMELINE_PADDING}px`;
233
+ setStyle('left', leftStyle);
234
+ setLabelStyle('left', leftStyle);
235
+
236
+ const t = root.startTime + left / scale;
237
+ const labelT = t - root.startTime;
238
+ if (labelT < 0 || labelT > root.duration) {
239
+ labelTextRef.current?.removeAttribute('data-text');
240
+ } else {
241
+ labelTextRef.current?.setAttribute(
242
+ 'data-text',
243
+ formatTimeSelection(labelT)
244
+ );
245
+ }
246
+
247
+ if (isDragging) {
248
+ const xDelta = x - xStart;
249
+ const width = Math.abs(xDelta);
250
+ if (!hasMoved) {
251
+ if (width < 4) return;
252
+ hasMoved = true;
253
+ setSelectionStyle('display', 'flex');
254
+ removeHover();
255
+ }
256
+
257
+ if (xDelta > 0) {
258
+ setSelectionStyle('left', '');
259
+ setSelectionStyle('right', '0');
260
+ } else {
261
+ setSelectionStyle('left', '0');
262
+ setSelectionStyle('right', '');
263
+ }
264
+ setSelectionStyle('width', `${width}px`);
265
+
266
+ const leftStart = Math.max(
267
+ 0,
268
+ Math.min(
269
+ xStart + scrollLeft - rect.left - TIMELINE_PADDING,
270
+ root.duration * scale
271
+ )
272
+ );
273
+ const labelTStart = leftStart / scale;
274
+ let t1: number;
275
+ let t2: number;
276
+ if (labelTStart < labelT) {
277
+ t1 = labelTStart;
278
+ t2 = labelT;
279
+ } else {
280
+ t1 = labelT;
281
+ t2 = labelTStart;
282
+ }
283
+ selectionRef.current?.setAttribute(
284
+ 'data-range',
285
+ `${formatTimeSelection(t1)} — ${formatTimeSelection(t2)}`
286
+ );
287
+ selectionRef.current?.setAttribute(
288
+ 'data-duration',
289
+ `${formatTimeSelection(t2 - t1)} selected`
290
+ );
291
+ }
292
+
293
+ if (Date.now() < hoverStartT) {
294
+ nextFrame = requestAnimationFrame(onFrame);
295
+ return;
296
+ }
297
+
298
+ if (scrollLeft !== scrollX || scrollTop !== scrollY) {
299
+ scrollX = scrollLeft;
300
+ scrollY = scrollTop;
301
+ nextFrame = requestAnimationFrame(onFrame);
302
+ return;
303
+ }
304
+
305
+ if (x - rect.left < 128) {
306
+ labelTextRef.current?.setAttribute('data-align', 'left');
307
+ } else if (x - rect.left > rect.width - 128) {
308
+ labelTextRef.current?.setAttribute('data-align', 'right');
309
+ } else {
310
+ labelTextRef.current?.removeAttribute('data-align');
311
+ }
312
+
313
+ if (!hasMoved && !isExternalDrag) {
314
+ const cache = memoCacheRef.current;
315
+
316
+ // Span Hover
317
+ const rowMin = getRowFromY(scrollTop) - HOVER_OVERSCAN;
318
+ const rowMax = getRowFromY(scrollTop + rect.height) + HOVER_OVERSCAN;
319
+ for (const span of spansRef.current) {
320
+ const isHovered =
321
+ span.row >= rowMin &&
322
+ span.row <= rowMax &&
323
+ t >= span.startTime &&
324
+ t <= span.endTime;
325
+ if (span.isHovered === isHovered) continue;
326
+ span.isHovered = isHovered;
327
+ cache.set(span.span.spanId, {});
328
+ }
329
+
330
+ // Event Hover
331
+ const eventSpreadPx = 12;
332
+ const eventSpreadMs = eventSpreadPx / scale;
333
+ for (const event of eventsRef.current) {
334
+ const isHovered =
335
+ t >= event.timestamp - eventSpreadMs &&
336
+ t <= event.timestamp + eventSpreadMs;
337
+ if (event.isHovered === isHovered) continue;
338
+ event.isHovered = isHovered;
339
+ const $event = event.ref?.current;
340
+ if (!$event) continue;
341
+ $event.setAttribute('data-hovered', String(isHovered));
342
+ }
343
+
344
+ dispatch({
345
+ type: 'forceRender',
346
+ });
347
+ }
348
+ };
349
+ nextFrame = requestAnimationFrame(onFrame);
350
+
351
+ const onPointerEnter = (event: PointerEvent): void => {
352
+ if (event.pointerType !== 'mouse') return;
353
+ hasEnteredRef.current = true;
354
+ };
355
+ const onPointerLeave = (): void => {
356
+ if (!hasEnteredRef.current) return;
357
+ hasEnteredRef.current = false;
358
+ removeHover();
359
+ };
360
+
361
+ const onMouseMove = ({ clientX }: MouseEvent): void => {
362
+ x = clientX;
363
+ xRef.current = x;
364
+ cancelAnimationFrame(nextFrame);
365
+ nextFrame = requestAnimationFrame(onFrame);
366
+ };
367
+
368
+ const onContextMenu = (event: MouseEvent): void => {
369
+ event.preventDefault();
370
+ };
371
+ const onMouseDown = (event: MouseEvent): void => {
372
+ if (event.button === 2) {
373
+ isRightClick = true;
374
+ event.preventDefault();
375
+ } else if (event.button !== 0) {
376
+ return;
377
+ } else {
378
+ isRightClick = false;
379
+ }
380
+ if (timelineRef.current?.contains(event.target as HTMLElement)) {
381
+ xStart = x;
382
+ isDragging = true;
383
+ } else {
384
+ isExternalDrag = true;
385
+ requestAnimationFrame(removeHover);
386
+ }
387
+ };
388
+ const onMouseUp = (event: Event): void => {
389
+ isExternalDrag = false;
390
+
391
+ if (!isDragging) return;
392
+ isDragging = false;
393
+
394
+ if (!hasMoved) return;
395
+ hasMoved = false;
396
+ setSelectionStyle('display', '');
397
+ setSelectionStyle('left', '');
398
+ setSelectionStyle('right', '');
399
+ setSelectionStyle('width', '');
400
+
401
+ event.preventDefault();
402
+ event.stopImmediatePropagation();
403
+
404
+ if (isRightClick) {
405
+ isRightClick = false;
406
+ return;
407
+ }
408
+
409
+ if (!rectRef.current) updateRect();
410
+ const rect = rectRef.current;
411
+ if (!rect) return;
412
+
413
+ const { scrollLeft } = $timeline;
414
+
415
+ const start = Math.max(
416
+ 0,
417
+ Math.min(
418
+ (xStart + scrollLeft - rect.left - TIMELINE_PADDING) / scale,
419
+ root.duration
420
+ )
421
+ );
422
+ const end = Math.max(
423
+ 0,
424
+ Math.min(
425
+ (x + scrollLeft - rect.left - TIMELINE_PADDING) / scale,
426
+ root.duration
427
+ )
428
+ );
429
+
430
+ dispatch({
431
+ type: 'scaleToRange',
432
+ t1: start + root.startTime,
433
+ t2: end + root.startTime,
434
+ });
435
+ };
436
+
437
+ const onKeyDown = (event: KeyboardEvent): void => {
438
+ if (!isDragging) return;
439
+ if (event.key !== 'Escape') return;
440
+
441
+ isRightClick = true;
442
+ onMouseUp(event);
443
+ };
444
+
445
+ const onWindowScroll = (): void => {
446
+ rectRef.current = undefined;
447
+ trackpadZoomRef.current = undefined;
448
+ cancelAnimationFrame(nextFrame);
449
+ nextFrame = requestAnimationFrame(onFrame);
450
+ };
451
+
452
+ const onScroll = (): void => {
453
+ cancelAnimationFrame(nextFrame);
454
+ nextFrame = requestAnimationFrame(onFrame);
455
+ };
456
+
457
+ const observer = new ResizeObserver(() => {
458
+ // NOTE: I tried to use the entry from this to immediately set the rect,
459
+ // but for some reason it has different dimensions than the one from
460
+ // .getBoundingClientRect()
461
+ rectRef.current = undefined;
462
+ });
463
+ observer.observe($timeline);
464
+
465
+ window.addEventListener('mousemove', onMouseMove);
466
+ $timeline.addEventListener('contextmenu', onContextMenu);
467
+ window.addEventListener('mousedown', onMouseDown);
468
+ window.addEventListener('mouseup', onMouseUp);
469
+ window.addEventListener('blur', onMouseUp);
470
+ window.addEventListener('keydown', onKeyDown, true);
471
+ window.addEventListener('scroll', onWindowScroll);
472
+ $timeline.addEventListener('scroll', onScroll);
473
+ $timeline.addEventListener('pointerenter', onPointerEnter);
474
+ $timeline.addEventListener('pointerleave', onPointerLeave);
475
+
476
+ return () => {
477
+ observer.disconnect();
478
+ window.removeEventListener('mousemove', onMouseMove);
479
+ $timeline.removeEventListener('contextmenu', onContextMenu);
480
+ window.removeEventListener('mousedown', onMouseDown);
481
+ window.removeEventListener('mouseup', onMouseUp);
482
+ window.removeEventListener('blur', onMouseUp);
483
+ window.removeEventListener('keydown', onKeyDown, true);
484
+ window.removeEventListener('scroll', onWindowScroll);
485
+ $timeline.removeEventListener('scroll', onScroll);
486
+ $timeline.removeEventListener('pointerenter', onPointerEnter);
487
+ $timeline.removeEventListener('pointerleave', onPointerLeave);
488
+ cancelAnimationFrame(nextFrame);
489
+ xRef.current = x;
490
+ removeHover();
491
+ };
492
+ }, [
493
+ dispatch,
494
+ root,
495
+ scale,
496
+ setStyle,
497
+ setLabelStyle,
498
+ setSelectionStyle,
499
+ memoCacheRef,
500
+ timelineRef,
501
+ scrollSnapshotRef,
502
+ ]);
503
+
504
+ const trackpadZoomRef = useRef<TrackpadZoom>(undefined);
505
+ useTrackpadZoom((delta) => {
506
+ const $timeline = timelineRef.current;
507
+ if (!$timeline) return;
508
+
509
+ rectRef.current ??= $timeline.getBoundingClientRect();
510
+ const rect = rectRef.current;
511
+ const anchorX = Math.max(
512
+ 0,
513
+ Math.min(
514
+ xRef.current - rect.left - TIMELINE_PADDING,
515
+ rect.width - 2 * TIMELINE_PADDING
516
+ )
517
+ );
518
+
519
+ let anchorT = 0;
520
+ let existing = trackpadZoomRef.current;
521
+ if (existing?.anchorX === anchorX) {
522
+ anchorT = existing.anchorT;
523
+ } else {
524
+ anchorT = ($timeline.scrollLeft + anchorX) / scale;
525
+ existing = {
526
+ anchorT,
527
+ anchorX,
528
+ };
529
+ trackpadZoomRef.current = existing;
530
+ }
531
+
532
+ dispatch({
533
+ type: 'trackpadScale',
534
+ delta: delta / 64,
535
+ anchorT,
536
+ anchorX,
537
+ });
538
+ });
539
+
540
+ return (
541
+ <>
542
+ <div className={styles.cursorMarkerStickyParent}>
543
+ <div
544
+ className={styles.cursorMarkerLabelContainer}
545
+ ref={labelRef}
546
+ style={labelStyle}
547
+ >
548
+ <div className={styles.cursorMarkerLabel} ref={labelTextRef} />
549
+ </div>
550
+ </div>
551
+ <div className={styles.cursorMarkerStickyParent}>
552
+ <div className={styles.cursorMarkerContainer} ref={ref} style={style}>
553
+ <div className={styles.cursorMarker}>
554
+ <div
555
+ className={styles.cursorSelection}
556
+ ref={selectionRef}
557
+ style={selectionStyle}
558
+ />
559
+ </div>
560
+ </div>
561
+ </div>
562
+ </>
563
+ );
564
+ }